Merge branch '2.7' into 2.8
diff --git a/.gitattributes b/.gitattributes
index 4cf2927..780a8a8 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -1,3 +1,7 @@
 # Do not merge `pom.xml` from older version, as it will typically conflict
+#
+# note: also need:
+# git config --global merge.ours.driver true
+# (and if ever need to disable change `true` to `false`
 
 pom.xml merge=ours
diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md
new file mode 100644
index 0000000..0874104
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE.md
@@ -0,0 +1,6 @@
+We appreciate issues as very valuable contributions, but just to make sure here are things that are important to do before filing an issue:
+
+* Only report issues, and ask Usage Questions on [Jackson-users](https://groups.google.com/forum/#!search/jackson-users) list -- ypu are more likely to get help that way
+* Check to see if this issue has already been reported (quick glance at existing issues): no deep search necessary, just quick sanity check
+* Include version information for Jackson version you use
+* (optional but highly recommended) Verify that the problem occurs with the latest patch of same minor version; and even better, if possible, try using the latest stable patch version
diff --git a/.travis.yml b/.travis.yml
index 7f8f005..5a380fe 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -14,10 +14,9 @@
 branches:
   only:
     - master
-    - "2.7"
+    - "2.8"
 
 env:
   global:
     - secure: "ZIFMeNzZCvLYWICiUyHFSm8Ypz6lYFbF/+LGz6a+Sh8B9tSnvYvlrE4gSFJj3NzRWY0RG/vizoyFEpVgxOnzXDMLuuy/dreupnHR1FfVmiaiceK4JHRwAzl0lQzr2hdVwJbqpX0GfrxKmbg8Jvv9WPKtfM6X4167ElVj4O/8IRc="
     - secure: "VOC/J8eFbM2OeysBp0Gx0G73MySRATCoN7hc9Ok0kJXE/dbE/2KOoFlTwwxUgErwJXkjJKKXafYcbq/22S7wkaoDW5XAvplSu3skxdE0NRGVzozcDMXO5UoGlt9Ti4XIBMCvy7bB/NO+J5IgNedCtcNnBsrGZCdodW3DTYtqQLs="
-
diff --git a/README.md b/README.md
index 1c3d553..0bff2e5 100644
--- a/README.md
+++ b/README.md
@@ -11,6 +11,7 @@
 
 [![Build Status](https://travis-ci.org/FasterXML/jackson-databind.svg?branch=master)](https://travis-ci.org/FasterXML/jackson-databind) [![Maven Central](https://maven-badges.herokuapp.com/maven-central/com.fasterxml.jackson.core/jackson-databind/badge.svg)](https://maven-badges.herokuapp.com/maven-central/com.fasterxml.jackson.core/jackson-databind)
 [![Javadoc](https://javadoc-emblem.rhcloud.com/doc/com.fasterxml.jackson.core/jackson-databind/badge.svg)](http://www.javadoc.io/doc/com.fasterxml.jackson.core/jackson-databind)
+[![Coverage Status](https://coveralls.io/repos/github/FasterXML/jackson-databind/badge.svg?branch=master)](https://coveralls.io/github/FasterXML/jackson-databind?branch=master)
 
 -----
 
@@ -375,7 +376,7 @@
 But here are couple of potentially useful use cases:
 
 ```java
-// Convert from int[] to List<Integer>
+// Convert from List<Integer> to int[]
 List<Integer> sourceList = ...;
 int[] ints = mapper.convertValue(sourceList, int[].class);
 // Convert a POJO into Map!
@@ -425,7 +426,7 @@
 
 # Further reading
 
-* [Overall Jackson Docs](../../../jackson/docs)
+* [Overall Jackson Docs](../../../jackson-docs)
 * [Project wiki page](https://github.com/FasterXML/jackson-databind/wiki)
 
 Related:
diff --git a/attic/MappingIteratorReadTest.java b/attic/MappingIteratorReadTest.java
deleted file mode 100644
index 25aa64c..0000000
--- a/attic/MappingIteratorReadTest.java
+++ /dev/null
@@ -1,25 +0,0 @@
-package com.fasterxml.jackson.databind.seq;
-
-import java.util.List;
-
-import com.fasterxml.jackson.core.type.TypeReference;
-import com.fasterxml.jackson.databind.*;
-
-/**
- * Test(s) for [databind#823], adding support for reading root-level
- * sequences.
- */
-public class MappingIteratorReadTest extends BaseMapTest
-{
-    public void testSimple() throws Exception
-    {
-        final ObjectMapper MAPPER = new ObjectMapper();
-        final String JSON = aposToQuotes("{'str':'a'}{'str':'b'}\n  {'str':'c'}");
-        MappingIterator<StringWrapper> it = MAPPER
-                .readValue(JSON, new TypeReference<MappingIterator<StringWrapper>>() { });
-        List<StringWrapper> all = it.readAll();
-        assertEquals(3, all.size());
-        assertEquals("c", all.get(2).str);
-        it.close();
-    }
-}
diff --git a/pom.xml b/pom.xml
index 4117e5a..c0f6e38 100644
--- a/pom.xml
+++ b/pom.xml
@@ -5,12 +5,12 @@
   <parent>
     <groupId>com.fasterxml.jackson</groupId>
     <artifactId>jackson-parent</artifactId>
-    <version>2.7</version>
+    <version>2.8</version>
   </parent>
 
   <groupId>com.fasterxml.jackson.core</groupId>
   <artifactId>jackson-databind</artifactId>
-  <version>2.7.9.6-SNAPSHOT</version>
+  <version>2.8.11.4-SNAPSHOT</version>
   <name>jackson-databind</name>
   <packaging>bundle</packaging>
   <description>General data-binding functionality for Jackson: works on core streaming API</description>
@@ -25,13 +25,12 @@
   </scm>
 
   <properties>
-    <!-- Ok, so, Jackson 2.7 require JDK 1.7 (except for annotations/streaming). But
-        we do not have strict need for Java 7 bytecode. And, unfortunately, it looks
-        like we have some issues with Mockito tests if we try to go "full 1.7"...
-        So that is why... this:
+    <!-- With Jackson 2.8 we will require JDK 7 (except for annotations/streaming),
+         and new language features (diamond pattern) may be used.
+         Whether JDK dependencies are directly used is an open question as of Feb-2016
       -->
-    <javac.src.version>1.6</javac.src.version>
-    <javac.target.version>1.6</javac.target.version>
+    <javac.src.version>1.7</javac.src.version>
+    <javac.target.version>1.7</javac.target.version>
 
     <!-- Can not use default, since group id != Java package name here -->
     <osgi.export>com.fasterxml.jackson.databind.*;version=${project.version}</osgi.export>
@@ -51,23 +50,28 @@
     <dependency>
       <groupId>com.fasterxml.jackson.core</groupId>
       <artifactId>jackson-core</artifactId>
-      <version>2.7.9</version>
+      <version>2.8.10</version>
     </dependency>
 
     <!-- and for testing we need a few libraries
          libs for which we use reflection for code, but direct dep for testing
       -->
-    <!-- Mock -->
+
+    <dependency>
+      <groupId>junit</groupId>
+      <artifactId>junit</artifactId>
+      <scope>test</scope>
+    </dependency>
     <dependency>
       <groupId>org.powermock</groupId>
       <artifactId>powermock-module-junit4</artifactId>
-      <version>1.6.3</version>
+      <version>1.6.5</version>
       <scope>test</scope>
     </dependency>
     <dependency>
       <groupId>org.powermock</groupId>
       <artifactId>powermock-api-mockito</artifactId>
-      <version>1.6.3</version>
+      <version>1.6.5</version>
       <scope>test</scope>
     </dependency>
     <!-- For testing TestNoClassDefFoundDeserializer -->
@@ -77,6 +81,12 @@
       <version>1.0.0</version>
       <scope>test</scope>
     </dependency>
+    <dependency>
+      <groupId>com.google.jimfs</groupId>
+      <artifactId>jimfs</artifactId>
+      <version>1.1</version>
+      <scope>test</scope>
+    </dependency>
   </dependencies>
 
   <build>
diff --git a/release-notes/CREDITS b/release-notes/CREDITS
index 092a4f0..fcfc2ba 100644
--- a/release-notes/CREDITS
+++ b/release-notes/CREDITS
@@ -149,6 +149,10 @@
    (2.6.3)
   * Reported #1120: String value omitted from weirdStringException
    (2.6.6)
+  * Reported, fixed #1235: `java.nio.file.Path` support incomplete
+   (2.8.0)
+  * Reported #1270: Generic type returned from type id resolver seems to be ignored
+   (2.8.0)
 
 Steve Sanbeg: (sanbeg@github)
   * Contributed #482: Make date parsing error behavior consistent with JDK
@@ -367,6 +371,8 @@
 Jayson Minard (apatrida@github)
   * Reported #1005: Synthetic constructors confusing Jackson data binding
    (2.6.4)
+  * Reported #1438: `ACCEPT_CASE_INSENSITIVE_PROPERTIES` is not respected for creator properties
+   (2.8.5)
 
 David Bakin (david-bakin@github)
   * Reported #1013: `@JsonUnwrapped` is not treated as assuming `@JsonProperty("")`
@@ -486,9 +492,6 @@
     of non-ignored `processor` property (added in 2.7)
    (2.7.8)
 
-Frédéric Camblor (fcamblor@github)
-  * Reported #1451: Type parameter not passed by `ObjectWriter` if serializer pre-fetch disabled
-
 Diego de Estrada (diegode@github)
   * Contributed fix for #1367: No Object Id found for an instance when using `@ConstructorProperties`
    (2.7.9)
@@ -496,3 +499,149 @@
 Kevin Hogeland (khogeland@github)
   * Reported #1501: `ArrayIndexOutOfBoundsException` on non-static inner class constructor
    (2.7.9)
+
+Artur Jonkisz (ajonkisz@github)
+  * Reported #960: `@JsonCreator` not working on a factory with no arguments for ae enum type
+   (2.8.0)
+
+Mikhail Kokho (mkokho@github)
+  * Contributed impl for #990: Allow failing on `null` values for creator (add
+  `DeserializationFeature.FAIL_ON_NULL_CREATOR_PROPERTIES`)
+   (2.8.0)
+
+Aleksandr Oksenenko (oleksandr-oksenenko@github)
+  * Reported #999: External property is not deserialized
+   (2.8.0)
+
+Lokesh Kumar (LokeshN@github)
+  * Contributed impl for #1082: Can not use static Creator factory methods for `Enum`s,
+    with JsonCreator.Mode.PROPERTIES
+   (2.8.0)
+  * Reported #1217: `@JsonIgnoreProperties` on Pojo fields not working for deserialization
+   (2.8.0)
+
+Ross Goldberg
+  * Reported #1165, provided fix for: `CoreXMLDeserializers` does not handle
+    time-only `XMLGregorianCalendar`s
+   (2.8.0)
+
+Maarten Billemont (lhunath@github)
+  * Suggested #1184: Allow overriding of `transient` with explicit inclusion with `@JsonProperty`
+   (2.8.0)
+
+Vladimir Kulev (lightoze@github)
+  * Reported #1028: Ignore USE_BIG_DECIMAL_FOR_FLOATS for NaN/Infinity
+   (2.8.0)
+
+Ari Fogel (arifogel@github)
+  * Reported #1261, contributed fix for: `@JsonIdentityInfo` deserialization fails with
+    combination of forward references, `@JsonCreator`
+   (2.8.0)
+
+Andriy Plokhotnyuk (plokhotnyuk@github)
+  * Requested #1277: Add caching of resolved generic types for `TypeFactory`
+   (2.8.0)
+
+Arek Gabiga (arekgabiga@github)
+  * Reported #1297: Deserialization of generic type with Map.class
+   (2.8.1)
+
+Chris Jester-Young (cky@github)
+  * Contributed #1335: Unconditionally call `TypeIdResolver.getDescForKnownTypeIds`
+   (2.8.2)
+
+Andrew Snare (asnare@github)
+  * Reported #1315: Binding numeric values can BigDecimal lose precision
+   (2.8.2)
+
+Gili Tzabari (cowwoc@github)
+  * Reported #1351: `@JsonInclude(NON_DEFAULT)` doesn't omit null fields
+   (2.8.3)
+
+Oleg Zhukov (OlegZhukov@github)
+  * Reported #1384: `@JsonDeserialize(keyUsing = ...)` does not work correctly
+   together with `DefaultTyping.NON_FINAL`
+   (2.8.4)
+
+Pavel Popov (tolkonepiu@github)
+  * Contributed fix #1389: Problem with handling of multi-argument creator with Enums
+   (2.8.4)
+
+Josh Gruenberg (joshng@github)
+  * Reported #1403: Reference-chain hints use incorrect class-name for inner classes
+   (2.8.4)
+
+Kevin Donnelly (kpdonn@github)
+  * Reported #1432: Off by 1 bug in PropertyValueBuffer
+   (2.8.5)
+
+Nathanial Ofiesh (ofiesh@github)
+  * Reported #1441: Failure with custom Enum key deserializer, polymorphic types
+   (2.8.5)
+
+Frédéric Camblor (fcamblor@github)
+  * Reported #1451: Type parameter not passed by `ObjectWriter` if serializer pre-fetch disabled
+   (2.8.6)
+
+Stephan Schroevers (Stephan202@github)
+  * Reported #1505: @JsonEnumDefaultValue should take precedence over FAIL_ON_NUMBERS_FOR_ENUMS
+   (2.8.7)
+
+Alex Panchenko (panchenko@github)
+  * Reported #1543: JsonFormat.Shape.NUMBER_INT does not work when defined on enum type in 2.8
+   (2.8.8)
+
+Joshua Jones
+  * Reported #1573, contributed fix: Missing properties when deserializing using a builder class
+   with a non-default constructor and a mutator annotated with `@JsonUnwrapped`
+   (2.8.8)
+
+Ivo Studens (istudens@redhat.com)
+  * Contributed #1585: Invoke ServiceLoader.load() inside of a privileged block
+    when loading modules using `ObjectMapper.findModules()`
+   (2.8.9)
+
+Javy Luo (AnywnYu@github)
+  * Reported #1595: `JsonIgnoreProperties.allowSetters` is not working in Jackson 2.8
+   (2.8.9)
+
+Marco Catania (catanm@github.com)
+  * Contributed #1597: Escape JSONP breaking characters
+   (2.8.9)
+
+Andrew Joseph (apjoseph@github)
+  * Reported #1629 `FromStringDeserializer` ignores registered `DeserializationProblemHandler`
+    for `java.util.UUID`
+   (2.8.9)
+
+Joe Littlejohn (joelittlejohn@github)
+  * Contributed #1642: Support `READ_UNKNOWN_ENUM_VALUES_AS_NULL` with `@JsonCreator`
+   (2.8.9)
+
+Slobodan Pejic (slobo-showbie@github)
+  * Reported #1647, contributed fix: Missing properties from base class when recursive
+    types are involved
+   (2.8.9)
+
+Bertrand Renuart (brenuart@github)
+  * Reported #1648: `DateTimeSerializerBase` ignores configured date format when creating contextual
+   (2.8.9)
+  * Reported #1651: `StdDateFormat` fails to parse 'zulu' date when TimeZone other than UTC
+   (2.8.9)
+
+Kevin Gallardo (newkek@github)
+  * Reported #1658: Infinite recursion when deserializing a class extending a Map,
+    with a recursive value type
+   (2.8.10)
+
+Guixiong Wu (吴桂雄)
+  * Reported #2032: Blacklist another serialization gadget (ibatis)
+   (2.8.11.2)
+
+svarzee@github
+  * Reported #2109, suggested fix: Canonical string for reference type is built incorrectly
+   (2.8.11.3 / 2.9.7)
+
+Connor Kuhn (ckuhn@github)
+  * Contributed #1341: FAIL_ON_MISSING_EXTERNAL_TYPE_ID_PROPERTY
+   (2.9.0)
diff --git a/release-notes/VERSION b/release-notes/VERSION
index e31ca61..b2c8243 100644
--- a/release-notes/VERSION
+++ b/release-notes/VERSION
@@ -1,74 +1,272 @@
 Project: jackson-databind
-
 ------------------------------------------------------------------------
 === Releases ===
 ------------------------------------------------------------------------
 
-Not yet released
+2.8.11.4 (not released)
+
+#2326: Block one more gadget type (CVE-2019-12086)
+
+2.8.11.3 (23-Nov-2018)
 
 #2326: Block class for CVE-2019-12086
  (contributed by MaximilianTews@github)
 
-2.7.9.5 (23-Nov-2018)
+2.8.11.2 (08-Jun-2018)
 
+#1941: `TypeFactory.constructFromCanonical()` throws NPE for Unparameterized
+  generic canonical strings
+ (reported by ayushgp@github)
+#2032: CVE-2018-11307: Potential information exfiltration with default typing, serialization gadget from MyBatis
+ (reported by Guixiong Wu)
+#2052: CVE-2018-12022: Block polymorphic deserialization of types from Jodd-db library
+ (reported by Guixiong Wu)
+#2058: CVE-2018-12023: Block polymorphic deserialization of types from Oracle JDBC driver
+ (reported by Guixiong Wu)
+
+2.8.11.1 (11-Feb-2018)
+
+#1872: `NullPointerException` in `SubTypeValidator.validateSubType` when
+  validating Spring interface
+ (reported by Rob W)
 #1899: Another two gadgets to exploit default typing issue in jackson-databind
  (reported by OneSourceCat@github)
+#1931: Two more `c3p0` gadgets to exploit default typing issue
+
+2.8.11 (24-Dec-2017)
+
+#1604: Nested type arguments doesn't work with polymorphic types
+#1680: Blacklist couple more types for deserialization
+#1767: Allow `DeserializationProblemHandler` to respond to primitive types
+ (reported by nhtzr@github)
+#1768: Improve `TypeFactory.constructFromCanonical()` to work with
+  `java.lang.reflect.Type.getTypeName()` format
+#1804: `ValueInstantiator.canInstantiate()` ignores `canCreateUsingArrayDelegate()`
+ (reported by henryptung@github)
+#1807: Jackson-databind caches plain map deserializer and use it even map has `@JsonDeserializer`
+ (reported by lexas2509@github)
+#1855: Blacklist for more serialization gadgets (dbcp/tomcat, spring)
+
+2.8.10 (24-Aug-2017)
+
+#1657: `StdDateFormat` deserializes dates with no tz/offset as UTC instead of
+  configured timezone
+ (reported by Bertrand R)
+#1658: Infinite recursion when deserializing a class extending a Map,
+  with a recursive value type
+ (reported by Kevin G)
+#1679: `StackOverflowError` in Dynamic `StdKeySerializer`
+#1711: Delegating creator fails to work for binary data (`byte[]`) with
+ binary formats (CBOR, Smile)
+#1735: Missing type checks when using polymorphic type ids
+#1737: Block more JDK types from polymorphic deserialization
+
+2.8.9 (12-Jun-2017)
+
+#1595: `JsonIgnoreProperties.allowSetters` is not working in Jackson 2.8
+ (reported by Javy L)
+#1597: Escape JSONP breaking characters
+ (contributed by Marco C)
+#1629: `FromStringDeserializer` ignores registered `DeserializationProblemHandler`
+  for `java.util.UUID`
+ (reported by Andrew J)
+#1642: Support `READ_UNKNOWN_ENUM_VALUES_AS_NULL` with `@JsonCreator`
+ (contributed by Joe L)
+#1647: Missing properties from base class when recursive types are involved
+ (reported by Slobodan P)
+#1648: `DateTimeSerializerBase` ignores configured date format when creating contextual
+ (reported by Bertrand R)
+#1651: `StdDateFormat` fails to parse 'zulu' date when TimeZone other than UTC
+ (reported by Bertrand R)
+
+2.8.8.1 (19-Apr-2017)
+
+#1585: Invoke ServiceLoader.load() inside of a privileged block when loading
+  modules using `ObjectMapper.findModules()`
+ (contributed by Ivo S)
+#1599: Jackson Deserializer security vulnerability
+ (reported by ayound@github)
+#1607: @JsonIdentityReference not used when setup on class only
+ (reported by vboulaye@github)
+
+2.8.8 (05-Apr-2017)
+
+(partial) #994: `DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS` only works for POJOs, Maps
+#1345: `@JsonProperty(access = READ_ONLY)` together with generated constructor (Lombok) causes
+ exception: "Could not find creator property with name ..."
+ (reported by Raniz85@github)
+#1533: `AsPropertyTypeDeserializer` ignores `DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT`
+#1543: JsonFormat.Shape.NUMBER_INT does not work when defined on enum type in 2.8
+ (reported by Alex P)
+#1570: `Enum` key for `Map` ignores `SerializationFeature.WRITE_ENUMS_USING_INDEX`
+ (reported by SolaKun@github)
+#1573: Missing properties when deserializing using a builder class with a non-default
+  constructor and a mutator annotated with `@JsonUnwrapped`
+ (reported by Joshua J)
+#1575: Problem with `@JsonIgnoreProperties` on recursive property (regression in 2.8)
+ (reported by anujkumar04@github)
+- Minor fix to creation of `PropertyMetadata`, had one path that could lead to NPE
+
+2.8.7 (21-Feb-2017)
+
+#935: `@JsonProperty(access = Access.READ_ONLY)` - unexpected behaviour
+#1317: '@JsonIgnore' annotation not working with creator properties, serialization
+
+2.8.6 (12-Jan-2017)
+
+#349: @JsonAnySetter with @JsonUnwrapped: deserialization fails with arrays
+ (reported by hdave@github)
+#1388: `@JsonIdentityInfo`: id has to be the first key in deserialization when
+  deserializing with `@JsonCreator`
+ (reported by moodysalem@github)
+#1425: `JsonNode.binaryValue()` ignores illegal character if it's the last one
+ (reported by binoternary@github)
+#1453: `UntypedObjectDeserializer` does not retain `float` type (over `double`)
+#1456: `TypeFactory` type resolution broken in 2.7 for generic types
+   when using `constructType` with context
+#1473: Add explicit deserializer for `StringBuilder` due to Java 9 changes
+#1493: `ACCEPT_CASE_INSENSITIVE_PROPERTIES` fails with `@JsonUnwrapped`
+
+2.8.5 (14-Nov-2016)
+
+#1417: Further issues with `@JsonInclude` with `NON_DEFAULT`
+#1421: ACCEPT_SINGLE_VALUE_AS_ARRAY partially broken in 2.7.x, 2.8.x
+#1429: `StdKeyDeserializer` can erroneously use a static factory method
+  with more than one argument
+#1432: Off by 1 bug in PropertyValueBuffer
+ (reported by Kevin D)
+#1438: `ACCEPT_CASE_INSENSITIVE_PROPERTIES` is not respected for creator properties
+ (reported by Jayson M)
+#1439: NPE when using with filter id, serializing `java.util.Map` types
+#1441: Failure with custom Enum key deserializer, polymorphic types
+ (reported by Nathanial O)
+#1445: Map key deserializerModifiers ignored
+ (reported by alfonsobonso@github)
+- Improvements to #1411 fix to ensure consistent `null` key handling
+
+2.8.4 (14-Oct-2016)
+
+#466: Jackson ignores Type information when raw return type is BigDecimal or BigInteger 
+#1001: Parameter names module gets confused with delegate creator which is a static method
+#1324: Boolean parsing with `StdDeserializer` is too slow with huge integer value
+ (reported by pavankumar-parankusam@github)
+#1383: Problem with `@JsonCreator` with 1-arg factory-method, implicit param names
+#1384: `@JsonDeserialize(keyUsing = ...)` does not work correctly together with
+  DefaultTyping.NON_FINAL
+ (reported by Oleg Z)
+#1385: Polymorphic type lost when using `@JsonValue`
+ (reported by TomMarkuske@github)
+#1389 Problem with handling of multi-argument creator with Enums
+ (fix contributed by Pavel P)
+#1392: Custom UnmodifiableSetMixin Fails in Jackson 2.7+ but works in Jackson 2.6
+ (reported by Rob W)
+#1395: Problems deserializing primitive `long` field while using `TypeResolverBuilder`
+ (reported by UghZan3@github)
+#1403: Reference-chain hints use incorrect class-name for inner classes
+ (reported by Josh G)
+#1411: MapSerializer._orderEntries should check for null keys
+ (reported by Jörn H)
+
+2.8.3 (17-Sep-2016)
+
+#929: `@JsonCreator` not working on a factory with multiple arguments for a enum type
+#1351: `@JsonInclude(NON_DEFAULT)` doesn't omit null fields
+ (reported by Gili T)
+#1353: Improve error-handling for `java.net.URL` deserialization
+#1361: Change `TokenBuffer` to use new `writeEmbeddedObject()` if possible
+
+2.8.2 (30-Aug-2016)
+
+#1315: Binding numeric values can BigDecimal lose precision
+ (reported by Andrew S)
+#1327: Class level `@JsonInclude(JsonInclude.Include.NON_EMPTY)` is ignored
+ (reported by elruwen@github)
+#1335: Unconditionally call `TypeIdResolver.getDescForKnownTypeIds`
+ (contributed by Chris J-Y)
+
+2.8.1 (20-Jul-2016)
+
+#1256: `Optional.empty()` not excluded if property declared with type `Object`
+#1288: Type id not exposed for `JsonTypeInfo.As.EXTERNAL_PROPERTY` even when `visible` set to `true`
+ (reported by libetl@github)
+#1289: Optimize construction of `ArrayList`, `LinkedHashMap` instances
+#1291: Backward-incompatible behaviour of 2.8: deserializing enum types
+   with two static factory methods fail by default
+#1297: Deserialization of generic type with Map.class
+ (reported by Arek G)
+#1302: NPE for `ResolvedRecursiveType` in 2.8.0 due to caching
+
+2.8.0 (04-Jul-2016)
+
+#621: Allow definition of "ignorable types" without annotation (using
+  `Mapper.configOverride(type).setIsIgnoredType(true)`
+#867: Support `SerializationFeature.WRITE_EMPTY_JSON_ARRAYS ` for `JsonNode`
+#903: Add `JsonGenerator` reference to `SerializerProvider`
+#931: Add new method in `Deserializers.Base` to support `ReferenceType`
+#960: `@JsonCreator` not working on a factory with no arguments for an enum type
+ (reported by Artur J)
+#990: Allow failing on `null` values for creator (add 
+  `DeserializationFeature.FAIL_ON_NULL_CREATOR_PROPERTIES`)
+ (contributed by mkokho@github)
+#999: External property is not deserialized
+ (reported by Aleksandr O)
+#1017: Add new mapping exception type ('InvalidTypeIdException') for subtype resolution errors
+ (suggested by natnan@github)
+#1028: Ignore USE_BIG_DECIMAL_FOR_FLOATS for NaN/Infinity
+ (reported by Vladimir K, lightoze@github)
+#1047: Allow use of `@JsonAnySetter` on a Map-valued field, no need for setter
+#1082: Can not use static Creator factory methods for `Enum`s, with JsonCreator.Mode.PROPERTIES
+ (contributed by Lokesh K)
+#1084: Change `TypeDeserializerBase` to take `JavaType` for `defaultImpl`, NOT `Class`
+#1126: Allow deserialization of unknown Enums using a predefined value
+ (contributed by Alejandro R)
+#1136: Implement `TokenBuffer.writeEmbeddedObject(Object)`
+ (suggested by Gregoire C, gcxRun@github)
+#1165: CoreXMLDeserializers does not handle time-only XMLGregorianCalendars
+ (reported, contributed fix by Ross G)
+#1181: Add the ability to specify the initial capacity of the ArrayNode
+ (suggested by Matt V, mveitas@github)
+#1184: Allow overriding of `transient` with explicit inclusion with `@JsonProperty`
+ (suggested by Maarten B)
+#1187: Refactor `AtomicReferenceDeserializer` into `ReferenceTypeDeserializer`
+#1204: Add a convenience accessor `JavaType.hasContentType()` (true for container or reference type)
+#1206: Add "anchor type" member for `ReferenceType`
+#1211: Change `JsonValueSerializer` to get `AnnotatedMethod`, not "raw" method
+#1217: `@JsonIgnoreProperties` on Pojo fields not working for deserialization
+ (reported by Lokesh K)
+#1221: Use `Throwable.addSuppressed()` directly and/or via try-with-resources
+#1232: Add support for `JsonFormat.Feature.ACCEPT_CASE_INSENSITIVE_PROPERTIES`
+#1233: Add support for `JsonFormat.Feature.WRITE_SORTED_MAP_ENTRIES`
+#1235: `java.nio.file.Path` support incomplete
+ (reported by, fix contributed by Benson M)
+#1261: JsonIdentityInfo broken deserialization involving forward references and/or cycles
+ (reported by, fix contributed by Ari F)
+#1270: Generic type returned from type id resolver seems to be ignored
+ (reported by Benson M)
+#1277: Add caching of resolved generic types for `TypeFactory`
+ (requested by Andriy P)
+
+2.7.9.5 (23-Nov-2018)
+
 #2097: Block more classes from polymorphic deserialization (CVE-2018-14718
   - CVE-2018-14721)
+ (reported by Guixiong Wu)
+#2109: Canonical string for reference type is built incorrectly
+ (reported by svarzee@github)
 #2186: Block more classes from polymorphic deserialization (CVE-2018-19360,
   CVE-2018-19361, CVE-2018-19362)
  (reported by Guixiong Wu)
 
-2.7.9.4 (08-Jun-2018)
-
-#2032: CVE-2018-11307: Potential information exfiltration with default typing, serialization gadget from MyBatis
-#2052: CVE-2018-12022: Block polymorphic deserialization of types from Jodd-db library
-#2058: CVE-2018-12023: Block polymorphic deserialization of types from Oracle JDBC driver
-
-2.7.9.3 (11-Feb-2018)
-
-#1872 `NullPointerException` in `SubTypeValidator.validateSubType` when
-  validating Spring interface
- (reported by Rob W)
-#1931: Two more `c3p0` gadgets to exploit default typing issue
-
-2.7.9.2 (20-Dec-2017)
-
-#1607: @JsonIdentityReference not used when setup on class only
- (reported by vboulaye@github)
-#1628: Don't print to error stream about failure to load JDK 7 types
- (reported by Villane@github)
-#1680: Blacklist couple more types for deserialization
-#1737: Block more JDK types from polymorphic deserialization
-#1855: Blacklist for more serialization gadgets (dbcp/tomcat, spring)
-
-2.7.9.1 (18-Apr-2017)
-
-#1599: Jackson Deserializer security vulnerability
- (reported by ayound@github)
-- Minor robustification of method resolution in `AnnotatedClass`
-
 2.7.9 (04-Feb-2017)
 
 #1367: No Object Id found for an instance when using `@ConstructorProperties`
- (reported by kajo-bellabeat@github; fix by diegode@github)
-#1392: Custom UnmodifiableSetMixin Fails in Jackson 2.7+ but works in Jackson 2.6
- (reported by Rob W)
-#1411: MapSerializer._orderEntries should check for null keys
- (reported by Jörn H)
-#1432: Off by 1 bug in PropertyValueBuffer
- (reported by Kevin D)
-#1439: NPE when using with filter id, serializing `java.util.Map` types
-#1451: Type parameter not passed by `ObjectWriter` if serializer pre-fetch disabled
- (reported by Frédéric C)
-#1456: `TypeFactory` type resolution broken in 2.7 for generic types
-   when using `constructType` with context
- (reported by Dmitry S)
-#1476: Wrong constructor picked up when deserializing object
- (reported by laurentgo@github)
-#1501: `ArrayIndexOutOfBoundsException` on non-static inner class constructor
- (reported by Kevin H)
+#1505: @JsonEnumDefaultValue should take precedence over FAIL_ON_NUMBERS_FOR_ENUMS
+ (suggested by Stephan S)
 #1506: Missing `KeyDeserializer` for `CharSequence`
+#1513: `MapSerializer._orderEntries()` throws NPE when operating on `ConcurrentHashMap`
+ (reported by Sovietaced@github)
+- Simplified processing of class annotations (for `AnnotatedClass`) to try to
+  solve rare concurrency problems with "root name" annotations.
 
 2.7.8 (26-Sep-2016)
 
diff --git a/src/main/java/com/fasterxml/jackson/databind/AbstractTypeResolver.java b/src/main/java/com/fasterxml/jackson/databind/AbstractTypeResolver.java
index da6c889..587c29f 100644
--- a/src/main/java/com/fasterxml/jackson/databind/AbstractTypeResolver.java
+++ b/src/main/java/com/fasterxml/jackson/databind/AbstractTypeResolver.java
@@ -30,11 +30,13 @@
         return null;
     }
 
-    // !!! 29-Nov-2015, tatu: TODO: mark deprecated in 2.8
     /**
      * Older variant of {@link #resolveAbstractType(DeserializationConfig, BeanDescription)};
-     * obsoleted in 2.7, to be deprecated in 2.8
+     * obsoleted in 2.7
+     *
+     * @deprecated since 2.8 (may be removed from 2.9 or later)
      */
+    @Deprecated
     public JavaType resolveAbstractType(DeserializationConfig config,
             JavaType type) {
         return null;
@@ -46,10 +48,7 @@
      * when no concrete implementation was found.
      * It will be called after checking all other possibilities,
      * including defaulting.
-     *<p>
-     * Default implementation will call obsolete method for Jackson 2.7,
-     * to try to keep some level of backwards compatibility.
-     * 
+     *
      * @param config Configuration in use; should always be of type
      *    <code>DeserializationConfig</code>
      * @param typeDesc Description of the POJO type to resolve
@@ -62,6 +61,6 @@
      */
     public JavaType resolveAbstractType(DeserializationConfig config,
             BeanDescription typeDesc) {
-        return resolveAbstractType(config, typeDesc.getType());
+        return null;
     }
 }
diff --git a/src/main/java/com/fasterxml/jackson/databind/AnnotationIntrospector.java b/src/main/java/com/fasterxml/jackson/databind/AnnotationIntrospector.java
index 3966997..c1e3655 100644
--- a/src/main/java/com/fasterxml/jackson/databind/AnnotationIntrospector.java
+++ b/src/main/java/com/fasterxml/jackson/databind/AnnotationIntrospector.java
@@ -5,6 +5,7 @@
 
 import com.fasterxml.jackson.annotation.JsonCreator;
 import com.fasterxml.jackson.annotation.JsonFormat;
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
 import com.fasterxml.jackson.annotation.JsonInclude;
 import com.fasterxml.jackson.annotation.JsonProperty;
 import com.fasterxml.jackson.core.Version;
@@ -226,15 +227,46 @@
     }
 
     /**
-     * Method for finding list of properties to ignore for given class
-     * (null is returned if not specified).
-     * List of property names is applied
-     * after other detection mechanisms, to filter out these specific
-     * properties from being serialized and deserialized.
-     * 
+     * Method for finding information about properties to ignore either by
+     * name, or by more general specification ("ignore all unknown").
+     * This method combines multiple aspects of ignorals and deprecates
+     * earlier methods such as
+     * {@link #findPropertiesToIgnore(Annotated, boolean)} and
+     * {@link #findIgnoreUnknownProperties(AnnotatedClass)}.
+     *
+     * @since 2.8
+     */
+    public JsonIgnoreProperties.Value findPropertyIgnorals(Annotated ac)
+    {
+        // 28-Apr-2016, tatu: For backwards compatibility let's delegate to older
+        //   methods, for Jackson 2.8
+        String[] ignorals = findPropertiesToIgnore(ac, true);
+        Boolean b = (ac instanceof AnnotatedClass) ?
+                findIgnoreUnknownProperties((AnnotatedClass) ac) : null;
+        JsonIgnoreProperties.Value v;
+        if (ignorals == null) {
+            if (b == null) {
+                return null;
+            }
+            v = JsonIgnoreProperties.Value.empty();
+        } else {
+            v = JsonIgnoreProperties.Value.forIgnoredProperties(ignorals);
+        }
+        if (b != null) {
+            v = b.booleanValue() ? v.withIgnoreUnknown() : v.withoutIgnoreUnknown();
+        }
+        return v;
+    }
+
+    /**
      * @param forSerialization True if requesting properties to ignore for serialization;
      *   false if for deserialization
+     * 
+     * @since 2.6
+     *
+     * @deprecated Since 2.8, use {@link #findPropertyIgnorals} instead
      */
+    @Deprecated // since 2.8
     public String[] findPropertiesToIgnore(Annotated ac, boolean forSerialization) {
         return null;
     }
@@ -242,15 +274,17 @@
     /**
      * @deprecated Since 2.6, use variant that takes second argument.
      */
-    @Deprecated
+    @Deprecated // since 2.6
     public String[] findPropertiesToIgnore(Annotated ac) {
-        // Changed in 2.7 to call from old to new; with 2.6 was opposite
-        return findPropertiesToIgnore(ac, true);
+        return null;
     }
-    
+
     /**
      * Method for checking whether an annotation indicates that all unknown properties
+     *
+     * @deprecated Since 2.8, use {@link #findPropertyIgnorals} instead
      */
+    @Deprecated // since 2.8
     public Boolean findIgnoreUnknownProperties(AnnotatedClass ac) { return null; }
 
     /**
@@ -981,14 +1015,19 @@
         return false;
     }
 
-    // TODO: Deprecate in 2.8?
     /**
      * Method for determining the String value to use for serializing
      * given enumeration entry; used when serializing enumerations
      * as Strings (the standard method).
      *
      * @return Serialized enum value.
+     *
+     * @deprecated Since 2.8: use {@link #findEnumValues} instead because this method
+     *    does not properly handle override settings (defaults to <code>enum.name</code>
+     *    without indicating whether that is explicit or not), and is inefficient to
+     *    call one-by-one.
      */
+    @Deprecated
     public String findEnumValue(Enum<?> value) {
         return value.name();
     }
@@ -1018,6 +1057,18 @@
         return names;
     }
 
+    /**
+     * Finds the Enum value that should be considered the default value, if possible.
+     *
+     * @param enumCls The Enum class to scan for the default value.
+     * @return null if none found or it's not possible to determine one.
+     *
+     * @since 2.8
+     */
+    public Enum<?> findDefaultEnumValue(Class<Enum<?>> enumCls) {
+        return null;
+    }
+
     /*
     /**********************************************************
     /* Deserialization: general annotations
diff --git a/src/main/java/com/fasterxml/jackson/databind/BeanDescription.java b/src/main/java/com/fasterxml/jackson/databind/BeanDescription.java
index dc7838f..cd21182 100644
--- a/src/main/java/com/fasterxml/jackson/databind/BeanDescription.java
+++ b/src/main/java/com/fasterxml/jackson/databind/BeanDescription.java
@@ -21,12 +21,6 @@
  */
 public abstract class BeanDescription
 {
-    /*
-    /**********************************************************
-    /* Configuration
-    /**********************************************************
-     */
-
     /**
      * Bean type information, including raw class and possible
      * * generics information
@@ -58,6 +52,13 @@
     public Class<?> getBeanClass() { return _type.getRawClass(); }
 
     /**
+     * @since 2.9
+     */
+    public boolean isNonStaticInnerClass() {
+        return getClassInfo().isNonStaticInnerClass();
+    }
+
+    /**
      * Method for accessing low-level information about Class this
      * item describes.
      */
@@ -80,7 +81,7 @@
      * types of member object, such as return and argument types of
      * methods and constructors, and types of fields.
      *
-     * @deprecated Since 2.7, use {@link #resolveType(java.lang.reflect.Type)} instead.
+     * @deprecated Since 2.7, should not need to access bindings directly
      */
     @Deprecated
     public abstract TypeBindings bindingsForBeanType();
@@ -88,7 +89,11 @@
     /**
      * Method for resolving given JDK type, using this bean as the
      * generic type resolution context.
+     *
+     * @deprecated Since 2.8, should simply call <code>getType</code> of
+     *    property accessor directly.
      */
+    @Deprecated
     public abstract JavaType resolveType(java.lang.reflect.Type jdkType);
 
     /**
@@ -172,6 +177,15 @@
     public abstract AnnotatedMethod findAnySetter();
 
     /**
+     * Method used to locate the field of the class that implements
+     * {@link com.fasterxml.jackson.annotation.JsonAnySetter} If no such method
+     * exists null is returned. If more than one are found, an exception is thrown.
+     * 
+     * @since 2.8
+     */
+    public abstract AnnotatedMember findAnySetterField();
+
+    /**
      * Method for locating the getter method that is annotated with
      * {@link com.fasterxml.jackson.annotation.JsonValue} annotation,
      * if any. If multiple ones are found,
@@ -188,6 +202,12 @@
      */
 
     /**
+     * Method for finding annotation-indicated inclusion definition (if any);
+     * possibly overriding given default value.
+     *<p>
+     * NOTE: does NOT use global inclusion default settings as the base, unless
+     * passed as `defValue`.
+     *
      * @since 2.7
      */
     public abstract JsonInclude.Value findPropertyInclusion(JsonInclude.Value defValue);
diff --git a/src/main/java/com/fasterxml/jackson/databind/BeanProperty.java b/src/main/java/com/fasterxml/jackson/databind/BeanProperty.java
index 924641d..525aa11 100644
--- a/src/main/java/com/fasterxml/jackson/databind/BeanProperty.java
+++ b/src/main/java/com/fasterxml/jackson/databind/BeanProperty.java
@@ -136,7 +136,10 @@
      * use {@link #findPropertyFormat} if such defaults would be useful.
      *
      * @since 2.6
+     * 
+     * @deprecated since 2.8 use {@link #findPropertyFormat} instead.
      */
+    @Deprecated
     public JsonFormat.Value findFormatOverrides(AnnotationIntrospector intr);
 
     /**
@@ -195,7 +198,6 @@
      */
     public static class Std implements BeanProperty
     {
-
         protected final PropertyName _name;
         protected final JavaType _type;
         protected final PropertyName _wrapperName;
@@ -234,16 +236,6 @@
             this(base._name, newType, base._wrapperName, base._contextAnnotations, base._member, base._metadata);
         }
 
-        @Deprecated // since 2.3
-        public Std(String name, JavaType type, PropertyName wrapperName,
-                Annotations contextAnnotations, AnnotatedMember member,
-                boolean isRequired)
-        {
-            this(new PropertyName(name), type, wrapperName, contextAnnotations,
-                    member,
-                    isRequired ? PropertyMetadata.STD_REQUIRED : PropertyMetadata.STD_OPTIONAL);
-        }
-
         public Std withType(JavaType type) {
             return new Std(this, type);
         }
@@ -307,13 +299,6 @@
         @Override public PropertyMetadata getMetadata() { return _metadata; }
         @Override public AnnotatedMember getMember() { return _member; }
 
-        /**
-         *<p>
-         * TODO: move to {@link BeanProperty} in near future, once all standard
-         * implementations define it.
-         * 
-         * @since 2.5
-         */
         @Override
         public boolean isVirtual() { return false; }
 
diff --git a/src/main/java/com/fasterxml/jackson/databind/DatabindContext.java b/src/main/java/com/fasterxml/jackson/databind/DatabindContext.java
index 849b9cc..f42a0bb 100644
--- a/src/main/java/com/fasterxml/jackson/databind/DatabindContext.java
+++ b/src/main/java/com/fasterxml/jackson/databind/DatabindContext.java
@@ -4,9 +4,8 @@
 import java.util.Locale;
 import java.util.TimeZone;
 
-import com.fasterxml.jackson.annotation.JsonFormat;
-import com.fasterxml.jackson.annotation.ObjectIdGenerator;
-import com.fasterxml.jackson.annotation.ObjectIdResolver;
+import com.fasterxml.jackson.annotation.*;
+
 import com.fasterxml.jackson.databind.cfg.HandlerInstantiator;
 import com.fasterxml.jackson.databind.cfg.MapperConfig;
 import com.fasterxml.jackson.databind.introspect.Annotated;
@@ -90,7 +89,7 @@
      * @since 2.7
      */
     public abstract JsonFormat.Value getDefaultPropertyFormat(Class<?> baseType);
-    
+
     /*
     /**********************************************************
     /* Generic attributes (2.3+)
diff --git a/src/main/java/com/fasterxml/jackson/databind/DeserializationConfig.java b/src/main/java/com/fasterxml/jackson/databind/DeserializationConfig.java
index 58487eb..68556ad 100644
--- a/src/main/java/com/fasterxml/jackson/databind/DeserializationConfig.java
+++ b/src/main/java/com/fasterxml/jackson/databind/DeserializationConfig.java
@@ -3,12 +3,10 @@
 import java.text.DateFormat;
 import java.util.*;
 
-import com.fasterxml.jackson.annotation.JsonAutoDetect;
-import com.fasterxml.jackson.annotation.JsonFormat;
-import com.fasterxml.jackson.annotation.JsonInclude;
-import com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility;
-import com.fasterxml.jackson.annotation.PropertyAccessor;
+import com.fasterxml.jackson.annotation.*;
+
 import com.fasterxml.jackson.core.*;
+
 import com.fasterxml.jackson.databind.cfg.*;
 import com.fasterxml.jackson.databind.deser.DeserializationProblemHandler;
 import com.fasterxml.jackson.databind.introspect.*;
@@ -104,9 +102,9 @@
      */
     public DeserializationConfig(BaseSettings base,
             SubtypeResolver str, SimpleMixInResolver mixins,
-            RootNameLookup rootNames)
+            RootNameLookup rootNames, ConfigOverrides configOverrides)
     {
-        super(base, str, mixins, rootNames);
+        super(base, str, mixins, rootNames, configOverrides);
         _deserFeatures = collectFeatureDefaults(DeserializationFeature.class);
         _nodeFactory = JsonNodeFactory.instance;
         _problemHandlers = null;
@@ -116,6 +114,15 @@
         _formatReadFeaturesToChange = 0;
     }
 
+    /**
+     * @deprecated Since 2.8, remove from 2.9 or later
+     */
+    @Deprecated
+    public DeserializationConfig(BaseSettings base, SubtypeResolver str,
+            SimpleMixInResolver mixins, RootNameLookup rootNames) {
+        this(base, str, mixins, rootNames, null);
+    }
+    
     private DeserializationConfig(DeserializationConfig src,
             int mapperFeatures, int deserFeatures,
             int parserFeatures, int parserFeatureMask,
@@ -233,15 +240,14 @@
     }
 
     /**
-     * Copy-constructor used for making a copy to be used by new {@link ObjectMapper}
-     * or {@link ObjectReader}.
+     * Copy-constructor used for making a copy used by new {@link ObjectMapper}.
      *
-     * @since 2.6
+     * @since 2.8
      */
     protected DeserializationConfig(DeserializationConfig src, SimpleMixInResolver mixins,
-            RootNameLookup rootNames)
+            RootNameLookup rootNames, ConfigOverrides configOverrides)
     {
-        super(src, mixins, rootNames);
+        super(src, mixins, rootNames, configOverrides);
         _deserFeatures = src._deserFeatures;
         _problemHandlers = src._problemHandlers;
         _nodeFactory = src._nodeFactory;
@@ -767,35 +773,12 @@
         return getClassIntrospector().forDirectClassAnnotations(this, type, this);
     }
 
-    @Override
-    public VisibilityChecker<?> getDefaultVisibilityChecker()
-    {
-        VisibilityChecker<?> vchecker = super.getDefaultVisibilityChecker();
-        if (!isEnabled(MapperFeature.AUTO_DETECT_SETTERS)) {
-            vchecker = vchecker.withSetterVisibility(Visibility.NONE);
-        }
-        if (!isEnabled(MapperFeature.AUTO_DETECT_CREATORS)) {
-            vchecker = vchecker.withCreatorVisibility(Visibility.NONE);
-        }
-        if (!isEnabled(MapperFeature.AUTO_DETECT_GETTERS)) {
-            vchecker = vchecker.withGetterVisibility(Visibility.NONE);
-        }
-        if (!isEnabled(MapperFeature.AUTO_DETECT_IS_GETTERS)) {
-            vchecker = vchecker.withIsGetterVisibility(Visibility.NONE);
-        }
-        if (!isEnabled(MapperFeature.AUTO_DETECT_FIELDS)) {
-            vchecker = vchecker.withFieldVisibility(Visibility.NONE);
-        }
-        return vchecker;
-    }
-
     /*
     /**********************************************************
     /* Configuration: default settings with per-type overrides
     /**********************************************************
      */
-    
-    // property inclusion not used on deserialization yet (2.7): may be added in future
+
     @Override
     public JsonInclude.Value getDefaultPropertyInclusion() {
         return EMPTY_INCLUDE;
@@ -803,13 +786,28 @@
 
     @Override
     public JsonInclude.Value getDefaultPropertyInclusion(Class<?> baseType) {
+        ConfigOverride overrides = findConfigOverride(baseType);
+        if (overrides != null) {
+            JsonInclude.Value v = overrides.getInclude();
+            if (v != null) {
+                return v;
+            }
+        }
         return EMPTY_INCLUDE;
     }
 
     @Override
-    public JsonFormat.Value getDefaultPropertyFormat(Class<?> baseType) {
-        // !!! TODO: per-type defaults
-        return EMPTY_FORMAT;
+    public JsonInclude.Value getDefaultPropertyInclusion(Class<?> baseType,
+            JsonInclude.Value defaultIncl)
+    {
+        ConfigOverride overrides = findConfigOverride(baseType);
+        if (overrides != null) {
+            JsonInclude.Value v = overrides.getInclude();
+            if (v != null) {
+                return v;
+            }
+        }
+        return defaultIncl;
     }
 
     /*
diff --git a/src/main/java/com/fasterxml/jackson/databind/DeserializationContext.java b/src/main/java/com/fasterxml/jackson/databind/DeserializationContext.java
index 3e504bd..8ee553b 100644
--- a/src/main/java/com/fasterxml/jackson/databind/DeserializationContext.java
+++ b/src/main/java/com/fasterxml/jackson/databind/DeserializationContext.java
@@ -12,12 +12,16 @@
 import com.fasterxml.jackson.core.*;
 import com.fasterxml.jackson.databind.cfg.ContextAttributes;
 import com.fasterxml.jackson.databind.deser.*;
+import com.fasterxml.jackson.databind.deser.impl.ObjectIdReader;
 import com.fasterxml.jackson.databind.deser.impl.ReadableObjectId;
 import com.fasterxml.jackson.databind.deser.impl.TypeWrappedDeserializer;
 import com.fasterxml.jackson.databind.exc.InvalidFormatException;
+import com.fasterxml.jackson.databind.exc.InvalidTypeIdException;
 import com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException;
 import com.fasterxml.jackson.databind.introspect.Annotated;
+import com.fasterxml.jackson.databind.introspect.BeanPropertyDefinition;
 import com.fasterxml.jackson.databind.jsontype.TypeDeserializer;
+import com.fasterxml.jackson.databind.jsontype.TypeIdResolver;
 import com.fasterxml.jackson.databind.node.JsonNodeFactory;
 import com.fasterxml.jackson.databind.type.TypeFactory;
 import com.fasterxml.jackson.databind.util.*;
@@ -236,7 +240,7 @@
     public final JsonFormat.Value getDefaultPropertyFormat(Class<?> baseType) {
         return _config.getDefaultPropertyFormat(baseType);
     }
-    
+
     @Override
     public final AnnotationIntrospector getAnnotationIntrospector() {
         return _config.getAnnotationIntrospector();
@@ -405,11 +409,6 @@
     /**********************************************************
      */
 
-    @Deprecated // since 2.3, use overloaded variant
-    public boolean hasValueDeserializerFor(JavaType type) {
-        return hasValueDeserializerFor(type, null);
-    }
-
     /**
      * Method for checking whether we could find a deserializer
      * for given type.
@@ -518,9 +517,6 @@
      */
     public abstract ReadableObjectId findObjectId(Object id, ObjectIdGenerator<?> generator, ObjectIdResolver resolver);
 
-    @Deprecated // since 2.4
-    public abstract ReadableObjectId findObjectId(Object id, ObjectIdGenerator<?> generator);
-
     /**
      * Method called to ensure that every object id encounter during processing
      * are resolved.
@@ -690,12 +686,12 @@
         return deser;
     }
 
-    @Deprecated // since 2.5; remove from 2.7
+    @Deprecated // since 2.5; remove from 2.9
     public JsonDeserializer<?> handlePrimaryContextualization(JsonDeserializer<?> deser, BeanProperty prop) throws JsonMappingException {
         return handlePrimaryContextualization(deser, prop, TypeFactory.unknownType());
     }
 
-    @Deprecated // since 2.5; remove from 2.7
+    @Deprecated // since 2.5; remove from 2.9
     public JsonDeserializer<?> handleSecondaryContextualization(JsonDeserializer<?> deser, BeanProperty prop) throws JsonMappingException {
         if (deser instanceof ContextualDeserializer) {
             deser = ((ContextualDeserializer) deser).createContextual(this, prop);
@@ -769,7 +765,7 @@
     public <T> T readValue(JsonParser p, JavaType type) throws IOException {
         JsonDeserializer<Object> deser = findRootValueDeserializer(type);
         if (deser == null) {
-            throw mappingException("Could not find JsonDeserializer for type %s", type);
+            reportMappingException("Could not find JsonDeserializer for type %s", type);
         }
         return (T) deser.deserialize(p, this);
     }
@@ -794,7 +790,8 @@
         JsonDeserializer<Object> deser = findContextualValueDeserializer(type, prop);
         if (deser == null) {
             String propName = (prop == null) ? "NULL" : ("'"+prop.getName()+"'");
-            throw mappingException("Could not find JsonDeserializer for type %s (via property %s)",
+            reportMappingException(
+                    "Could not find JsonDeserializer for type %s (via property %s)",
                     type, propName);
         }
         return (T) deser.deserialize(p, this);
@@ -802,43 +799,429 @@
 
     /*
     /**********************************************************
-    /* Methods for problem handling, reporting
+    /* Methods for problem handling
     /**********************************************************
      */
 
     /**
-     * Method deserializers can call to inform configured {@link DeserializationProblemHandler}s
-     * of an unrecognized property.
+     * Method that deserializers should call if they encounter an unrecognized
+     * property (and once that is not explicitly designed as ignorable), to
+     * inform possibly configured {@link DeserializationProblemHandler}s and
+     * let it handle the problem.
      * 
      * @return True if there was a configured problem handler that was able to handle the
      *   problem
      */
     public boolean handleUnknownProperty(JsonParser p, JsonDeserializer<?> deser,
             Object instanceOrClass, String propName)
-        throws IOException, JsonProcessingException
+        throws IOException
     {
         LinkedNode<DeserializationProblemHandler> h = _config.getProblemHandlers();
-        if (h != null) {
-            while (h != null) {
-                // Can bail out if it's handled
-                if (h.value().handleUnknownProperty(this, p, deser, instanceOrClass, propName)) {
-                    return true;
-                }
-                h = h.next();
+        while (h != null) {
+            // Can bail out if it's handled
+            if (h.value().handleUnknownProperty(this, p, deser, instanceOrClass, propName)) {
+                return true;
             }
+            h = h.next();
         }
-        return false;
+        // Nope, not handled. Potentially that's a problem...
+        if (!isEnabled(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES)) {
+            p.skipChildren();
+            return true;
+        }
+        // Do we know properties that are expected instead?
+        Collection<Object> propIds = (deser == null) ? null : deser.getKnownPropertyNames();
+        throw UnrecognizedPropertyException.from(_parser,
+                instanceOrClass, propName, propIds);
     }
 
     /**
-     * Helper method for reporting a problem with unhandled unknown exception
+     * Method that deserializers should call if they encounter a String value
+     * that can not be converted to expected key of a {@link java.util.Map}
+     * valued property.
+     * Default implementation will try to call {@link DeserializationProblemHandler#handleWeirdNumberValue}
+     * on configured handlers, if any, to allow for recovery; if recovery does not
+     * succeed, will throw {@link InvalidFormatException} with given message.
+     *
+     * @param keyClass Expected type for key
+     * @param keyValue String value from which to deserialize key
+     * @param msg Error message template caller wants to use if exception is to be thrown
+     * @param msgArgs Optional arguments to use for message, if any
+     *
+     * @return Key value to use
+     *
+     * @throws IOException To indicate unrecoverable problem, usually based on <code>msg</code>
+     * 
+     * @since 2.8
+     */
+    public Object handleWeirdKey(Class<?> keyClass, String keyValue,
+            String msg, Object... msgArgs)
+        throws IOException
+    {
+        // but if not handled, just throw exception
+        if (msgArgs.length > 0) {
+            msg = String.format(msg, msgArgs);
+        }
+        LinkedNode<DeserializationProblemHandler> h = _config.getProblemHandlers();
+        while (h != null) {
+            // Can bail out if it's handled
+            Object key = h.value().handleWeirdKey(this, keyClass, keyValue, msg);
+            if (key != DeserializationProblemHandler.NOT_HANDLED) {
+                // Sanity check for broken handlers, otherwise nasty to debug:
+                if ((key == null) || keyClass.isInstance(key)) {
+                    return key;
+                }
+                throw weirdStringException(keyValue, keyClass, String.format(
+                        "DeserializationProblemHandler.handleWeirdStringValue() for type %s returned value of type %s",
+                        keyClass, key.getClass()));
+            }
+            h = h.next();
+        }
+        throw weirdKeyException(keyClass, keyValue, msg);
+    }
+
+    /**
+     * Method that deserializers should call if they encounter a String value
+     * that can not be converted to target property type, in cases where some
+     * String values could be acceptable (either with different settings,
+     * or different value).
+     * Default implementation will try to call {@link DeserializationProblemHandler#handleWeirdStringValue}
+     * on configured handlers, if any, to allow for recovery; if recovery does not
+     * succeed, will throw {@link InvalidFormatException} with given message.
+     *
+     * @param targetClass Type of property into which incoming number should be converted
+     * @param value String value from which to deserialize property value
+     * @param msg Error message template caller wants to use if exception is to be thrown
+     * @param msgArgs Optional arguments to use for message, if any
+     *
+     * @return Property value to use
+     *
+     * @throws IOException To indicate unrecoverable problem, usually based on <code>msg</code>
+     * 
+     * @since 2.8
+     */
+    public Object handleWeirdStringValue(Class<?> targetClass, String value,
+            String msg, Object... msgArgs)
+        throws IOException
+    {
+        // but if not handled, just throw exception
+        if (msgArgs.length > 0) {
+            msg = String.format(msg, msgArgs);
+        }
+        LinkedNode<DeserializationProblemHandler> h = _config.getProblemHandlers();
+        while (h != null) {
+            // Can bail out if it's handled
+            Object instance = h.value().handleWeirdStringValue(this, targetClass, value, msg);
+            if (instance != DeserializationProblemHandler.NOT_HANDLED) {
+                // Sanity check for broken handlers, otherwise nasty to debug:
+                if (_isCompatible(targetClass, instance)) {
+                    return instance;
+                }
+                throw weirdStringException(value, targetClass, String.format(
+                        "DeserializationProblemHandler.handleWeirdStringValue() for type %s returned value of type %s",
+                        targetClass, instance.getClass()));
+            }
+            h = h.next();
+        }
+        throw weirdStringException(value, targetClass, msg);
+    }
+
+    /**
+     * Method that deserializers should call if they encounter a numeric value
+     * that can not be converted to target property type, in cases where some
+     * numeric values could be acceptable (either with different settings,
+     * or different numeric value).
+     * Default implementation will try to call {@link DeserializationProblemHandler#handleWeirdNumberValue}
+     * on configured handlers, if any, to allow for recovery; if recovery does not
+     * succeed, will throw {@link InvalidFormatException} with given message.
+     *
+     * @param targetClass Type of property into which incoming number should be converted
+     * @param value Number value from which to deserialize property value
+     * @param msg Error message template caller wants to use if exception is to be thrown
+     * @param msgArgs Optional arguments to use for message, if any
+     *
+     * @return Property value to use
+     *
+     * @throws IOException To indicate unrecoverable problem, usually based on <code>msg</code>
+     * 
+     * @since 2.8
+     */
+    public Object handleWeirdNumberValue(Class<?> targetClass, Number value,
+            String msg, Object... msgArgs)
+        throws IOException
+    {
+        if (msgArgs.length > 0) {
+            msg = String.format(msg, msgArgs);
+        }
+        LinkedNode<DeserializationProblemHandler> h = _config.getProblemHandlers();
+        while (h != null) {
+            // Can bail out if it's handled
+            Object key = h.value().handleWeirdNumberValue(this, targetClass, value, msg);
+            if (key != DeserializationProblemHandler.NOT_HANDLED) {
+                // Sanity check for broken handlers, otherwise nasty to debug:
+                if (_isCompatible(targetClass, key)) {
+                    return key;
+                }
+                throw weirdNumberException(value, targetClass, String.format(
+                        "DeserializationProblemHandler.handleWeirdNumberValue() for type %s returned value of type %s",
+                        targetClass, key.getClass()));
+            }
+            h = h.next();
+        }
+        throw weirdNumberException(value, targetClass, msg);
+    }
+
+    /**
+     * Method that deserializers should call if they fail to instantiate value
+     * due to lack of viable instantiator (usually creator, that is, constructor
+     * or static factory method). Method should be called at point where value
+     * has not been decoded, so that handler has a chance to handle decoding
+     * using alternate mechanism, and handle underlying content (possibly by
+     * just skipping it) to keep input state valid
+     *
+     * @param instClass Type that was to be instantiated
+     * @param p Parser that points to the JSON value to decode
+     *
+     * @return Object that should be constructed, if any; has to be of type <code>instClass</code>
+     *
+     * @since 2.8
+     */
+    public Object handleMissingInstantiator(Class<?> instClass, JsonParser p,
+            String msg, Object... msgArgs)
+        throws IOException
+    {
+        if (msgArgs.length > 0) {
+            msg = String.format(msg, msgArgs);
+        }
+        LinkedNode<DeserializationProblemHandler> h = _config.getProblemHandlers();
+        while (h != null) {
+            // Can bail out if it's handled
+            Object instance = h.value().handleMissingInstantiator(this,
+                    instClass, p, msg);
+            if (instance != DeserializationProblemHandler.NOT_HANDLED) {
+                // Sanity check for broken handlers, otherwise nasty to debug:
+                if (_isCompatible(instClass, instance)) {
+                    return instance;
+                }
+                throw instantiationException(instClass, String.format(
+                        "DeserializationProblemHandler.handleMissingInstantiator() for type %s returned value of type %s",
+                        instClass, instance.getClass()));
+            }
+            h = h.next();
+        }
+        throw instantiationException(instClass, msg);
+    }
+
+    /**
+     * Method that deserializers should call if they fail to instantiate value
+     * due to an exception that was thrown by constructor (or other mechanism used
+     * to create instances).
+     * Default implementation will try to call {@link DeserializationProblemHandler#handleInstantiationProblem}
+     * on configured handlers, if any, to allow for recovery; if recovery does not
+     * succeed, will throw exception constructed with {@link #instantiationException}.
+     *
+     * @param instClass Type that was to be instantiated
+     * @param argument (optional) Argument that was passed to constructor or equivalent
+     *    instantiator; often a {@link java.lang.String}.
+     * @param t Exception that caused failure
+     *
+     * @return Object that should be constructed, if any; has to be of type <code>instClass</code>
+     *
+     * @since 2.8
+     */
+    public Object handleInstantiationProblem(Class<?> instClass, Object argument,
+            Throwable t)
+        throws IOException
+    {
+        LinkedNode<DeserializationProblemHandler> h = _config.getProblemHandlers();
+        while (h != null) {
+            // Can bail out if it's handled
+            Object instance = h.value().handleInstantiationProblem(this, instClass, argument, t);
+            if (instance != DeserializationProblemHandler.NOT_HANDLED) {
+                // Sanity check for broken handlers, otherwise nasty to debug:
+                if (_isCompatible(instClass, instance)) {
+                    return instance;
+                }
+                throw instantiationException(instClass, String.format(
+                        "DeserializationProblemHandler.handleInstantiationProblem() for type %s returned value of type %s",
+                        instClass, instance.getClass()));
+            }
+            h = h.next();
+        }
+        // 18-May-2016, tatu: Only wrap if not already a valid type to throw
+        if (t instanceof IOException) {
+            throw (IOException) t;
+        }
+        throw instantiationException(instClass, t);
+    }
+
+    /**
+     * Method that deserializers should call if the first token of the value to
+     * deserialize is of unexpected type (that is, type of token that deserializer
+     * can not handle). This could occur, for example, if a Number deserializer
+     * encounter {@link JsonToken#START_ARRAY} instead of
+     * {@link JsonToken#VALUE_NUMBER_INT} or {@link JsonToken#VALUE_NUMBER_FLOAT}.
+     * 
+     * @param instClass Type that was to be instantiated
+     * @param p Parser that points to the JSON value to decode
+     *
+     * @return Object that should be constructed, if any; has to be of type <code>instClass</code>
+     *
+     * @since 2.8
+     */
+    public Object handleUnexpectedToken(Class<?> instClass, JsonParser p)
+        throws IOException
+    {
+        return handleUnexpectedToken(instClass, p.getCurrentToken(), p, null);
+    }
+    
+    /**
+     * Method that deserializers should call if the first token of the value to
+     * deserialize is of unexpected type (that is, type of token that deserializer
+     * can not handle). This could occur, for example, if a Number deserializer
+     * encounter {@link JsonToken#START_ARRAY} instead of
+     * {@link JsonToken#VALUE_NUMBER_INT} or {@link JsonToken#VALUE_NUMBER_FLOAT}.
+     * 
+     * @param instClass Type that was to be instantiated
+     * @param p Parser that points to the JSON value to decode
+     *
+     * @return Object that should be constructed, if any; has to be of type <code>instClass</code>
+     *
+     * @since 2.8
+     */
+    public Object handleUnexpectedToken(Class<?> instClass, JsonToken t,
+            JsonParser p,
+            String msg, Object... msgArgs)
+        throws IOException
+    {
+        if (msgArgs.length > 0) {
+            msg = String.format(msg, msgArgs);
+        }
+        LinkedNode<DeserializationProblemHandler> h = _config.getProblemHandlers();
+        while (h != null) {
+            Object instance = h.value().handleUnexpectedToken(this,
+                    instClass, t, p, msg);
+            if (instance != DeserializationProblemHandler.NOT_HANDLED) {
+                if (_isCompatible(instClass, instance)) {
+                    return instance;
+                }
+                reportMappingException("DeserializationProblemHandler.handleUnexpectedToken() for type %s returned value of type %s",
+                        instClass, instance.getClass());
+            }
+            h = h.next();
+        }
+        if (msg == null) {
+            if (t == null) {
+                msg = String.format("Unexpected end-of-input when binding data into %s",
+                        _calcName(instClass));
+            } else {
+                msg = String.format("Can not deserialize instance of %s out of %s token",
+                        _calcName(instClass), t);
+            }
+        }
+        reportMappingException(msg);
+        return null; // never gets here
+    }
+
+    /**
+     * Method that deserializers should call if they encounter a type id
+     * (for polymorphic deserialization) that can not be resolved to an
+     * actual type; usually since there is no mapping defined.
+     * Default implementation will try to call {@link DeserializationProblemHandler#handleUnknownTypeId}
+     * on configured handlers, if any, to allow for recovery; if recovery does not
+     * succeed, will throw exception constructed with {@link #unknownTypeIdException}.
+     *
+     * @param baseType Base type from which resolution starts
+     * @param id Type id that could not be converted
+     * @param extraDesc Additional problem description to add to default exception message,
+     *    if resolution fails.
+     *
+     * @return {@link JavaType} that id resolves to
+     *
+     * @throws IOException To indicate unrecoverable problem, if resolution can not
+     *    be made to work
+     *
+     * @since 2.8
+     */
+    public JavaType handleUnknownTypeId(JavaType baseType, String id,
+            TypeIdResolver idResolver, String extraDesc) throws IOException
+    {
+        LinkedNode<DeserializationProblemHandler> h = _config.getProblemHandlers();
+        while (h != null) {
+            // Can bail out if it's handled
+            JavaType type = h.value().handleUnknownTypeId(this, baseType, id, idResolver, extraDesc);
+            if (type != null) {
+                if (type.hasRawClass(Void.class)) {
+                    return null;
+                }
+                // But ensure there's type compatibility
+                if (type.isTypeOrSubTypeOf(baseType.getRawClass())) {
+                    return type;
+                }
+                throw unknownTypeIdException(baseType, id,
+                        "problem handler tried to resolve into non-subtype: "+type);
+            }
+            h = h.next();
+        }
+        // 24-May-2016, tatu: Actually we may still not want to fail quite yet
+        if (!isEnabled(DeserializationFeature.FAIL_ON_INVALID_SUBTYPE)) {
+            return null;
+        }
+        throw unknownTypeIdException(baseType, id, extraDesc);
+    }
+
+    /**
+     * @since 2.9.2
+     */
+    protected boolean _isCompatible(Class<?> target, Object value)
+    {
+        if ((value == null) || target.isInstance(value)) {
+            return true;
+        }
+        // [databind#1767]: Make sure to allow wrappers for primitive fields
+        return target.isPrimitive()
+                && ClassUtil.wrapperType(target).isInstance(value);
+    }
+
+    /*
+    /**********************************************************
+    /* Methods for problem reporting, in cases where recovery
+    /* is not considered possible
+    /**********************************************************
+     */
+
+    /**
+     * Method for deserializers to call 
+     * when the token encountered was of type different than what <b>should</b>
+     * be seen at that position, usually within a sequence of expected tokens.
+     * Note that this method will throw a {@link JsonMappingException} and no
+     * recovery is attempted (via {@link DeserializationProblemHandler}, as
+     * problem is considered to be difficult to recover from, in general.
+     * 
+     * @since 2.8
+     */
+    public void reportWrongTokenException(JsonParser p,
+            JsonToken expToken, String msg, Object... msgArgs)
+        throws JsonMappingException
+    {
+        if ((msg != null) && (msgArgs.length > 0)) {
+            msg = String.format(msg, msgArgs);
+        }
+        throw wrongTokenException(p, expToken, msg);
+    }
+    
+    /**
+     * Helper method for reporting a problem with unhandled unknown property.
      * 
      * @param instanceOrClass Either value being populated (if one has been
      *   instantiated), or Class that indicates type that would be (or
      *   have been) instantiated
      * @param deser Deserializer that had the problem, if called by deserializer
      *   (or on behalf of one)
+     *
+     * @deprecated Since 2.8 call {@link #handleUnknownProperty} instead
      */
+    @Deprecated
     public void reportUnknownProperty(Object instanceOrClass, String fieldName,
             JsonDeserializer<?> deser)
         throws JsonMappingException
@@ -855,128 +1238,89 @@
     /**
      * @since 2.8
      */
-    public JsonMappingException reportMappingException(String msg, Object... msgArgs)
+    public void reportMappingException(String msg, Object... msgArgs)
         throws JsonMappingException
     {
         if (msgArgs.length > 0) {
             msg = String.format(msg, msgArgs);
         }
-        throw mappingException(msg);
+        throw JsonMappingException.from(getParser(), msg);
     }
 
     /**
      * @since 2.8
      */
-    public JsonMappingException reportInstantiationException(Class<?> instClass, Throwable t)
+    public void reportMissingContent(String msg, Object... msgArgs)
         throws JsonMappingException
     {
-        throw instantiationException(instClass, t);
-    }
-
-    /**
-     * @since 2.8
-     */
-    public JsonMappingException reportInstantiationException(Class<?> instClass,
-            String msg, Object... msgArgs)
-        throws JsonMappingException
-    {
-        if (msgArgs.length > 0) {
+        if (msg == null) {
+            msg = "No content to map due to end-of-input";
+        } else if (msgArgs.length > 0) {
             msg = String.format(msg, msgArgs);
         }
-        throw instantiationException(instClass, msg);
+        throw JsonMappingException.from(getParser(), msg);
     }
 
     /**
      * @since 2.8
      */
-    public <T> T reportWeirdStringException(String value, Class<?> instClass,
-            String msg, Object... msgArgs)
+    public void reportUnresolvedObjectId(ObjectIdReader oidReader, Object bean)
         throws JsonMappingException
     {
-        if (msgArgs.length > 0) {
-            msg = String.format(msg, msgArgs);
+        String msg = String.format("No Object Id found for an instance of %s, to assign to property '%s'",
+                bean.getClass().getName(), oidReader.propertyName);
+        throw JsonMappingException.from(getParser(), msg);
+    }
+
+    /**
+     * Helper method called to indicate problem in POJO (serialization) definitions or settings
+     * regarding specific Java type, unrelated to actual JSON content to map.
+     * Default behavior is to construct and throw a {@link JsonMappingException}.
+     *
+     * @since 2.9
+     */
+    public <T> T reportBadTypeDefinition(BeanDescription bean,
+            String message, Object... args) throws JsonMappingException {
+        if (args != null && args.length > 0) {
+            message = String.format(message, args);
         }
-        throw weirdStringException(value, instClass, msg);
+        String beanDesc = (bean == null) ? "N/A" : _desc(bean.getType().getGenericSignature());
+        throw mappingException("Invalid type definition for type %s: %s",
+                beanDesc, message);
     }
 
     /**
-     * @since 2.8
+     * Helper method called to indicate problem in POJO (serialization) definitions or settings
+     * regarding specific property (of a type), unrelated to actual JSON content to map.
+     * Default behavior is to construct and throw a {@link JsonMappingException}.
+     *
+     * @since 2.9
      */
-    public <T> T reportWeirdNumberException(Number value, Class<?> instClass,
-            String msg, Object... msgArgs)
-        throws JsonMappingException
-    {
-        if (msgArgs.length > 0) {
-            msg = String.format(msg, msgArgs);
+    public <T> T reportBadPropertyDefinition(BeanDescription bean, BeanPropertyDefinition prop,
+            String message, Object... args) throws JsonMappingException {
+        if (args != null && args.length > 0) {
+            message = String.format(message, args);
         }
-        throw weirdNumberException(value, instClass, msg);
-    }
-
-    /**
-     * @since 2.8
-     */
-    public <T> T reportWeirdKeyException(Class<?> keyClass, String keyValue,
-            String msg, Object... msgArgs)
-        throws JsonMappingException
-    {
-        if (msgArgs.length > 0) {
-            msg = String.format(msg, msgArgs);
-        }
-        throw weirdKeyException(keyClass, keyValue, msg);
-    }
-
-    /**
-     * @since 2.8
-     */
-    public <T> T reportWrongTokenException(JsonParser p,
-            JsonToken expToken, String msg, Object... msgArgs)
-        throws JsonMappingException
-    {
-        if (msgArgs.length > 0) {
-            msg = String.format(msg, msgArgs);
-        }
-        throw wrongTokenException(p, expToken, msg);
-    }
-
-    /**
-     * @since 2.8
-     */
-    public <T> T reportUnknownTypeException(JavaType type, String id,
-            String extraDesc) throws JsonMappingException
-    {
-        throw unknownTypeException(type, id, extraDesc);
-    }
-
-    /**
-     * @since 2.8
-     */
-    public <T> T reportEndOfInputException(Class<?> instClass) throws JsonMappingException {
-        throw endOfInputException(instClass);
+        String propName = (prop == null)  ? "N/A" : _quotedString(prop.getName());
+        String beanDesc = (bean == null) ? "N/A" : _desc(bean.getType().getGenericSignature());
+        throw mappingException("Invalid definition for property %s (of type %s): %s",
+                propName, beanDesc, message);
     }
 
     /*
     /**********************************************************
-    /* Methods for constructing exceptions
+    /* Methods for constructing exceptions, "untyped"
     /**********************************************************
      */
-    
-    /**
-     * Helper method for constructing generic mapping exception for specified type
-     */
-    public JsonMappingException mappingException(Class<?> targetClass) {
-        return mappingException(targetClass, _parser.getCurrentToken());
-    }
 
-    public JsonMappingException mappingException(Class<?> targetClass, JsonToken token) {
-        String tokenDesc = (token == null) ? "<end of input>" : String.format("%s token", token);
-        return JsonMappingException.from(_parser,
-                String.format("Can not deserialize instance of %s out of %s",
-                        _calcName(targetClass), tokenDesc));
-    }
-    
     /**
      * Helper method for constructing generic mapping exception with specified
-     * message and current location information
+     * message and current location information.
+     * Note that application code should almost always call
+     * one of <code>handleXxx</code> methods, or {@link #reportMappingException(String, Object...)}
+     * instead.
+     * 
+     * @since 2.6
      */
     public JsonMappingException mappingException(String message) {
         return JsonMappingException.from(getParser(), message);
@@ -985,74 +1329,58 @@
     /**
      * Helper method for constructing generic mapping exception with specified
      * message and current location information
+     * Note that application code should almost always call
+     * one of <code>handleXxx</code> methods, or {@link #reportMappingException(String, Object...)}
+     * instead.
      * 
      * @since 2.6
      */
     public JsonMappingException mappingException(String msgTemplate, Object... args) {
-        String message = String.format(msgTemplate, args);
-        return JsonMappingException.from(getParser(), message);
-    }
-    
-    /**
-     * Helper method for constructing instantiation exception for specified type,
-     * to indicate problem with physically constructing instance of
-     * specified class (missing constructor, exception from constructor)
-     */
-    public JsonMappingException instantiationException(Class<?> instClass, Throwable t) {
-        return JsonMappingException.from(_parser,
-                String.format("Can not construct instance of %s, problem: %s", instClass.getName(), t.getMessage()), t);
-    }
-
-    public JsonMappingException instantiationException(Class<?> instClass, String msg) {
-        return JsonMappingException.from(_parser,
-                String.format("Can not construct instance of %s, problem: %s", instClass.getName(), msg));
+        if (args != null && args.length > 0) {
+            msgTemplate = String.format(msgTemplate, args);
+        }
+        return JsonMappingException.from(getParser(), msgTemplate);
     }
 
     /**
-     * Method that will construct an exception suitable for throwing when
-     * some String values are acceptable, but the one encountered is not.
+     * Helper method for constructing generic mapping exception for specified type
      * 
-     * @param value String value from input being deserialized
-     * @param instClass Type that String should be deserialized into
-     * @param msg Message that describes specific problem
-     * 
-     * @since 2.1
+     * @deprecated Since 2.8 use {@link #handleUnexpectedToken(Class, JsonParser)} instead
      */
-    public JsonMappingException weirdStringException(String value, Class<?> instClass, String msg) {
-        return InvalidFormatException.from(_parser,
-                String.format("Can not construct instance of %s from String value (%s): %s",
-                        instClass.getName(), _quotedString(value), msg),
-                value, instClass);
+    @Deprecated
+    public JsonMappingException mappingException(Class<?> targetClass) {
+        return mappingException(targetClass, _parser.getCurrentToken());
     }
 
     /**
-     * Helper method for constructing exception to indicate that input JSON
-     * Number was not suitable for deserializing into given target type.
+     * @deprecated Since 2.8 use {@link #handleUnexpectedToken(Class, JsonParser)} instead
      */
-    public JsonMappingException weirdNumberException(Number value, Class<?> instClass, String msg) {
-        return InvalidFormatException.from(_parser,
-                String.format("Can not construct instance of %s from number value (%s): %s",
-                        instClass.getName(), String.valueOf(value), msg),
-                value, instClass);
+    @Deprecated
+    public JsonMappingException mappingException(Class<?> targetClass, JsonToken token) {
+        String tokenDesc = (token == null) ? "<end of input>" : String.format("%s token", token);
+        return JsonMappingException.from(_parser,
+                String.format("Can not deserialize instance of %s out of %s",
+                        _calcName(targetClass), tokenDesc));
     }
 
-    /**
-     * Helper method for constructing exception to indicate that given JSON
-     * Object field name was not in format to be able to deserialize specified
-     * key type.
+    /*
+    /**********************************************************
+    /* Methods for constructing semantic exceptions; usually not
+    /* to be called directly, call `handleXxx()` instead
+    /**********************************************************
      */
-    public JsonMappingException weirdKeyException(Class<?> keyClass, String keyValue, String msg) {
-        return InvalidFormatException.from(_parser,
-                String.format("Can not construct Map key of type %s from String (%s): %s",
-                        keyClass.getName(), _quotedString(keyValue), msg),
-                keyValue, keyClass);
-    }
 
     /**
-     * Helper method for indicating that the current token was expected to be another
-     * token.
+     * Helper method for constructing {@link JsonMappingException} to indicate
+     * that the token encountered was of type different than what <b>should</b>
+     * be seen at that position, usually within a sequence of expected tokens.
+     * Note that most of the time this method should NOT be directly called;
+     * instead, {@link #reportWrongTokenException} should be called and will
+     * call this method as necessary.
      */
-    public JsonMappingException wrongTokenException(JsonParser p, JsonToken expToken, String msg0) {
+    public JsonMappingException wrongTokenException(JsonParser p, JsonToken expToken,
+            String msg0)
+    {
         String msg = String.format("Unexpected token (%s), expected %s",
                 p.getCurrentToken(), expToken);
         if (msg0 != null) {
@@ -1062,17 +1390,118 @@
     }
 
     /**
-     * Helper method for constructing exception to indicate that given
-     * type id (parsed from JSON) could not be converted to a Java type.
+     * Helper method for constructing exception to indicate that given JSON
+     * Object field name was not in format to be able to deserialize specified
+     * key type.
+     * Note that most of the time this method should NOT be called; instead,
+     * {@link #handleWeirdKey} should be called which will call this method
+     * if necessary.
      */
-    @Deprecated // since 2.5, use overloaded variant
-    public JsonMappingException unknownTypeException(JavaType type, String id) {
-        return JsonMappingException.from(_parser, "Could not resolve type id '"+id+"' into a subtype of "+type);
+    public JsonMappingException weirdKeyException(Class<?> keyClass, String keyValue,
+            String msg) {
+        return InvalidFormatException.from(_parser,
+                String.format("Can not deserialize Map key of type %s from String %s: %s",
+                        keyClass.getName(), _quotedString(keyValue), msg),
+                keyValue, keyClass);
     }
 
     /**
-     * @since 2.5
+     * Helper method for constructing exception to indicate that input JSON
+     * String was not suitable for deserializing into given target type.
+     * Note that most of the time this method should NOT be called; instead,
+     * {@link #handleWeirdStringValue} should be called which will call this method
+     * if necessary.
+     * 
+     * @param value String value from input being deserialized
+     * @param instClass Type that String should be deserialized into
+     * @param msg Message that describes specific problem
+     * 
+     * @since 2.1
      */
+    public JsonMappingException weirdStringException(String value, Class<?> instClass,
+            String msg) {
+        return InvalidFormatException.from(_parser,
+                String.format("Can not deserialize value of type %s from String %s: %s",
+                        instClass.getName(), _quotedString(value), msg),
+                value, instClass);
+    }
+
+    /**
+     * Helper method for constructing exception to indicate that input JSON
+     * Number was not suitable for deserializing into given target type.
+     * Note that most of the time this method should NOT be called; instead,
+     * {@link #handleWeirdNumberValue} should be called which will call this method
+     * if necessary.
+     */
+    public JsonMappingException weirdNumberException(Number value, Class<?> instClass,
+            String msg) {
+        return InvalidFormatException.from(_parser,
+                String.format("Can not deserialize value of type %s from number %s: %s",
+                        instClass.getName(), String.valueOf(value), msg),
+                value, instClass);
+    }
+
+    /**
+     * Helper method for constructing instantiation exception for specified type,
+     * to indicate problem with physically constructing instance of
+     * specified class (missing constructor, exception from constructor)
+     *<p>
+     * Note that most of the time this method should NOT be called; instead,
+     * {@link #handleInstantiationProblem} should be called which will call this method
+     * if necessary.
+     */
+    public JsonMappingException instantiationException(Class<?> instClass, Throwable t) {
+        return JsonMappingException.from(_parser,
+                String.format("Can not construct instance of %s, problem: %s",
+                        instClass.getName(), t.getMessage()), t);
+    }
+
+    /**
+     * Helper method for constructing instantiation exception for specified type,
+     * to indicate that instantiation failed due to missing instantiator
+     * (creator; constructor or factory method).
+     *<p>
+     * Note that most of the time this method should NOT be called; instead,
+     * {@link #handleMissingInstantiator} should be called which will call this method
+     * if necessary.
+     */
+    public JsonMappingException instantiationException(Class<?> instClass, String msg) {
+        return JsonMappingException.from(_parser,
+                String.format("Can not construct instance of %s: %s",
+                        instClass.getName(), msg));
+    }
+
+    /**
+     * Helper method for constructing exception to indicate that given type id
+     * could not be resolved to a valid subtype of specified base type, during
+     * polymorphic deserialization.
+     *<p>
+     * Note that most of the time this method should NOT be called; instead,
+     * {@link #handleUnknownTypeId} should be called which will call this method
+     * if necessary.
+     */
+    public JsonMappingException unknownTypeIdException(JavaType baseType, String typeId,
+            String extraDesc) {
+        String msg = String.format("Could not resolve type id '%s' into a subtype of %s",
+                typeId, baseType);
+        if (extraDesc != null) {
+            msg = msg + ": "+extraDesc;
+        }
+        return InvalidTypeIdException.from(_parser, msg, baseType, typeId);
+    }
+
+    /*
+    /**********************************************************
+    /* Deprecated exception factory methods
+    /**********************************************************
+     */
+
+    /**
+     * @since 2.5
+     *
+     * @deprecated Since 2.8 use {@link #handleUnknownTypeId} instead
+     */
+    @Deprecated
     public JsonMappingException unknownTypeException(JavaType type, String id,
             String extraDesc) {
         String msg = String.format("Could not resolve type id '%s' into a subtype of %s",
@@ -1083,6 +1512,13 @@
         return JsonMappingException.from(_parser, msg);
     }
 
+    /**
+     * Helper method for constructing exception to indicate that end-of-input was
+     * reached while still expecting more tokens to deserialize value of specified type.
+     *
+     * @deprecated Since 2.8; currently no way to catch EOF at databind level
+     */
+    @Deprecated
     public JsonMappingException endOfInputException(Class<?> instClass) {
         return JsonMappingException.from(_parser, "Unexpected end-of-input when trying to deserialize a "
                 +instClass.getName());
@@ -1090,7 +1526,7 @@
 
     /*
     /**********************************************************
-    /* Overridable internal methods
+    /* Other internal methods
     /**********************************************************
      */
 
@@ -1112,12 +1548,6 @@
     protected String determineClassName(Object instance) {
         return ClassUtil.getClassDescription(instance);
     }
-    
-    /*
-    /**********************************************************
-    /* Other internal methods
-    /**********************************************************
-     */
 
     protected String _calcName(Class<?> cls) {
         if (cls.isArray()) {
diff --git a/src/main/java/com/fasterxml/jackson/databind/DeserializationFeature.java b/src/main/java/com/fasterxml/jackson/databind/DeserializationFeature.java
index 53da367..1505419 100644
--- a/src/main/java/com/fasterxml/jackson/databind/DeserializationFeature.java
+++ b/src/main/java/com/fasterxml/jackson/databind/DeserializationFeature.java
@@ -230,7 +230,34 @@
      * @since 2.6
      */
     FAIL_ON_MISSING_CREATOR_PROPERTIES(false),
-    
+
+    /**
+      * Feature that determines what happens if one or more Creator properties (properties
+      * bound to parameters of Creator method (constructor or static factory method))
+      * are bound to null values - either from the JSON or as a default value. This
+      * is useful if you want to avoid nulls in your codebase, and particularly useful
+      * if you are using Java or Scala optionals for non-mandatory fields.
+      * Feature is disabled by default, so that no exception is thrown for missing creator
+      * property values, unless they are explicitly marked as `required`.
+      *
+      * @since 2.8
+      */
+    FAIL_ON_NULL_CREATOR_PROPERTIES(false),
+
+    /**
+     * Feature that determines what happens when a property annotated with
+     * {@link com.fasterxml.jackson.annotation.JsonTypeInfo.As#EXTERNAL_PROPERTY} is missing,
+     * but associated type id is available. If enabled, {@link JsonMappingException} is always
+     * thrown when property value is missing (if type id does exist);
+     * if disabled, exception is only thrown if property is marked as `required`.
+     *<p>
+     * Feature is enabled by default, so that exception is thrown when a subtype property is
+     * missing.
+     *
+     * @since 2.9
+     */
+    FAIL_ON_MISSING_EXTERNAL_TYPE_ID_PROPERTY(true),
+
     /**
      * Feature that determines whether Jackson code should catch
      * and wrap {@link Exception}s (but never {@link Error}s!)
@@ -354,6 +381,18 @@
     READ_UNKNOWN_ENUM_VALUES_AS_NULL(false),
 
     /**
+     * Feature that allows unknown Enum values to be ignored and a predefined value specified through
+     * {@link com.fasterxml.jackson.annotation.JsonEnumDefaultValue @JsonEnumDefaultValue} annotation.
+     * If disabled, unknown Enum values will throw exceptions.
+     * If enabled, but no predefined default Enum value is specified, an exception will be thrown as well.
+     *<p>
+     * Feature is disabled by default.
+     *
+     * @since 2.8
+     */
+    READ_UNKNOWN_ENUM_VALUES_USING_DEFAULT_VALUE(false),
+
+    /**
      * Feature that controls whether numeric timestamp values are expected
      * to be written using nanosecond timestamps (enabled) or not (disabled),
      * <b>if and only if</b> datatype supports such resolution.
@@ -377,6 +416,13 @@
      * If enabled, contextual <code>TimeZone</code> will essentially override any other
      * TimeZone information; if disabled, it will only be used if value itself does not
      * contain any TimeZone information.
+     *<p>
+     * Note that exact behavior depends on date/time types in question; and specifically
+     * JDK type of {@link java.util.Date} does NOT have in-built timezone information
+     * so this setting has no effect.
+     *<p>
+     * As of Jackson 2.8, this feature is supported only by extension modules for Joda
+     * and Java 8 date/tyime datatypes.
      * 
      * @since 2.2
      */
diff --git a/src/main/java/com/fasterxml/jackson/databind/JavaType.java b/src/main/java/com/fasterxml/jackson/databind/JavaType.java
index 752edd1..292cc39 100644
--- a/src/main/java/com/fasterxml/jackson/databind/JavaType.java
+++ b/src/main/java/com/fasterxml/jackson/databind/JavaType.java
@@ -131,6 +131,26 @@
     public abstract JavaType withContentValueHandler(Object h);
 
     /**
+     * Mutant factory method that will try to copy handlers that the specified
+     * source type instance had, if any; this must be done recursively where
+     * necessary (as content types may be structured).
+     *
+     * @since 2.8.4
+     */
+    public JavaType withHandlersFrom(JavaType src) {
+        JavaType type = this;
+        Object h = src.getTypeHandler();
+        if (h != _typeHandler) {
+            type = type.withTypeHandler(h);
+        }
+        h = src.getValueHandler();
+        if (h != _valueHandler) {
+            type = type.withValueHandler(h);
+        }
+        return type;
+    }
+
+    /**
      * Mutant factory method that may be called on structured types
      * that have a so-called content type (element of arrays, value type
      * of Maps, referenced type of referential types),
@@ -223,6 +243,17 @@
     public final boolean hasRawClass(Class<?> clz) { return _class == clz; }
 
     /**
+     * Accessor that allows determining whether {@link #getContentType()} should
+     * return a non-null value (that is, there is a "content type") or not.
+     * True if {@link #isContainerType()} or {@link #isReferenceType()} return true.
+     *
+     * @since 2.8
+     */
+    public boolean hasContentType() {
+        return true;
+    }
+
+    /**
      * @since 2.6
      */
     public final boolean isTypeOrSubTypeOf(Class<?> clz) {
@@ -447,6 +478,18 @@
      */
     public boolean hasValueHandler() { return _valueHandler != null; }
 
+    /**
+     * Helper method that checks whether this type, or its (optional) key
+     * or content type has {@link #getValueHandler} or {@link #getTypeHandler()};
+     * that is, are there any non-standard handlers associated with this
+     * type object.
+     *
+     * @since 2.8
+     */
+    public boolean hasHandlers() {
+        return (_typeHandler != null) || (_valueHandler != null);
+    }
+    
     /*
     /**********************************************************
     /* Support for producing signatures
diff --git a/src/main/java/com/fasterxml/jackson/databind/JsonMappingException.java b/src/main/java/com/fasterxml/jackson/databind/JsonMappingException.java
index d73b75c..00896ea 100644
--- a/src/main/java/com/fasterxml/jackson/databind/JsonMappingException.java
+++ b/src/main/java/com/fasterxml/jackson/databind/JsonMappingException.java
@@ -7,7 +7,6 @@
 
 import com.fasterxml.jackson.annotation.JsonIgnore;
 import com.fasterxml.jackson.core.*;
-import com.fasterxml.jackson.databind.util.ClassUtil;
 
 /**
  * Checked exception used to signal fatal problems with mapping of
@@ -45,14 +44,10 @@
      */
     public static class Reference implements Serializable
     {
-        private static final long serialVersionUID = 1L;
+        private static final long serialVersionUID = 2L; // changes between 2.7 and 2.8
 
-        /**
-         * Object through which reference was resolved. Can be either
-         * actual instance (usually the case for serialization), or
-         * Class (usually the case for deserialization).
-         */
-        protected Object _from;
+        // transient since 2.8
+        protected transient Object _from;
 
         /**
          * Name of field (for beans) or key (for Maps) that is part
@@ -66,7 +61,7 @@
          * Index within a {@link Collection} instance that contained
          * the reference; used if index is relevant and available.
          * If either not applicable, or not available, -1 is used to
-         * denote "not known".
+         * denote "not known" (or not relevant).
          */
         protected int _index = -1;
 
@@ -76,9 +71,9 @@
          * non-serializable (and has to be dropped) but we still want to pass
          * actual description along.
          *
-         * @since 2.7.4
+         * @since 2.8
          */
-        protected String _asString;
+        protected String _desc;
 
         /**
          * Default constructor for deserialization/sub-classing purposes
@@ -100,39 +95,54 @@
             _index = index;
         }
 
-        private Reference(Reference src, String asString, Object newFrom) {
-            _asString = asString;
-            _from = newFrom;
-            _fieldName = src._fieldName;
-            _index = src._index;
-        }
+        // Setters to let Jackson deserialize instances, but not to be called from outside
+        void setFieldName(String n) { _fieldName = n; }
+        void setIndex(int ix) { _index = ix; }
+        void setDescription(String d) { _desc = d; }
 
-        public void setFrom(Object o) { _from = o; }
-        public void setFieldName(String n) { _fieldName = n; }
-        public void setIndex(int ix) { _index = ix; }
-
+        /**
+         * Object through which reference was resolved. Can be either
+         * actual instance (usually the case for serialization), or
+         * Class (usually the case for deserialization).
+         *<p>
+         * Note that this value must be `transient` to allow serializability (as
+         * often such Object is NOT serializable; or, in case of `Class`, may
+         * not available at the point of deserialization). As such will return
+         * `null` if instance has been passed using JDK serialization.
+         */
+        @JsonIgnore
         public Object getFrom() { return _from; }
+
         public String getFieldName() { return _fieldName; }
         public int getIndex() { return _index; }
-
-        @Override public String toString() {
-            if (_asString == null) {
+        public String getDescription() {
+            if (_desc == null) {
                 StringBuilder sb = new StringBuilder();
 
                 if (_from == null) { // can this ever occur?
                     sb.append("UNKNOWN");
                 } else {
                     Class<?> cls = (_from instanceof Class<?>) ? (Class<?>)_from : _from.getClass();
-                    /* Hmmh. Although Class.getName() is mostly ok, it does look
-                     * butt-ugly for arrays. So let's use getSimpleName() instead;
-                     * but have to prepend package name too.
-                     */
+                    // Hmmh. Although Class.getName() is mostly ok, it does look
+                    // butt-ugly for arrays.
+                    // 06-Oct-2016, tatu: as per [databind#1403], `getSimpleName()` not so good
+                    //   as it drops enclosing class. So let's try bit different approach
+                    int arrays = 0;
+                    while (cls.isArray()) {
+                        cls = cls.getComponentType();
+                        ++arrays;
+                    }
+                    sb.append(cls.getName());
+                    while (--arrays >= 0) {
+                        sb.append("[]");
+                    }
+                    /* was:
                     String pkgName = ClassUtil.getPackageName(cls);
                     if (pkgName != null) {
                         sb.append(pkgName);
                         sb.append('.');
                     }
-                    sb.append(cls.getSimpleName());
+                    */
                 }
                 sb.append('[');
                 if (_fieldName != null) {
@@ -145,22 +155,26 @@
                     sb.append('?');
                 }
                 sb.append(']');
-                _asString = sb.toString();
+                _desc = sb.toString();
             }
-            return _asString;
+            return _desc;
+        }
+
+        @Override
+        public String toString() {
+            return getDescription();
         }
 
         /**
          * May need some cleaning here, given that `from` may or may not be serializable.
          *
-         * since 2.7.4
+         * since 2.8
          */
         Object writeReplace() {
-            // as per [databind#1195], reference may cause trouble, if non-serializable
-            // instance (either directly or transitively); and even use of Class would often
-            // be problematic. Because of this, clear up `_from` always, but ensure that
-            // description is preserved
-            return new Reference(this, toString(), null);
+            // as per [databind#1195], need to ensure description is not null, since
+            // `_from` is transient
+            getDescription();
+            return this;
         }
     }
 
@@ -295,11 +309,7 @@
      * @since 2.7
      */
     public static JsonMappingException from(SerializerProvider ctxt, String msg) {
-        /* 17-Aug-2015, tatu: As per [databind#903] this is bit problematic as
-         *   SerializerProvider instance does not currently hold on to generator...
-         */
-        JsonGenerator g = null;
-        return new JsonMappingException(g, msg);
+        return new JsonMappingException(ctxt.getGenerator(), msg);
     }
 
     /**
@@ -309,8 +319,7 @@
         /* 17-Aug-2015, tatu: As per [databind#903] this is bit problematic as
          *   SerializerProvider instance does not currently hold on to generator...
          */
-        JsonGenerator g = null;
-        return new JsonMappingException(g, msg, problem);
+        return new JsonMappingException(ctxt.getGenerator(), msg, problem);
     }
     
     /**
diff --git a/src/main/java/com/fasterxml/jackson/databind/JsonNode.java b/src/main/java/com/fasterxml/jackson/databind/JsonNode.java
index e1c472b..142ed73 100644
--- a/src/main/java/com/fasterxml/jackson/databind/JsonNode.java
+++ b/src/main/java/com/fasterxml/jackson/databind/JsonNode.java
@@ -508,9 +508,24 @@
      */
     public double doubleValue() { return 0.0; }
 
+    /**
+     * Returns floating point value for this node (as {@link BigDecimal}), <b>if and only if</b>
+     * this node is numeric ({@link #isNumber} returns true). For other
+     * types returns <code>BigDecimal.ZERO</code>.
+     *
+     * @return {@link BigDecimal} value this node contains, if numeric node; <code>BigDecimal.ZERO</code> for non-number nodes.
+     */
     public BigDecimal decimalValue() { return BigDecimal.ZERO; }
+
+    /**
+     * Returns integer value for this node (as {@link BigDecimal}), <b>if and only if</b>
+     * this node is numeric ({@link #isNumber} returns true). For other
+     * types returns <code>BigInteger.ZERO</code>.
+     *
+     * @return {@link BigInteger} value this node contains, if numeric node; <code>BigInteger.ZERO</code> for non-number nodes.
+     */
     public BigInteger bigIntegerValue() { return BigInteger.ZERO; }
-    
+
     /*
     /**********************************************************
     /* Public API, value access with conversion(s)/coercion(s)
@@ -649,13 +664,13 @@
     public boolean asBoolean(boolean defaultValue) {
         return defaultValue;
     }
-    
+
     /*
     /**********************************************************
     /* Public API, value find / existence check methods
     /**********************************************************
      */
-    
+
     /**
      * Method that allows checking whether this node is JSON Object node
      * and contains value for specified property. If this is the case
diff --git a/src/main/java/com/fasterxml/jackson/databind/JsonSerializer.java b/src/main/java/com/fasterxml/jackson/databind/JsonSerializer.java
index 88e5f50..3506cd2 100644
--- a/src/main/java/com/fasterxml/jackson/databind/JsonSerializer.java
+++ b/src/main/java/com/fasterxml/jackson/databind/JsonSerializer.java
@@ -157,16 +157,16 @@
         if (clz == null) {
             clz = value.getClass();
         }
-        throw serializers.mappingException("Type id handling not implemented for type %s (by serializer of type %s)",
+        serializers.reportMappingProblem("Type id handling not implemented for type %s (by serializer of type %s)",
                 clz.getName(), getClass().getName());
     }
-    
+
     /*
     /**********************************************************
     /* Other accessors
     /**********************************************************
      */
-    
+
     /**
      * Method for accessing type of Objects this serializer can handle.
      * Note that this information is not guaranteed to be exact -- it
@@ -187,10 +187,8 @@
      *<p>
      * Default implementation will consider only null values to be empty.
      * 
-     * @since 2.0
-     * 
      * @deprecated Since 2.5 Use {@link #isEmpty(SerializerProvider, Object)} instead;
-     *   will be removed from 2.8
+     *   will be removed from 2.9
      */
     @Deprecated
     public boolean isEmpty(T value) {
@@ -204,7 +202,7 @@
      *<p>
      * Default implementation will consider only null values to be empty.
      *<p>
-     * NOTE: replaces {@link #isEmpty(Object)}, deprecated in 2.5
+     * NOTE: replaces {@link #isEmpty(Object)}, which was deprecated in 2.5
      * 
      * @since 2.5
      */
diff --git a/src/main/java/com/fasterxml/jackson/databind/MapperFeature.java b/src/main/java/com/fasterxml/jackson/databind/MapperFeature.java
index 425f251..e163b5f 100644
--- a/src/main/java/com/fasterxml/jackson/databind/MapperFeature.java
+++ b/src/main/java/com/fasterxml/jackson/databind/MapperFeature.java
@@ -21,7 +21,7 @@
     /* Introspection features
     /******************************************************
      */
-    
+
     /**
      * Feature that determines whether annotation introspection
      * is used for configuration; if enabled, configured
@@ -220,11 +220,13 @@
     ALLOW_FINAL_FIELDS_AS_MUTATORS(true),
 
     /**
-     * Feature that determines for <code>transient</code> modifier for fields
-     * is handled: if disabled, it is only taken to mean exclusion of
+     * Feature that determines how <code>transient</code> modifier for fields
+     * is handled: if disabled, it is only taken to mean exclusion of the field
+     * as accessor; if true, removal of the whole property.
      *<p>
      * Feature is disabled by default, meaning that existence of `transient`
-     * for a field does not necessarily lead to ignoral of getters or setters.
+     * for a field does not necessarily lead to ignoral of getters or setters
+     * but just ignoring the use of field for access.
      *
      * @since 2.6
      */
diff --git a/src/main/java/com/fasterxml/jackson/databind/Module.java b/src/main/java/com/fasterxml/jackson/databind/Module.java
index 37ca295..d7d0d01 100644
--- a/src/main/java/com/fasterxml/jackson/databind/Module.java
+++ b/src/main/java/com/fasterxml/jackson/databind/Module.java
@@ -1,6 +1,7 @@
 package com.fasterxml.jackson.databind;
 
 import com.fasterxml.jackson.core.*;
+import com.fasterxml.jackson.databind.cfg.MutableConfigOverride;
 import com.fasterxml.jackson.databind.deser.BeanDeserializerModifier;
 import com.fasterxml.jackson.databind.deser.DeserializationProblemHandler;
 import com.fasterxml.jackson.databind.deser.Deserializers;
@@ -143,6 +144,31 @@
         public boolean isEnabled(JsonParser.Feature f);
 
         public boolean isEnabled(JsonGenerator.Feature f);
+
+        /*
+        /**********************************************************
+        /* Mutant accessors
+        /**********************************************************
+         */
+
+        /**
+         * "Mutant accessor" for getting a mutable configuration override object for
+         * given type, needed to add or change per-type overrides applied
+         * to properties of given type.
+         * Usage is through returned object by colling "setter" methods, which
+         * directly modify override object and take effect directly.
+         * For example you can do
+         *<pre>
+         *   mapper.configOverride(java.util.Date.class)
+         *       .setFormat(JsonFormat.Value.forPattern("yyyy-MM-dd"));
+         *<pre>
+         * to change the default format to use for properties of type
+         * {@link java.util.Date} (possibly further overridden by per-property
+         * annotations)
+         *
+         * @since 2.8
+         */
+        public MutableConfigOverride configOverride(Class<?> type);
         
         /*
         /**********************************************************
diff --git a/src/main/java/com/fasterxml/jackson/databind/ObjectMapper.java b/src/main/java/com/fasterxml/jackson/databind/ObjectMapper.java
index e75eaa2..cb64cee 100644
--- a/src/main/java/com/fasterxml/jackson/databind/ObjectMapper.java
+++ b/src/main/java/com/fasterxml/jackson/databind/ObjectMapper.java
@@ -3,6 +3,8 @@
 import java.io.*;
 import java.lang.reflect.Type;
 import java.net.URL;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
 import java.text.DateFormat;
 import java.util.*;
 import java.util.concurrent.ConcurrentHashMap;
@@ -19,6 +21,8 @@
 import com.fasterxml.jackson.databind.cfg.ContextAttributes;
 import com.fasterxml.jackson.databind.cfg.HandlerInstantiator;
 import com.fasterxml.jackson.databind.cfg.MapperConfig;
+import com.fasterxml.jackson.databind.cfg.MutableConfigOverride;
+import com.fasterxml.jackson.databind.cfg.ConfigOverrides;
 import com.fasterxml.jackson.databind.deser.*;
 import com.fasterxml.jackson.databind.introspect.*;
 import com.fasterxml.jackson.databind.jsonFormatVisitors.JsonFormatVisitorWrapper;
@@ -28,6 +32,7 @@
 import com.fasterxml.jackson.databind.node.*;
 import com.fasterxml.jackson.databind.ser.*;
 import com.fasterxml.jackson.databind.type.*;
+import com.fasterxml.jackson.databind.util.ClassUtil;
 import com.fasterxml.jackson.databind.util.RootNameLookup;
 import com.fasterxml.jackson.databind.util.StdDateFormat;
 import com.fasterxml.jackson.databind.util.TokenBuffer;
@@ -130,7 +135,10 @@
      * Since 2.4 there are special exceptions for JSON Tree model
      * types (sub-types of {@link TreeNode}: default typing is never
      * applied to them
-     * (see <a href="https://github.com/FasterXML/jackson-databind/issues/88">Issue#88</a> for details)
+     * (see <a href="https://github.com/FasterXML/jackson-databind/issues/88">databind#88</a> for details)
+     *<p>
+     * Since 2.8(.4) additional checks are made to avoid attempts at default
+     * typing primitive-valued properties.
      */
     public enum DefaultTyping {
         /**
@@ -221,6 +229,12 @@
          */
         public boolean useForType(JavaType t)
         {
+            // 03-Oct-2016, tatu: As per [databind#1395], need to skip
+            //  primitive types too, regardless
+            if (t.isPrimitive()) {
+                return false;
+            }
+
             switch (_appliesFor) {
             case NON_CONCRETE_AND_ARRAYS:
                 while (t.isArrayType()) {
@@ -273,12 +287,6 @@
     protected final static VisibilityChecker<?> STD_VISIBILITY_CHECKER = VisibilityChecker.Std.defaultInstance();
 
     /**
-     * @deprecated Since 2.6, do not use: will be removed in 2.7 or later
-     */
-    @Deprecated
-    protected final static PrettyPrinter _defaultPrettyPrinter = new DefaultPrettyPrinter();
-
-    /**
      * Base settings contain defaults used for all {@link ObjectMapper}
      * instances.
      */
@@ -288,7 +296,7 @@
             STD_VISIBILITY_CHECKER, null, TypeFactory.defaultInstance(),
             null, StdDateFormat.instance, null,
             Locale.getDefault(),
-            null, // to indicate "use default TimeZone"
+            null, // to indicate "use Jackson default TimeZone" (UTC since Jackson 2.7)
             Base64Variants.getDefaultVariant() // 2.1
     );
 
@@ -322,6 +330,14 @@
      */
     protected SubtypeResolver _subtypeResolver;
 
+    /**
+     * Currently active per-type configuration overrides, accessed by
+     * declared type of property.
+     *
+     * @since 2.8
+     */
+    protected ConfigOverrides _propertyOverrides;
+
     /*
     /**********************************************************
     /* Configuration settings: mix-in annotations
@@ -481,12 +497,12 @@
         _subtypeResolver = src._subtypeResolver;
         _typeFactory = src._typeFactory;
         _injectableValues = src._injectableValues;
+        _propertyOverrides = src._propertyOverrides.copy();
+        _mixIns = src._mixIns.copy();
 
-        SimpleMixInResolver mixins = src._mixIns.copy();
-        _mixIns = mixins;
         RootNameLookup rootNames = new RootNameLookup();
-        _serializationConfig = new SerializationConfig(src._serializationConfig, mixins, rootNames);
-        _deserializationConfig = new DeserializationConfig(src._deserializationConfig, mixins, rootNames);
+        _serializationConfig = new SerializationConfig(src._serializationConfig, _mixIns, rootNames, _propertyOverrides);
+        _deserializationConfig = new DeserializationConfig(src._deserializationConfig, _mixIns, rootNames, _propertyOverrides);
         _serializerProvider = src._serializerProvider.copy();
         _deserializationContext = src._deserializationContext.copy();
 
@@ -538,12 +554,13 @@
 
         SimpleMixInResolver mixins = new SimpleMixInResolver(null);
         _mixIns = mixins;
-
         BaseSettings base = DEFAULT_BASE.withClassIntrospector(defaultClassIntrospector());
+        ConfigOverrides propOverrides = new ConfigOverrides();
+        _propertyOverrides = propOverrides;
         _serializationConfig = new SerializationConfig(base,
-                    _subtypeResolver, mixins, rootNames);
+                    _subtypeResolver, mixins, rootNames, propOverrides);
         _deserializationConfig = new DeserializationConfig(base,
-                    _subtypeResolver, mixins, rootNames);
+                    _subtypeResolver, mixins, rootNames, propOverrides);
 
         // Some overrides we may need
         final boolean needOrder = _jsonFactory.requiresPropertyOrdering();
@@ -772,14 +789,21 @@
             public boolean isEnabled(JsonParser.Feature f) {
                 return mapper.isEnabled(f);
             }
-            
+
             @Override
             public boolean isEnabled(JsonGenerator.Feature f) {
                 return mapper.isEnabled(f);
             }
-            
+
+            // // // Mutant accessors
+
+            @Override
+            public MutableConfigOverride configOverride(Class<?> type) {
+                return mapper.configOverride(type);
+            }
+
             // // // Methods for registering handlers: deserializers
-            
+
             @Override
             public void addDeserializers(Deserializers d) {
                 DeserializerFactory df = mapper._deserializationContext._factory.withAdditionalDeserializers(d);
@@ -945,14 +969,28 @@
     public static List<Module> findModules(ClassLoader classLoader)
     {
         ArrayList<Module> modules = new ArrayList<Module>();
-        ServiceLoader<Module> loader = (classLoader == null) ?
-                ServiceLoader.load(Module.class) : ServiceLoader.load(Module.class, classLoader);
+        ServiceLoader<Module> loader = secureGetServiceLoader(Module.class, classLoader);
         for (Module module : loader) {
             modules.add(module);
         }
         return modules;
     }
 
+    private static <T> ServiceLoader<T> secureGetServiceLoader(final Class<T> clazz, final ClassLoader classLoader) {
+        final SecurityManager sm = System.getSecurityManager();
+        if (sm == null) {
+            return (classLoader == null) ?
+                    ServiceLoader.load(clazz) : ServiceLoader.load(clazz, classLoader);
+        }
+        return AccessController.doPrivileged(new PrivilegedAction<ServiceLoader<T>>() {
+            @Override
+            public ServiceLoader<T> run() {
+                return (classLoader == null) ?
+                        ServiceLoader.load(clazz) : ServiceLoader.load(clazz, classLoader);
+            }
+        });
+    }
+
     /**
      * Convenience method that is functionally equivalent to:
      *<code>
@@ -1464,6 +1502,33 @@
      */
 
     /**
+     * Accessor for getting a mutable configuration override object for
+     * given type, needed to add or change per-type overrides applied
+     * to properties of given type.
+     * Usage is through returned object by colling "setter" methods, which
+     * directly modify override object and take effect directly.
+     * For example you can do
+     *<pre>
+     *   mapper.configOverride(java.util.Date.class)
+     *       .setFormat(JsonFormat.Value.forPattern("yyyy-MM-dd"));
+     *<pre>
+     * to change the default format to use for properties of type
+     * {@link java.util.Date} (possibly further overridden by per-property
+     * annotations)
+     *
+     * @since 2.8
+     */
+    public MutableConfigOverride configOverride(Class<?> type) {
+        return _propertyOverrides.findOrCreateOverride(type);
+    }
+
+    /*
+    /**********************************************************
+    /* Configuration, basic type handling
+    /**********************************************************
+     */
+
+    /**
      * Accessor for getting currently configured {@link TypeFactory} instance.
      */
     public TypeFactory getTypeFactory() {
@@ -1557,10 +1622,10 @@
      * @since 2.4
      */
     public ObjectMapper setConfig(DeserializationConfig config) {
-    	_deserializationConfig = config;
-    	return this;
+        _deserializationConfig = config;
+        return this;
     }
-    
+
     /*
     /**********************************************************
     /* Configuration, serialization
@@ -1717,7 +1782,7 @@
 
     /**
      * Method for overriding default TimeZone to use for formatting.
-     * Default value used is UTC (NOT local timezone).
+     * Default value used is UTC (NOT default TimeZone of JVM).
      */
     public ObjectMapper setTimeZone(TimeZone tz) {
         _deserializationConfig = _deserializationConfig.with(tz);
@@ -2044,10 +2109,10 @@
      */
     @Override
     @SuppressWarnings("unchecked")
-    public <T> T readValue(JsonParser jp, Class<T> valueType)
+    public <T> T readValue(JsonParser p, Class<T> valueType)
         throws IOException, JsonParseException, JsonMappingException
     {
-        return (T) _readValue(getDeserializationConfig(), jp, _typeFactory.constructType(valueType));
+        return (T) _readValue(getDeserializationConfig(), p, _typeFactory.constructType(valueType));
     } 
 
     /**
@@ -2068,10 +2133,10 @@
      */
     @Override
     @SuppressWarnings("unchecked")
-    public <T> T readValue(JsonParser jp, TypeReference<?> valueTypeRef)
+    public <T> T readValue(JsonParser p, TypeReference<?> valueTypeRef)
         throws IOException, JsonParseException, JsonMappingException
     {
-        return (T) _readValue(getDeserializationConfig(), jp, _typeFactory.constructType(valueTypeRef));
+        return (T) _readValue(getDeserializationConfig(), p, _typeFactory.constructType(valueTypeRef));
     }
 
     /**
@@ -2091,10 +2156,10 @@
      */
     @Override
     @SuppressWarnings("unchecked")
-    public final <T> T readValue(JsonParser jp, ResolvedType valueType)
+    public final <T> T readValue(JsonParser p, ResolvedType valueType)
         throws IOException, JsonParseException, JsonMappingException
     {
-        return (T) _readValue(getDeserializationConfig(), jp, (JavaType) valueType);
+        return (T) _readValue(getDeserializationConfig(), p, (JavaType) valueType);
     }
 
     /**
@@ -2110,10 +2175,10 @@
      *   expected for result type (or has other mismatch issues)
      */
     @SuppressWarnings("unchecked")
-    public <T> T readValue(JsonParser jp, JavaType valueType)
+    public <T> T readValue(JsonParser p, JavaType valueType)
         throws IOException, JsonParseException, JsonMappingException
     {
-        return (T) _readValue(getDeserializationConfig(), jp, valueType);
+        return (T) _readValue(getDeserializationConfig(), p, valueType);
     }
     
     /**
@@ -2137,7 +2202,7 @@
      *    of type {@link JsonParser} supports (JSON for default case)
      */
     @Override
-    public <T extends TreeNode> T readTree(JsonParser jp)
+    public <T extends TreeNode> T readTree(JsonParser p)
         throws IOException, JsonProcessingException
     {
         /* 02-Mar-2009, tatu: One twist; deserialization provider
@@ -2148,14 +2213,14 @@
          *   calling readValue(), since that'll choke on it otherwise
          */
         DeserializationConfig cfg = getDeserializationConfig();
-        JsonToken t = jp.getCurrentToken();
+        JsonToken t = p.getCurrentToken();
         if (t == null) {
-            t = jp.nextToken();
+            t = p.nextToken();
             if (t == null) {
                 return null;
             }
         }
-        JsonNode n = (JsonNode) _readValue(cfg, jp, JSON_NODE_TYPE);
+        JsonNode n = (JsonNode) _readValue(cfg, p, JSON_NODE_TYPE);
         if (n == null) {
             n = getNodeFactory().nullNode();
         }
@@ -2584,9 +2649,9 @@
         JsonNode result;
         try {
             writeValue(buf, fromValue);
-            JsonParser jp = buf.asParser();
-            result = readTree(jp);
-            jp.close();
+            JsonParser p = buf.asParser();
+            result = readTree(p);
+            p.close();
         } catch (IOException e) { // should not occur, no real i/o...
             throw new IllegalArgumentException(e.getMessage(), e);
         }
@@ -2745,8 +2810,6 @@
     public <T> T readValue(URL src, Class<T> valueType)
         throws IOException, JsonParseException, JsonMappingException
     {
-     // !!! TODO
-//    	_setupClassLoaderForDeserialization(valueType);
         return (T) _readMapAndClose(_jsonFactory.createParser(src), _typeFactory.constructType(valueType));
     } 
 
@@ -2792,8 +2855,6 @@
     public <T> T readValue(String content, Class<T> valueType)
         throws IOException, JsonParseException, JsonMappingException
     {
-     // !!! TODO
-//    	_setupClassLoaderForDeserialization(valueType);
         return (T) _readMapAndClose(_jsonFactory.createParser(content), _typeFactory.constructType(valueType));
     } 
 
@@ -2839,8 +2900,6 @@
     public <T> T readValue(Reader src, Class<T> valueType)
         throws IOException, JsonParseException, JsonMappingException
     {
-     // !!! TODO
-//    	_setupClassLoaderForDeserialization(valueType);
         return (T) _readMapAndClose(_jsonFactory.createParser(src), _typeFactory.constructType(valueType));
     } 
 
@@ -2862,8 +2921,6 @@
     public <T> T readValue(InputStream src, Class<T> valueType)
         throws IOException, JsonParseException, JsonMappingException
     {
-     // !!! TODO
-//    	_setupClassLoaderForDeserialization(valueType);
         return (T) _readMapAndClose(_jsonFactory.createParser(src), _typeFactory.constructType(valueType));
     } 
 
@@ -2885,8 +2942,6 @@
     public <T> T readValue(byte[] src, Class<T> valueType)
         throws IOException, JsonParseException, JsonMappingException
     {
-     // !!! TODO
-//      _setupClassLoaderForDeserialization(valueType);
         return (T) _readMapAndClose(_jsonFactory.createParser(src), _typeFactory.constructType(valueType));
     } 
     
@@ -2895,8 +2950,6 @@
                                Class<T> valueType)
         throws IOException, JsonParseException, JsonMappingException
     {
-     // !!! TODO
-//    	_setupClassLoaderForDeserialization(valueType);
         return (T) _readMapAndClose(_jsonFactory.createParser(src, offset, len), _typeFactory.constructType(valueType));
     } 
 
@@ -2929,7 +2982,20 @@
     {
         return (T) _readMapAndClose(_jsonFactory.createParser(src, offset, len), valueType);
     } 
-    
+
+    @SuppressWarnings("unchecked")
+    public <T> T readValue(DataInput src, Class<T> valueType) throws IOException
+    {
+        return (T) _readMapAndClose(_jsonFactory.createParser(src),
+                _typeFactory.constructType(valueType));
+    }
+
+    @SuppressWarnings("unchecked")
+    public <T> T readValue(DataInput src, JavaType valueType) throws IOException
+    {
+        return (T) _readMapAndClose(_jsonFactory.createParser(src), valueType);
+    }
+
     /*
     /**********************************************************
     /* Extended Public API: serialization
@@ -2965,6 +3031,15 @@
     }
 
     /**
+     * @since 2.8
+     */
+    public void writeValue(DataOutput out, Object value)
+        throws IOException
+    {
+        _configAndWriteValue(_jsonFactory.createGenerator(out, JsonEncoding.UTF8), value);
+    }
+
+    /**
      * Method that can be used to serialize any Java value as
      * JSON output, using Writer provided.
      *<p>
@@ -2991,7 +3066,7 @@
     @SuppressWarnings("resource")
     public String writeValueAsString(Object value)
         throws JsonProcessingException
-    {        
+    {
         // alas, we have to pull the recycler directly here...
         SegmentedStringWriter sw = new SegmentedStringWriter(_jsonFactory._getBufferRecycler());
         try {
@@ -3508,23 +3583,23 @@
             _serializerProvider(config).serializeValue(buf, fromValue);
 
             // then matching read, inlined 'readValue' with minor mods:
-            final JsonParser jp = buf.asParser();
+            final JsonParser p = buf.asParser();
             Object result;
             // ok to pass in existing feature flags; unwrapping handled by mapper
             final DeserializationConfig deserConfig = getDeserializationConfig();
-            JsonToken t = _initForReading(jp);
+            JsonToken t = _initForReading(p);
             if (t == JsonToken.VALUE_NULL) {
-                DeserializationContext ctxt = createDeserializationContext(jp, deserConfig);
+                DeserializationContext ctxt = createDeserializationContext(p, deserConfig);
                 result = _findRootDeserializer(ctxt, toValueType).getNullValue(ctxt);
             } else if (t == JsonToken.END_ARRAY || t == JsonToken.END_OBJECT) {
                 result = null;
             } else { // pointing to event other than null
-                DeserializationContext ctxt = createDeserializationContext(jp, deserConfig);
+                DeserializationContext ctxt = createDeserializationContext(p, deserConfig);
                 JsonDeserializer<Object> deser = _findRootDeserializer(ctxt, toValueType);
-                // note: no handling of unwarpping
-                result = deser.deserialize(jp, ctxt);
+                // note: no handling of unwrapping
+                result = deser.deserialize(p, ctxt);
             }
-            jp.close();
+            p.close();
             return result;
         } catch (IOException e) { // should not occur, no real i/o...
             throw new IllegalArgumentException(e.getMessage(), e);
@@ -3604,14 +3679,6 @@
     protected DefaultSerializerProvider _serializerProvider(SerializationConfig config) {
         return _serializerProvider.createInstance(config, _serializerFactory);
     }
-    
-    /**
-     * @deprecated Since 2.6, use {@link SerializationConfig#constructDefaultPrettyPrinter()} directly
-     */
-    @Deprecated
-    protected PrettyPrinter _defaultPrettyPrinter() {
-        return _serializationConfig.constructDefaultPrettyPrinter();
-    }
 
     /**
      * Method called to configure the generator as necessary and then
@@ -3626,54 +3693,13 @@
             _configAndWriteCloseable(g, value, cfg);
             return;
         }
-        boolean closed = false;
         try {
             _serializerProvider(cfg).serializeValue(g, value);
-            closed = true;
-            g.close();
-        } finally {
-            /* won't try to close twice; also, must catch exception (so it 
-             * will not mask exception that is pending)
-             */
-            if (!closed) {
-                /* 04-Mar-2014, tatu: But! Let's try to prevent auto-closing of
-                 *    structures, which typically causes more damage.
-                 */
-                g.disable(JsonGenerator.Feature.AUTO_CLOSE_JSON_CONTENT);
-                try {
-                    g.close();
-                } catch (IOException ioe) { }
-            }
-        }
-    }
-
-    @Deprecated // since 2.7, not used internally any more
-    protected final void _configAndWriteValue(JsonGenerator g, Object value, Class<?> viewClass)
-        throws IOException
-    {
-        SerializationConfig cfg = getSerializationConfig().withView(viewClass);
-        cfg.initialize(g); // since 2.5
-
-        // [JACKSON-282]: consider Closeable
-        if (cfg.isEnabled(SerializationFeature.CLOSE_CLOSEABLE) && (value instanceof Closeable)) {
-            _configAndWriteCloseable(g, value, cfg);
+        } catch (Exception e) {
+            ClassUtil.closeOnFailAndThrowAsIAE(g, e);
             return;
         }
-        boolean closed = false;
-        try {
-            _serializerProvider(cfg).serializeValue(g, value);
-            closed = true;
-            g.close();
-        } finally {
-            if (!closed) {
-                // 04-Mar-2014, tatu: But! Let's try to prevent auto-closing of
-                //    structures, which typically causes more damage.
-                g.disable(JsonGenerator.Feature.AUTO_CLOSE_JSON_CONTENT);
-                try {
-                    g.close();
-                } catch (IOException ioe) { }
-            }
-        }
+        g.close();
     }
 
     /**
@@ -3686,30 +3712,16 @@
         Closeable toClose = (Closeable) value;
         try {
             _serializerProvider(cfg).serializeValue(g, value);
-            JsonGenerator tmpGen = g;
-            g = null;
-            tmpGen.close();
             Closeable tmpToClose = toClose;
             toClose = null;
             tmpToClose.close();
-        } finally {
-            // Need to close both generator and value, as long as they haven't yet been closed
-            if (g != null) {
-                // 04-Mar-2014, tatu: But! Let's try to prevent auto-closing of
-                //    structures, which typically causes more damage.
-                g.disable(JsonGenerator.Feature.AUTO_CLOSE_JSON_CONTENT);
-                try {
-                    g.close();
-                } catch (IOException ioe) { }
-            }
-            if (toClose != null) {
-                try {
-                    toClose.close();
-                } catch (IOException ioe) { }
-            }
+        } catch (Exception e) {
+            ClassUtil.closeOnFailAndThrowAsIAE(g, toClose, e);
+            return;
         }
+        g.close();
     }
-    
+
     /**
      * Helper method used when value to serialize is {@link Closeable} and its <code>close()</code>
      * method is to be called right after serialization has been called
@@ -3723,16 +3735,11 @@
             if (cfg.isEnabled(SerializationFeature.FLUSH_AFTER_WRITE_VALUE)) {
                 g.flush();
             }
-            Closeable tmpToClose = toClose;
-            toClose = null;
-            tmpToClose.close();
-        } finally {
-            if (toClose != null) {
-                try {
-                    toClose.close();
-                } catch (IOException ioe) { }
-            }
+        } catch (Exception e) {
+            ClassUtil.closeOnFailAndThrowAsIAE(null, toClose, e);
+            return;
         }
+        toClose.close();
     }
 
     /*
@@ -3746,75 +3753,71 @@
      * for deserializing a single root value.
      * Can be overridden if a custom context is needed.
      */
-    protected DefaultDeserializationContext createDeserializationContext(JsonParser jp,
+    protected DefaultDeserializationContext createDeserializationContext(JsonParser p,
             DeserializationConfig cfg) {
-        return _deserializationContext.createInstance(cfg, jp, _injectableValues);
+        return _deserializationContext.createInstance(cfg, p, _injectableValues);
     }
     
     /**
      * Actual implementation of value reading+binding operation.
      */
-    protected Object _readValue(DeserializationConfig cfg, JsonParser jp, JavaType valueType)
-        throws IOException, JsonParseException, JsonMappingException
+    protected Object _readValue(DeserializationConfig cfg, JsonParser p, JavaType valueType)
+        throws IOException
     {
         /* First: may need to read the next token, to initialize
          * state (either before first read from parser, or after
          * previous token has been cleared)
          */
         Object result;
-        JsonToken t = _initForReading(jp);
+        JsonToken t = _initForReading(p);
         if (t == JsonToken.VALUE_NULL) {
-            // [JACKSON-643]: Ask JsonDeserializer what 'null value' to use:
-            DeserializationContext ctxt = createDeserializationContext(jp, cfg);
+            // Ask JsonDeserializer what 'null value' to use:
+            DeserializationContext ctxt = createDeserializationContext(p, cfg);
             result = _findRootDeserializer(ctxt, valueType).getNullValue(ctxt);
         } else if (t == JsonToken.END_ARRAY || t == JsonToken.END_OBJECT) {
             result = null;
         } else { // pointing to event other than null
-            DeserializationContext ctxt = createDeserializationContext(jp, cfg);
+            DeserializationContext ctxt = createDeserializationContext(p, cfg);
             JsonDeserializer<Object> deser = _findRootDeserializer(ctxt, valueType);
             // ok, let's get the value
             if (cfg.useRootWrapping()) {
-                result = _unwrapAndDeserialize(jp, ctxt, cfg, valueType, deser);
+                result = _unwrapAndDeserialize(p, ctxt, cfg, valueType, deser);
             } else {
-                result = deser.deserialize(jp, ctxt);
+                result = deser.deserialize(p, ctxt);
             }
         }
         // Need to consume the token too
-        jp.clearCurrentToken();
+        p.clearCurrentToken();
         return result;
     }
     
-    protected Object _readMapAndClose(JsonParser jp, JavaType valueType)
-        throws IOException, JsonParseException, JsonMappingException
+    protected Object _readMapAndClose(JsonParser p0, JavaType valueType)
+        throws IOException
     {
-        try {
+        try (JsonParser p = p0) {
             Object result;
-            JsonToken t = _initForReading(jp);
+            JsonToken t = _initForReading(p);
             if (t == JsonToken.VALUE_NULL) {
-                // [JACKSON-643]: Ask JsonDeserializer what 'null value' to use:
-                DeserializationContext ctxt = createDeserializationContext(jp,
+                // Ask JsonDeserializer what 'null value' to use:
+                DeserializationContext ctxt = createDeserializationContext(p,
                         getDeserializationConfig());
                 result = _findRootDeserializer(ctxt, valueType).getNullValue(ctxt);
             } else if (t == JsonToken.END_ARRAY || t == JsonToken.END_OBJECT) {
                 result = null;
             } else {
                 DeserializationConfig cfg = getDeserializationConfig();
-                DeserializationContext ctxt = createDeserializationContext(jp, cfg);
+                DeserializationContext ctxt = createDeserializationContext(p, cfg);
                 JsonDeserializer<Object> deser = _findRootDeserializer(ctxt, valueType);
                 if (cfg.useRootWrapping()) {
-                    result = _unwrapAndDeserialize(jp, ctxt, cfg, valueType, deser);
+                    result = _unwrapAndDeserialize(p, ctxt, cfg, valueType, deser);
                 } else {
-                    result = deser.deserialize(jp, ctxt);
+                    result = deser.deserialize(p, ctxt);
                 }
                 ctxt.checkUnresolvedObjectId();
             }
             // Need to consume the token too
-            jp.clearCurrentToken();
+            p.clearCurrentToken();
             return result;
-        } finally {
-            try {
-                jp.close();
-            } catch (IOException ioe) { }
         }
     }
 
@@ -3863,25 +3866,29 @@
         // 12-Jun-2015, tatu: Should try to support namespaces etc but...
         String expSimpleName = expRootName.getSimpleName();
         if (p.getCurrentToken() != JsonToken.START_OBJECT) {
-            throw JsonMappingException.from(p, "Current token not START_OBJECT (needed to unwrap root name '"
-                    +expSimpleName+"'), but "+p.getCurrentToken());
+            ctxt.reportWrongTokenException(p, JsonToken.START_OBJECT,
+                    "Current token not START_OBJECT (needed to unwrap root name '%s'), but %s",
+                    expSimpleName, p.getCurrentToken());
+            
         }
         if (p.nextToken() != JsonToken.FIELD_NAME) {
-            throw JsonMappingException.from(p, "Current token not FIELD_NAME (to contain expected root name '"
+            ctxt.reportWrongTokenException(p, JsonToken.FIELD_NAME,
+                    "Current token not FIELD_NAME (to contain expected root name '"
                     +expSimpleName+"'), but "+p.getCurrentToken());
         }
         String actualName = p.getCurrentName();
         if (!expSimpleName.equals(actualName)) {
-            throw JsonMappingException.from(p, "Root name '"+actualName+"' does not match expected ('"
-                    +expSimpleName+"') for type "+rootType);
+            ctxt.reportMappingException("Root name '%s' does not match expected ('%s') for type %s",
+                    actualName, expSimpleName, rootType);
         }
         // ok, then move to value itself....
         p.nextToken();
         Object result = deser.deserialize(p, ctxt);
         // and last, verify that we now get matching END_OBJECT
         if (p.nextToken() != JsonToken.END_OBJECT) {
-            throw JsonMappingException.from(p, "Current token not END_OBJECT (to match wrapper object with root name '"
-                    +expSimpleName+"'), but "+p.getCurrentToken());
+            ctxt.reportWrongTokenException(p, JsonToken.END_OBJECT,
+                    "Current token not END_OBJECT (to match wrapper object with root name '%s'), but %s",
+                    expSimpleName, p.getCurrentToken());
         }
         return result;
     }
diff --git a/src/main/java/com/fasterxml/jackson/databind/ObjectReader.java b/src/main/java/com/fasterxml/jackson/databind/ObjectReader.java
index 2279c1f..d1ec95f 100644
--- a/src/main/java/com/fasterxml/jackson/databind/ObjectReader.java
+++ b/src/main/java/com/fasterxml/jackson/databind/ObjectReader.java
@@ -338,11 +338,8 @@
     /**********************************************************
      */
 
-    /**
-     * NOTE: changed from static to non-static in 2.5; unfortunate but
-     * necessary change to support overridability
-     */
-    protected JsonToken _initForReading(JsonParser p) throws IOException
+    protected JsonToken _initForReading(DeserializationContext ctxt, JsonParser p)
+        throws IOException
     {
         if (_schema != null) {
             p.setSchema(_schema);
@@ -358,26 +355,28 @@
             t = p.nextToken();
             if (t == null) {
                 // Throw mapping exception, since it's failure to map, not an actual parsing problem
-                throw JsonMappingException.from(p, "No content to map due to end-of-input");
+                ctxt.reportMissingContent(null); // default msg is fine
             }
         }
         return t;
     }
 
     /**
-     * Alternative to {@link #_initForReading(JsonParser)} used in cases where reading
+     * Alternative to {@link #_initForReading} used in cases where reading
      * of multiple values means that we may or may not want to advance the stream,
      * but need to do other initialization.
      *<p>
      * Base implementation only sets configured {@link FormatSchema}, if any, on parser.
      * 
-     * @since 2.5
+     * @since 2.8
      */
-    protected void _initForMultiRead(JsonParser p) throws IOException {
+    protected void _initForMultiRead(DeserializationContext ctxt, JsonParser p)
+        throws IOException
+    {
         if (_schema != null) {
             p.setSchema(_schema);
         }
-        _config.initialize(p); // since 2.5
+        _config.initialize(p);
     }
 
     /*
@@ -528,6 +527,24 @@
      */
 
     /**
+     * Convenience method to bind from {@link JsonPointer}.  
+     * {@link JsonPointerBasedFilter} is registered and will be used for parsing later. 
+     * @since 2.6
+     */
+    public ObjectReader at(final String value) {
+        return new ObjectReader(this, new JsonPointerBasedFilter(value));
+    }
+
+    /**
+     * Convenience method to bind from {@link JsonPointer}
+      * {@link JsonPointerBasedFilter} is registered and will be used for parsing later.
+     * @since 2.6
+     */
+    public ObjectReader at(final JsonPointer pointer) {
+        return new ObjectReader(this, new JsonPointerBasedFilter(pointer));
+    }
+
+    /**
      * Mutant factory method that will construct a new instance that has
      * specified underlying {@link DeserializationConfig}.
      *<p>
@@ -736,7 +753,10 @@
     {
         if (value == _valueToUpdate) return this;
         if (value == null) {
-            throw new IllegalArgumentException("cat not update null value");
+            // 18-Oct-2016, tatu: Actually, should be allowed, to remove value
+            //   to update, if any
+            return _new(this, _config, _valueType, _rootDeserializer, null,
+                    _schema, _injectableValues, _dataFormatReaders);
         }
         JavaType t;
         
@@ -1280,7 +1300,19 @@
         
         return (T) _bindAndClose(_considerFilter(treeAsTokens(src), false));
     }
-    
+
+    /**
+     * @since 2.8
+     */
+    @SuppressWarnings("unchecked")
+    public <T> T readValue(DataInput src) throws IOException
+    {
+        if (_dataFormatReaders != null) {
+            _reportUndetectableSource(src);
+        }
+        return (T) _bindAndClose(_considerFilter(_parserFactory.createParser(src), false));
+    }
+
     /**
      * Method that reads content from given input source,
      * using configuration of this reader, and binds it as JSON Tree.
@@ -1296,7 +1328,6 @@
         if (_dataFormatReaders != null) {
             return _detectBindAndCloseAsTree(in);
         }
-
         return _bindAndCloseAsTree(_considerFilter(_parserFactory.createParser(in), false));
     }
     
@@ -1315,7 +1346,6 @@
         if (_dataFormatReaders != null) {
             _reportUndetectableSource(r);
         }
-        
         return _bindAndCloseAsTree(_considerFilter(_parserFactory.createParser(r), false));
     }
 
@@ -1334,10 +1364,17 @@
         if (_dataFormatReaders != null) {
             _reportUndetectableSource(json);
         }
-
         return _bindAndCloseAsTree(_considerFilter(_parserFactory.createParser(json), false));
     }
 
+    public JsonNode readTree(DataInput src) throws IOException
+    {
+        if (_dataFormatReaders != null) {
+            _reportUndetectableSource(src);
+        }
+        return _bindAndCloseAsTree(_considerFilter(_parserFactory.createParser(src), false));
+    }
+
     /*
     /**********************************************************
     /* Deserialization methods; reading sequence of values
@@ -1404,9 +1441,9 @@
             _reportUndetectableSource(src);
         }
         JsonParser p = _considerFilter(_parserFactory.createParser(src), true);
-        _initForMultiRead(p);
-        p.nextToken();
         DeserializationContext ctxt = createDeserializationContext(p);
+        _initForMultiRead(ctxt, p);
+        p.nextToken();
         return _newIterator(p, ctxt, _findRootDeserializer(ctxt), true);
     }
     
@@ -1423,9 +1460,9 @@
             _reportUndetectableSource(json);
         }
         JsonParser p = _considerFilter(_parserFactory.createParser(json), true);
-        _initForMultiRead(p);
-        p.nextToken();
         DeserializationContext ctxt = createDeserializationContext(p);
+        _initForMultiRead(ctxt, p);
+        p.nextToken();
         return _newIterator(p, ctxt, _findRootDeserializer(ctxt), true);
     }
 
@@ -1478,6 +1515,17 @@
         return _bindAndReadValues(_considerFilter(_parserFactory.createParser(src), true));
     }
 
+    /**
+     * @since 2.8
+     */
+    public <T> MappingIterator<T> readValues(DataInput src) throws IOException
+    {
+        if (_dataFormatReaders != null) {
+            _reportUndetectableSource(src);
+        }
+        return _bindAndReadValues(_considerFilter(_parserFactory.createParser(src), true));
+    }
+
     /*
     /**********************************************************
     /* Implementation of rest of ObjectCodec methods
@@ -1516,10 +1564,10 @@
          * before first read from parser, or after previous token has been cleared)
          */
         Object result;
-        JsonToken t = _initForReading(p);
+        final DeserializationContext ctxt = createDeserializationContext(p);
+        JsonToken t = _initForReading(ctxt, p);
         if (t == JsonToken.VALUE_NULL) {
             if (valueToUpdate == null) {
-                DeserializationContext ctxt = createDeserializationContext(p);
                 result = _findRootDeserializer(ctxt).getNullValue(ctxt);
             } else {
                 result = valueToUpdate;
@@ -1527,7 +1575,6 @@
         } else if (t == JsonToken.END_ARRAY || t == JsonToken.END_OBJECT) {
             result = valueToUpdate;
         } else { // pointing to event other than null
-            DeserializationContext ctxt = createDeserializationContext(p);
             JsonDeserializer<Object> deser = _findRootDeserializer(ctxt);
             if (_unwrapRoot) {
                 result = _unwrapAndDeserialize(p, ctxt, _valueType, deser);
@@ -1555,14 +1602,15 @@
                 ? p : new FilteringParserDelegate(p, _filter, false, multiValue);
     }
     
-    protected Object _bindAndClose(JsonParser p) throws IOException
+    protected Object _bindAndClose(JsonParser p0) throws IOException
     {
-        try {
+        try (JsonParser p = p0) {
             Object result;
-            JsonToken t = _initForReading(p);
+
+            DeserializationContext ctxt = createDeserializationContext(p);
+            JsonToken t = _initForReading(ctxt, p);
             if (t == JsonToken.VALUE_NULL) {
                 if (_valueToUpdate == null) {
-                    DeserializationContext ctxt = createDeserializationContext(p);
                     result = _findRootDeserializer(ctxt).getNullValue(ctxt);
                 } else {
                     result = _valueToUpdate;
@@ -1570,7 +1618,6 @@
             } else if (t == JsonToken.END_ARRAY || t == JsonToken.END_OBJECT) {
                 result = _valueToUpdate;
             } else {
-                DeserializationContext ctxt = createDeserializationContext(p);
                 JsonDeserializer<Object> deser = _findRootDeserializer(ctxt);
                 if (_unwrapRoot) {
                     result = _unwrapAndDeserialize(p, ctxt, _valueType, deser);
@@ -1584,31 +1631,23 @@
                 }
             }
             return result;
-        } finally {
-            try {
-                p.close();
-            } catch (IOException ioe) { }
         }
     }
 
-    protected JsonNode _bindAndCloseAsTree(JsonParser p) throws IOException {
-        try {
+    protected JsonNode _bindAndCloseAsTree(JsonParser p0) throws IOException {
+        try (JsonParser p = p0) {
             return _bindAsTree(p);
-        } finally {
-            try {
-                p.close();
-            } catch (IOException ioe) { }
         }
     }
     
     protected JsonNode _bindAsTree(JsonParser p) throws IOException
     {
         JsonNode result;
-        JsonToken t = _initForReading(p);
+        DeserializationContext ctxt = createDeserializationContext(p);
+        JsonToken t = _initForReading(ctxt, p);
         if (t == JsonToken.VALUE_NULL || t == JsonToken.END_ARRAY || t == JsonToken.END_OBJECT) {
             result = NullNode.instance;
         } else {
-            DeserializationContext ctxt = createDeserializationContext(p);
             JsonDeserializer<Object> deser = _findTreeDeserializer(ctxt);
             if (_unwrapRoot) {
                 result = (JsonNode) _unwrapAndDeserialize(p, ctxt, JSON_NODE_TYPE, deser);
@@ -1626,9 +1665,9 @@
      */
     protected <T> MappingIterator<T> _bindAndReadValues(JsonParser p) throws IOException
     {
-        _initForMultiRead(p);
-        p.nextToken();
         DeserializationContext ctxt = createDeserializationContext(p);
+        _initForMultiRead(ctxt, p);
+        p.nextToken();
         return _newIterator(p, ctxt, _findRootDeserializer(ctxt), true);
     }
 
@@ -1640,17 +1679,19 @@
         String expSimpleName = expRootName.getSimpleName();
 
         if (p.getCurrentToken() != JsonToken.START_OBJECT) {
-            throw JsonMappingException.from(p, "Current token not START_OBJECT (needed to unwrap root name '"
-                    +expSimpleName+"'), but "+p.getCurrentToken());
+            ctxt.reportWrongTokenException(p, JsonToken.START_OBJECT,
+                    "Current token not START_OBJECT (needed to unwrap root name '%s'), but %s",
+                    expSimpleName, p.getCurrentToken());
         }
         if (p.nextToken() != JsonToken.FIELD_NAME) {
-            throw JsonMappingException.from(p, "Current token not FIELD_NAME (to contain expected root name '"
-                    +expSimpleName+"'), but "+p.getCurrentToken());
+            ctxt.reportWrongTokenException(p, JsonToken.FIELD_NAME,
+                    "Current token not FIELD_NAME (to contain expected root name '%s'), but %s", 
+                    expSimpleName, p.getCurrentToken());
         }
         String actualName = p.getCurrentName();
         if (!expSimpleName.equals(actualName)) {
-            throw JsonMappingException.from(p, "Root name '"+actualName+"' does not match expected ('"
-                    +expSimpleName+"') for type "+rootType);
+            ctxt.reportMappingException("Root name '%s' does not match expected ('%s') for type %s",
+                    actualName, expSimpleName, rootType);
         }
         // ok, then move to value itself....
         p.nextToken();
@@ -1663,8 +1704,9 @@
         }
         // and last, verify that we now get matching END_OBJECT
         if (p.nextToken() != JsonToken.END_OBJECT) {
-            throw JsonMappingException.from(p, "Current token not END_OBJECT (to match wrapper object with root name '"
-                    +expSimpleName+"'), but "+p.getCurrentToken());
+            ctxt.reportWrongTokenException(p, JsonToken.END_OBJECT,
+                    "Current token not END_OBJECT (to match wrapper object with root name '%s'), but %s",
+                    expSimpleName, p.getCurrentToken());
         }
         return result;
     }
@@ -1805,7 +1847,7 @@
         // Sanity check: must have actual type...
         JavaType t = _valueType;
         if (t == null) {
-            throw JsonMappingException.from(ctxt, "No value type configured for ObjectReader");
+            ctxt.reportMappingException("No value type configured for ObjectReader");
         }
         
         // First: have we already seen it?
@@ -1816,7 +1858,7 @@
         // Nope: need to ask provider to resolve it
         deser = ctxt.findRootValueDeserializer(t);
         if (deser == null) { // can this happen?
-            throw JsonMappingException.from(ctxt, "Can not find a deserializer for type "+t);
+            ctxt.reportMappingException("Can not find a deserializer for type %s", t);
         }
         _rootDeserializers.put(t, deser);
         return deser;
@@ -1833,8 +1875,8 @@
             // Nope: need to ask provider to resolve it
             deser = ctxt.findRootValueDeserializer(JSON_NODE_TYPE);
             if (deser == null) { // can this happen?
-                throw JsonMappingException.from(ctxt,
-                        "Can not find a deserializer for type "+JSON_NODE_TYPE);
+                ctxt.reportMappingException("Can not find a deserializer for type %s",
+                        JSON_NODE_TYPE);
             }
             _rootDeserializers.put(JSON_NODE_TYPE, deser);
         }
@@ -1868,22 +1910,4 @@
         }
         return deser;
     }
-
-    /**
-     * Convenience method to bind from {@link JsonPointer}.  
-     * {@link JsonPointerBasedFilter} is registered and will be used for parsing later. 
-     * @since 2.6
-     */
-    public ObjectReader at(final String value) {
-        return new ObjectReader(this, new JsonPointerBasedFilter(value));
-    }
-
-    /**
-     * Convenience method to bind from {@link JsonPointer}
-	 * {@link JsonPointerBasedFilter} is registered and will be used for parsing later.
-     * @since 2.6
-     */
-    public ObjectReader at(final JsonPointer pointer) {
-        return new ObjectReader(this, new JsonPointerBasedFilter(pointer));
-    }
 }
diff --git a/src/main/java/com/fasterxml/jackson/databind/ObjectWriter.java b/src/main/java/com/fasterxml/jackson/databind/ObjectWriter.java
index a4b2a52..3a6988b 100644
--- a/src/main/java/com/fasterxml/jackson/databind/ObjectWriter.java
+++ b/src/main/java/com/fasterxml/jackson/databind/ObjectWriter.java
@@ -17,6 +17,7 @@
 import com.fasterxml.jackson.databind.ser.*;
 import com.fasterxml.jackson.databind.ser.impl.TypeWrappedSerializer;
 import com.fasterxml.jackson.databind.type.TypeFactory;
+import com.fasterxml.jackson.databind.util.ClassUtil;
 
 /**
  * Builder object that can be used for per-serialization configuration of
@@ -183,7 +184,7 @@
 
         _serializerProvider = base._serializerProvider;
         _serializerFactory = base._serializerFactory;
-        _generatorFactory = base._generatorFactory;
+        _generatorFactory = f;
 
         _generatorSettings = base._generatorSettings;
         _prefetch = base._prefetch;
@@ -760,6 +761,14 @@
     }
 
     /**
+     * @since 2.8
+     */
+    public SequenceWriter writeValues(DataOutput out) throws IOException {
+        return _newSequenceWriter(false,
+                _generatorFactory.createGenerator(out), true);
+    }
+
+    /**
      * Method for creating a {@link SequenceWriter} to write an array of
      * root-level values, using configuration of this {@link ObjectWriter}.
      * Resulting writer needs to be {@link SequenceWriter#close()}d after all
@@ -838,6 +847,13 @@
                 _generatorFactory.createGenerator(out, JsonEncoding.UTF8), true);
     }
 
+    /**
+     * @since 2.8
+     */
+    public SequenceWriter writeValuesAsArray(DataOutput out) throws IOException {
+        return _newSequenceWriter(true, _generatorFactory.createGenerator(out), true);
+    }
+
     /*
     /**********************************************************
     /* Simple accessors
@@ -852,11 +868,22 @@
         return _config.isEnabled(f);
     }
 
+    /**
+     * @since 2.8.5
+     */
+    @Deprecated
     public boolean isEnabled(JsonParser.Feature f) {
         return _generatorFactory.isEnabled(f);
     }
 
     /**
+     * @since 2.8.5
+     */
+    public boolean isEnabled(JsonGenerator.Feature f) {
+        return _generatorFactory.isEnabled(f);
+    }
+    
+    /**
      * @since 2.2
      */
     public SerializationConfig getConfig() {
@@ -903,8 +930,7 @@
      * Method that can be used to serialize any Java value as
      * JSON output, using provided {@link JsonGenerator}.
      */
-    public void writeValue(JsonGenerator gen, Object value)
-        throws IOException, JsonGenerationException, JsonMappingException
+    public void writeValue(JsonGenerator gen, Object value) throws IOException
     {
         _configureGenerator(gen);
         if (_config.isEnabled(SerializationFeature.CLOSE_CLOSEABLE)
@@ -916,16 +942,11 @@
                 if (_config.isEnabled(SerializationFeature.FLUSH_AFTER_WRITE_VALUE)) {
                     gen.flush();
                 }
-                Closeable tmpToClose = toClose;
-                toClose = null;
-                tmpToClose.close();
-            } finally {
-                if (toClose != null) {
-                    try {
-                        toClose.close();
-                    } catch (IOException ioe) { }
-                }
+            } catch (Exception e) {
+                ClassUtil.closeOnFailAndThrowAsIAE(null, toClose, e);
+                return;
             }
+            toClose.close();
         } else {
             _prefetch.serialize(gen, value, _serializerProvider());
             if (_config.isEnabled(SerializationFeature.FLUSH_AFTER_WRITE_VALUE)) {
@@ -984,6 +1005,15 @@
     }
 
     /**
+     * @since 2.8
+     */
+    public void writeValue(DataOutput out, Object value)
+        throws IOException
+    {
+        _configAndWriteValue(_generatorFactory.createGenerator(out), value);
+    }
+
+    /**
      * Method that can be used to serialize any Java value as
      * a String. Functionally equivalent to calling
      * {@link #writeValue(Writer,Object)} with {@link java.io.StringWriter}
@@ -1124,24 +1154,13 @@
             _writeCloseable(gen, value);
             return;
         }
-        boolean closed = false;
         try {
             _prefetch.serialize(gen, value, _serializerProvider());
-            closed = true;
-            gen.close();
-        } finally {
-            // won't try to close twice; also, must catch exception (so it 
-            // will not mask exception that is pending)
-            if (!closed) {
-                /* 04-Mar-2014, tatu: But! Let's try to prevent auto-closing of
-                 *    structures, which typically causes more damage.
-                 */
-                gen.disable(JsonGenerator.Feature.AUTO_CLOSE_JSON_CONTENT);
-                try {
-                    gen.close();
-                } catch (IOException ioe) { }
-            }
+        } catch (Exception e) {
+            ClassUtil.closeOnFailAndThrowAsIAE(gen, e);
+            return;
         }
+        gen.close();
     }
 
     /**
@@ -1154,31 +1173,14 @@
         Closeable toClose = (Closeable) value;
         try {
             _prefetch.serialize(gen, value, _serializerProvider());
-            JsonGenerator tmpGen = gen;
-            gen = null;
-            tmpGen.close();
             Closeable tmpToClose = toClose;
             toClose = null;
             tmpToClose.close();
-        } finally {
-            /* Need to close both generator and value, as long as they haven't yet
-             * been closed
-             */
-            if (gen != null) {
-                /* 04-Mar-2014, tatu: But! Let's try to prevent auto-closing of
-                 *    structures, which typically causes more damage.
-                 */
-                gen.disable(JsonGenerator.Feature.AUTO_CLOSE_JSON_CONTENT);
-                try {
-                    gen.close();
-                } catch (IOException ioe) { }
-            }
-            if (toClose != null) {
-                try {
-                    toClose.close();
-                } catch (IOException ioe) { }
-            }
+        } catch (Exception e) {
+            ClassUtil.closeOnFailAndThrowAsIAE(gen, toClose, e);
+            return;
         }
+        gen.close();
     }
 
     /**
diff --git a/src/main/java/com/fasterxml/jackson/databind/PropertyMetadata.java b/src/main/java/com/fasterxml/jackson/databind/PropertyMetadata.java
index e92ef9e..52ec5b5 100644
--- a/src/main/java/com/fasterxml/jackson/databind/PropertyMetadata.java
+++ b/src/main/java/com/fasterxml/jackson/databind/PropertyMetadata.java
@@ -72,6 +72,21 @@
         return construct(req, desc, null, null);
     }
 
+    /**
+     * @since 2.8.8
+     */
+    public static PropertyMetadata construct(Boolean req, String desc, Integer index,
+            String defaultValue) {
+        if ((desc != null) || (index != null) || (defaultValue != null)) {
+            return new PropertyMetadata(req, desc, index, defaultValue);
+        }
+        if (req == null) {
+            return STD_REQUIRED_OR_OPTIONAL;
+        }
+        return req ? STD_REQUIRED : STD_OPTIONAL;
+    }
+
+    @Deprecated // since 2.8.8
     public static PropertyMetadata construct(boolean req, String desc, Integer index,
             String defaultValue) {
         if (desc != null || index != null || defaultValue != null) {
@@ -79,7 +94,7 @@
         }
         return req ? STD_REQUIRED : STD_OPTIONAL;
     }
-    
+
     /**
      * Minor optimization: let's canonicalize back to placeholders in cases
      * where there is no real data to consider
diff --git a/src/main/java/com/fasterxml/jackson/databind/PropertyNamingStrategy.java b/src/main/java/com/fasterxml/jackson/databind/PropertyNamingStrategy.java
index fcd02c5..e302426 100644
--- a/src/main/java/com/fasterxml/jackson/databind/PropertyNamingStrategy.java
+++ b/src/main/java/com/fasterxml/jackson/databind/PropertyNamingStrategy.java
@@ -422,7 +422,7 @@
     public static class LowerCaseWithUnderscoresStrategy extends SnakeCaseStrategy {}
 
     /**
-     * @deprecated In 2.7 use {@link SnakeCaseStrategy} instead
+     * @deprecated In 2.7 use {@link UpperCamelCaseStrategy} instead
      */
     @Deprecated
     public static class PascalCaseStrategy extends UpperCamelCaseStrategy {}
diff --git a/src/main/java/com/fasterxml/jackson/databind/SerializationConfig.java b/src/main/java/com/fasterxml/jackson/databind/SerializationConfig.java
index bf0c3f0..f57590f 100644
--- a/src/main/java/com/fasterxml/jackson/databind/SerializationConfig.java
+++ b/src/main/java/com/fasterxml/jackson/databind/SerializationConfig.java
@@ -3,14 +3,12 @@
 import java.text.DateFormat;
 import java.util.*;
 
-import com.fasterxml.jackson.annotation.JsonAutoDetect;
-import com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility;
-import com.fasterxml.jackson.annotation.JsonFormat;
-import com.fasterxml.jackson.annotation.JsonInclude;
-import com.fasterxml.jackson.annotation.PropertyAccessor;
+import com.fasterxml.jackson.annotation.*;
+
 import com.fasterxml.jackson.core.*;
 import com.fasterxml.jackson.core.util.DefaultPrettyPrinter;
 import com.fasterxml.jackson.core.util.Instantiatable;
+
 import com.fasterxml.jackson.databind.cfg.*;
 import com.fasterxml.jackson.databind.introspect.ClassIntrospector;
 import com.fasterxml.jackson.databind.introspect.SimpleMixInResolver;
@@ -46,12 +44,13 @@
     // since 2.7
     // Default is "USE_DEFAULTS, USE_DEFAULTS"
     protected final static JsonInclude.Value DEFAULT_INCLUSION = JsonInclude.Value.empty();
-    
+
     /*
     /**********************************************************
     /* Configured helper objects
     /**********************************************************
      */
+
     /**
      * Object used for resolving filter ids to filter instances.
      * Non-null if explicitly defined; null by default.
@@ -134,9 +133,9 @@
      */
     public SerializationConfig(BaseSettings base,
             SubtypeResolver str, SimpleMixInResolver mixins,
-            RootNameLookup rootNames)
+            RootNameLookup rootNames, ConfigOverrides configOverrides)
     {
-        super(base, str, mixins, rootNames);
+        super(base, str, mixins, rootNames, configOverrides);
         _serFeatures = collectFeatureDefaults(SerializationFeature.class);
         _filterProvider = null;
         _defaultPrettyPrinter = DEFAULT_PRETTY_PRINTER;
@@ -147,6 +146,17 @@
         _serializationInclusion = DEFAULT_INCLUSION;
     }
 
+    /**
+     * @deprecated Since 2.8, remove from 2.9 or later
+     */
+    @Deprecated
+    public SerializationConfig(BaseSettings base,
+            SubtypeResolver str, SimpleMixInResolver mixins,
+            RootNameLookup rootNames)
+    {
+        this(base, str, mixins, rootNames, null);
+    }
+    
     private SerializationConfig(SerializationConfig src, SubtypeResolver str)
     {
         super(src, str);
@@ -290,15 +300,14 @@
     }
 
     /**
-     * Copy-constructor used for making a copy to be used by new {@link ObjectMapper}
-     * or {@link ObjectReader}.
+     * Copy-constructor used for making a copy to be used by new {@link ObjectMapper}.
      *
-     * @since 2.6
+     * @since 2.8
      */
     protected SerializationConfig(SerializationConfig src, SimpleMixInResolver mixins,
-            RootNameLookup rootNames)
+            RootNameLookup rootNames, ConfigOverrides configOverrides)
     {
-        super(src, mixins, rootNames);
+        super(src, mixins, rootNames, configOverrides);
         _serFeatures = src._serFeatures;
         _serializationInclusion = src._serializationInclusion;
         _filterProvider = src._filterProvider;
@@ -857,29 +866,6 @@
         return getClassIntrospector().forDirectClassAnnotations(this, type, this);
     }
 
-    @Override
-    public VisibilityChecker<?> getDefaultVisibilityChecker()
-    {
-        VisibilityChecker<?> vchecker = super.getDefaultVisibilityChecker();
-        // then global overrides (disabling)
-        if (!isEnabled(MapperFeature.AUTO_DETECT_SETTERS)) {
-            vchecker = vchecker.withSetterVisibility(Visibility.NONE);
-        }
-        if (!isEnabled(MapperFeature.AUTO_DETECT_CREATORS)) {
-            vchecker = vchecker.withCreatorVisibility(Visibility.NONE);
-        }
-        if (!isEnabled(MapperFeature.AUTO_DETECT_GETTERS)) {
-            vchecker = vchecker.withGetterVisibility(Visibility.NONE);
-        }
-        if (!isEnabled(MapperFeature.AUTO_DETECT_IS_GETTERS)) {
-            vchecker = vchecker.withIsGetterVisibility(Visibility.NONE);
-        }
-        if (!isEnabled(MapperFeature.AUTO_DETECT_FIELDS)) {
-            vchecker = vchecker.withFieldVisibility(Visibility.NONE);
-        }
-        return vchecker;
-    }
-
     /*
     /**********************************************************
     /* Configuration: default settings with per-type overrides
@@ -903,16 +889,30 @@
 
     @Override
     public JsonInclude.Value getDefaultPropertyInclusion(Class<?> baseType) {
-        // !!! TODO: per-type defaults
+        ConfigOverride overrides = findConfigOverride(baseType);
+        if (overrides != null) {
+            JsonInclude.Value v = overrides.getInclude();
+            if (v != null) {
+                return v;
+            }
+        }
         return _serializationInclusion;
     }
 
     @Override
-    public JsonFormat.Value getDefaultPropertyFormat(Class<?> baseType) {
-        // !!! TODO: per-type defaults
-        return EMPTY_FORMAT;
+    public JsonInclude.Value getDefaultPropertyInclusion(Class<?> baseType,
+            JsonInclude.Value defaultIncl)
+    {
+        ConfigOverride overrides = findConfigOverride(baseType);
+        if (overrides != null) {
+            JsonInclude.Value v = overrides.getInclude();
+            if (v != null) {
+                return v;
+            }
+        }
+        return defaultIncl;
     }
-    
+
     /*
     /**********************************************************
     /* Configuration: other
diff --git a/src/main/java/com/fasterxml/jackson/databind/SerializationFeature.java b/src/main/java/com/fasterxml/jackson/databind/SerializationFeature.java
index fe40906..e8d1cb3 100644
--- a/src/main/java/com/fasterxml/jackson/databind/SerializationFeature.java
+++ b/src/main/java/com/fasterxml/jackson/databind/SerializationFeature.java
@@ -288,8 +288,16 @@
      * Note that this does not change behavior of {@link java.util.Map}s, or
      * "Collection-like" types.
      *<p>
+     * NOTE: unlike other {@link SerializationFeature}s, this feature <b>can not</b> be
+     * dynamically changed on per-call basis, because its effect is considered during
+     * construction of serializers and property handlers.
+     *<p>
      * Feature is enabled by default.
+     *
+     * @deprecated Since 2.8 there are better mechanism for specifying filtering; specifically
+     *   using {@link com.fasterxml.jackson.annotation.JsonInclude} or configuration overrides.
      */
+    @Deprecated // since 2.8
     WRITE_EMPTY_JSON_ARRAYS(true),
 
     /**
diff --git a/src/main/java/com/fasterxml/jackson/databind/SerializerProvider.java b/src/main/java/com/fasterxml/jackson/databind/SerializerProvider.java
index 90df103..bce67fa 100644
--- a/src/main/java/com/fasterxml/jackson/databind/SerializerProvider.java
+++ b/src/main/java/com/fasterxml/jackson/databind/SerializerProvider.java
@@ -7,11 +7,13 @@
 import java.util.TimeZone;
 
 import com.fasterxml.jackson.annotation.JsonFormat;
+import com.fasterxml.jackson.annotation.JsonInclude;
 import com.fasterxml.jackson.annotation.ObjectIdGenerator;
 import com.fasterxml.jackson.core.JsonGenerator;
 import com.fasterxml.jackson.databind.cfg.ContextAttributes;
 import com.fasterxml.jackson.databind.deser.ContextualDeserializer;
 import com.fasterxml.jackson.databind.introspect.Annotated;
+import com.fasterxml.jackson.databind.introspect.BeanPropertyDefinition;
 import com.fasterxml.jackson.databind.jsontype.TypeSerializer;
 import com.fasterxml.jackson.databind.ser.*;
 import com.fasterxml.jackson.databind.ser.impl.FailingSerializer;
@@ -153,7 +155,7 @@
     /* State, for non-blueprint instances: generic
     /**********************************************************
      */
-    
+
     /**
      * For fast lookups, we will have a local non-shared read-only
      * map that contains serializers previously fetched.
@@ -312,7 +314,8 @@
         
     /*
     /**********************************************************
-    /* DatabindContext implementation
+    /* DatabindContext implementation (and closely related
+    /* but ser-specific)
     /**********************************************************
      */
 
@@ -355,7 +358,14 @@
     public final JsonFormat.Value getDefaultPropertyFormat(Class<?> baseType) {
         return _config.getDefaultPropertyFormat(baseType);
     }
-    
+
+    /**
+     * @since 2.8
+     */
+    public final JsonInclude.Value getDefaultPropertyInclusion(Class<?> baseType) {
+        return _config.getDefaultPropertyInclusion();
+    }
+
     /**
      * Method for accessing default Locale to use: convenience method for
      *<pre>
@@ -1071,12 +1081,12 @@
         }
     }
 
-    public final void defaultSerializeNull(JsonGenerator jgen) throws IOException
+    public final void defaultSerializeNull(JsonGenerator gen) throws IOException
     {
         if (_stdNullValueSerializer) { // minor perf optimization
-            jgen.writeNull();
+            gen.writeNull();
         } else {
-            _nullValueSerializer.serialize(null, jgen, this);
+            _nullValueSerializer.serialize(null, gen, this);
         }
     }
 
@@ -1087,13 +1097,95 @@
      */
 
     /**
+     * Factory method for constructing a {@link JsonMappingException};
+     * usually only indirectly used by calling
+     * {@link #reportMappingProblem(String, Object...)}.
+     *
      * @since 2.6
      */
     public JsonMappingException mappingException(String message, Object... args) {
         if (args != null && args.length > 0) {
             message = String.format(message, args);
         }
-        return JsonMappingException.from(this, message);
+        return JsonMappingException.from(getGenerator(), message);
+    }
+
+    /**
+     * Factory method for constructing a {@link JsonMappingException};
+     * usually only indirectly used by calling
+     * {@link #reportMappingProblem(Throwable, String, Object...)}
+     * 
+     * @since 2.8
+     */
+    protected JsonMappingException mappingException(Throwable t, String message, Object... args) {
+        if (args != null && args.length > 0) {
+            message = String.format(message, args);
+        }
+        return JsonMappingException.from(getGenerator(), message, t);
+    }
+
+    /**
+     * Helper method called to indicate problem; default behavior is to construct and
+     * throw a {@link JsonMappingException}, but in future may collect more than one
+     * and only throw after certain number, or at the end of serialization.
+     *
+     * @since 2.8
+     */
+    public void reportMappingProblem(String message, Object... args) throws JsonMappingException {
+        throw mappingException(message, args);
+    }
+
+    /**
+     * Helper method called to indicate problem; default behavior is to construct and
+     * throw a {@link JsonMappingException}, but in future may collect more than one
+     * and only throw after certain number, or at the end of serialization.
+     *
+     * @since 2.8
+     */
+    public void reportMappingProblem(Throwable t, String message, Object... args) throws JsonMappingException {
+        throw mappingException(t, message, args);
+    }
+
+    /**
+     * Helper method called to indicate problem in POJO (serialization) definitions or settings
+     * regarding specific Java type, unrelated to actual JSON content to map.
+     * Default behavior is to construct and throw a {@link JsonMappingException}.
+     *
+     * @since 2.9
+     */
+    public <T> T reportBadTypeDefinition(BeanDescription bean,
+            String message, Object... args) throws JsonMappingException {
+        if (args != null && args.length > 0) {
+            message = String.format(message, args);
+        }
+        String beanDesc = (bean == null) ? "N/A" : _desc(bean.getType().getGenericSignature());
+        throw mappingException("Invalid type definition for type %s: %s",
+                beanDesc, message);
+    }
+
+    /**
+     * Helper method called to indicate problem in POJO (serialization) definitions or settings
+     * regarding specific property (of a type), unrelated to actual JSON content to map.
+     * Default behavior is to construct and throw a {@link JsonMappingException}.
+     *
+     * @since 2.9
+     */
+    public <T> T reportBadPropertyDefinition(BeanDescription bean, BeanPropertyDefinition prop,
+            String message, Object... args) throws JsonMappingException {
+        if (args != null && args.length > 0) {
+            message = String.format(message, args);
+        }
+        String propName = (prop == null)  ? "N/A" : _quotedString(prop.getName());
+        String beanDesc = (bean == null) ? "N/A" : _desc(bean.getType().getGenericSignature());
+        throw mappingException("Invalid definition for property %s (of type %s): %s",
+                propName, beanDesc, message);
+    }
+
+    /**
+     * @since 2.8
+     */
+    public JsonGenerator getGenerator() {
+        return null;
     }
 
     /*
@@ -1112,11 +1204,10 @@
                 return;
             }
         }
-        throw JsonMappingException.from(this,
-                "Incompatible types: declared root type ("+rootType+") vs "
-                +value.getClass().getName());
+        reportMappingProblem("Incompatible types: declared root type (%s) vs %s",
+                rootType, value.getClass().getName());
     }
-    
+
     /**
      * Method that will try to find a serializer, either from cache
      * or by constructing one; but will not return an "unknown" serializer
@@ -1169,7 +1260,8 @@
             /* We better only expose checked exceptions, since those
              * are what caller is expected to handle
              */
-            throw JsonMappingException.from(this, iae.getMessage(), iae);
+            reportMappingProblem(iae, iae.getMessage());
+            return null; // never gets here
         }
 
         if (ser != null) {
@@ -1189,7 +1281,8 @@
             /* We better only expose checked exceptions, since those
              * are what caller is expected to handle
              */
-            throw JsonMappingException.from(this, iae.getMessage(), iae);
+            reportMappingProblem(iae, iae.getMessage());
+            return null; // never gets here
         }
     
         if (ser != null) {
@@ -1247,6 +1340,20 @@
     /**********************************************************
      */
 
+    protected String _desc(Object value) {
+        if (value == null) {
+            return "N/A";
+        }
+        return "'"+value+"'";
+    }
+
+    protected String _quotedString(Object value) {
+        if (value == null) {
+            return "N/A";
+        }
+        return String.valueOf(value);
+    }
+
     protected final DateFormat _dateFormat()
     {
         if (_dateFormat != null) {
diff --git a/src/main/java/com/fasterxml/jackson/databind/annotation/JsonAppend.java b/src/main/java/com/fasterxml/jackson/databind/annotation/JsonAppend.java
index ade257f..445f605 100644
--- a/src/main/java/com/fasterxml/jackson/databind/annotation/JsonAppend.java
+++ b/src/main/java/com/fasterxml/jackson/databind/annotation/JsonAppend.java
@@ -34,14 +34,15 @@
 
     /**
      * Indicator used to determine whether properties defined are to be
-     * appended before (false) or prepended before (true) regular properties.
+     * appended after (false) or prepended before (true) regular properties.
      * Affects all kinds of properties defined using this annotation.
      */
     public boolean prepend() default false;
-    
+
     /**
      * Definition of a single attribute-backed property.
-     * Attribute-backed properties will be appended after regular properties
+     * Attribute-backed properties will be appended after (or prepended before,
+     * as per {@link #prepend}) regular properties
      * in specified order, although their placement may be further changed
      * by the usual property-ordering functionality (alphabetic sorting;
      * explicit ordering)
diff --git a/src/main/java/com/fasterxml/jackson/databind/annotation/JsonDeserialize.java b/src/main/java/com/fasterxml/jackson/databind/annotation/JsonDeserialize.java
index 740b65c..ba6a35f 100644
--- a/src/main/java/com/fasterxml/jackson/databind/annotation/JsonDeserialize.java
+++ b/src/main/java/com/fasterxml/jackson/databind/annotation/JsonDeserialize.java
@@ -25,6 +25,17 @@
  *  )
  *</pre>
  *<p>
+ * Something to note on usage:
+ *<ul>
+ * <li>All other annotations regarding behavior during building should be on <b>Builder</b>
+ *    class and NOT on target POJO class: for example &#64;JsonIgnoreProperties should be on
+ *    Builder to prevent "unknown property" errors.
+ *  </li>
+ * <li>Similarly configuration overrides (see {@link com.fasterxml.jackson.databind.ObjectMapper#configOverride})
+ *    should be targeted at Builder class, not target POJO class.
+ *  </li>
+ * </ul>
+ *
  */
 @Target({ElementType.ANNOTATION_TYPE, ElementType.METHOD, ElementType.FIELD, ElementType.TYPE, ElementType.PARAMETER})
 @Retention(RetentionPolicy.RUNTIME)
diff --git a/src/main/java/com/fasterxml/jackson/databind/annotation/JsonPOJOBuilder.java b/src/main/java/com/fasterxml/jackson/databind/annotation/JsonPOJOBuilder.java
index 9e8d46f..3bab933 100644
--- a/src/main/java/com/fasterxml/jackson/databind/annotation/JsonPOJOBuilder.java
+++ b/src/main/java/com/fasterxml/jackson/databind/annotation/JsonPOJOBuilder.java
@@ -14,8 +14,16 @@
  * Annotation is typically used if the naming convention
  * of a Builder class is different from defaults:
  *<ul>
+ * <li>By default, setters are expected to have names like `withName()` (for property "name");
+ *     override by {@link #withPrefix()} property.
+ *  </li>
  * </ul>
- * 
+ *<p>
+ * In addition to configuration using this annotation, note that many other configuration
+ * annotations are also applied to Builders, for example
+ * {@link com.fasterxml.jackson.annotation.JsonIgnoreProperties} can be used to ignore
+ * "unknown" properties.
+ *
  * @since 2.0
  */
 @Target({ElementType.ANNOTATION_TYPE, ElementType.TYPE})
diff --git a/src/main/java/com/fasterxml/jackson/databind/cfg/BaseSettings.java b/src/main/java/com/fasterxml/jackson/databind/cfg/BaseSettings.java
index 66c24b7..3421e87 100644
--- a/src/main/java/com/fasterxml/jackson/databind/cfg/BaseSettings.java
+++ b/src/main/java/com/fasterxml/jackson/databind/cfg/BaseSettings.java
@@ -121,7 +121,8 @@
     /**
      * Default {@link java.util.TimeZone} used with serialization formats,
      * if (and only if!) explicitly set by use; otherwise `null` to indicate
-     * "use default", which currently (Jackson 2.6) means "GMT"
+     * "use default", which means "UTC" (from Jackson 2.7); earlier versions
+     * (up to 2.6) used "GMT".
      *<p>
      * Note that if a new value is set, timezone is also assigned to
      * {@link #_dateFormat} of this object.
diff --git a/src/main/java/com/fasterxml/jackson/databind/cfg/ConfigOverride.java b/src/main/java/com/fasterxml/jackson/databind/cfg/ConfigOverride.java
new file mode 100644
index 0000000..18e6304
--- /dev/null
+++ b/src/main/java/com/fasterxml/jackson/databind/cfg/ConfigOverride.java
@@ -0,0 +1,57 @@
+package com.fasterxml.jackson.databind.cfg;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+import com.fasterxml.jackson.annotation.JsonInclude;
+
+/**
+ * Configuration object that is accessed by databinding functionality
+ * to find overrides to configuration of properties, based on declared
+ * type of the property. Such overrides have precedence over annotations
+ * attached to actual type ({@link java.lang.Class}), but can be further
+ * overridden by annotations attached to the property itself.
+ *
+ * @since 2.8
+ */
+public abstract class ConfigOverride
+{
+    /**
+     * Definitions of format overrides, if any.
+     */
+    protected JsonFormat.Value _format;
+
+    /**
+     * Definitions of inclusion overrides, if any.
+     */
+    protected JsonInclude.Value _include;
+
+    /**
+     * Definitions of property ignoral (whether to serialize, deserialize
+     * given logical property) overrides, if any.
+     */
+    protected JsonIgnoreProperties.Value _ignorals;
+
+    /**
+     * Flag that indicates whether "is ignorable type" is specified for this type;
+     * and if so, is it to be ignored (true) or not ignored (false); `null` is
+     * used to indicate "not specified", in which case other configuration (class
+     * annotation) is used.
+     */
+    protected Boolean _isIgnoredType;
+    
+    protected ConfigOverride() { }
+    protected ConfigOverride(ConfigOverride src) {
+        _format = src._format;
+        _include = src._include;
+        _ignorals = src._ignorals;
+        _isIgnoredType = src._isIgnoredType;
+    }
+
+    public JsonFormat.Value getFormat() { return _format; }
+    public JsonInclude.Value getInclude() { return _include; }
+    public JsonIgnoreProperties.Value getIgnorals() { return _ignorals; }
+
+    public Boolean getIsIgnoredType() {
+        return _isIgnoredType;
+    }
+}
diff --git a/src/main/java/com/fasterxml/jackson/databind/cfg/ConfigOverrides.java b/src/main/java/com/fasterxml/jackson/databind/cfg/ConfigOverrides.java
new file mode 100644
index 0000000..9fd944e
--- /dev/null
+++ b/src/main/java/com/fasterxml/jackson/databind/cfg/ConfigOverrides.java
@@ -0,0 +1,59 @@
+package com.fasterxml.jackson.databind.cfg;
+
+import java.util.*;
+
+/**
+ * Container for individual {@link ConfigOverride} values.
+ * 
+ * @since 2.8
+ */
+public class ConfigOverrides
+    implements java.io.Serializable
+{
+    private static final long serialVersionUID = 1L;
+
+    protected Map<Class<?>, MutableConfigOverride> _overrides;
+
+    public ConfigOverrides() {
+        _overrides = null;
+    }
+
+    protected ConfigOverrides(Map<Class<?>, MutableConfigOverride> overrides) {
+        _overrides = overrides;
+    }
+
+    public ConfigOverrides copy()
+    {
+        if (_overrides == null) {
+            return new ConfigOverrides();
+        }
+        Map<Class<?>, MutableConfigOverride> newOverrides = _newMap();
+        for (Map.Entry<Class<?>, MutableConfigOverride> entry : _overrides.entrySet()) {
+            newOverrides.put(entry.getKey(), entry.getValue().copy());
+        }
+        return new ConfigOverrides(newOverrides);
+    }
+
+    public ConfigOverride findOverride(Class<?> type) {
+        if (_overrides == null) {
+            return null;
+        }
+        return _overrides.get(type);
+    }
+
+    public MutableConfigOverride findOrCreateOverride(Class<?> type) {
+        if (_overrides == null) {
+            _overrides = _newMap();
+        }
+        MutableConfigOverride override = _overrides.get(type);
+        if (override == null) {
+            override = new MutableConfigOverride();
+            _overrides.put(type, override);
+        }
+        return override;
+    }
+
+    protected Map<Class<?>, MutableConfigOverride> _newMap() {
+        return new HashMap<Class<?>, MutableConfigOverride>();
+    }
+}
diff --git a/src/main/java/com/fasterxml/jackson/databind/cfg/MapperConfig.java b/src/main/java/com/fasterxml/jackson/databind/cfg/MapperConfig.java
index 194db6e..1ae5732 100644
--- a/src/main/java/com/fasterxml/jackson/databind/cfg/MapperConfig.java
+++ b/src/main/java/com/fasterxml/jackson/databind/cfg/MapperConfig.java
@@ -5,14 +5,13 @@
 import java.util.TimeZone;
 
 import com.fasterxml.jackson.annotation.*;
-
 import com.fasterxml.jackson.core.Base64Variant;
 import com.fasterxml.jackson.core.SerializableString;
 import com.fasterxml.jackson.core.io.SerializedString;
 import com.fasterxml.jackson.core.type.TypeReference;
-
 import com.fasterxml.jackson.databind.*;
 import com.fasterxml.jackson.databind.introspect.Annotated;
+import com.fasterxml.jackson.databind.introspect.AnnotatedClass;
 import com.fasterxml.jackson.databind.introspect.ClassIntrospector;
 import com.fasterxml.jackson.databind.introspect.VisibilityChecker;
 import com.fasterxml.jackson.databind.jsontype.SubtypeResolver;
@@ -358,13 +357,27 @@
 
     /**
      * Accessor for default property inclusion to use for serialization,
-     * considering possible per-type override for given base type.
+     * considering possible per-type override for given base type.<br>
+     * NOTE: if no override found, defaults to value returned by
+     * {@link #getDefaultPropertyInclusion()}.
      *
      * @since 2.7
      */
     public abstract JsonInclude.Value getDefaultPropertyInclusion(Class<?> baseType);
 
     /**
+     * Accessor for default property inclusion to use for serialization,
+     * considering possible per-type override for given base type; but
+     * if none found, returning given <code>defaultIncl</code>
+     *
+     * @param defaultIncl Inclusion setting to return if no overrides found.
+     * 
+     * @since 2.8.2
+     */
+    public abstract JsonInclude.Value getDefaultPropertyInclusion(Class<?> baseType,
+            JsonInclude.Value defaultIncl);
+
+    /**
      * Accessor for default format settings to use for serialization (and, to a degree
      * deserialization), considering baseline settings and per-type defaults
      * for given base type (if any).
@@ -372,7 +385,37 @@
      * @since 2.7
      */
     public abstract JsonFormat.Value getDefaultPropertyFormat(Class<?> baseType);
-    
+
+    /**
+     * Accessor for default property ignorals to use, if any, for given base type,
+     * based on config overrides settings (see {@link #findConfigOverride(Class)}).
+     *
+     * @since 2.8
+     */
+    public abstract JsonIgnoreProperties.Value getDefaultPropertyIgnorals(Class<?> baseType);
+
+    /**
+     * Helper method that may be called to see if there are property ignoral
+     * definitions from annotations (via {@link AnnotatedClass}) or through
+     * "config overrides". If both exist, config overrides have precedence
+     * over class annotations.
+     *
+     * @since 2.8
+     */
+    public abstract JsonIgnoreProperties.Value getDefaultPropertyIgnorals(Class<?> baseType,
+            AnnotatedClass actualClass);
+
+    /**
+     * Accessor for finding possible {@link ConfigOverride} to use for
+     * properties of given type. Note that only directly associate override
+     * is found; no type hierarchy traversal is performed.
+     *
+     * @since 2.8
+     * 
+     * @return Override object if there is an override for specified type; `null` if not
+     */
+    public abstract ConfigOverride findConfigOverride(Class<?> type);
+
     /*
     /**********************************************************
     /* Configuration: other
diff --git a/src/main/java/com/fasterxml/jackson/databind/cfg/MapperConfigBase.java b/src/main/java/com/fasterxml/jackson/databind/cfg/MapperConfigBase.java
index 11513ec..6f90f9b 100644
--- a/src/main/java/com/fasterxml/jackson/databind/cfg/MapperConfigBase.java
+++ b/src/main/java/com/fasterxml/jackson/databind/cfg/MapperConfigBase.java
@@ -1,20 +1,15 @@
 package com.fasterxml.jackson.databind.cfg;
 
 import java.text.DateFormat;
-import java.util.Locale;
-import java.util.Map;
-import java.util.TimeZone;
+import java.util.*;
 
-import com.fasterxml.jackson.annotation.JsonAutoDetect;
-import com.fasterxml.jackson.annotation.PropertyAccessor;
+import com.fasterxml.jackson.annotation.*;
+import com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility;
 import com.fasterxml.jackson.core.Base64Variant;
-import com.fasterxml.jackson.databind.AnnotationIntrospector;
-import com.fasterxml.jackson.databind.JavaType;
-import com.fasterxml.jackson.databind.MapperFeature;
-import com.fasterxml.jackson.databind.PropertyName;
-import com.fasterxml.jackson.databind.PropertyNamingStrategy;
+import com.fasterxml.jackson.databind.*;
 import com.fasterxml.jackson.databind.introspect.ClassIntrospector;
 import com.fasterxml.jackson.databind.introspect.ClassIntrospector.MixInResolver;
+import com.fasterxml.jackson.databind.introspect.AnnotatedClass;
 import com.fasterxml.jackson.databind.introspect.SimpleMixInResolver;
 import com.fasterxml.jackson.databind.introspect.VisibilityChecker;
 import com.fasterxml.jackson.databind.jsontype.SubtypeResolver;
@@ -47,6 +42,9 @@
     /**
      * Registered concrete subtypes that can be used instead of (or
      * in addition to) ones declared using annotations.
+     *<p>
+     * Note that instances are stateful and as such may need to be copied,
+     * and may NOT be demoted down to {@link BaseSettings}.
      */
     protected final SubtypeResolver _subtypeResolver;
 
@@ -74,10 +72,23 @@
     protected final ContextAttributes _attributes;
 
     /**
+     * Simple cache used for finding out possible root name for root name
+     * wrapping.
+     *<p>
+     * Note that instances are stateful (for caching) and as such may need to be copied,
+     * and may NOT be demoted down to {@link BaseSettings}.
+     *
      * @since 2.6
      */
     protected final RootNameLookup _rootNames;
-    
+
+    /**
+     * Configuration overrides to apply, keyed by type of property.
+     *
+     * @since 2.8
+     */
+    protected final ConfigOverrides _configOverrides;
+
     /*
     /**********************************************************
     /* Construction
@@ -87,10 +98,12 @@
     /**
      * Constructor used when creating a new instance (compared to
      * that of creating fluent copies)
+     *
+     * @since 2.8
      */
     protected MapperConfigBase(BaseSettings base,
             SubtypeResolver str, SimpleMixInResolver mixins,
-            RootNameLookup rootNames)
+            RootNameLookup rootNames, ConfigOverrides configOverrides)
     {
         super(base, DEFAULT_MAPPER_FEATURES);
         _mixIns = mixins;
@@ -100,8 +113,20 @@
         _view = null;
         // default to "no attributes"
         _attributes = ContextAttributes.getEmpty();
+        _configOverrides = configOverrides;
     }
-    
+
+    /**
+     * @deprecated Since 2.8, remove from 2.9 or later
+     */
+    @Deprecated
+    protected MapperConfigBase(BaseSettings base,
+            SubtypeResolver str, SimpleMixInResolver mixins,
+            RootNameLookup rootNames)
+    {
+        this(base, str, mixins, rootNames, null);
+    }
+
     /**
      * Pass-through constructor used when no changes are needed to the
      * base class.
@@ -115,6 +140,7 @@
         _rootName = src._rootName;
         _view = src._view;
         _attributes = src._attributes;
+        _configOverrides = src._configOverrides;
     }
 
     protected MapperConfigBase(MapperConfigBase<CFG,T> src, BaseSettings base)
@@ -126,6 +152,7 @@
         _rootName = src._rootName;
         _view = src._view;
         _attributes = src._attributes;
+        _configOverrides = src._configOverrides;
     }
     
     protected MapperConfigBase(MapperConfigBase<CFG,T> src, int mapperFeatures)
@@ -137,6 +164,7 @@
         _rootName = src._rootName;
         _view = src._view;
         _attributes = src._attributes;
+        _configOverrides = src._configOverrides;
     }
 
     protected MapperConfigBase(MapperConfigBase<CFG,T> src, SubtypeResolver str) {
@@ -147,6 +175,7 @@
         _rootName = src._rootName;
         _view = src._view;
         _attributes = src._attributes;
+        _configOverrides = src._configOverrides;
     }
 
     protected MapperConfigBase(MapperConfigBase<CFG,T> src, PropertyName rootName) {
@@ -157,6 +186,7 @@
         _rootName = rootName;
         _view = src._view;
         _attributes = src._attributes;
+        _configOverrides = src._configOverrides;
     }
 
     protected MapperConfigBase(MapperConfigBase<CFG,T> src, Class<?> view)
@@ -168,6 +198,7 @@
         _rootName = src._rootName;
         _view = view;
         _attributes = src._attributes;
+        _configOverrides = src._configOverrides;
     }
 
     /**
@@ -182,6 +213,7 @@
         _rootName = src._rootName;
         _view = src._view;
         _attributes = src._attributes;
+        _configOverrides = src._configOverrides;
     }
     
     /**
@@ -196,13 +228,14 @@
         _rootName = src._rootName;
         _view = src._view;
         _attributes = attr;
+        _configOverrides = src._configOverrides;
     }
 
     /**
-     * @since 2.6
+     * @since 2.8
      */
     protected MapperConfigBase(MapperConfigBase<CFG,T> src, SimpleMixInResolver mixins,
-            RootNameLookup rootNames)
+            RootNameLookup rootNames, ConfigOverrides configOverrides)
     {
         super(src);
         _mixIns = mixins;
@@ -211,8 +244,39 @@
         _rootName = src._rootName;
         _view = src._view;
         _attributes = src._attributes;
+        _configOverrides = configOverrides;
     }
-    
+
+    /*
+    /**********************************************************
+    /* Overrides
+    /**********************************************************
+     */
+
+    // note: demoted in 2.8 from sub-classes, as there's no difference
+    @Override
+    public VisibilityChecker<?> getDefaultVisibilityChecker()
+    {
+        VisibilityChecker<?> vchecker = super.getDefaultVisibilityChecker();
+        // then global overrides (disabling)
+        if (!isEnabled(MapperFeature.AUTO_DETECT_SETTERS)) {
+            vchecker = vchecker.withSetterVisibility(Visibility.NONE);
+        }
+        if (!isEnabled(MapperFeature.AUTO_DETECT_CREATORS)) {
+            vchecker = vchecker.withCreatorVisibility(Visibility.NONE);
+        }
+        if (!isEnabled(MapperFeature.AUTO_DETECT_GETTERS)) {
+            vchecker = vchecker.withGetterVisibility(Visibility.NONE);
+        }
+        if (!isEnabled(MapperFeature.AUTO_DETECT_IS_GETTERS)) {
+            vchecker = vchecker.withIsGetterVisibility(Visibility.NONE);
+        }
+        if (!isEnabled(MapperFeature.AUTO_DETECT_FIELDS)) {
+            vchecker = vchecker.withFieldVisibility(Visibility.NONE);
+        }
+        return vchecker;
+    }
+
     /*
     /**********************************************************
     /* Addition fluent factory methods, common to all sub-types
@@ -446,6 +510,54 @@
 
     /*
     /**********************************************************
+    /* Property config override access
+    /**********************************************************
+     */
+    
+    @Override
+    public final ConfigOverride findConfigOverride(Class<?> type) {
+        return _configOverrides.findOverride(type);
+    }
+
+    @Override
+    public final JsonFormat.Value getDefaultPropertyFormat(Class<?> type) {
+        ConfigOverride overrides = _configOverrides.findOverride(type);
+        if (overrides != null) {
+            JsonFormat.Value v = overrides.getFormat();
+            if (v != null) {
+                return v;
+            }
+        }
+        return EMPTY_FORMAT;
+    }
+
+    @Override
+    public final JsonIgnoreProperties.Value getDefaultPropertyIgnorals(Class<?> type) {
+        ConfigOverride overrides = _configOverrides.findOverride(type);
+        if (overrides != null) {
+            JsonIgnoreProperties.Value v = overrides.getIgnorals();
+            if (v != null) {
+                return v;
+            }
+        }
+        // 01-May-2015, tatu: Could return `Value.empty()` but for now `null`
+        //   seems simpler as callers can avoid processing.
+        return null;
+    }
+
+    @Override
+    public final JsonIgnoreProperties.Value getDefaultPropertyIgnorals(Class<?> baseType,
+            AnnotatedClass actualClass)
+    {
+        AnnotationIntrospector intr = getAnnotationIntrospector();
+        JsonIgnoreProperties.Value base = (intr == null) ? null
+                : intr.findPropertyIgnorals(actualClass);
+        JsonIgnoreProperties.Value overrides = getDefaultPropertyIgnorals(baseType);
+        return JsonIgnoreProperties.Value.merge(base, overrides);
+    }
+
+    /*
+    /**********************************************************
     /* Other config access
     /**********************************************************
      */
@@ -465,7 +577,7 @@
         }
         return _rootNames.findRootName(rawRootType, this);
     }
-    
+
     /*
     /**********************************************************
     /* ClassIntrospector.MixInResolver impl:
diff --git a/src/main/java/com/fasterxml/jackson/databind/cfg/MutableConfigOverride.java b/src/main/java/com/fasterxml/jackson/databind/cfg/MutableConfigOverride.java
new file mode 100644
index 0000000..902e18b
--- /dev/null
+++ b/src/main/java/com/fasterxml/jackson/databind/cfg/MutableConfigOverride.java
@@ -0,0 +1,51 @@
+package com.fasterxml.jackson.databind.cfg;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+import com.fasterxml.jackson.annotation.JsonInclude;
+
+/**
+ * Extension of {@link ConfigOverride} that allows changing of
+ * contained configuration settings. Exposed to
+ * {@link com.fasterxml.jackson.databind.Module}s that want to set
+ * overrides, but not exposed to functionality that wants to apply
+ * overrides.
+ *
+ * @since 2.8
+ */
+public class MutableConfigOverride
+    extends ConfigOverride
+    implements java.io.Serializable
+{
+    private static final long serialVersionUID = 1L;
+
+    public MutableConfigOverride() { super(); }
+
+    protected MutableConfigOverride(MutableConfigOverride src) {
+        super(src);
+    }
+    
+    protected MutableConfigOverride copy() {
+        return new MutableConfigOverride(this);
+    }
+
+    public MutableConfigOverride setFormat(JsonFormat.Value v) {
+        _format = v;
+        return this;
+    }
+    
+    public MutableConfigOverride setInclude(JsonInclude.Value v) {
+        _include = v;
+        return this;
+    }
+
+    public MutableConfigOverride setIgnorals(JsonIgnoreProperties.Value v) {
+        _ignorals = v;
+        return this;
+    }
+    
+    public MutableConfigOverride setIsIgnoredType(Boolean v) {
+        _isIgnoredType = v;
+        return this;
+    }
+}
diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/AbstractDeserializer.java b/src/main/java/com/fasterxml/jackson/databind/deser/AbstractDeserializer.java
index 7b13fba..8515376 100644
--- a/src/main/java/com/fasterxml/jackson/databind/deser/AbstractDeserializer.java
+++ b/src/main/java/com/fasterxml/jackson/databind/deser/AbstractDeserializer.java
@@ -3,10 +3,17 @@
 import java.io.IOException;
 import java.util.*;
 
+import com.fasterxml.jackson.annotation.ObjectIdGenerator;
+import com.fasterxml.jackson.annotation.ObjectIdGenerators;
+import com.fasterxml.jackson.annotation.ObjectIdResolver;
+
 import com.fasterxml.jackson.core.*;
+
 import com.fasterxml.jackson.databind.*;
 import com.fasterxml.jackson.databind.deser.impl.ObjectIdReader;
 import com.fasterxml.jackson.databind.deser.impl.ReadableObjectId;
+import com.fasterxml.jackson.databind.introspect.AnnotatedMember;
+import com.fasterxml.jackson.databind.introspect.ObjectIdInfo;
 import com.fasterxml.jackson.databind.jsontype.TypeDeserializer;
 
 /**
@@ -17,7 +24,8 @@
  */
 public class AbstractDeserializer
     extends JsonDeserializer<Object>
-    implements java.io.Serializable
+    implements ContextualDeserializer, // since 2.9
+        java.io.Serializable
 {
     private static final long serialVersionUID = 1L;
 
@@ -33,7 +41,13 @@
     protected final boolean _acceptBoolean;
     protected final boolean _acceptInt;
     protected final boolean _acceptDouble;
-    
+
+    /*
+    /**********************************************************
+    /* Life cycle
+    /**********************************************************
+     */
+
     public AbstractDeserializer(BeanDeserializerBuilder builder,
             BeanDescription beanDesc, Map<String, SettableBeanProperty> backRefProps)
     {
@@ -58,6 +72,22 @@
         _acceptInt = (cls == Integer.TYPE) || cls.isAssignableFrom(Integer.class);
         _acceptDouble = (cls == Double.TYPE) || cls.isAssignableFrom(Double.class);
     }
+
+    /**
+     * @since 2.9
+     */
+    protected AbstractDeserializer(AbstractDeserializer base,
+            ObjectIdReader objectIdReader)
+    {
+        _baseType = base._baseType;
+        _backRefProperties = base._backRefProperties;
+        _acceptString = base._acceptString;
+        _acceptBoolean = base._acceptBoolean;
+        _acceptInt = base._acceptInt;
+        _acceptDouble = base._acceptDouble;
+
+        _objectIdReader = objectIdReader;
+    }
     
     /**
      * Factory method used when constructing instances for non-POJO types, like
@@ -68,7 +98,44 @@
     public static AbstractDeserializer constructForNonPOJO(BeanDescription beanDesc) {
         return new AbstractDeserializer(beanDesc);
     }
-    
+
+    @Override
+    public JsonDeserializer<?> createContextual(DeserializationContext ctxt,
+            BeanProperty property) throws JsonMappingException
+    {
+        // First: may have an override for Object Id:
+        final AnnotationIntrospector intr = ctxt.getAnnotationIntrospector();
+        final AnnotatedMember accessor = (property == null || intr == null)
+                ? null : property.getMember();
+        if (accessor != null && intr != null) {
+            ObjectIdInfo objectIdInfo = intr.findObjectIdInfo(accessor);
+            if (objectIdInfo != null) { // some code duplication here as well (from BeanDeserializerFactory)
+                // 2.1: allow modifications by "id ref" annotations as well:
+                objectIdInfo = intr.findObjectReferenceInfo(accessor, objectIdInfo);
+                
+                Class<?> implClass = objectIdInfo.getGeneratorType();
+                // 02-May-2017, tatu: Alas, properties are NOT available for abstract classes; can not
+                //    support this particular type
+                if (implClass == ObjectIdGenerators.PropertyGenerator.class) {
+                    ctxt.reportMappingException(
+"Invalid Object Id definition for abstract type %s: can not use `PropertyGenerator` on polymorphic types using property annotation",
+handledType().getName());
+                }
+                ObjectIdResolver resolver = ctxt.objectIdResolverInstance(accessor, objectIdInfo);
+                JavaType type = ctxt.constructType(implClass);
+                JavaType idType = ctxt.getTypeFactory().findTypeParameters(type, ObjectIdGenerator.class)[0];
+                SettableBeanProperty idProp = null;
+                ObjectIdGenerator<?> idGen = ctxt.objectIdGeneratorInstance(accessor, objectIdInfo);
+                JsonDeserializer<?> deser = ctxt.findRootValueDeserializer(idType);
+                ObjectIdReader oir = ObjectIdReader.construct(idType, objectIdInfo.getPropertyName(),
+                         idGen, deser, idProp, resolver);
+                return new AbstractDeserializer(this, oir);
+            }
+        }
+        // either way, need to resolve serializer:
+        return this;
+    }
+
     /*
     /**********************************************************
     /* Public accessors
@@ -146,9 +213,8 @@
     public Object deserialize(JsonParser p, DeserializationContext ctxt)
         throws IOException
     {
-        // This method should never be called...
-        throw ctxt.instantiationException(_baseType.getRawClass(),
-                "abstract types either need to be mapped to concrete types, have custom deserializer, or be instantiated with additional type information");
+        return ctxt.handleMissingInstantiator(_baseType.getRawClass(), p,
+                "abstract types either need to be mapped to concrete types, have custom deserializer, or contain additional type information");
     }
 
     /*
diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/BasicDeserializerFactory.java b/src/main/java/com/fasterxml/jackson/databind/deser/BasicDeserializerFactory.java
index 828137f..3dd3c4b 100644
--- a/src/main/java/com/fasterxml/jackson/databind/deser/BasicDeserializerFactory.java
+++ b/src/main/java/com/fasterxml/jackson/databind/deser/BasicDeserializerFactory.java
@@ -6,6 +6,7 @@
 import java.util.concurrent.atomic.AtomicReference;
 
 import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
 import com.fasterxml.jackson.core.JsonLocation;
 import com.fasterxml.jackson.databind.*;
 import com.fasterxml.jackson.databind.cfg.DeserializerFactoryConfig;
@@ -259,13 +260,14 @@
                 instantiator = insts.findValueInstantiator(config, beanDesc, instantiator);
                 // let's do sanity check; easier to spot buggy handlers
                 if (instantiator == null) {
-                    throw JsonMappingException.from(ctxt.getParser(),
-                            "Broken registered ValueInstantiators (of type "+insts.getClass().getName()+"): returned null ValueInstantiator");
+		    ctxt.reportMappingException(
+						"Broken registered ValueInstantiators (of type %s): returned null ValueInstantiator",
+						insts.getClass().getName());
                 }
             }
         }
 
-        // Sanity check: does the chosen instantatior have incomplete creators?
+        // Sanity check: does the chosen ValueInstantiator have incomplete creators?
         if (instantiator.getIncompleteParameter() != null) {
             final AnnotatedParameter nonAnnotatedParam = instantiator.getIncompleteParameter();
             final AnnotatedWithParams ctor = nonAnnotatedParam.getOwner();
@@ -279,7 +281,8 @@
             BeanDescription beanDesc)
         throws JsonMappingException
     {
-        if (beanDesc.getBeanClass() == JsonLocation.class) {
+        Class<?> raw = beanDesc.getBeanClass();
+        if (raw == JsonLocation.class) {
             return new JsonLocationInstantiator();
         }
         return null;
@@ -293,7 +296,7 @@
             BeanDescription beanDesc)
         throws JsonMappingException
     {
-        CreatorCollector creators =  new CreatorCollector(beanDesc, ctxt.getConfig());
+        CreatorCollector creators = new CreatorCollector(beanDesc, ctxt.getConfig());
         AnnotationIntrospector intr = ctxt.getAnnotationIntrospector();
         
         // need to construct suitable visibility checker:
@@ -311,10 +314,8 @@
          */
         Map<AnnotatedWithParams,BeanPropertyDefinition[]> creatorDefs = _findCreatorsFromProperties(ctxt,
                 beanDesc);
-
-        /* Important: first add factory methods; then constructors, so
-         * latter can override former!
-         */
+        // Important: first add factory methods; then constructors, so
+        // latter can override former!
         _addDeserializerFactoryMethods(ctxt, beanDesc, vchecker, intr, creators, creatorDefs);
         // constructors only usable on concrete types:
         if (beanDesc.getType().isConcrete()) {
@@ -409,7 +410,7 @@
         // 25-Jan-2017, tatu: As per [databind#1501], [databind#1502], [databind#1503], best
         //     for now to skip attempts at using anything but no-args constructor (see
         //     `InnerClassProperty` construction for that)
-        final boolean isNonStaticInnerClass = ClassUtil.isNonStaticInnerClass(beanDesc.getBeanClass());
+        final boolean isNonStaticInnerClass = beanDesc.isNonStaticInnerClass();
         if (isNonStaticInnerClass) {
             // TODO: look for `@JsonCreator` annotated ones, throw explicit exception?
             return;
@@ -423,7 +424,7 @@
             final int argCount = ctor.getParameterCount();
 
             // some single-arg factory methods (String, number) are auto-detected
-            if ((argCount == 1) && !isNonStaticInnerClass) {
+            if (argCount == 1) {
                 BeanPropertyDefinition argDef = (propDefs == null) ? null : propDefs[0];
                 boolean useProps = _checkIfCreatorPropertyBased(intr, ctor, argDef);
 
@@ -511,10 +512,13 @@
                 if (impl == null || impl.isEmpty()) {
                     // Let's consider non-static inner class as a special case...
                     int ix = nonAnnotatedParam.getIndex();
-                    if ((ix == 0) && ClassUtil.isNonStaticInnerClass(ctor.getDeclaringClass())) {
+                    // 25-Jan-2017, tatu: Non-static inner classes skipped altogether, now
+                    /*
+                    if ((ix == 0) && isNonStaticInnerClass) {
                         throw new IllegalArgumentException("Non-static inner classes like "
                                 +ctor.getDeclaringClass().getName()+" can not use @JsonCreator for constructors");
                     }
+                    */
                     throw new IllegalArgumentException("Argument #"+ix
                             +" of constructor "+ctor+" has no property name annotation; must have name when multiple-parameter constructor annotated as Creator");
                 }
@@ -841,30 +845,16 @@
                 metadata = PropertyMetadata.STD_REQUIRED_OR_OPTIONAL;
             } else {
                 Boolean b = intr.hasRequiredMarker(param);
-                boolean req = (b != null && b.booleanValue());
                 String desc = intr.findPropertyDescription(param);
                 Integer idx = intr.findPropertyIndex(param);
                 String def = intr.findPropertyDefaultValue(param);
-                metadata = PropertyMetadata.construct(req, desc, idx, def);
+                metadata = PropertyMetadata.construct(b, desc, idx, def);
             }
         }
-        // 15-Oct-2015, tatu: Not 100% if context needed; removing it does not make any
-        //    existing unit tests fail. Still seems like the right thing to do.
-        java.lang.reflect.Type paramType = param.getParameterType();
-        JavaType t0 = beanDesc.resolveType(paramType);
-        BeanProperty.Std property = new BeanProperty.Std(name, t0,
+        JavaType type = resolveMemberAndTypeAnnotations(ctxt, param, param.getType());
+        BeanProperty.Std property = new BeanProperty.Std(name, type,
                 intr.findWrapperName(param),
                 beanDesc.getClassAnnotations(), param, metadata);
-        JavaType type = resolveType(ctxt, beanDesc, t0, param);
-        if (type != t0) {
-            property = property.withType(type);
-        }
-        // Is there an annotation that specifies exact deserializer?
-        JsonDeserializer<?> deser = findDeserializerFromAnnotation(ctxt, param);
-
-        // If yes, we are mostly done:
-        type = modifyTypeByAnnotation(ctxt, param, type);
-
         // Type deserializer: either comes from property (and already resolved)
         TypeDeserializer typeDeser = (TypeDeserializer) type.getTypeHandler();
         // or if not, based on type being referenced:
@@ -876,8 +866,12 @@
         SettableBeanProperty prop = new CreatorProperty(name, type, property.getWrapperName(),
                 typeDeser, beanDesc.getClassAnnotations(), param, index, injectableValueId,
                 metadata);
+        JsonDeserializer<?> deser = findDeserializerFromAnnotation(ctxt, param);
+        if (deser == null) {
+            deser = type.getValueHandler();
+        }
         if (deser != null) {
-            // As per [Issue#462] need to ensure we contextualize deserializer before passing it on
+            // As per [databind#462] need to ensure we contextualize deserializer before passing it on
             deser = ctxt.handlePrimaryContextualization(deser, prop, type);
             prop = prop.withValueDeserializer(deser);
         }
@@ -1118,16 +1112,16 @@
         // First: is there annotation-specified deserializer for values?
         @SuppressWarnings("unchecked")
         JsonDeserializer<Object> contentDeser = (JsonDeserializer<Object>) contentType.getValueHandler();
-        
+
         // Ok: need a key deserializer (null indicates 'default' here)
         KeyDeserializer keyDes = (KeyDeserializer) keyType.getValueHandler();
-        // Then optional type info (1.5); either attached to type, or resolved separately:
+        // Then optional type info; either attached to type, or resolved separately:
         TypeDeserializer contentTypeDeser = contentType.getTypeHandler();
         // but if not, may still be possible to find:
         if (contentTypeDeser == null) {
             contentTypeDeser = findTypeDeserializer(config, contentType);
         }
-        
+
         // 23-Nov-2010, tatu: Custom deserializer?
         JsonDeserializer<?> deser = _findCustomMapDeserializer(type, config, beanDesc,
                 keyDes, contentTypeDeser, contentDeser);
@@ -1164,7 +1158,7 @@
                         // But if so, also need to re-check creators...
                         beanDesc = config.introspectForCreation(type);
                     } else {
-                        // [Issue#292]: Actually, may be fine, but only if polymorphich deser enabled
+                        // [databind#292]: Actually, may be fine, but only if polymorphic deser enabled
                         if (type.getTypeHandler() == null) {
                             throw new IllegalArgumentException("Can not find a deserializer for non-concrete Map type "+type);
                         }
@@ -1173,14 +1167,20 @@
                 }
                 if (deser == null) {
                     ValueInstantiator inst = findValueInstantiator(ctxt, beanDesc);
+                    // 01-May-2016, tatu: Which base type to use here gets tricky, since
+                    //   most often it ought to be `Map` or `EnumMap`, but due to abstract
+                    //   mapping it will more likely be concrete type like `HashMap`.
+                    //   So, for time being, just pass `Map.class`
                     MapDeserializer md = new MapDeserializer(type, inst, keyDes, contentDeser, contentTypeDeser);
-                    AnnotationIntrospector ai = config.getAnnotationIntrospector();
-                    md.setIgnorableProperties(ai.findPropertiesToIgnore(beanDesc.getClassInfo(), false));
+                    JsonIgnoreProperties.Value ignorals = config.getDefaultPropertyIgnorals(Map.class,
+                            beanDesc.getClassInfo());
+                    Set<String> ignored = (ignorals == null) ? null
+                            : ignorals.findIgnoredForDeserialization();
+                    md.setIgnorableProperties(ignored);
                     deser = md;
                 }
             }
         }
-        // and then new with 2.2: ability to post-process it too (Issue#120)
         if (_factoryConfig.hasDeserializerModifiers()) {
             for (BeanDeserializerModifier mod : _factoryConfig.deserializerModifiers()) {
                 deser = mod.modifyMapDeserializer(config, type, beanDesc, deser);
@@ -1247,23 +1247,27 @@
         final Class<?> enumClass = type.getRawClass();
         // 23-Nov-2010, tatu: Custom deserializer?
         JsonDeserializer<?> deser = _findCustomEnumDeserializer(enumClass, config, beanDesc);
+
         if (deser == null) {
+            ValueInstantiator valueInstantiator = _constructDefaultValueInstantiator(ctxt, beanDesc);
+            SettableBeanProperty[] creatorProps = (valueInstantiator == null) ? null
+                    : valueInstantiator.getFromObjectArguments(ctxt.getConfig());
             // May have @JsonCreator for static factory method:
             for (AnnotatedMethod factory : beanDesc.getFactoryMethods()) {
                 if (ctxt.getAnnotationIntrospector().hasCreatorAnnotation(factory)) {
-                    int argCount = factory.getParameterCount();
-                    if (argCount == 1) {
-                        Class<?> returnType = factory.getRawReturnType();
-                        // usually should be class, but may be just plain Enum<?> (for Enum.valueOf()?)
-                        if (returnType.isAssignableFrom(enumClass)) {
-                            deser = EnumDeserializer.deserializerForCreator(config, enumClass, factory);
-                            break;
-                        }
+                    if (factory.getParameterCount() == 0) { // [databind#960]
+                        deser = EnumDeserializer.deserializerForNoArgsCreator(config, enumClass, factory);
+                        break;
                     }
-                    throw new IllegalArgumentException("Unsuitable method ("+factory+") decorated with @JsonCreator (for Enum type "
-                            +enumClass.getName()+")");
+                    Class<?> returnType = factory.getRawReturnType();
+                    // usually should be class, but may be just plain Enum<?> (for Enum.valueOf()?)
+                    if (returnType.isAssignableFrom(enumClass)) {
+                        deser = EnumDeserializer.deserializerForCreator(config, enumClass, factory, valueInstantiator, creatorProps);
+                        break;
+                    }
                 }
             }
+           
             // Need to consider @JsonValue if one found
             if (deser == null) {
                 deser = new EnumDeserializer(constructEnumResolver(enumClass,
@@ -1316,9 +1320,7 @@
         if (deser == null) {
             // Just one referential type as of JDK 1.7 / Java 7: AtomicReference (Java 8 adds Optional)
             if (AtomicReference.class.isAssignableFrom(type.getRawClass())) {
-                // 19-Apr-2016, tatu: By default we'd get something that expect to see an
-                //   AtomicReference... but what we need is something else, so...
-                return new AtomicReferenceDeserializer(contentType, contentTypeDeser, contentDeser);
+                return new AtomicReferenceDeserializer(type, contentTypeDeser, contentDeser);
             }
         }
         if (deser != null) {
@@ -1408,12 +1410,12 @@
         // the only non-standard thing is this:
         if (deser == null) {
             if (type.isEnumType()) {
-                return _createEnumKeyDeserializer(ctxt, type);
+                deser = _createEnumKeyDeserializer(ctxt, type);
+            } else {
+                deser = StdKeyDeserializers.findStringBasedKeyDeserializer(config, type);
             }
-            deser = StdKeyDeserializers.findStringBasedKeyDeserializer(config, type);
         }
-        
-        // and then new with 2.2: ability to post-process it too (Issue#120)
+        // and then post-processing
         if (deser != null) {
             if (_factoryConfig.hasDeserializerModifiers()) {
                 for (BeanDeserializerModifier mod : _factoryConfig.deserializerModifiers()) {
@@ -1472,7 +1474,7 @@
                         +enumClass.getName()+")");
             }
         }
-        // [JACKSON-749] Also, need to consider @JsonValue, if one found
+        // Also, need to consider @JsonValue, if one found
         return StdKeyDeserializers.constructEnumKeyDeserializer(enumRes);
     }
 
@@ -1569,7 +1571,7 @@
             return StringDeserializer.instance;
         }
         if (rawType == CLASS_ITERABLE) {
-            // [Issue#199]: Can and should 'upgrade' to a Collection type:
+            // [databind#199]: Can and should 'upgrade' to a Collection type:
             TypeFactory tf = ctxt.getTypeFactory();
             JavaType[] tps = tf.findTypeParameters(type, CLASS_ITERABLE);
             JavaType elemType = (tps == null || tps.length != 1) ? TypeFactory.unknownType() : tps[0];
@@ -1768,18 +1770,24 @@
     
     /**
      * Helper method called to check if a class or method
-     * has annotation that tells which class to use for deserialization.
+     * has annotation that tells which class to use for deserialization; and if
+     * so, to instantiate, that deserializer to use.
+     * Note that deserializer will NOT yet be contextualized so caller needs to
+     * take care to call contextualization appropriately.
      * Returns null if no such annotation found.
      */
     protected JsonDeserializer<Object> findDeserializerFromAnnotation(DeserializationContext ctxt,
             Annotated ann)
         throws JsonMappingException
     {
-        Object deserDef = ctxt.getAnnotationIntrospector().findDeserializer(ann);
-        if (deserDef == null) {
-            return null;
+        AnnotationIntrospector intr = ctxt.getAnnotationIntrospector();
+        if (intr != null) {
+            Object deserDef = intr.findDeserializer(ann);
+            if (deserDef != null) {
+                return ctxt.deserializerInstance(ann, deserDef);
+            }
         }
-        return ctxt.deserializerInstance(ann, deserDef);
+        return null;
     }
 
     /**
@@ -1788,35 +1796,109 @@
      * Returns null if no such annotation found.
      */
     protected KeyDeserializer findKeyDeserializerFromAnnotation(DeserializationContext ctxt,
-                                                                      Annotated ann)
+            Annotated ann)
             throws JsonMappingException
     {
-        Object deserDef = ctxt.getAnnotationIntrospector().findKeyDeserializer(ann);
-        if (deserDef == null) {
-            return null;
+        AnnotationIntrospector intr = ctxt.getAnnotationIntrospector();
+        if (intr != null) {
+            Object deserDef = intr.findKeyDeserializer(ann);
+            if (deserDef != null) {
+                return ctxt.keyDeserializerInstance(ann, deserDef);
+            }
         }
-        return ctxt.keyDeserializerInstance(ann, deserDef);
+        return null;
     }
 
     /**
+     * Helper method used to resolve additional type-related annotation information
+     * like type overrides, or handler (serializer, deserializer) overrides,
+     * so that from declared field, property or constructor parameter type
+     * is used as the base and modified based on annotations, if any.
+     * 
+     * @since 2.8 Combines functionality of <code>modifyTypeByAnnotation</code>
+     *     and <code>resolveType</code>
+     */
+    protected JavaType resolveMemberAndTypeAnnotations(DeserializationContext ctxt,
+            AnnotatedMember member, JavaType type)
+        throws JsonMappingException
+    {
+        AnnotationIntrospector intr = ctxt.getAnnotationIntrospector();
+        if (intr == null) {
+            return type;
+        }
+
+        // First things first: see if we can find annotations on declared
+        // type
+
+        if (type.isMapLikeType()) {
+            JavaType keyType = type.getKeyType();
+            if (keyType != null) {
+                Object kdDef = intr.findKeyDeserializer(member);
+                KeyDeserializer kd = ctxt.keyDeserializerInstance(member, kdDef);
+                if (kd != null) {
+                    type = ((MapLikeType) type).withKeyValueHandler(kd);
+                    keyType = type.getKeyType(); // just in case it's used below
+                }
+            }
+        }
+
+        if (type.hasContentType()) { // that is, is either container- or reference-type
+            Object cdDef = intr.findContentDeserializer(member);
+            JsonDeserializer<?> cd = ctxt.deserializerInstance(member, cdDef);
+            if (cd != null) {
+                type = type.withContentValueHandler(cd);
+            }
+            TypeDeserializer contentTypeDeser = findPropertyContentTypeDeserializer(
+                    ctxt.getConfig(), type, (AnnotatedMember) member);            	
+            if (contentTypeDeser != null) {
+                type = type.withContentTypeHandler(contentTypeDeser);
+            }
+        }
+        TypeDeserializer valueTypeDeser = findPropertyTypeDeserializer(ctxt.getConfig(),
+                    type, (AnnotatedMember) member);
+        if (valueTypeDeser != null) {
+            type = type.withTypeHandler(valueTypeDeser);
+        }
+
+        // Second part: find actual type-override annotations on member, if any
+
+        // 18-Jun-2016, tatu: Should we re-do checks for annotations on refined
+        //   subtypes as well? Code pre-2.8 did not do this, but if we get bug
+        //   reports may need to consider
+        type = intr.refineDeserializationType(ctxt.getConfig(), member, type);
+        return type;
+    }
+
+    protected EnumResolver constructEnumResolver(Class<?> enumClass,
+            DeserializationConfig config, AnnotatedMethod jsonValueMethod)
+    {
+        if (jsonValueMethod != null) {
+            Method accessor = jsonValueMethod.getAnnotated();
+            if (config.canOverrideAccessModifiers()) {
+                ClassUtil.checkAndFixAccess(accessor, config.isEnabled(MapperFeature.OVERRIDE_PUBLIC_ACCESS_MODIFIERS));
+            }
+            return EnumResolver.constructUnsafeUsingMethod(enumClass, accessor, config.getAnnotationIntrospector());
+        }
+        // 14-Mar-2016, tatu: We used to check `DeserializationFeature.READ_ENUMS_USING_TO_STRING`
+        //   here, but that won't do: it must be dynamically changeable...
+        return EnumResolver.constructUnsafe(enumClass, config.getAnnotationIntrospector());
+    }
+
+    /*
+    /**********************************************************
+    /* Deprecated helper methods
+    /**********************************************************
+     */
+    
+    /**
      * Method called to see if given method has annotations that indicate
      * a more specific type than what the argument specifies.
-     * If annotations are present, they must specify compatible Class;
-     * instance of which can be assigned using the method. This means
-     * that the Class has to be raw class of type, or its sub-class
-     * (or, implementing class if original Class instance is an interface).
      *
-     * @param a Method or field that the type is associated with
-     * @param type Type of field, or the setter argument
-     *
-     * @return Original type if no annotations are present; or a more
-     *   specific type derived from it if type annotation(s) was found
-     *
-     * @throws JsonMappingException if invalid annotation is found
+     * @deprecated Since 2.8; call {@link #resolveMemberAndTypeAnnotations} instead
      */
-    @SuppressWarnings({ "unchecked" })
-    protected <T extends JavaType> T modifyTypeByAnnotation(DeserializationContext ctxt,
-            Annotated a, T type)
+    @Deprecated
+    protected JavaType modifyTypeByAnnotation(DeserializationContext ctxt,
+            Annotated a, JavaType type)
         throws JsonMappingException
     {
         AnnotationIntrospector intr = ctxt.getAnnotationIntrospector();
@@ -1825,6 +1907,7 @@
         }
 
         // First, deserializers for key/value types?
+        /*
         if (type.isMapLikeType()) {
             JavaType keyType = type.getKeyType();
             // 21-Mar-2011, tatu: ... and associated deserializer too (unless already assigned)
@@ -1850,90 +1933,26 @@
                 }
             }
         }
+        */
         // then: type refinement(s)?
-        type = (T) intr.refineDeserializationType(ctxt.getConfig(), a, type);
-        return type;
+        return intr.refineDeserializationType(ctxt.getConfig(), a, type);
     }
 
     /**
-     * Helper method used to resolve method return types and field
-     * types. The main trick here is that the containing bean may
-     * have type variable binding information (when deserializing
-     * using generic type passed as type reference), which is
-     * needed in some cases.
+     * @deprecated since 2.8 call {@link #resolveMemberAndTypeAnnotations} instead.
      */
+    @Deprecated // since 2.8
     protected JavaType resolveType(DeserializationContext ctxt,
             BeanDescription beanDesc, JavaType type, AnnotatedMember member)
         throws JsonMappingException
     {
-        AnnotationIntrospector intr = ctxt.getAnnotationIntrospector();
-        if (intr == null) {
-            return type;
-        }
-        
-        // Also need to handle keyUsing, contentUsing
-
-        if (type.isMapLikeType()) {
-            JavaType keyType = type.getKeyType();
-            if (keyType != null) {
-                Object kdDef = intr.findKeyDeserializer(member);
-                KeyDeserializer kd = ctxt.keyDeserializerInstance(member, kdDef);
-                if (kd != null) {
-                    type = ((MapLikeType) type).withKeyValueHandler(kd);
-                    keyType = type.getKeyType(); // just in case it's used below
-                }
-            }
-        }
-
-        if (type.isContainerType() || type.isReferenceType()) {
-            Object cdDef = intr.findContentDeserializer(member);
-            JsonDeserializer<?> cd = ctxt.deserializerInstance(member, cdDef);
-            if (cd != null) {
-                type = type.withContentValueHandler(cd);
-            }
-            /* 04-Feb-2010, tatu: Need to figure out JAXB annotations that indicate type
-             *    information to use for polymorphic members; and specifically types for
-             *    collection values (contents).
-             *    ... but only applies to members (fields, methods), not classes
-             */
-            if (member instanceof AnnotatedMember) {
-            	TypeDeserializer contentTypeDeser = findPropertyContentTypeDeserializer(
-            	        ctxt.getConfig(), type, (AnnotatedMember) member);            	
-            	if (contentTypeDeser != null) {
-            	    type = type.withContentTypeHandler(contentTypeDeser);
-            	}
-            }
-        }
-        TypeDeserializer valueTypeDeser;
-
-        if (member instanceof AnnotatedMember) { // JAXB allows per-property annotations
-            valueTypeDeser = findPropertyTypeDeserializer(ctxt.getConfig(),
-                    type, (AnnotatedMember) member);
-        } else { // classes just have Jackson annotations
-            // probably only occurs if 'property' is null anyway
-            valueTypeDeser = findTypeDeserializer(ctxt.getConfig(), type);
-        }
-        if (valueTypeDeser != null) {
-            type = type.withTypeHandler(valueTypeDeser);
-        }
-        return type;
-    }
-    
-    protected EnumResolver constructEnumResolver(Class<?> enumClass,
-            DeserializationConfig config, AnnotatedMethod jsonValueMethod)
-    {
-        if (jsonValueMethod != null) {
-            Method accessor = jsonValueMethod.getAnnotated();
-            if (config.canOverrideAccessModifiers()) {
-                ClassUtil.checkAndFixAccess(accessor, config.isEnabled(MapperFeature.OVERRIDE_PUBLIC_ACCESS_MODIFIERS));
-            }
-            return EnumResolver.constructUnsafeUsingMethod(enumClass, accessor);
-        }
-        // 14-Mar-2016, tatu: We used to check `DeserializationFeature.READ_ENUMS_USING_TO_STRING`
-        //   here, but that won't do: it must be dynamically changeable...
-        return EnumResolver.constructUnsafe(enumClass, config.getAnnotationIntrospector());
+        return resolveMemberAndTypeAnnotations(ctxt, member, type);
     }
 
+    /**
+     * @deprecated since 2.8 call <code>findJsonValueMethod</code> on {@link BeanDescription} instead
+     */
+    @Deprecated // not used, possibly remove as early as 2.9
     protected AnnotatedMethod _findJsonValueFor(DeserializationConfig config, JavaType enumType)
     {
         if (enumType == null) {
diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/BeanDeserializer.java b/src/main/java/com/fasterxml/jackson/databind/deser/BeanDeserializer.java
index d0ebaba..76603d5 100644
--- a/src/main/java/com/fasterxml/jackson/databind/deser/BeanDeserializer.java
+++ b/src/main/java/com/fasterxml/jackson/databind/deser/BeanDeserializer.java
@@ -6,6 +6,7 @@
 import com.fasterxml.jackson.core.*;
 import com.fasterxml.jackson.databind.*;
 import com.fasterxml.jackson.databind.deser.impl.*;
+import com.fasterxml.jackson.databind.deser.impl.ReadableObjectId.Referring;
 import com.fasterxml.jackson.databind.util.NameTransformer;
 import com.fasterxml.jackson.databind.util.TokenBuffer;
 
@@ -30,6 +31,14 @@
 
     private static final long serialVersionUID = 1L;
 
+    /**
+     * Lazily constructed exception used as root cause if reporting problem
+     * with creator method that returns <code>null</code> (which is not allowed)
+     *
+     * @since 3.8
+     */
+    protected transient Exception _nullFromCreator;
+    
     /*
     /**********************************************************
     /* Life-cycle, construction, initialization
@@ -68,10 +77,14 @@
         super(src, oir);
     }
 
-    public BeanDeserializer(BeanDeserializerBase src, HashSet<String> ignorableProps) {
+    public BeanDeserializer(BeanDeserializerBase src, Set<String> ignorableProps) {
         super(src, ignorableProps);
     }
 
+    public BeanDeserializer(BeanDeserializerBase src, BeanPropertyMap props) {
+        super(src, props);
+    }
+
     @Override
     public JsonDeserializer<Object> unwrappingDeserializer(NameTransformer unwrapper)
     {
@@ -94,16 +107,21 @@
     }
 
     @Override
-    public BeanDeserializer withIgnorableProperties(HashSet<String> ignorableProps) {
+    public BeanDeserializer withIgnorableProperties(Set<String> ignorableProps) {
         return new BeanDeserializer(this, ignorableProps);
     }
 
     @Override
+    public BeanDeserializerBase withBeanProperties(BeanPropertyMap props) {
+        return new BeanDeserializer(this, props);
+    }
+
+    @Override
     protected BeanDeserializerBase asArrayDeserializer() {
         SettableBeanProperty[] props = _beanProperties.getPropertiesInInsertionOrder();
         return new BeanAsArrayDeserializer(this, props);
     }
-    
+
     /*
     /**********************************************************
     /* JsonDeserializer implementation
@@ -112,9 +130,6 @@
 
     /**
      * Main deserialization method for bean-based objects (POJOs).
-     *<p>
-     * NOTE: was declared 'final' in 2.2; should NOT be to let extensions
-     * like Afterburner change definition.
      */
     @Override
     public Object deserialize(JsonParser p, DeserializationContext ctxt) throws IOException
@@ -168,9 +183,10 @@
             return deserializeFromObject(p, ctxt);
         default:
         }
-        throw ctxt.mappingException(handledType());
+        return ctxt.handleUnexpectedToken(handledType(), p);
     }
 
+    @Deprecated // since 2.8; remove unless getting used
     protected Object _missingToken(JsonParser p, DeserializationContext ctxt) throws IOException {
         throw ctxt.endOfInputException(handledType());
     }
@@ -366,10 +382,10 @@
         final PropertyBasedCreator creator = _propertyBasedCreator;
         PropertyValueBuffer buffer = creator.startBuilding(p, ctxt, _objectIdReader);
 
-        // 04-Jan-2010, tatu: May need to collect unknown properties for polymorphic cases
         TokenBuffer unknown = null;
 
         JsonToken t = p.getCurrentToken();
+        List<BeanReferring> referrings = null;
         for (; t == JsonToken.FIELD_NAME; t = p.nextToken()) {
             String propName = p.getCurrentName();
             p.nextToken(); // to point to value
@@ -388,11 +404,11 @@
                     try {
                         bean = creator.build(ctxt, buffer);
                     } catch (Exception e) {
-                        wrapInstantiationProblem(e, ctxt);
-                        bean = null; // never gets here
+                        bean = wrapInstantiationProblem(e, ctxt);
                     }
                     if (bean == null) {
-                        throw ctxt.instantiationException(_beanType.getRawClass(), "JSON Creator returned null");
+                        return ctxt.handleInstantiationProblem(handledType(), null,
+                                _creatorReturnedNullException());
                     }
                     // [databind#631]: Assign current value, to be accessible by custom serializers
                     p.setCurrentValue(bean);
@@ -412,11 +428,22 @@
             // regular property? needs buffering
             SettableBeanProperty prop = _beanProperties.find(propName);
             if (prop != null) {
-                buffer.bufferProperty(prop, _deserializeWithErrorWrapping(p, ctxt, prop));
+                try {
+                    buffer.bufferProperty(prop, _deserializeWithErrorWrapping(p, ctxt, prop));
+                } catch (UnresolvedForwardReference reference) {
+                    // 14-Jun-2016, tatu: As per [databind#1261], looks like we need additional
+                    //    handling of forward references here. Not exactly sure why existing
+                    //    facilities did not cover, but this does appear to solve the problem
+                    BeanReferring referring = handleUnresolvedReference(ctxt,
+                            prop, buffer, reference);
+                    if (referrings == null) {
+                        referrings = new ArrayList<BeanReferring>();
+                    }
+                    referrings.add(referring);
+                }
                 continue;
             }
-            // As per [JACKSON-313], things marked as ignorable should not be
-            // passed to any setter
+            // Things marked as ignorable should not be passed to any setter
             if (_ignorableProps != null && _ignorableProps.contains(propName)) {
                 handleIgnoredProperty(p, ctxt, handledType(), propName);
                 continue;
@@ -446,6 +473,11 @@
             wrapInstantiationProblem(e, ctxt);
             bean = null; // never gets here
         }
+        if (referrings != null) {
+            for (BeanReferring referring : referrings) {
+               referring.setBean(bean);
+            }
+        }
         if (unknown != null) {
             // polymorphic?
             if (bean.getClass() != _beanType.getRawClass()) {
@@ -457,6 +489,20 @@
         return bean;
     }
 
+    /**
+     * @since 2.8
+     */
+    private BeanReferring handleUnresolvedReference(DeserializationContext ctxt,
+            SettableBeanProperty prop, PropertyValueBuffer buffer,
+            UnresolvedForwardReference reference)
+        throws JsonMappingException
+    {
+        BeanReferring referring = new BeanReferring(ctxt, reference,
+                prop.getType(), buffer, prop);
+        reference.getRoid().appendReferring(referring);
+        return referring;
+    }
+
     protected final Object _deserializeWithErrorWrapping(JsonParser p,
             DeserializationContext ctxt, SettableBeanProperty prop)
         throws IOException
@@ -496,9 +542,9 @@
             p2.close();
             return ob;
         }
-        throw ctxt.mappingException(handledType());
+        return ctxt.handleUnexpectedToken(handledType(), p);
     }
-    
+
     /*
     /**********************************************************
     /* Deserializing when we have to consider an active View
@@ -586,13 +632,24 @@
                 handleIgnoredProperty(p, ctxt, bean, propName);
                 continue;
             }
-            // but... others should be passed to unwrapped property deserializers
-            tokens.writeFieldName(propName);
-            tokens.copyCurrentStructure(p);
+            // 29-Nov-2016, tatu: probably should try to avoid sending content
+            //    both to any setter AND buffer... but, for now, the only thing
+            //    we can do.
             // how about any setter? We'll get copies but...
-            if (_anySetter != null) {
+            if (_anySetter == null) {
+                // but... others should be passed to unwrapped property deserializers
+                tokens.writeFieldName(propName);
+                tokens.copyCurrentStructure(p);
+            } else {
+                // Need to copy to a separate buffer first
+                TokenBuffer b2 = new TokenBuffer(p, ctxt);
+                b2.copyCurrentStructure(p);
+                tokens.writeFieldName(propName);
+                tokens.append(b2);
                 try {
-                    _anySetter.deserializeAndSet(p, ctxt, bean, propName);
+                    JsonParser p2 = b2.asParser(p);
+                    p2.nextToken();
+                    _anySetter.deserializeAndSet(p2, ctxt, bean, propName);
                 } catch (Exception e) {
                     wrapAndThrow(e, bean, propName, ctxt);
                 }
@@ -635,12 +692,28 @@
                 handleIgnoredProperty(p, ctxt, bean, propName);
                 continue;
             }
-            // but... others should be passed to unwrapped property deserializers
-            tokens.writeFieldName(propName);
-            tokens.copyCurrentStructure(p);
+            // 29-Nov-2016, tatu: probably should try to avoid sending content
+            //    both to any setter AND buffer... but, for now, the only thing
+            //    we can do.
             // how about any setter? We'll get copies but...
-            if (_anySetter != null) {
-                _anySetter.deserializeAndSet(p, ctxt, bean, propName);
+            if (_anySetter == null) {
+                // but... others should be passed to unwrapped property deserializers
+                tokens.writeFieldName(propName);
+                tokens.copyCurrentStructure(p);
+            } else {
+                // Need to copy to a separate buffer first
+                TokenBuffer b2 = new TokenBuffer(p, ctxt);
+                b2.copyCurrentStructure(p);
+                tokens.writeFieldName(propName);
+                tokens.append(b2);
+                try {
+                    JsonParser p2 = b2.asParser(p);
+                    p2.nextToken();
+                    _anySetter.deserializeAndSet(p2, ctxt, bean, propName);
+                } catch (Exception e) {
+                    wrapAndThrow(e, bean, propName, ctxt);
+                }
+                continue;
             }
         }
         tokens.writeEndObject();
@@ -672,8 +745,7 @@
                     try {
                         bean = creator.build(ctxt, buffer);
                     } catch (Exception e) {
-                        wrapInstantiationProblem(e, ctxt);
-                        continue; // never gets here
+                        bean = wrapInstantiationProblem(e, ctxt);
                     }
                     // [databind#631]: Assign current value, to be accessible by custom serializers
                     p.setCurrentValue(bean);
@@ -688,7 +760,8 @@
                         // !!! 08-Jul-2011, tatu: Could probably support; but for now
                         //   it's too complicated, so bail out
                         tokens.close();
-                        throw ctxt.mappingException("Can not create polymorphic instances with unwrapped values");
+                        ctxt.reportMappingException("Can not create polymorphic instances with unwrapped values");
+                        return null;
                     }
                     return _unwrappedPropertyHandler.processUnwrapped(p, ctxt, bean, tokens);
                 }
@@ -709,15 +782,29 @@
                 handleIgnoredProperty(p, ctxt, handledType(), propName);
                 continue;
             }
-            tokens.writeFieldName(propName);
-            tokens.copyCurrentStructure(p);
-            // "any property"?
-            if (_anySetter != null) {
+            // 29-Nov-2016, tatu: probably should try to avoid sending content
+            //    both to any setter AND buffer... but, for now, the only thing
+            //    we can do.
+            // how about any setter? We'll get copies but...
+            if (_anySetter == null) {
+                // but... others should be passed to unwrapped property deserializers
+                tokens.writeFieldName(propName);
+                tokens.copyCurrentStructure(p);
+            } else {
+                // Need to copy to a separate buffer first
+                TokenBuffer b2 = new TokenBuffer(p, ctxt);
+                b2.copyCurrentStructure(p);
+                tokens.writeFieldName(propName);
+                tokens.append(b2);
                 try {
-                    buffer.bufferAnyProperty(_anySetter, propName, _anySetter.deserialize(p, ctxt));
+                    JsonParser p2 = b2.asParser(p);
+                    p2.nextToken();
+                    buffer.bufferAnyProperty(_anySetter, propName,
+                            _anySetter.deserialize(p2, ctxt));
                 } catch (Exception e) {
                     wrapAndThrow(e, _beanType.getRawClass(), propName, ctxt);
                 }
+                continue;
             }
         }
 
@@ -853,7 +940,8 @@
                         if (bean.getClass() != _beanType.getRawClass()) {
                             // !!! 08-Jul-2011, tatu: Could theoretically support; but for now
                             //   it's too complicated, so bail out
-                            throw ctxt.mappingException("Can not create polymorphic instances with unwrapped values");
+                            ctxt.reportMappingException("Can not create polymorphic instances with external type ids");
+                            return null;
                         }
                         return ext.complete(p, ctxt, bean);
                     }
@@ -889,8 +977,53 @@
         try {
             return ext.complete(p, ctxt, buffer, creator);
         } catch (Exception e) {
-            wrapInstantiationProblem(e, ctxt);
-            return null; // never gets here
+            return wrapInstantiationProblem(e, ctxt);
+        }
+    }
+
+    /**
+     * Helper method for getting a lazily construct exception to be reported
+     * to {@link DeserializationContext#handleInstantiationProblem(Class, Object, Throwable)}.
+     *
+     * @since 2.8
+     */
+    protected Exception _creatorReturnedNullException() {
+        if (_nullFromCreator == null) {
+            _nullFromCreator = new NullPointerException("JSON Creator returned null");
+        }
+        return _nullFromCreator;
+    }
+
+    /**
+     * @since 2.8
+     */
+    static class BeanReferring extends Referring
+    {
+        private final DeserializationContext _context;
+        private final SettableBeanProperty _prop;
+        private Object _bean;
+
+        BeanReferring(DeserializationContext ctxt, UnresolvedForwardReference ref,
+                JavaType valueType, PropertyValueBuffer buffer, SettableBeanProperty prop)
+        {
+            super(ref, valueType);
+            _context = ctxt;
+            _prop = prop;
+        }
+
+        public void setBean(Object bean) {
+            _bean = bean;
+        }
+
+        @Override
+        public void handleResolvedForwardReference(Object id, Object value) throws IOException
+        {
+            if (_bean == null) {
+                _context.reportMappingException(
+"Can not resolve ObjectId forward reference using property '%s' (of type %s): Bean not yet resolved",
+_prop.getName(), _prop.getDeclaringClass().getName());
+        }
+            _prop.set(_bean, value);
         }
     }
 }
diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/BeanDeserializerBase.java b/src/main/java/com/fasterxml/jackson/databind/deser/BeanDeserializerBase.java
index d3ad9b4..63eafbb 100644
--- a/src/main/java/com/fasterxml/jackson/databind/deser/BeanDeserializerBase.java
+++ b/src/main/java/com/fasterxml/jackson/databind/deser/BeanDeserializerBase.java
@@ -5,13 +5,11 @@
 import java.lang.reflect.InvocationTargetException;
 import java.util.*;
 
-import com.fasterxml.jackson.annotation.JsonFormat;
-import com.fasterxml.jackson.annotation.JsonTypeInfo;
-import com.fasterxml.jackson.annotation.ObjectIdGenerator;
-import com.fasterxml.jackson.annotation.ObjectIdGenerators;
-import com.fasterxml.jackson.annotation.ObjectIdResolver;
+import com.fasterxml.jackson.annotation.*;
+
 import com.fasterxml.jackson.core.*;
 import com.fasterxml.jackson.core.JsonParser.NumberType;
+
 import com.fasterxml.jackson.databind.*;
 import com.fasterxml.jackson.databind.deser.impl.*;
 import com.fasterxml.jackson.databind.deser.std.StdDelegatingDeserializer;
@@ -139,7 +137,7 @@
      * track of recognized but ignorable properties: these will
      * be skipped without errors or warnings.
      */
-    final protected HashSet<String> _ignorableProps;
+    final protected Set<String> _ignorableProps;
 
     /**
      * Flag that can be set to ignore and skip unknown properties.
@@ -206,7 +204,7 @@
     protected BeanDeserializerBase(BeanDeserializerBuilder builder,
             BeanDescription beanDesc,
             BeanPropertyMap properties, Map<String, SettableBeanProperty> backRefs,
-            HashSet<String> ignorableProps, boolean ignoreAllUnknown,
+            Set<String> ignorableProps, boolean ignoreAllUnknown,
             boolean hasViews)
     {
         super(beanDesc.getType());
@@ -355,10 +353,9 @@
         }
     }
 
-    public BeanDeserializerBase(BeanDeserializerBase src, HashSet<String> ignorableProps)
+    public BeanDeserializerBase(BeanDeserializerBase src, Set<String> ignorableProps)
     {
         super(src._beanType);
-        
         _classAnnotations = src._classAnnotations;
         _beanType = src._beanType;
         
@@ -379,7 +376,40 @@
 
         _vanillaProcessing = src._vanillaProcessing;
         _objectIdReader = src._objectIdReader;
-        _beanProperties = src._beanProperties;
+
+        // 01-May-2016, tatu: [databind#1217]: Remove properties from mapping,
+        //    to avoid them being deserialized
+        _beanProperties = src._beanProperties.withoutProperties(ignorableProps);
+    }
+
+    /**
+     * @since 2.8
+     */
+    protected BeanDeserializerBase(BeanDeserializerBase src, BeanPropertyMap beanProps)
+    {
+        super(src._beanType);
+        
+        _classAnnotations = src._classAnnotations;
+        _beanType = src._beanType;
+        
+        _valueInstantiator = src._valueInstantiator;
+        _delegateDeserializer = src._delegateDeserializer;
+        _propertyBasedCreator = src._propertyBasedCreator;
+        
+        _beanProperties = beanProps;
+        _backRefs = src._backRefs;
+        _ignorableProps = src._ignorableProps;
+        _ignoreAllUnknown = src._ignoreAllUnknown;
+        _anySetter = src._anySetter;
+        _injectables = src._injectables;
+        _objectIdReader = src._objectIdReader;
+        
+        _nonStandardCreation = src._nonStandardCreation;
+        _unwrappedPropertyHandler = src._unwrappedPropertyHandler;
+        _needViewProcesing = src._needViewProcesing;
+        _serializationShape = src._serializationShape;
+
+        _vanillaProcessing = src._vanillaProcessing;
     }
     
     @Override
@@ -387,9 +417,20 @@
 
     public abstract BeanDeserializerBase withObjectIdReader(ObjectIdReader oir);
 
-    public abstract BeanDeserializerBase withIgnorableProperties(HashSet<String> ignorableProps);
+    public abstract BeanDeserializerBase withIgnorableProperties(Set<String> ignorableProps);
 
     /**
+     * Mutant factory method that custom sub-classes must override; not left as
+     * abstract to prevent more drastic backwards compatibility problems.
+     *
+     * @since 2.8
+     */
+    public BeanDeserializerBase withBeanProperties(BeanPropertyMap props) {
+        throw new UnsupportedOperationException("Class "+getClass().getName()
+                +" does not override `withBeanProperties()`, needs to");
+    }
+    
+    /**
      * Fluent factory for creating a variant that can handle
      * POJO output as a JSON Array. Implementations may ignore this request
      * if no such input is possible.
@@ -416,53 +457,42 @@
         ExternalTypeHandler.Builder extTypes = null;
         // if ValueInstantiator can use "creator" approach, need to resolve it here...
         SettableBeanProperty[] creatorProps;
+
         if (_valueInstantiator.canCreateFromObjectWith()) {
             creatorProps = _valueInstantiator.getFromObjectArguments(ctxt.getConfig());
-            // also: need to try to resolve 'external' type ids...
-            for (SettableBeanProperty prop : creatorProps) {
-                if (prop.hasValueTypeDeserializer()) {
-                    TypeDeserializer typeDeser = prop.getValueTypeDeserializer();
-                    if (typeDeser.getTypeInclusion() == JsonTypeInfo.As.EXTERNAL_PROPERTY) {
-                        if (extTypes == null) {
-                            extTypes = new ExternalTypeHandler.Builder();
-                        }
-                        extTypes.addExternal(prop, typeDeser);
-                    }
-                }
-            }
         } else {
             creatorProps = null;
         }
-
         UnwrappedPropertyHandler unwrapped = null;
 
-        for (SettableBeanProperty origProp : _beanProperties) {
-            SettableBeanProperty prop = origProp;
+        // 24-Mar-2017, tatu: Looks like we may have to iterate over
+        //   properties twice, to handle potential issues with recursive
+        //   types (see [databind#1575] f.ex).
 
-            // May already have deserializer from annotations, if so, skip:
+        // First loop: find deserializer if not yet known, but do not yet
+        // contextualize (since that can lead to problems with self-references)
+        for (SettableBeanProperty prop : _beanProperties) {
             if (!prop.hasValueDeserializer()) {
                 // [databind#125]: allow use of converters
                 JsonDeserializer<?> deser = findConvertingDeserializer(ctxt, prop);
                 if (deser == null) {
-                    deser = findDeserializer(ctxt, prop.getType(), prop);
+                    deser = ctxt.findNonContextualValueDeserializer(prop.getType());
                 }
-                prop = prop.withValueDeserializer(deser);
-            } else { // may need contextual version
-                JsonDeserializer<Object> deser = prop.getValueDeserializer();
-                /* Important! This is the only place where actually handle "primary"
-                 * property deserializers -- call is different from other places.
-                 */
-                JsonDeserializer<?> cd = ctxt.handlePrimaryContextualization(deser, prop,
-                        prop.getType());
-                if (cd != deser) {
-                    prop = prop.withValueDeserializer(cd);
-                }
+                SettableBeanProperty newProp = prop.withValueDeserializer(deser);
+                _replaceProperty(_beanProperties, creatorProps, prop, newProp);
             }
+        }
 
+        // Second loop: contextualize, find other pieces
+        for (SettableBeanProperty origProp : _beanProperties) {
+            SettableBeanProperty prop = origProp;
+            JsonDeserializer<?> deser = prop.getValueDeserializer();
+            deser = ctxt.handlePrimaryContextualization(deser, prop, prop.getType());
+            prop = prop.withValueDeserializer(deser);
             // Need to link managed references with matching back references
             prop = _resolveManagedReferenceProperty(ctxt, prop);
 
-            // [databind#351[: need to wrap properties that require object id resolution.
+            // [databind#351]: need to wrap properties that require object id resolution.
             if (!(prop instanceof ManagedReferenceProperty)) {
                 prop = _resolvedObjectIdProperty(ctxt, prop);
             }
@@ -474,36 +504,18 @@
                     unwrapped = new UnwrappedPropertyHandler();
                 }
                 unwrapped.addProperty(prop);
-                /* 12-Dec-2014, tatu: As per [databind#647], we will have problems if
-                 *    the original property is left in place. So let's remove it now.
-                 */
+                // 12-Dec-2014, tatu: As per [databind#647], we will have problems if
+                //    the original property is left in place. So let's remove it now.
+                // 25-Mar-2017, tatu: Wonder if this could be problematic wrt creators?
                 _beanProperties.remove(prop);
                 continue;
             }
             // non-static inner classes too:
             prop = _resolveInnerClassValuedProperty(ctxt, prop);
             if (prop != origProp) {
-                _beanProperties.replace(prop);
-                // [databind#795]: Make sure PropertyBasedCreator's properties stay in sync
-                if (creatorProps != null) {
-                    // 18-May-2015, tatu: _Should_ start with consistent set. But can we really
-                    //   fully count on this? May need to revisit in future; seems to hold for now.
-                    for (int i = 0, len = creatorProps.length; i < len; ++i) {
-                        if (creatorProps[i] == origProp) {
-                            creatorProps[i] = prop;
-                            break;
-                        }
-                        // ... as per above, it is possible we'd need to add this as fallback
-                        // if (but only if) identity check fails?
-                        /*
-                        if (creatorProps[i].getName().equals(prop.getName())) {
-                            creatorProps[i] = prop;
-                            break;
-                        }
-                        */
-                    }
-                }
+                _replaceProperty(_beanProperties, creatorProps, origProp, prop);
             }
+
             // one more thing: if this property uses "external property" type inclusion,
             // it needs different handling altogether
             if (prop.hasValueTypeDeserializer()) {
@@ -519,13 +531,11 @@
                 }
             }
         }
-
         // "any setter" may also need to be resolved now
         if (_anySetter != null && !_anySetter.hasValueDeserializer()) {
             _anySetter = _anySetter.withValueDeserializer(findDeserializer(ctxt,
                     _anySetter.getType(), _anySetter.getProperty()));
         }
-
         // as well as delegate-based constructor:
         if (_valueInstantiator.canCreateUsingDelegate()) {
             JavaType delegateType = _valueInstantiator.getDelegateType(ctxt.getConfig());
@@ -556,7 +566,9 @@
         }
 
         if (extTypes != null) {
-            _externalTypeIdHandler = extTypes.build();
+            // 21-Jun-2016, tatu: related to [databind#999], may need to link type ids too,
+            //    so need to pass collected properties
+            _externalTypeIdHandler = extTypes.build(_beanProperties);
             // we consider this non-standard, to offline handling
             _nonStandardCreation = true;
         }
@@ -565,11 +577,38 @@
         if (unwrapped != null) { // we consider this non-standard, to offline handling
             _nonStandardCreation = true;
         }
-
         // may need to disable vanilla processing, if unwrapped handling was enabled...
         _vanillaProcessing = _vanillaProcessing && !_nonStandardCreation;
     }
 
+    /**
+     * @since 2.8.8
+     */
+    protected void _replaceProperty(BeanPropertyMap props, SettableBeanProperty[] creatorProps,
+            SettableBeanProperty origProp, SettableBeanProperty newProp)
+    {
+        props.replace(newProp);
+        // [databind#795]: Make sure PropertyBasedCreator's properties stay in sync
+        if (creatorProps != null) {
+            // 18-May-2015, tatu: _Should_ start with consistent set. But can we really
+            //   fully count on this? May need to revisit in future; seems to hold for now.
+            for (int i = 0, len = creatorProps.length; i < len; ++i) {
+                if (creatorProps[i] == origProp) {
+                    creatorProps[i] = newProp;
+                    return;
+                }
+            }
+            // ... as per above, it is possible we'd need to add this as fallback
+            // if (but only if) identity check fails?
+            /*
+            if (creatorProps[i].getName().equals(prop.getName())) {
+                creatorProps[i] = prop;
+                break;
+            }
+            */
+        }
+    }
+
     private JsonDeserializer<Object> _findDelegateDeserializer(DeserializationContext ctxt, JavaType delegateType,
             AnnotatedWithParams delegateCreator) throws JsonMappingException {
         // Need to create a temporary property to allow contextual deserializers:
@@ -594,6 +633,9 @@
      * Helper method that can be used to see if specified property is annotated
      * to indicate use of a converter for property value (in case of container types,
      * it is container type itself, not key or content type).
+     *<p>
+     * NOTE: returned deserializer is NOT yet contextualized, caller needs to take
+     * care to do that.
      * 
      * @since 2.2
      */
@@ -607,8 +649,10 @@
             if (convDef != null) {
                 Converter<Object,Object> conv = ctxt.converterInstance(prop.getMember(), convDef);
                 JavaType delegateType = conv.getInputType(ctxt.getTypeFactory());
-                JsonDeserializer<?> ser = ctxt.findContextualValueDeserializer(delegateType, prop);
-                return new StdDelegatingDeserializer<Object>(conv, delegateType, ser);
+                // 25-Mar-2017, tatu: should not yet contextualize
+//                JsonDeserializer<?> deser = ctxt.findContextualValueDeserializer(delegateType, prop);
+                JsonDeserializer<?> deser = ctxt.findNonContextualValueDeserializer(delegateType);
+                return new StdDelegatingDeserializer<Object>(conv, delegateType, deser);
             }
         }
         return null;
@@ -626,7 +670,7 @@
             BeanProperty property) throws JsonMappingException
     {
         ObjectIdReader oir = _objectIdReader;
-        
+
         // First: may have an override for Object Id:
         final AnnotationIntrospector intr = ctxt.getAnnotationIntrospector();
         final AnnotatedMember accessor = (property == null || intr == null)
@@ -670,22 +714,39 @@
         }
         // And possibly add more properties to ignore
         if (accessor != null) {
-            String[] ignorals = intr.findPropertiesToIgnore(accessor, false);
-            if (ignorals != null && ignorals.length != 0) {
-                HashSet<String> newIgnored = ArrayBuilders.setAndArray(contextual._ignorableProps, ignorals);
-                contextual = contextual.withIgnorableProperties(newIgnored);
+            JsonIgnoreProperties.Value ignorals = intr.findPropertyIgnorals(accessor);
+            if (ignorals != null) {
+                Set<String> ignored = ignorals.findIgnoredForDeserialization();
+                if (!ignored.isEmpty()) {
+                    Set<String> prev = contextual._ignorableProps;
+                    if ((prev != null) && !prev.isEmpty()) {
+                        ignored = new HashSet<String>(ignored);
+                        ignored.addAll(prev);
+                    }
+                    contextual = contextual.withIgnorableProperties(ignored);
+                }
             }
         }
 
         // One more thing: are we asked to serialize POJO as array?
+        JsonFormat.Value format = findFormatOverrides(ctxt, property, handledType());
         JsonFormat.Shape shape = null;
-        if (accessor != null) {
-            JsonFormat.Value format = intr.findFormat((Annotated) accessor);
-
-            if (format != null) {
+        if (format != null) {
+            if (format.hasShape()) {
                 shape = format.getShape();
             }
+            // 16-May-2016, tatu: How about per-property case-insensitivity?
+            Boolean B = format.getFeature(JsonFormat.Feature.ACCEPT_CASE_INSENSITIVE_PROPERTIES);
+            if (B != null) {
+                // !!! TODO
+                BeanPropertyMap propsOrig = _beanProperties;
+                BeanPropertyMap props = propsOrig.withCaseInsensitivity(B.booleanValue());
+                if (props != propsOrig) {
+                    contextual = contextual.withBeanProperties(props);
+                }
+            }
         }
+
         if (shape == null) {
             shape = _serializationShape;
         }
@@ -730,11 +791,11 @@
      * in case where object id resolution is required.
      */
     protected SettableBeanProperty _resolvedObjectIdProperty(DeserializationContext ctxt,
-            SettableBeanProperty prop)
+            SettableBeanProperty prop) throws JsonMappingException
     {
         ObjectIdInfo objectIdInfo = prop.getObjectIdInfo();
         JsonDeserializer<Object> valueDeser = prop.getValueDeserializer();
-        ObjectIdReader objectIdReader = valueDeser.getObjectIdReader();
+        ObjectIdReader objectIdReader = (valueDeser == null) ? null : valueDeser.getObjectIdReader();
         if (objectIdInfo == null && objectIdReader == null) {
             return prop;
         }
@@ -1077,7 +1138,9 @@
         } else {
             // should we worry about UUIDs? They should be fine, right?
             // 07-Aug-2014, tatu: Maybe, but not necessarily; had issues with
-            //   Smile format; [Smile#19], possibly related.
+            //   Smile format; [dataformat-smile#19], possibly related.
+            // 01-Sep-2016, tatu: For non-JSON, might want to consider `writeEmbeddedObject`
+            //   but that won't work for default impl (JSON and most dataformats)
             buf.writeObject(rawId);
         }
         JsonParser bufParser = buf.asParser();
@@ -1119,20 +1182,29 @@
     protected Object deserializeFromObjectUsingNonDefault(JsonParser p,
             DeserializationContext ctxt) throws IOException
     {
-        if (_delegateDeserializer != null) {
+        final JsonDeserializer<Object> delegateDeser = _delegateDeserializer();
+        if (delegateDeser != null) {
             return _valueInstantiator.createUsingDelegate(ctxt,
-                    _delegateDeserializer.deserialize(p, ctxt));
+                    delegateDeser.deserialize(p, ctxt));
         }
         if (_propertyBasedCreator != null) {
             return _deserializeUsingPropertyBased(p, ctxt);
         }
         // should only occur for abstract types...
         if (_beanType.isAbstract()) {
-            throw JsonMappingException.from(p, "Can not instantiate abstract type "+_beanType
-                    +" (need to add/enable type information?)");
+            return ctxt.handleMissingInstantiator(handledType(), p,
+                    "abstract type (need to add/enable type information?)");
         }
-        throw JsonMappingException.from(p, "No suitable constructor found for type "
-                +_beanType+": can not instantiate from JSON object (missing default constructor or creator, or perhaps need to add/enable type information?)");
+        // 25-Jan-2017, tatu: We do not actually support use of Creators for non-static
+        //   inner classes -- with one and only one exception; that of default constructor!
+        //   -- so let's indicate it
+        Class<?> raw = _beanType.getRawClass();
+        if (ClassUtil.isNonStaticInnerClass(raw)) {
+            return ctxt.handleMissingInstantiator(raw, p,
+"can only instantiate non-static inner class by using default, no-argument constructor");
+        }
+        return ctxt.handleMissingInstantiator(raw, p,
+"no suitable constructor found, can not deserialize from Object value (missing default constructor or creator, or perhaps need to add/enable type information?)");
     }
 
     protected abstract Object _deserializeUsingPropertyBased(final JsonParser p,
@@ -1140,18 +1212,20 @@
         throws IOException, JsonProcessingException;
 
     @SuppressWarnings("incomplete-switch")
-    public Object deserializeFromNumber(JsonParser p, DeserializationContext ctxt) throws IOException
+    public Object deserializeFromNumber(JsonParser p, DeserializationContext ctxt)
+        throws IOException
     {
         // First things first: id Object Id is used, most likely that's it
         if (_objectIdReader != null) {
             return deserializeFromObjectId(p, ctxt);
         }
-
+        final JsonDeserializer<Object> delegateDeser = _delegateDeserializer();
         switch (p.getNumberType()) {
         case INT:
-            if (_delegateDeserializer != null) {
+            if (delegateDeser != null) {
                 if (!_valueInstantiator.canCreateFromInt()) {
-                    Object bean = _valueInstantiator.createUsingDelegate(ctxt, _delegateDeserializer.deserialize(p, ctxt));
+                    Object bean = _valueInstantiator.createUsingDelegate(ctxt,
+                            delegateDeser.deserialize(p, ctxt));
                     if (_injectables != null) {
                         injectValues(ctxt, bean);
                     }
@@ -1160,9 +1234,10 @@
             }
             return _valueInstantiator.createFromInt(ctxt, p.getIntValue());
         case LONG:
-            if (_delegateDeserializer != null) {
+            if (delegateDeser != null) {
                 if (!_valueInstantiator.canCreateFromInt()) {
-                    Object bean = _valueInstantiator.createUsingDelegate(ctxt, _delegateDeserializer.deserialize(p, ctxt));
+                    Object bean = _valueInstantiator.createUsingDelegate(ctxt,
+                            delegateDeser.deserialize(p, ctxt));
                     if (_injectables != null) {
                         injectValues(ctxt, bean);
                     }
@@ -1172,14 +1247,17 @@
             return _valueInstantiator.createFromLong(ctxt, p.getLongValue());
         }
         // actually, could also be BigInteger, so:
-        if (_delegateDeserializer != null) {
-            Object bean = _valueInstantiator.createUsingDelegate(ctxt, _delegateDeserializer.deserialize(p, ctxt));
+        if (delegateDeser != null) {
+            Object bean = _valueInstantiator.createUsingDelegate(ctxt,
+                    delegateDeser.deserialize(p, ctxt));
             if (_injectables != null) {
                 injectValues(ctxt, bean);
             }
             return bean;
         }
-        throw ctxt.instantiationException(handledType(), "no suitable creator method found to deserialize from JSON integer number");
+        return ctxt.handleMissingInstantiator(handledType(), p,
+                "no suitable creator method found to deserialize from Number value (%s)",
+                p.getNumberValue());
     }
 
     public Object deserializeFromString(JsonParser p, DeserializationContext ctxt) throws IOException
@@ -1188,13 +1266,13 @@
         if (_objectIdReader != null) {
             return deserializeFromObjectId(p, ctxt);
         }
-        
-        /* Bit complicated if we have delegating creator; may need to use it,
-         * or might not...
-         */
-        if (_delegateDeserializer != null) {
+        // Bit complicated if we have delegating creator; may need to use it,
+        // or might not...
+        JsonDeserializer<Object> delegateDeser = _delegateDeserializer();
+        if (delegateDeser != null) {
             if (!_valueInstantiator.canCreateFromString()) {
-                Object bean = _valueInstantiator.createUsingDelegate(ctxt, _delegateDeserializer.deserialize(p, ctxt));
+                Object bean = _valueInstantiator.createUsingDelegate(ctxt,
+                        delegateDeser.deserialize(p, ctxt));
                 if (_injectables != null) {
                     injectValues(ctxt, bean);
                 }
@@ -1213,9 +1291,11 @@
         NumberType t = p.getNumberType();
         // no separate methods for taking float...
         if ((t == NumberType.DOUBLE) || (t == NumberType.FLOAT)) {
-            if (_delegateDeserializer != null) {
+            JsonDeserializer<Object> delegateDeser = _delegateDeserializer();
+            if (delegateDeser != null) {
                 if (!_valueInstantiator.canCreateFromDouble()) {
-                    Object bean = _valueInstantiator.createUsingDelegate(ctxt, _delegateDeserializer.deserialize(p, ctxt));
+                    Object bean = _valueInstantiator.createUsingDelegate(ctxt,
+                            delegateDeser.deserialize(p, ctxt));
                     if (_injectables != null) {
                         injectValues(ctxt, bean);
                     }
@@ -1225,10 +1305,14 @@
             return _valueInstantiator.createFromDouble(ctxt, p.getDoubleValue());
         }
         // actually, could also be BigDecimal, so:
-        if (_delegateDeserializer != null) {
-            return _valueInstantiator.createUsingDelegate(ctxt, _delegateDeserializer.deserialize(p, ctxt));
+        JsonDeserializer<Object> delegateDeser = _delegateDeserializer();
+        if (delegateDeser != null) {
+            return _valueInstantiator.createUsingDelegate(ctxt,
+                    delegateDeser.deserialize(p, ctxt));
         }
-        throw ctxt.instantiationException(handledType(), "no suitable creator method found to deserialize from JSON floating-point number");
+        return ctxt.handleMissingInstantiator(handledType(), p,
+                "no suitable creator method found to deserialize from Number value (%s)",
+                p.getNumberValue());
     }
 
     /**
@@ -1236,9 +1320,11 @@
      */
     public Object deserializeFromBoolean(JsonParser p, DeserializationContext ctxt) throws IOException
     {
-        if (_delegateDeserializer != null) {
+        JsonDeserializer<Object> delegateDeser = _delegateDeserializer();
+        if (delegateDeser != null) {
             if (!_valueInstantiator.canCreateFromBoolean()) {
-                Object bean = _valueInstantiator.createUsingDelegate(ctxt, _delegateDeserializer.deserialize(p, ctxt));
+                Object bean = _valueInstantiator.createUsingDelegate(ctxt,
+                        delegateDeser.deserialize(p, ctxt));
                 if (_injectables != null) {
                     injectValues(ctxt, bean);
                 }
@@ -1251,28 +1337,16 @@
 
     public Object deserializeFromArray(JsonParser p, DeserializationContext ctxt) throws IOException
     {
-        if (_arrayDelegateDeserializer != null) {
-            try {
-                Object bean = _valueInstantiator.createUsingArrayDelegate(ctxt, _arrayDelegateDeserializer.deserialize(p, ctxt));
-                if (_injectables != null) {
-                    injectValues(ctxt, bean);
-                }
-                return bean;
-            } catch (Exception e) {
-                wrapInstantiationProblem(e, ctxt);
-            }
-        }
+        // note: can not call `_delegateDeserializer()` since order reversed here:
+        JsonDeserializer<Object> delegateDeser = _arrayDelegateDeserializer;
         // fallback to non-array delegate
-        if (_delegateDeserializer != null) {
-            try {
-                Object bean = _valueInstantiator.createUsingArrayDelegate(ctxt, _delegateDeserializer.deserialize(p, ctxt));
-                if (_injectables != null) {
-                    injectValues(ctxt, bean);
-                }
-                return bean;
-            } catch (Exception e) {
-                wrapInstantiationProblem(e, ctxt);
+        if ((delegateDeser != null) || ((delegateDeser = _delegateDeserializer) != null)) {
+            Object bean = _valueInstantiator.createUsingArrayDelegate(ctxt,
+                    delegateDeser.deserialize(p, ctxt));
+            if (_injectables != null) {
+                injectValues(ctxt, bean);
             }
+            return bean;
         }
         if (ctxt.isEnabled(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS)) {
             JsonToken t = p.nextToken();
@@ -1281,8 +1355,7 @@
             }
             final Object value = deserialize(p, ctxt);
             if (p.nextToken() != JsonToken.END_ARRAY) {
-                throw ctxt.wrongTokenException(p, JsonToken.END_ARRAY, 
-                        "Attempted to unwrap single value array for single '" + _valueClass.getName() + "' value but there was more than a single value in the array");
+                handleMissingEndArrayForSingle(p, ctxt);
             }
             return value;
         }
@@ -1291,9 +1364,10 @@
             if (t == JsonToken.END_ARRAY) {
                 return null;
             }
-            throw ctxt.mappingException(handledType(), JsonToken.START_ARRAY);
+            return ctxt.handleUnexpectedToken(handledType(),
+                    JsonToken.START_ARRAY, p, null);
         }
-        throw ctxt.mappingException(handledType());
+        return ctxt.handleUnexpectedToken(handledType(), p);
     }
 
     public Object deserializeFromEmbedded(JsonParser p, DeserializationContext ctxt)
@@ -1304,12 +1378,35 @@
         if (_objectIdReader != null) {
             return deserializeFromObjectId(p, ctxt);
         }
+        // 26-Jul-2017, tatu: as per [databind#1711] need to support delegating case too
+        JsonDeserializer<Object> delegateDeser = _delegateDeserializer();
+        if (delegateDeser != null) {
+            if (!_valueInstantiator.canCreateFromString()) {
+                Object bean = _valueInstantiator.createUsingDelegate(ctxt,
+                        delegateDeser.deserialize(p, ctxt));
+                if (_injectables != null) {
+                    injectValues(ctxt, bean);
+                }
+                return bean;
+            }
+        }
 
         // TODO: maybe add support for ValueInstantiator, embedded?
         
         return p.getEmbeddedObject();
     }
 
+    /**
+     * @since 2.9
+     */
+    private final JsonDeserializer<Object> _delegateDeserializer() {
+        JsonDeserializer<Object> deser = _delegateDeserializer;
+        if (deser == null) {
+            deser = _arrayDelegateDeserializer;
+        }
+        return deser;
+    }
+
     /*
     /**********************************************************
     /* Overridable helper methods
@@ -1548,7 +1645,7 @@
         return t;
     }
 
-    protected void wrapInstantiationProblem(Throwable t, DeserializationContext ctxt)
+    protected Object wrapInstantiationProblem(Throwable t, DeserializationContext ctxt)
         throws IOException
     {
         while (t instanceof InvocationTargetException && t.getCause() != null) {
@@ -1567,6 +1664,6 @@
                 throw (RuntimeException) t;
             }
         }
-        throw ctxt.instantiationException(_beanType.getRawClass(), t);
+        return ctxt.handleInstantiationProblem(_beanType.getRawClass(), null, t);
     }
 }
diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/BeanDeserializerBuilder.java b/src/main/java/com/fasterxml/jackson/databind/deser/BeanDeserializerBuilder.java
index 6975148..5ca54d5 100644
--- a/src/main/java/com/fasterxml/jackson/databind/deser/BeanDeserializerBuilder.java
+++ b/src/main/java/com/fasterxml/jackson/databind/deser/BeanDeserializerBuilder.java
@@ -20,16 +20,23 @@
 {
     /*
     /**********************************************************
+    /* Configuration
+    /**********************************************************
+     */
+
+    final protected DeserializationConfig _config;
+
+    /*
+    /**********************************************************
     /* General information about POJO
     /**********************************************************
      */
 
+    /**
+     * Introspected information about POJO for deserializer to handle
+     */
     final protected BeanDescription _beanDesc;
 
-    final protected boolean _defaultViewInclusion;
-    
-    final protected boolean _caseInsensitivePropertyComparison;
-    
     /*
     /**********************************************************
     /* Accumulated information about properties
@@ -63,6 +70,10 @@
      */
     protected ValueInstantiator _valueInstantiator;
 
+    /**
+     * Handler for Object Id values, if Object Ids are enabled for the
+     * bean type.
+     */
     protected ObjectIdReader _objectIdReader;
     
     /**
@@ -88,7 +99,7 @@
      * In addition, Builder may have additional configuration
      */
     protected JsonPOJOBuilder.Value _builderConfig;
-    
+
     /*
     /**********************************************************
     /* Life-cycle: construction
@@ -99,8 +110,7 @@
             DeserializationConfig config)
     { 
         _beanDesc = beanDesc;
-        _defaultViewInclusion = config.isEnabled(MapperFeature.DEFAULT_VIEW_INCLUSION);
-        _caseInsensitivePropertyComparison = config.isEnabled(MapperFeature.ACCEPT_CASE_INSENSITIVE_PROPERTIES);
+        _config = config;
     }
 
     /**
@@ -110,8 +120,7 @@
     protected BeanDeserializerBuilder(BeanDeserializerBuilder src)
     {
         _beanDesc = src._beanDesc;
-        _defaultViewInclusion = src._defaultViewInclusion;
-        _caseInsensitivePropertyComparison = src._caseInsensitivePropertyComparison;
+        _config = src._config;
 
         // let's make copy of properties
         _properties.putAll(src._properties);
@@ -174,6 +183,10 @@
         if (_backRefProperties == null) {
             _backRefProperties = new HashMap<String, SettableBeanProperty>(4);
         }
+        // 15-Sep-2016, tatu: For some reason fixing access at point of `build()` does
+        //    NOT work (2 failing unit tests). Not 100% clear why, but for now force
+        //    access set early; unfortunate, but since it works....
+        prop.fixAccess(_config);
         _backRefProperties.put(referenceName, prop);
         // also: if we had property with same name, actually remove it
         if (_properties != null) {
@@ -190,10 +203,15 @@
         if (_injectables == null) {
             _injectables = new ArrayList<ValueInjector>();
         }
+        boolean fixAccess = _config.canOverrideAccessModifiers();
+        boolean forceAccess = fixAccess && _config.isEnabled(MapperFeature.OVERRIDE_PUBLIC_ACCESS_MODIFIERS);
+        if (fixAccess) {
+            member.fixAccess(forceAccess);
+        }
         _injectables.add(new ValueInjector(propName, propType,
                 contextAnnotations, member, valueId));
     }
-    
+
     /**
      * Method that will add property name as one of properties that can
      * be ignored if not recognized.
@@ -299,7 +317,7 @@
     public JsonPOJOBuilder.Value getBuilderConfig() {
         return _builderConfig;
     }
-    
+
     /*
     /**********************************************************
     /* Build method(s)
@@ -309,21 +327,20 @@
     /**
      * Method for constructing a {@link BeanDeserializer}, given all
      * information collected.
-     *<p>
-     * NOTE: Signature of this method did unfortunately change between Jackson 2.1
-     * and Jackson 2.2
      */
     public JsonDeserializer<?> build()
     {
         Collection<SettableBeanProperty> props = _properties.values();
-        BeanPropertyMap propertyMap = BeanPropertyMap.construct(props, _caseInsensitivePropertyComparison);
+        _fixAccess(props);
+
+        BeanPropertyMap propertyMap = BeanPropertyMap.construct(props,
+                _config.isEnabled(MapperFeature.ACCEPT_CASE_INSENSITIVE_PROPERTIES));
         propertyMap.assignIndexes();
 
         // view processing must be enabled if:
         // (a) fields are not included by default (when deserializing with view), OR
         // (b) one of properties has view(s) to included in defined
-        boolean anyViews = !_defaultViewInclusion;
-
+        boolean anyViews = !_config.isEnabled(MapperFeature.DEFAULT_VIEW_INCLUSION);
         if (!anyViews) {
             for (SettableBeanProperty prop : props) {
                 if (prop.hasViews()) {
@@ -342,7 +359,7 @@
             ObjectIdValueProperty prop = new ObjectIdValueProperty(_objectIdReader, PropertyMetadata.STD_REQUIRED);
             propertyMap = propertyMap.withProperty(prop);
         }
-        
+
         return new BeanDeserializer(this,
                 _beanDesc, propertyMap, _backRefProperties, _ignorableProps, _ignoreAllUnknown,
                 anyViews);
@@ -370,8 +387,10 @@
         if (_buildMethod == null) {
             // as per [databind#777], allow empty name
             if (!expBuildMethodName.isEmpty()) {
-                throw new IllegalArgumentException("Builder class "+_beanDesc.getBeanClass().getName()
-                    +" does not have build method (name: '"+expBuildMethodName+"')");
+                throw new IllegalArgumentException(String.format(
+                        "Builder class %s does not have build method (name: '%s')",
+                        _beanDesc.getBeanClass().getName(),
+                        expBuildMethodName));
             }
         } else {
             // also: type of the method must be compatible
@@ -387,10 +406,12 @@
         }
         // And if so, we can try building the deserializer
         Collection<SettableBeanProperty> props = _properties.values();
-        BeanPropertyMap propertyMap = BeanPropertyMap.construct(props, _caseInsensitivePropertyComparison);
+        _fixAccess(props);
+        BeanPropertyMap propertyMap = BeanPropertyMap.construct(props,
+                _config.isEnabled(MapperFeature.ACCEPT_CASE_INSENSITIVE_PROPERTIES));
         propertyMap.assignIndexes();
 
-        boolean anyViews = !_defaultViewInclusion;
+        boolean anyViews = !_config.isEnabled(MapperFeature.DEFAULT_VIEW_INCLUSION);
 
         if (!anyViews) {
             for (SettableBeanProperty prop : props) {
@@ -415,4 +436,50 @@
                 _beanDesc, propertyMap, _backRefProperties, _ignorableProps, _ignoreAllUnknown,
                 anyViews);
     }
+
+    /*
+    /**********************************************************
+    /* Internal helper method(s)
+    /**********************************************************
+     */
+
+    private void _fixAccess(Collection<SettableBeanProperty> mainProps)
+    {
+        /* 07-Sep-2016, tatu: Ideally we should be able to avoid forcing
+         *   access to properties that are likely ignored, but due to
+         *   renaming it seems this is not a safe thing to do (there was
+         *   at least one failing test). May need to dig deeper in future;
+         *   for now let's just play it safe.
+         */
+        /*
+        Set<String> ignorable = _ignorableProps;
+        if (ignorable == null) {
+            ignorable = Collections.emptySet();
+        }
+        */
+        for (SettableBeanProperty prop : mainProps) {
+            /*
+            // first: no point forcing access on to-be-ignored properties
+            if (ignorable.contains(prop.getName())) {
+                continue;
+            }
+            */
+            prop.fixAccess(_config);
+        }
+        // 15-Sep-2016, tatu: Access via back-ref properties has been done earlier
+        //   as it has to, for some reason, so not repeated here.
+/*        
+        if (_backRefProperties != null) {
+            for (SettableBeanProperty prop : _backRefProperties.values()) {
+                prop.fixAccess(_config);
+            }
+        }
+        */
+        if (_anySetter != null) {
+            _anySetter.fixAccess(_config);
+        }
+        if (_buildMethod != null) {
+            _buildMethod.fixAccess(_config.isEnabled(MapperFeature.OVERRIDE_PUBLIC_ACCESS_MODIFIERS));
+        }
+    }
 }
diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/BeanDeserializerFactory.java b/src/main/java/com/fasterxml/jackson/databind/deser/BeanDeserializerFactory.java
index b462c0c..d93745c 100644
--- a/src/main/java/com/fasterxml/jackson/databind/deser/BeanDeserializerFactory.java
+++ b/src/main/java/com/fasterxml/jackson/databind/deser/BeanDeserializerFactory.java
@@ -2,18 +2,17 @@
 
 import java.util.*;
 
-import com.fasterxml.jackson.annotation.ObjectIdGenerator;
-import com.fasterxml.jackson.annotation.ObjectIdGenerators;
-import com.fasterxml.jackson.annotation.ObjectIdResolver;
+import com.fasterxml.jackson.annotation.*;
+
 import com.fasterxml.jackson.databind.*;
 import com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder;
 import com.fasterxml.jackson.databind.cfg.DeserializerFactoryConfig;
+import com.fasterxml.jackson.databind.cfg.ConfigOverride;
 import com.fasterxml.jackson.databind.deser.impl.*;
 import com.fasterxml.jackson.databind.deser.std.ThrowableDeserializer;
 import com.fasterxml.jackson.databind.introspect.*;
 import com.fasterxml.jackson.databind.jsontype.TypeDeserializer;
 import com.fasterxml.jackson.databind.jsontype.impl.SubTypeValidator;
-import com.fasterxml.jackson.databind.util.ArrayBuilders;
 import com.fasterxml.jackson.databind.util.ClassUtil;
 import com.fasterxml.jackson.databind.util.SimpleBeanPropertyDefinition;
 
@@ -41,7 +40,6 @@
 
     private final static Class<?>[] NO_VIEWS = new Class<?>[0];
 
-
     /*
     /**********************************************************
     /* Life-cycle
@@ -118,7 +116,7 @@
          */
         // 29-Nov-2015, tatu: Also, filter out calls to primitive types, they are
         //    not something we could materialize anything for
-        if (type.isAbstract() && !type.isPrimitive()) {
+        if (type.isAbstract() && !type.isPrimitive() && !type.isEnumType()) {
             // Let's make it possible to materialize abstract types.
             JavaType concreteType = materializeAbstractType(ctxt, type, beanDesc);
             if (concreteType != null) {
@@ -129,7 +127,6 @@
                 return buildBeanDeserializer(ctxt, concreteType, beanDesc);
             }
         }
-
         // Otherwise, may want to check handlers for standard types, from superclass:
         @SuppressWarnings("unchecked")
         JsonDeserializer<Object> deser = (JsonDeserializer<Object>) findStdDeserializer(ctxt, type, beanDesc);
@@ -224,7 +221,7 @@
         try {
             valueInstantiator = findValueInstantiator(ctxt, beanDesc);
         } catch (NoClassDefFoundError error) {
-            return new NoClassDefFoundDeserializer<Object>(error);
+            return new ErrorThrowingDeserializer(error);
         }
         BeanDeserializerBuilder builder = constructBeanDeserializerBuilder(ctxt, beanDesc);
         builder.setValueInstantiator(valueInstantiator);
@@ -237,7 +234,6 @@
         addInjectables(ctxt, beanDesc, builder);
         
         final DeserializationConfig config = ctxt.getConfig();
-        // [JACKSON-440]: update builder now that all information is in?
         if (_factoryConfig.hasDeserializerModifiers()) {
             for (BeanDeserializerModifier mod : _factoryConfig.deserializerModifiers()) {
                 builder = mod.updateBuilder(config, beanDesc, builder);
@@ -245,9 +241,6 @@
         }
         JsonDeserializer<?> deserializer;
 
-        /* 19-Mar-2012, tatu: This check used to be done earlier; but we have to defer
-         *   it a bit to collect information on ObjectIdReader, for example.
-         */
         if (type.isAbstract() && !valueInstantiator.canInstantiate()) {
             deserializer = builder.buildAbstract();
         } else {
@@ -448,31 +441,48 @@
             BeanDescription beanDesc, BeanDeserializerBuilder builder)
         throws JsonMappingException
     {
-        final SettableBeanProperty[] creatorProps =
-                builder.getValueInstantiator().getFromObjectArguments(ctxt.getConfig());
         final boolean isConcrete = !beanDesc.getType().isAbstract();
+        final SettableBeanProperty[] creatorProps = isConcrete
+                ? builder.getValueInstantiator().getFromObjectArguments(ctxt.getConfig())
+                : null;
+        final boolean hasCreatorProps = (creatorProps != null);
         
-        // Things specified as "ok to ignore"?
-        AnnotationIntrospector intr = ctxt.getAnnotationIntrospector();
-        if (intr != null) {
-            Boolean B = intr.findIgnoreUnknownProperties(beanDesc.getClassInfo());
-            if (B != null) {
-                builder.setIgnoreUnknownProperties(B.booleanValue());
+        // 01-May-2016, tatu: Which base type to use here gets tricky, since
+        //   it may often make most sense to use general type for overrides,
+        //   but what we have here may be more specific impl type. But for now
+        //   just use it as is.
+        JsonIgnoreProperties.Value ignorals = ctxt.getConfig()
+                .getDefaultPropertyIgnorals(beanDesc.getBeanClass(),
+                        beanDesc.getClassInfo());
+        Set<String> ignored;
+
+        if (ignorals != null) {
+            boolean ignoreAny = ignorals.getIgnoreUnknown();
+            builder.setIgnoreUnknownProperties(ignoreAny);
+            // Or explicit/implicit definitions?
+            ignored = ignorals.findIgnoredForDeserialization();
+            for (String propName : ignored) {
+                builder.addIgnorable(propName);
             }
+        } else {
+            ignored = Collections.emptySet();
         }
-        // Or explicit/implicit definitions?
-        Set<String> ignored = ArrayBuilders.arrayToSet(intr.findPropertiesToIgnore(beanDesc.getClassInfo(), false));        
-        for (String propName : ignored) {
-            builder.addIgnorable(propName);
-        }
+
         // Also, do we have a fallback "any" setter?
-        AnnotatedMethod anySetter = beanDesc.findAnySetter();
-        if (anySetter != null) {
-            builder.setAnySetter(constructAnySetter(ctxt, beanDesc, anySetter));
+        AnnotatedMethod anySetterMethod = beanDesc.findAnySetter();
+        AnnotatedMember anySetterField = null;
+        if (anySetterMethod != null) {
+            builder.setAnySetter(constructAnySetter(ctxt, beanDesc, anySetterMethod));
+        }
+        else {
+        	anySetterField = beanDesc.findAnySetterField();
+        	if(anySetterField != null) {
+        		builder.setAnySetter(constructAnySetter(ctxt, beanDesc, anySetterField));
+        	}
         }
         // NOTE: we do NOT add @JsonIgnore'd properties into blocked ones if there's any-setter
         // Implicit ones via @JsonIgnore and equivalent?
-        if (anySetter == null) {
+        if (anySetterMethod == null && anySetterField == null) {
             Collection<String> ignored2 = beanDesc.getIgnoredPropertyNames();
             if (ignored2 != null) {
                 for (String propName : ignored2) {
@@ -482,8 +492,8 @@
                 }
             }
         }
-        final boolean useGettersAsSetters = (ctxt.isEnabled(MapperFeature.USE_GETTERS_AS_SETTERS)
-                && ctxt.isEnabled(MapperFeature.AUTO_DETECT_GETTERS));
+        final boolean useGettersAsSetters = ctxt.isEnabled(MapperFeature.USE_GETTERS_AS_SETTERS)
+                && ctxt.isEnabled(MapperFeature.AUTO_DETECT_GETTERS);
 
         // Ok: let's then filter out property definitions
         List<BeanPropertyDefinition> propDefs = filterBeanProps(ctxt,
@@ -523,7 +533,7 @@
             }
             // 25-Sep-2014, tatu: No point in finding constructor parameters for abstract types
             //   (since they are never used anyway)
-            if (isConcrete && propDef.hasConstructorParameter()) {
+            if (hasCreatorProps && propDef.hasConstructorParameter()) {
                 /* If property is passed via constructor parameter, we must
                  * handle things in special way. Not sure what is the most optimal way...
                  * for now, let's just call a (new) method in builder, which does nothing.
@@ -540,8 +550,14 @@
                     }
                 }
                 if (cprop == null) {
-                    throw ctxt.mappingException("Could not find creator property with name '%s' (in class %s)",
-                            name, beanDesc.getBeanClass().getName());
+                    List<String> n = new ArrayList<>();
+                    for (SettableBeanProperty cp : creatorProps) {
+                        n.add(cp.getName());
+                    }
+                    ctxt.reportBadPropertyDefinition(beanDesc, propDef,
+                            "Could not find creator property with name '%s' (known Creator properties: %s)",
+                            name, n);
+                    continue;
                 }
                 if (prop != null) {
                     cprop.setFallbackSetter(prop);
@@ -595,9 +611,9 @@
                     rawPropertyType = property.getField().getRawType();
                 }
 
-                // [JACKSON-429] Some types are declared as ignorable as well
+                // Some types are declared as ignorable as well
                 if ((rawPropertyType != null)
-                        && (isIgnorableType(ctxt.getConfig(), beanDesc, rawPropertyType, ignoredTypes))) {
+                        && isIgnorableType(ctxt.getConfig(), beanDesc, rawPropertyType, ignoredTypes)) {
                     // important: make ignorable, to avoid errors if value is actually seen
                     builder.addIgnorable(name);
                     continue;
@@ -627,11 +643,18 @@
                     type = ((AnnotatedMethod) m).getParameterType(0);
                 } else {
                     type = m.getType();
+                    // 30-Mar-2017, tatu: Unfortunately it is not yet possible to make back-refs
+                    //    work through constructors; but let's at least indicate the issue for now
+                    if (m instanceof AnnotatedParameter) {
+                        ctxt.reportBadTypeDefinition(beanDesc,
+"Can not bind back references as Creator parameters: type %s (reference '%s', parameter index #%d)",
+beanDesc.getBeanClass().getName(), name, ((AnnotatedParameter) m).getIndex());
+                    }
                 }
                 SimpleBeanPropertyDefinition propDef = SimpleBeanPropertyDefinition.construct(
-                		ctxt.getConfig(), m);
-                builder.addBackReferenceProperty(name, constructSettableProperty(
-                        ctxt, beanDesc, propDef, type));
+                        ctxt.getConfig(), m, PropertyName.construct(name));
+                builder.addBackReferenceProperty(name, constructSettableProperty(ctxt,
+                        beanDesc, propDef, type));
             }
         }
     }
@@ -646,13 +669,8 @@
     {
         Map<Object, AnnotatedMember> raw = beanDesc.findInjectables();
         if (raw != null) {
-            boolean fixAccess = ctxt.canOverrideAccessModifiers();
-            boolean forceAccess = fixAccess && ctxt.isEnabled(MapperFeature.OVERRIDE_PUBLIC_ACCESS_MODIFIERS);
             for (Map.Entry<Object, AnnotatedMember> entry : raw.entrySet()) {
                 AnnotatedMember m = entry.getValue();
-                if (fixAccess) {
-                    m.fixAccess(forceAccess); // to ensure we can call it
-                }
                 builder.addInjectable(PropertyName.construct(m.getName()),
                         m.getType(),
                         beanDesc.getClassAnnotations(), m, entry.getKey());
@@ -664,37 +682,41 @@
      * Method called to construct fallback {@link SettableAnyProperty}
      * for handling unknown bean properties, given a method that
      * has been designated as such setter.
+     * 
+     * @param mutator Either 2-argument method (setter, with key and value), or Field
+     *     that contains Map; either way accessor used for passing "any values"
      */
+    @SuppressWarnings("unchecked")
     protected SettableAnyProperty constructAnySetter(DeserializationContext ctxt,
-            BeanDescription beanDesc, AnnotatedMethod setter)
+            BeanDescription beanDesc, AnnotatedMember mutator)
         throws JsonMappingException
     {
-        if (ctxt.canOverrideAccessModifiers()) {
-            setter.fixAccess(ctxt.isEnabled(MapperFeature.OVERRIDE_PUBLIC_ACCESS_MODIFIERS)); // to ensure we can call it
+        //find the java type based on the annotated setter method or setter field 
+        JavaType type = null;
+        if (mutator instanceof AnnotatedMethod) {
+            // we know it's a 2-arg method, second arg is the value
+            type = ((AnnotatedMethod) mutator).getParameterType(1);
+        } else if (mutator instanceof AnnotatedField) {
+            // get the type from the content type of the map object
+            type = ((AnnotatedField) mutator).getType().getContentType();
         }
-        // we know it's a 2-arg method, second arg is the value
-        JavaType type = setter.getParameterType(1);
-        BeanProperty.Std property = new BeanProperty.Std(PropertyName.construct(setter.getName()),
-                type, null, beanDesc.getClassAnnotations(), setter,
+        // First: various annotations on type itself, as well as type-overrides
+        // on accessor need to be resolved
+        type = resolveMemberAndTypeAnnotations(ctxt, mutator, type);
+        BeanProperty.Std prop = new BeanProperty.Std(PropertyName.construct(mutator.getName()),
+                type, null, beanDesc.getClassAnnotations(), mutator,
                 PropertyMetadata.STD_OPTIONAL);
-        type = resolveType(ctxt, beanDesc, type, setter);
-
-        /* AnySetter can be annotated with @JsonDeserialize (etc) just like a
-         * regular setter... so let's see if those are used.
-         * Returns null if no annotations, in which case binding will
-         * be done at a later point.
-         */
-        JsonDeserializer<Object> deser = findDeserializerFromAnnotation(ctxt, setter);
-        /* Otherwise, method may specify more specific (sub-)class for
-         * value (no need to check if explicit deser was specified):
-         */
-        type = modifyTypeByAnnotation(ctxt, setter, type);
+        // and then possible direct deserializer override on accessor
+        JsonDeserializer<Object> deser = findDeserializerFromAnnotation(ctxt, mutator);
         if (deser == null) {
             deser = type.getValueHandler();
         }
+        if (deser != null) {
+            // As per [databind#462] need to ensure we contextualize deserializer before passing it on
+            deser = (JsonDeserializer<Object>) ctxt.handlePrimaryContextualization(deser, prop, type);
+        }
         TypeDeserializer typeDeser = type.getTypeHandler();
-        return new SettableAnyProperty(property, setter, type,
-                deser, typeDeser);
+        return new SettableAnyProperty(prop, mutator, type, deser, typeDeser);
     }
 
     /**
@@ -711,43 +733,31 @@
     {
         // need to ensure method is callable (for non-public)
         AnnotatedMember mutator = propDef.getNonConstructorMutator();
-
-        if (ctxt.canOverrideAccessModifiers()) {
-            // [databind#877]: explicitly prevent forced access to `cause` of `Throwable`;
-            // never needed and attempts may cause problems on some platforms.
-            // !!! NOTE: should be handled better for 2.8 and later
-            if ((mutator instanceof AnnotatedField)
-                    && "cause".equals(mutator.getName())
-                    && Throwable.class.isAssignableFrom(propType0.getRawClass())) {
-                ;
-            } else {
-                mutator.fixAccess(ctxt.isEnabled(MapperFeature.OVERRIDE_PUBLIC_ACCESS_MODIFIERS));
-            }
+        // 08-Sep-2016, tatu: issues like [databind#1342] suggest something fishy
+        //   going on; add sanity checks to try to pin down actual problem...
+        //   Possibly passing creator parameter?
+        if (mutator == null) {
+            ctxt.reportBadPropertyDefinition(beanDesc, propDef, "No non-constructor mutator available");
         }
-        // note: this works since we know there's exactly one argument for methods
-        BeanProperty.Std property = new BeanProperty.Std(propDef.getFullName(),
-                propType0, propDef.getWrapperName(),
-                beanDesc.getClassAnnotations(), mutator, propDef.getMetadata());
-        JavaType type = resolveType(ctxt, beanDesc, propType0, mutator);
-        // did type change?
-        if (type != propType0) {
-            property = property.withType(type);
-        }
-
-        // First: does the Method specify the deserializer to use? If so, let's use it.
-        JsonDeserializer<Object> propDeser = findDeserializerFromAnnotation(ctxt, mutator);
-        type = modifyTypeByAnnotation(ctxt, mutator, type);
+        JavaType type = resolveMemberAndTypeAnnotations(ctxt, mutator, propType0);
+        // Does the Method specify the deserializer to use? If so, let's use it.
         TypeDeserializer typeDeser = type.getTypeHandler();
         SettableBeanProperty prop;
         if (mutator instanceof AnnotatedMethod) {
             prop = new MethodProperty(propDef, type, typeDeser,
                     beanDesc.getClassAnnotations(), (AnnotatedMethod) mutator);
         } else {
+            // 08-Sep-2016, tatu: wonder if we should verify it is `AnnotatedField` to be safe?
             prop = new FieldProperty(propDef, type, typeDeser,
                     beanDesc.getClassAnnotations(), (AnnotatedField) mutator);
         }
-        if (propDeser != null) {
-            prop = prop.withValueDeserializer(propDeser);
+        JsonDeserializer<?> deser = findDeserializerFromAnnotation(ctxt, mutator);
+        if (deser == null) {
+            deser = type.getValueHandler();
+        }
+        if (deser != null) {
+            deser = ctxt.handlePrimaryContextualization(deser, prop, type);
+            prop = prop.withValueDeserializer(deser);
         }
         // need to retain name of managed forward references:
         AnnotationIntrospector.ReferenceProperty ref = propDef.findReferenceType();
@@ -755,7 +765,7 @@
             prop.setManagedReferenceName(ref.getName());
         }
         ObjectIdInfo objectIdInfo = propDef.findObjectIdInfo();
-        if(objectIdInfo != null){
+        if (objectIdInfo != null){
             prop.setObjectIdInfo(objectIdInfo);
         }
         return prop;
@@ -770,21 +780,17 @@
         throws JsonMappingException
     {
         final AnnotatedMethod getter = propDef.getGetter();
-        // need to ensure it is callable now:
-        if (ctxt.canOverrideAccessModifiers()) {
-            getter.fixAccess(ctxt.isEnabled(MapperFeature.OVERRIDE_PUBLIC_ACCESS_MODIFIERS));
-        }
-        JavaType type = getter.getType();
-        // First: does the Method specify the deserializer to use? If so, let's use it.
-        JsonDeserializer<Object> propDeser = findDeserializerFromAnnotation(ctxt, getter);
-        type = modifyTypeByAnnotation(ctxt, getter, type);
-        // As per [Issue#501], need full resolution:
-        type = resolveType(ctxt, beanDesc, type, getter);
+        JavaType type = resolveMemberAndTypeAnnotations(ctxt, getter, getter.getType());
         TypeDeserializer typeDeser = type.getTypeHandler();
         SettableBeanProperty prop = new SetterlessProperty(propDef, type, typeDeser,
                 beanDesc.getClassAnnotations(), getter);
-        if (propDeser != null) {
-            prop = prop.withValueDeserializer(propDeser);
+        JsonDeserializer<?> deser = findDeserializerFromAnnotation(ctxt, getter);
+        if (deser == null) {
+            deser = type.getValueHandler();
+        }
+        if (deser != null) {
+            deser = ctxt.handlePrimaryContextualization(deser, prop, type);
+            prop = prop.withValueDeserializer(deser);
         }
         return prop;
     }
@@ -813,7 +819,7 @@
             throw new IllegalArgumentException("Can not deserialize Proxy class "+type.getName()+" as a Bean");
         }
         /* also: can't deserialize some local classes: static are ok; in-method not;
-         * and with [JACKSON-594], other non-static inner classes are ok
+         * other non-static inner classes are ok
          */
         typeStr = ClassUtil.isLocalType(type, true);
         if (typeStr != null) {
@@ -833,10 +839,21 @@
         if (status != null) {
             return status.booleanValue();
         }
-        BeanDescription desc = config.introspectClassAnnotations(type);
-        status = config.getAnnotationIntrospector().isIgnorableType(desc.getClassInfo());
-        // We default to 'false', i.e. not ignorable
-        return (status == null) ? false : status.booleanValue(); 
+        // 21-Apr-2016, tatu: For 2.8, can specify config overrides
+        ConfigOverride override = config.findConfigOverride(type);
+        if (override != null) {
+            status = override.getIsIgnoredType();
+        }
+        if (status == null) {
+            BeanDescription desc = config.introspectClassAnnotations(type);
+            status = config.getAnnotationIntrospector().isIgnorableType(desc.getClassInfo());
+            // We default to 'false', i.e. not ignorable
+            if (status == null) {
+                status = Boolean.FALSE;
+            }
+        }
+        ignoredTypes.put(type, status);
+        return status.booleanValue();
     }
 
     /**
diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/BuilderBasedDeserializer.java b/src/main/java/com/fasterxml/jackson/databind/deser/BuilderBasedDeserializer.java
index 26a00cf..817e29e 100644
--- a/src/main/java/com/fasterxml/jackson/databind/deser/BuilderBasedDeserializer.java
+++ b/src/main/java/com/fasterxml/jackson/databind/deser/BuilderBasedDeserializer.java
@@ -26,7 +26,7 @@
     private static final long serialVersionUID = 1L;
 
     protected final AnnotatedMethod _buildMethod;
-	
+
     /*
     /**********************************************************
     /* Life-cycle, construction, initialization
@@ -39,7 +39,7 @@
     public BuilderBasedDeserializer(BeanDeserializerBuilder builder,
             BeanDescription beanDesc,
             BeanPropertyMap properties, Map<String, SettableBeanProperty> backRefs,
-            HashSet<String> ignorableProps, boolean ignoreAllUnknown,
+            Set<String> ignorableProps, boolean ignoreAllUnknown,
             boolean hasViews)
     {
         super(builder, beanDesc, properties, backRefs,
@@ -66,7 +66,7 @@
         super(src, ignoreAllUnknown);
         _buildMethod = src._buildMethod;
     }
-    
+
     protected BuilderBasedDeserializer(BuilderBasedDeserializer src, NameTransformer unwrapper) {
         super(src, unwrapper);
         _buildMethod = src._buildMethod;
@@ -77,11 +77,16 @@
         _buildMethod = src._buildMethod;
     }
 
-    public BuilderBasedDeserializer(BuilderBasedDeserializer src, HashSet<String> ignorableProps) {
+    public BuilderBasedDeserializer(BuilderBasedDeserializer src, Set<String> ignorableProps) {
         super(src, ignorableProps);
         _buildMethod = src._buildMethod;
     }
-    
+
+    public BuilderBasedDeserializer(BuilderBasedDeserializer src, BeanPropertyMap props) {
+        super(src, props);
+        _buildMethod = src._buildMethod;
+    }
+
     @Override
     public JsonDeserializer<Object> unwrappingDeserializer(NameTransformer unwrapper)
     {
@@ -93,27 +98,32 @@
     }
 
     @Override
-    public BuilderBasedDeserializer withObjectIdReader(ObjectIdReader oir) {
+    public BeanDeserializerBase withObjectIdReader(ObjectIdReader oir) {
         return new BuilderBasedDeserializer(this, oir);
     }
 
     @Override
-    public BuilderBasedDeserializer withIgnorableProperties(HashSet<String> ignorableProps) {
+    public BeanDeserializerBase withIgnorableProperties(Set<String> ignorableProps) {
         return new BuilderBasedDeserializer(this, ignorableProps);
     }
 
     @Override
-    protected BeanAsArrayBuilderDeserializer asArrayDeserializer() {
+    public BeanDeserializerBase withBeanProperties(BeanPropertyMap props) {
+        return new BuilderBasedDeserializer(this, props);
+    }
+
+    @Override
+    protected BeanDeserializerBase asArrayDeserializer() {
         SettableBeanProperty[] props = _beanProperties.getPropertiesInInsertionOrder();
         return new BeanAsArrayBuilderDeserializer(this, props, _buildMethod);
     }
-    
+
     /*
     /**********************************************************
     /* JsonDeserializer implementation
     /**********************************************************
      */
-    
+
     protected final Object finishBuild(DeserializationContext ctxt, Object builder)
             throws IOException
     {
@@ -124,20 +134,19 @@
         try {
             return _buildMethod.getMember().invoke(builder);
         } catch (Exception e) {
-            wrapInstantiationProblem(e, ctxt);
-            return null;
+            return wrapInstantiationProblem(e, ctxt);
         }
     }
-    
+
     /**
      * Main deserialization method for bean-based objects (POJOs).
      */
     @Override
     public final Object deserialize(JsonParser p, DeserializationContext ctxt)
-        throws IOException, JsonProcessingException
+        throws IOException
     {
         JsonToken t = p.getCurrentToken();
-        
+
         // common case first:
         if (t == JsonToken.START_OBJECT) {
             t = p.nextToken();
@@ -148,27 +157,29 @@
             return finishBuild(ctxt, builder);
         }
         // and then others, generally requiring use of @JsonCreator
-        switch (t) {
-        case VALUE_STRING:
-            return finishBuild(ctxt, deserializeFromString(p, ctxt));
-        case VALUE_NUMBER_INT:
-            return finishBuild(ctxt, deserializeFromNumber(p, ctxt));
-        case VALUE_NUMBER_FLOAT:
-        	return finishBuild(ctxt, deserializeFromDouble(p, ctxt));
-        case VALUE_EMBEDDED_OBJECT:
-            return p.getEmbeddedObject();
-        case VALUE_TRUE:
-        case VALUE_FALSE:
-            return finishBuild(ctxt, deserializeFromBoolean(p, ctxt));
-        case START_ARRAY:
-            // these only work if there's a (delegating) creator...
-            return finishBuild(ctxt, deserializeFromArray(p, ctxt));
-        case FIELD_NAME:
-        case END_OBJECT: // added to resolve [JACKSON-319], possible related issues
-            return finishBuild(ctxt, deserializeFromObject(p, ctxt));
-        default:
-            throw ctxt.mappingException(handledType());
+        if (t != null) {
+            switch (t) {
+            case VALUE_STRING:
+                return finishBuild(ctxt, deserializeFromString(p, ctxt));
+            case VALUE_NUMBER_INT:
+                return finishBuild(ctxt, deserializeFromNumber(p, ctxt));
+            case VALUE_NUMBER_FLOAT:
+            	return finishBuild(ctxt, deserializeFromDouble(p, ctxt));
+            case VALUE_EMBEDDED_OBJECT:
+                return p.getEmbeddedObject();
+            case VALUE_TRUE:
+            case VALUE_FALSE:
+                return finishBuild(ctxt, deserializeFromBoolean(p, ctxt));
+            case START_ARRAY:
+                // these only work if there's a (delegating) creator...
+                return finishBuild(ctxt, deserializeFromArray(p, ctxt));
+            case FIELD_NAME:
+            case END_OBJECT:
+                return finishBuild(ctxt, deserializeFromObject(p, ctxt));
+            default:
+            }
         }
+        return ctxt.handleUnexpectedToken(handledType(), p);
     }
 
     /**
@@ -179,14 +190,14 @@
     @Override
     public Object deserialize(JsonParser p, DeserializationContext ctxt,
     		Object builder)
-        throws IOException, JsonProcessingException
+        throws IOException
     {
         /* Important: we call separate method which does NOT call
          * 'finishBuild()', to avoid problems with recursion
          */
         return finishBuild(ctxt, _deserialize(p, ctxt, builder));
     }
-    
+
     /*
     /**********************************************************
     /* Concrete deserialization methods
@@ -196,7 +207,7 @@
     protected final Object _deserialize(JsonParser p,
             DeserializationContext ctxt, Object builder)
         throws IOException, JsonProcessingException
-    {        
+    {
         if (_injectables != null) {
             injectValues(ctxt, builder);
         }
@@ -222,7 +233,7 @@
             // Skip field name:
             p.nextToken();
             SettableBeanProperty prop = _beanProperties.find(propName);
-            
+
             if (prop != null) { // normal case
                 try {
                     builder = prop.deserializeSetAndReturn(p, ctxt, builder);
@@ -235,7 +246,7 @@
         }
         return builder;
     }
-    
+
     /**
      * Streamlined version that is only used when no "special"
      * features are enabled.
@@ -312,7 +323,7 @@
      * Method called to deserialize bean using "property-based creator":
      * this means that a non-default constructor or factory method is
      * called, and then possibly other setters. The trick is that
-     * values for creator method need to be buffered, first; and 
+     * values for creator method need to be buffered, first; and
      * due to non-guaranteed ordering possibly some other properties
      * as well.
      */
@@ -321,7 +332,7 @@
     protected final Object _deserializeUsingPropertyBased(final JsonParser p,
             final DeserializationContext ctxt)
         throws IOException, JsonProcessingException
-    { 
+    {
         final PropertyBasedCreator creator = _propertyBasedCreator;
         PropertyValueBuffer buffer = creator.startBuilding(p, ctxt, _objectIdReader);
 
@@ -391,8 +402,7 @@
         try {
             bean = creator.build(ctxt, buffer);
         } catch (Exception e) {
-            wrapInstantiationProblem(e, ctxt);
-            return null; // never gets here
+            bean = wrapInstantiationProblem(e, ctxt);
         }
         if (unknown != null) {
             // polymorphic?
@@ -404,13 +414,13 @@
         }
         return bean;
     }
-    
+
     /*
     /**********************************************************
     /* Deserializing when we have to consider an active View
     /**********************************************************
      */
-    
+
     protected final Object deserializeWithView(JsonParser p, DeserializationContext ctxt,
             Object bean, Class<?> activeView)
         throws IOException, JsonProcessingException
@@ -437,7 +447,7 @@
         }
         return bean;
     }
-    
+
     /*
     /**********************************************************
     /* Handling for cases where we have "unwrapped" values
@@ -467,7 +477,7 @@
         }
 
         final Class<?> activeView = _needViewProcesing ? ctxt.getActiveView() : null;
-        
+
         for (; p.getCurrentToken() != JsonToken.END_OBJECT; p.nextToken()) {
             String propName = p.getCurrentName();
             p.nextToken();
@@ -505,7 +515,7 @@
         tokens.writeEndObject();
         _unwrappedPropertyHandler.processUnwrapped(p, ctxt, bean, tokens);
         return bean;
-    }    
+    }
 
     @SuppressWarnings("resource")
     protected Object deserializeWithUnwrapped(JsonParser p,
@@ -570,30 +580,7 @@
             // creator property?
             SettableBeanProperty creatorProp = creator.findCreatorProperty(propName);
             if (creatorProp != null) {
-                // Last creator property to set?
-                if (buffer.assignParameter(creatorProp, creatorProp.deserialize(p, ctxt))) {
-                    t = p.nextToken(); // to move to following FIELD_NAME/END_OBJECT
-                    Object bean;
-                    try {
-                        bean = creator.build(ctxt, buffer);
-                    } catch (Exception e) {
-                        wrapAndThrow(e, _beanType.getRawClass(), propName, ctxt);
-                        continue; // never gets here
-                    }
-                    // if so, need to copy all remaining tokens into buffer
-                    while (t == JsonToken.FIELD_NAME) {
-                        p.nextToken(); // to skip name
-                        tokens.copyCurrentStructure(p);
-                        t = p.nextToken();
-                    }
-                    tokens.writeEndObject();
-                    if (bean.getClass() != _beanType.getRawClass()) {
-                        // !!! 08-Jul-2011, tatu: Could probably support; but for now
-                        //   it's too complicated, so bail out
-                        throw ctxt.mappingException("Can not create polymorphic instances with unwrapped values");
-                    }
-                    return _unwrappedPropertyHandler.processUnwrapped(p, ctxt, bean, tokens);
-                }
+                buffer.assignParameter(creatorProp, creatorProp.deserialize(p, ctxt));
                 continue;
             }
             // Object Id property?
@@ -624,8 +611,7 @@
         try {
             bean = creator.build(ctxt, buffer);
         } catch (Exception e) {
-            wrapInstantiationProblem(e, ctxt);
-            return null; // never gets here
+            return wrapInstantiationProblem(e, ctxt);
         }
         return _unwrappedPropertyHandler.processUnwrapped(p, ctxt, bean, tokens);
     }
@@ -636,7 +622,7 @@
     /* external type id
     /**********************************************************
      */
-    
+
     protected Object deserializeWithExternalTypeId(JsonParser p, DeserializationContext ctxt)
         throws IOException, JsonProcessingException
     {
@@ -689,15 +675,14 @@
                 } catch (Exception e) {
                     wrapAndThrow(e, bean, propName, ctxt);
                 }
-                continue;
             } else {
                 // Unknown: let's call handler method
-                handleUnknownProperty(p, ctxt, bean, propName);         
+                handleUnknownProperty(p, ctxt, bean, propName);
             }
         }
         // and when we get this far, let's try finalizing the deal:
         return ext.complete(p, ctxt, bean);
-    }        
+    }
 
     protected Object deserializeUsingPropertyBasedWithExternalTypeId(JsonParser p,
     		DeserializationContext ctxt)
diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/CreatorProperty.java b/src/main/java/com/fasterxml/jackson/databind/deser/CreatorProperty.java
index 6a9ee45..d8e8602 100644
--- a/src/main/java/com/fasterxml/jackson/databind/deser/CreatorProperty.java
+++ b/src/main/java/com/fasterxml/jackson/databind/deser/CreatorProperty.java
@@ -4,7 +4,7 @@
 import java.lang.annotation.Annotation;
 
 import com.fasterxml.jackson.core.JsonParser;
-import com.fasterxml.jackson.core.JsonProcessingException;
+
 import com.fasterxml.jackson.databind.*;
 import com.fasterxml.jackson.databind.introspect.AnnotatedMember;
 import com.fasterxml.jackson.databind.introspect.AnnotatedParameter;
@@ -111,14 +111,24 @@
     
     @Override
     public CreatorProperty withValueDeserializer(JsonDeserializer<?> deser) {
+        if (_valueDeserializer == deser) {
+            return this;
+        }
         return new CreatorProperty(this, deser);
     }
 
+    @Override
+    public void fixAccess(DeserializationConfig config) {
+        if (_fallbackSetter != null) {
+            _fallbackSetter.fixAccess(config);
+        }
+    }
+
     /**
      * NOTE: one exception to immutability, due to problems with CreatorProperty instances
      * being shared between Bean, separate PropertyBasedCreator
      * 
-     * @since 2.6.0
+     * @since 2.6
      */
     public void setFallbackSetter(SettableBeanProperty fallbackSetter) {
         _fallbackSetter = fallbackSetter;
@@ -173,19 +183,17 @@
      */
 
     @Override
-    public void deserializeAndSet(JsonParser jp, DeserializationContext ctxt,
-                                  Object instance)
-        throws IOException, JsonProcessingException
+    public void deserializeAndSet(JsonParser p, DeserializationContext ctxt,
+            Object instance) throws IOException
     {
-        set(instance, deserialize(jp, ctxt));
+        set(instance, deserialize(p, ctxt));
     }
 
     @Override
-    public Object deserializeSetAndReturn(JsonParser jp,
-    		DeserializationContext ctxt, Object instance)
-        throws IOException, JsonProcessingException
+    public Object deserializeSetAndReturn(JsonParser p,
+            DeserializationContext ctxt, Object instance) throws IOException
     {
-        return setAndReturn(instance, deserialize(jp, ctxt));
+        return setAndReturn(instance, deserialize(p, ctxt));
     }
     
     @Override
diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/DefaultDeserializationContext.java b/src/main/java/com/fasterxml/jackson/databind/deser/DefaultDeserializationContext.java
index 002c55a..d759ddd 100644
--- a/src/main/java/com/fasterxml/jackson/databind/deser/DefaultDeserializationContext.java
+++ b/src/main/java/com/fasterxml/jackson/databind/deser/DefaultDeserializationContext.java
@@ -6,8 +6,9 @@
 import com.fasterxml.jackson.annotation.ObjectIdGenerator;
 import com.fasterxml.jackson.annotation.ObjectIdResolver;
 import com.fasterxml.jackson.annotation.ObjectIdGenerator.IdKey;
-import com.fasterxml.jackson.annotation.SimpleObjectIdResolver;
+
 import com.fasterxml.jackson.core.JsonParser;
+
 import com.fasterxml.jackson.databind.*;
 import com.fasterxml.jackson.databind.cfg.HandlerInstantiator;
 import com.fasterxml.jackson.databind.deser.impl.ReadableObjectId;
@@ -140,12 +141,6 @@
         return new ReadableObjectId(key);
     }
 
-    @Deprecated // since 2.4
-    @Override
-    public ReadableObjectId findObjectId(Object id, ObjectIdGenerator<?> gen) {
-        return findObjectId(id, gen, new SimpleObjectIdResolver());
-    }
-
     @Override
     public void checkUnresolvedObjectId() throws UnresolvedForwardReference
     {
diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/DeserializationProblemHandler.java b/src/main/java/com/fasterxml/jackson/databind/deser/DeserializationProblemHandler.java
index 6cf8423..e374867 100644
--- a/src/main/java/com/fasterxml/jackson/databind/deser/DeserializationProblemHandler.java
+++ b/src/main/java/com/fasterxml/jackson/databind/deser/DeserializationProblemHandler.java
@@ -3,11 +3,13 @@
 import java.io.IOException;
 
 import com.fasterxml.jackson.core.JsonParser;
-import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.core.JsonToken;
 import com.fasterxml.jackson.databind.DeserializationConfig;
 import com.fasterxml.jackson.databind.DeserializationContext;
+import com.fasterxml.jackson.databind.JavaType;
 import com.fasterxml.jackson.databind.JsonDeserializer;
 import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.jsontype.TypeIdResolver;
 
 /**
  * This is the class that can be registered (via
@@ -31,7 +33,15 @@
 public abstract class DeserializationProblemHandler
 {
     /**
-     * Method called when a JSON Map ("Object") entry with an unrecognized
+     * Marker value returned by some handler methods to indicate that
+     * they could not handle problem and produce replacement value.
+     *
+     * @since 2.7
+     */
+    public final static Object NOT_HANDLED = new Object();
+    
+    /**
+     * Method called when a JSON Object property with an unrecognized
      * name is encountered.
      * Content (supposedly) matching the property are accessible via
      * parser that can be obtained from passed deserialization context.
@@ -39,29 +49,268 @@
      * true to indicate it did handle property successfully.
      * Skipping is usually done like so:
      *<pre>
-     *  jp.skipChildren();
+     *  parser.skipChildren();
      *</pre>
      *<p>
-     * Note: version 1.2 added new deserialization feature
-     * (<code>DeserializationConfig.DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES</code>).
-     * It will only have effect <b>after</b> handler is called, and only
+     * Note: {@link com.fasterxml.jackson.databind.DeserializationFeature#FAIL_ON_UNKNOWN_PROPERTIES})
+     * takes effect only <b>after</b> handler is called, and only
      * if handler did <b>not</b> handle the problem.
      *
      * @param beanOrClass Either bean instance being deserialized (if one
      *   has been instantiated so far); or Class that indicates type that
      *   will be instantiated (if no instantiation done yet: for example
      *   when bean uses non-default constructors)
-     * @param jp Parser to use for handling problematic content
+     * @param p Parser to use for handling problematic content
      * 
      * @return True if the problem is resolved (and content available used or skipped);
      *  false if the handler did not anything and the problem is unresolved. Note that in
      *  latter case caller will either throw an exception or explicitly skip the content,
      *  depending on configuration.
      */
-    public boolean handleUnknownProperty(DeserializationContext ctxt, JsonParser jp,
+    public boolean handleUnknownProperty(DeserializationContext ctxt, JsonParser p,
             JsonDeserializer<?> deserializer, Object beanOrClass, String propertyName)
-        throws IOException, JsonProcessingException
+        throws IOException
     {
         return false;
     }
+
+    /**
+     * Method called when a property name from input can not be converted to a
+     * non-Java-String key type (passed as <code>rawKeyType</code>) due to format problem.
+     * Handler may choose to do one of 3 things:
+     *<ul>
+     * <li>Indicate it does not know what to do by returning {@link #NOT_HANDLED}
+     *  </li>
+     * <li>Throw a {@link IOException} to indicate specific fail message (instead of
+     *    standard exception caller would throw
+     *  </li>
+     * <li>Return actual key value to use as replacement, and continue processing.
+     *  </li>
+     * </ul>
+     *
+     * @param failureMsg Message that will be used by caller (by calling
+     *    {@link DeserializationContext#weirdKeyException(Class, String, String)})
+     *    to indicate type of failure unless handler produces key to use
+     *
+     * @return Either {@link #NOT_HANDLED} to indicate that handler does not know
+     *    what to do (and exception may be thrown), or value to use as key (possibly
+     *    <code>null</code>
+     *
+     * @since 2.8
+     */
+    public Object handleWeirdKey(DeserializationContext ctxt,
+            Class<?> rawKeyType, String keyValue,
+            String failureMsg)
+        throws IOException
+    {
+        return NOT_HANDLED;
+    }
+
+    /**
+     * Method called when a String value
+     * can not be converted to a non-String value type due to specific problem
+     * (as opposed to String values never being usable).
+     * Handler may choose to do one of 3 things:
+     *<ul>
+     * <li>Indicate it does not know what to do by returning {@link #NOT_HANDLED}
+     *  </li>
+     * <li>Throw a {@link IOException} to indicate specific fail message (instead of
+     *    standard exception caller would throw
+     *  </li>
+     * <li>Return actual converted value (of type <code>targetType</code>) to use as
+     *    replacement, and continue processing.
+     *  </li>
+     * </ul>
+     *
+     * @param failureMsg Message that will be used by caller (by calling
+     *    {@link DeserializationContext#weirdNumberException})
+     *    to indicate type of failure unless handler produces key to use
+     *
+     * @return Either {@link #NOT_HANDLED} to indicate that handler does not know
+     *    what to do (and exception may be thrown), or value to use as key (possibly
+     *    <code>null</code>
+     *
+     * @since 2.8
+     */
+    public Object handleWeirdStringValue(DeserializationContext ctxt,
+            Class<?> targetType, String valueToConvert,
+            String failureMsg)
+        throws IOException
+    {
+        return NOT_HANDLED;
+    }
+
+    /**
+     * Method called when a numeric value (integral or floating-point from input
+     * can not be converted to a non-numeric value type due to specific problem
+     * (as opposed to numeric values never being usable).
+     * Handler may choose to do one of 3 things:
+     *<ul>
+     * <li>Indicate it does not know what to do by returning {@link #NOT_HANDLED}
+     *  </li>
+     * <li>Throw a {@link IOException} to indicate specific fail message (instead of
+     *    standard exception caller would throw
+     *  </li>
+     * <li>Return actual converted value (of type <code>targetType</code>) to use as
+     *    replacement, and continue processing.
+     *  </li>
+     * </ul>
+     *
+     * @param failureMsg Message that will be used by caller (by calling
+     *    {@link DeserializationContext#weirdNumberException})
+     *    to indicate type of failure unless handler produces key to use
+     *
+     * @return Either {@link #NOT_HANDLED} to indicate that handler does not know
+     *    what to do (and exception may be thrown), or value to use as key (possibly
+     *    <code>null</code>
+     *
+     * @since 2.8
+     */
+    public Object handleWeirdNumberValue(DeserializationContext ctxt,
+            Class<?> targetType, Number valueToConvert,
+            String failureMsg)
+        throws IOException
+    {
+        return NOT_HANDLED;
+    }
+
+    /**
+     * Method that deserializers should call if the first token of the value to
+     * deserialize is of unexpected type (that is, type of token that deserializer
+     * can not handle). This could occur, for example, if a Number deserializer
+     * encounter {@link JsonToken#START_ARRAY} instead of
+     * {@link JsonToken#VALUE_NUMBER_INT} or {@link JsonToken#VALUE_NUMBER_FLOAT}.
+     *<ul>
+     * <li>Indicate it does not know what to do by returning {@link #NOT_HANDLED}
+     *  </li>
+     * <li>Throw a {@link IOException} to indicate specific fail message (instead of
+     *    standard exception caller would throw
+     *  </li>
+     * <li>Handle content to match (by consuming or skipping it), and return actual
+     *    instantiated value (of type <code>targetType</code>) to use as replacement;
+     *    value may be `null` as well as expected target type.
+     *  </li>
+     * </ul>
+     *
+     * @param failureMsg Message that will be used by caller
+     *    to indicate type of failure unless handler produces value to use
+     *
+     * @return Either {@link #NOT_HANDLED} to indicate that handler does not know
+     *    what to do (and exception may be thrown), or value to use (possibly
+     *    <code>null</code>
+     *
+     * @since 2.8
+     */
+    public Object handleUnexpectedToken(DeserializationContext ctxt,
+            Class<?> targetType, JsonToken t, JsonParser p,
+            String failureMsg)
+        throws IOException
+    {
+        return NOT_HANDLED;
+    }
+    
+    /**
+     * Method called when instance creation for a type fails due to an exception.
+     * Handler may choose to do one of following things:
+     *<ul>
+     * <li>Indicate it does not know what to do by returning {@link #NOT_HANDLED}
+     *  </li>
+     * <li>Throw a {@link IOException} to indicate specific fail message (instead of
+     *    standard exception caller would throw
+     *  </li>
+     * <li>Return actual instantiated value (of type <code>targetType</code>) to use as
+     *    replacement, and continue processing.
+     *  </li>
+     * <li>Return <code>null</code> to use null as value but not to try further
+     *   processing (in cases where properties would otherwise be bound)
+     *  </li>
+     * </ul>
+     *
+     * @param instClass Type that was to be instantiated
+     * @param argument (optional) Additional argument that was passed to creator, if any
+     * @param t Exception that caused instantiation failure
+     *
+     * @return Either {@link #NOT_HANDLED} to indicate that handler does not know
+     *    what to do (and exception may be thrown), or value to use (possibly
+     *    <code>null</code>
+     *
+     * @since 2.8
+     */
+    public Object handleInstantiationProblem(DeserializationContext ctxt,
+            Class<?> instClass, Object argument, Throwable t)
+        throws IOException
+    {
+        return NOT_HANDLED;
+    }
+
+    /**
+     * Method called when instance creation for a type fails due to lack of an
+     * instantiator. Method is called before actual deserialization from input
+     * is attempted, so handler may do one of following things:
+     *<ul>
+     * <li>Indicate it does not know what to do by returning {@link #NOT_HANDLED}
+     *  </li>
+     * <li>Throw a {@link IOException} to indicate specific fail message (instead of
+     *    standard exception caller would throw
+     *  </li>
+     * <li>Handle content to match (by consuming or skipping it), and return actual
+     *    instantiated value (of type <code>targetType</code>) to use as replacement;
+     *    value may be `null` as well as expected target type.
+     *  </li>
+     * </ul>
+     *
+     * @param instClass Type that was to be instantiated
+     * @param p Parser to use for accessing content that needs handling, to either
+     *   use it or skip it (latter with {@link JsonParser#skipChildren()}.
+     *
+     * @return Either {@link #NOT_HANDLED} to indicate that handler does not know
+     *    what to do (and exception may be thrown), or value to use (possibly
+     *    <code>null</code>
+     *
+     * @since 2.8
+     */
+    public Object handleMissingInstantiator(DeserializationContext ctxt,
+            Class<?> instClass, JsonParser p, String msg)
+        throws IOException
+    {
+        return NOT_HANDLED;
+    }
+    
+    /**
+     * Handler method called if resolution of type id from given String failed
+     * to produce a subtype; usually because logical id is not mapped to actual
+     * implementation class.
+     * Handler may choose to do one of following things:
+     *<ul>
+     * <li>Indicate it does not know what to do by returning `null`
+     *  </li>
+     * <li>Indicate that nothing should be deserialized, by return `Void.class`
+     *  </li>
+     * <li>Throw a {@link IOException} to indicate specific fail message (instead of
+     *    standard exception caller would throw
+     *  </li>
+     * <li>Return actual resolved type to use for type id.
+     *  </li>
+     * </ul>
+     *
+     * @param ctxt Deserialization context to use for accessing information or
+     *    constructing exception to throw
+     * @param baseType Base type to use for resolving subtype id
+     * @param subTypeId Subtype id that failed to resolve
+     * @param failureMsg Informational message that would be thrown as part of
+     *    exception, if resolution still fails
+     *
+     * @return Actual type to use, if resolved; `null` if handler does not know what
+     *     to do; or `Void.class` to indicate that nothing should be deserialized for
+     *     type with the id (which caller may choose to do... or not)
+     *
+     * @since 2.8
+     */
+    public JavaType handleUnknownTypeId(DeserializationContext ctxt,
+            JavaType baseType, String subTypeId, TypeIdResolver idResolver,
+            String failureMsg)
+        throws IOException
+    {
+        return null;
+    }
 }
diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/DeserializerCache.java b/src/main/java/com/fasterxml/jackson/databind/deser/DeserializerCache.java
index a4ab8d7..ded6b68 100644
--- a/src/main/java/com/fasterxml/jackson/databind/deser/DeserializerCache.java
+++ b/src/main/java/com/fasterxml/jackson/databind/deser/DeserializerCache.java
@@ -204,7 +204,7 @@
         if (type == null) {
             throw new IllegalArgumentException("Null JavaType passed");
         }
-        if (_hasCustomValueHandler(type)) {
+        if (_hasCustomHandlers(type)) {
             return null;
         }
         return _cachedDeserializers.get(type);
@@ -263,9 +263,8 @@
         try {
             deser = _createDeserializer(ctxt, factory, type);
         } catch (IllegalArgumentException iae) {
-            /* We better only expose checked exceptions, since those
-             * are what caller is expected to handle
-             */
+            // We better only expose checked exceptions, since those
+            // are what caller is expected to handle
             throw JsonMappingException.from(ctxt, iae.getMessage(), iae);
         }
         if (deser == null) {
@@ -274,10 +273,8 @@
         /* cache resulting deserializer? always true for "plain" BeanDeserializer
          * (but can be re-defined for sub-classes by using @JsonCachable!)
          */
-        // 08-Jun-2010, tatu: Related to [JACKSON-296], need to avoid caching MapSerializers... so:
-        boolean isResolvable = (deser instanceof ResolvableDeserializer);
         // 27-Mar-2015, tatu: As per [databind#735], avoid caching types with custom value desers
-        boolean addToCache = !_hasCustomValueHandler(type) && deser.isCachable();
+        boolean addToCache = !_hasCustomHandlers(type) && deser.isCachable();
 
         /* we will temporarily hold on to all created deserializers (to
          * handle cyclic references, and possibly reuse non-cached
@@ -291,7 +288,7 @@
         /* Need to resolve? Mostly done for bean deserializers; required for
          * resolving cyclic references.
          */
-        if (isResolvable) {
+        if (deser instanceof ResolvableDeserializer) {
             _incompleteDeserializers.put(type, deser);
             ((ResolvableDeserializer)deser).resolve(ctxt);
             _incompleteDeserializers.remove(type);
@@ -353,7 +350,7 @@
         }
         // otherwise need to do bit of introspection
         JavaType delegateType = conv.getInputType(ctxt.getTypeFactory());
-        // One more twist, as per [Issue#288]; probably need to get new BeanDesc
+        // One more twist, as per [databind#288]; probably need to get new BeanDesc
         if (!delegateType.hasRawClass(type.getRawClass())) {
             beanDesc = config.introspect(delegateType);
         }
@@ -382,13 +379,13 @@
                 return factory.createMapLikeDeserializer(ctxt, mlt, beanDesc);
             }
             if (type.isCollectionLikeType()) {
-                /* 03-Aug-2012, tatu: As per [Issue#40], one exception is if shape
+                /* 03-Aug-2012, tatu: As per [databind#40], one exception is if shape
                  *   is to be Shape.OBJECT. Ideally we'd determine it bit later on
                  *   (to allow custom handler checks), but that won't work for other
                  *   reasons. So do it here.
                  */
                 JsonFormat.Value format = beanDesc.findExpectedFormat(null);
-                if (format == null || format.getShape() != JsonFormat.Shape.OBJECT) {
+                if ((format == null) || format.getShape() != JsonFormat.Shape.OBJECT) {
                     CollectionLikeType clt = (CollectionLikeType) type;
                     if (clt.isTrueCollectionType()) {
                         return factory.createCollectionDeserializer(ctxt, (CollectionType) clt, beanDesc);
@@ -534,13 +531,23 @@
      * Helper method used to prevent both caching and cache lookups for structured
      * types that have custom value handlers
      *
-     * @since 2.4.6
+     * @since 2.8.11
      */
-    private boolean _hasCustomValueHandler(JavaType t) {
+    private boolean _hasCustomHandlers(JavaType t) {
         if (t.isContainerType()) {
+            // First: value types may have both value and type handlers
             JavaType ct = t.getContentType();
             if (ct != null) {
-                return (ct.getValueHandler() != null) || (ct.getTypeHandler() != null);
+                if ((ct.getValueHandler() != null) || (ct.getTypeHandler() != null)) {
+                    return true;
+                }
+            }
+            // Second: map(-like) types may have value handler for key (but not type; keys are untyped)
+            if (t.isMapLikeType()) {
+                JavaType kt = t.getKeyType();
+                if (kt.getValueHandler() != null) {
+                    return true;
+                }
             }
         }
         return false;
@@ -569,21 +576,21 @@
 
     // NOTE: changed 2.6 -> 2.7 to pass context; no way to make backwards compatible
     protected JsonDeserializer<Object> _handleUnknownValueDeserializer(DeserializationContext ctxt, JavaType type)
-            throws JsonMappingException
+        throws JsonMappingException
     {
-        /* Let's try to figure out the reason, to give better error
-         * messages
-         */
+        // Let's try to figure out the reason, to give better error messages
         Class<?> rawClass = type.getRawClass();
         if (!ClassUtil.isConcrete(rawClass)) {
-            throw JsonMappingException.from(ctxt, "Can not find a Value deserializer for abstract type "+type);
+            ctxt.reportMappingException("Can not find a Value deserializer for abstract type %s", type);
         }
-        throw JsonMappingException.from(ctxt, "Can not find a Value deserializer for type "+type);
+        ctxt.reportMappingException("Can not find a Value deserializer for type %s", type);
+        return null;
     }
 
     protected KeyDeserializer _handleUnknownKeyDeserializer(DeserializationContext ctxt, JavaType type)
         throws JsonMappingException
     {
-        throw JsonMappingException.from(ctxt, "Can not find a (Map) Key deserializer for type "+type);
+        ctxt.reportMappingException("Can not find a (Map) Key deserializer for type %s", type);
+        return null;
     }
 }
diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/Deserializers.java b/src/main/java/com/fasterxml/jackson/databind/deser/Deserializers.java
index eb9948e..360a08f 100644
--- a/src/main/java/com/fasterxml/jackson/databind/deser/Deserializers.java
+++ b/src/main/java/com/fasterxml/jackson/databind/deser/Deserializers.java
@@ -76,6 +76,8 @@
      *    by property annotation
      * 
      * @return Deserializer to use for the type; or null if this provider does not know how to construct it
+     *
+     * @since 2.7
      */
     public JsonDeserializer<?> findReferenceDeserializer(ReferenceType refType,
             DeserializationConfig config, BeanDescription beanDesc,
diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/SettableAnyProperty.java b/src/main/java/com/fasterxml/jackson/databind/deser/SettableAnyProperty.java
index 92261be..8ee86d4 100644
--- a/src/main/java/com/fasterxml/jackson/databind/deser/SettableAnyProperty.java
+++ b/src/main/java/com/fasterxml/jackson/databind/deser/SettableAnyProperty.java
@@ -1,10 +1,13 @@
 package com.fasterxml.jackson.databind.deser;
 
 import java.io.IOException;
+import java.util.Map;
 
 import com.fasterxml.jackson.core.*;
 import com.fasterxml.jackson.databind.*;
 import com.fasterxml.jackson.databind.deser.impl.ReadableObjectId.Referring;
+import com.fasterxml.jackson.databind.introspect.AnnotatedField;
+import com.fasterxml.jackson.databind.introspect.AnnotatedMember;
 import com.fasterxml.jackson.databind.introspect.AnnotatedMethod;
 import com.fasterxml.jackson.databind.jsontype.TypeDeserializer;
 
@@ -30,8 +33,10 @@
     /**
      * Annotated variant is needed for JDK serialization only
      */
-    final protected AnnotatedMethod _setter;
+    final protected AnnotatedMember _setter;
 
+    final boolean _setterIsField;
+    
     protected final JavaType _type;
 
     protected JsonDeserializer<Object> _valueDeserializer;
@@ -44,7 +49,7 @@
     /**********************************************************
      */
 
-    public SettableAnyProperty(BeanProperty property, AnnotatedMethod setter, JavaType type,
+    public SettableAnyProperty(BeanProperty property, AnnotatedMember setter, JavaType type,
             JsonDeserializer<Object> valueDeser, TypeDeserializer typeDeser)
     {
         _property = property;
@@ -52,11 +57,7 @@
         _type = type;
         _valueDeserializer = valueDeser;
         _valueTypeDeserializer = typeDeser;
-    }
-
-    public SettableAnyProperty withValueDeserializer(JsonDeserializer<Object> deser) {
-        return new SettableAnyProperty(_property, _setter, _type,
-                deser, _valueTypeDeserializer);
+        _setterIsField = setter instanceof AnnotatedField;
     }
 
     /**
@@ -69,8 +70,19 @@
         _type = src._type;
         _valueDeserializer = src._valueDeserializer;
         _valueTypeDeserializer = src._valueTypeDeserializer;
+        _setterIsField = src._setterIsField;
     }
-    
+
+    public SettableAnyProperty withValueDeserializer(JsonDeserializer<Object> deser) {
+        return new SettableAnyProperty(_property, _setter, _type,
+                deser, _valueTypeDeserializer);
+    }
+
+    public void fixAccess(DeserializationConfig config) {
+        _setter.fixAccess(
+                config.isEnabled(MapperFeature.OVERRIDE_PUBLIC_ACCESS_MODIFIERS));
+    }
+
     /*
     /**********************************************************
     /* JDK serialization handling
@@ -138,11 +150,27 @@
         return _valueDeserializer.deserialize(p, ctxt);
     }
 
+    @SuppressWarnings("unchecked")
     public void set(Object instance, String propName, Object value) throws IOException
     {
         try {
-            // note: can not use 'setValue()' due to taking 2 args
-            _setter.getAnnotated().invoke(instance, propName, value);
+            // if annotation in the field (only map is supported now)
+            if (_setterIsField) {
+                AnnotatedField field = (AnnotatedField) _setter;
+                Map<Object,Object> val = (Map<Object,Object>) field.getValue(instance);
+                /* 01-Jun-2016, tatu: At this point it is not quite clear what to do if
+                 *    field is `null` -- we can not necessarily count on zero-args
+                 *    constructor except for a small set of types, so for now just
+                 *    ignore if null. May need to figure out something better in future.
+                 */
+                if (val != null) {
+                    // add the property key and value
+                    val.put(propName, value);
+                }
+            } else {
+                // note: can not use 'setValue()' due to taking 2 args
+                ((AnnotatedMethod) _setter).callOnWith(instance, propName, value);
+            }
         } catch (Exception e) {
             _throwAsIOE(e, propName, value);
         }
diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/SettableBeanProperty.java b/src/main/java/com/fasterxml/jackson/databind/deser/SettableBeanProperty.java
index abb5cb9..65be982 100644
--- a/src/main/java/com/fasterxml/jackson/databind/deser/SettableBeanProperty.java
+++ b/src/main/java/com/fasterxml/jackson/databind/deser/SettableBeanProperty.java
@@ -4,12 +4,10 @@
 import java.lang.annotation.Annotation;
 
 import com.fasterxml.jackson.core.*;
+
 import com.fasterxml.jackson.databind.*;
 import com.fasterxml.jackson.databind.deser.impl.FailingDeserializer;
-import com.fasterxml.jackson.databind.introspect.AnnotatedMember;
-import com.fasterxml.jackson.databind.introspect.BeanPropertyDefinition;
-import com.fasterxml.jackson.databind.introspect.ConcreteBeanPropertyBase;
-import com.fasterxml.jackson.databind.introspect.ObjectIdInfo;
+import com.fasterxml.jackson.databind.introspect.*;
 import com.fasterxml.jackson.databind.jsonFormatVisitors.JsonObjectFormatVisitor;
 import com.fasterxml.jackson.databind.jsontype.TypeDeserializer;
 import com.fasterxml.jackson.databind.util.Annotations;
@@ -135,7 +133,7 @@
             boolean isRequired)
     {
         this(new PropertyName(propName), type, wrapper, typeDeser, contextAnnotations,
-                PropertyMetadata.construct(isRequired, null, null, null));
+                PropertyMetadata.construct(Boolean.valueOf(isRequired), null, null, null));
     }
     
     protected SettableBeanProperty(PropertyName propName, JavaType type, PropertyName wrapper,
@@ -309,7 +307,18 @@
         }
         _propertyIndex = index;
     }
-    
+
+    /**
+     * Method called to ensure that the mutator has proper access rights to
+     * be called, as per configuration. Overridden by implementations that
+     * have mutators that require access, fields and setters.
+     *
+     * @since 2.8.3
+     */
+    public void fixAccess(DeserializationConfig config) {
+        ;
+    }
+
     /*
     /**********************************************************
     /* BeanProperty impl
@@ -485,7 +494,7 @@
     public final Object deserialize(JsonParser p, DeserializationContext ctxt) throws IOException
     {
         JsonToken t = p.getCurrentToken();
-        
+
         if (t == JsonToken.VALUE_NULL) {
             return _valueDeserializer.getNullValue(ctxt);
         }
@@ -494,7 +503,7 @@
         }
         return _valueDeserializer.deserialize(p, ctxt);
     }
-    
+
     /*
     /**********************************************************
     /* Helper methods
diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/ValueInstantiator.java b/src/main/java/com/fasterxml/jackson/databind/deser/ValueInstantiator.java
index 522face..fceac96 100644
--- a/src/main/java/com/fasterxml/jackson/databind/deser/ValueInstantiator.java
+++ b/src/main/java/com/fasterxml/jackson/databind/deser/ValueInstantiator.java
@@ -2,8 +2,8 @@
 
 import java.io.IOException;
 
-import com.fasterxml.jackson.core.JsonProcessingException;
 import com.fasterxml.jackson.databind.*;
+import com.fasterxml.jackson.databind.deser.impl.PropertyValueBuffer;
 import com.fasterxml.jackson.databind.introspect.AnnotatedParameter;
 import com.fasterxml.jackson.databind.introspect.AnnotatedWithParams;
 
@@ -37,10 +37,30 @@
      */
 
     /**
+     * Accessor for raw (type-erased) type of instances to create.
+     *<p>
+     * NOTE: since this method has not existed since beginning of
+     * Jackson 2.0 series, default implementation will just return
+     * <code>Object.class</code>; implementations are expected
+     * to override it with real value.
+     *
+     * @since 2.8
+     */
+    public Class<?> getValueClass() {
+        return Object.class;
+    }
+
+    /**
      * Method that returns description of the value type this instantiator
      * handles. Used for error messages, diagnostics.
      */
-    public abstract String getValueTypeDesc();
+    public String getValueTypeDesc() {
+        Class<?> cls = getValueClass();
+        if (cls == null) {
+            return "UNKNOWN";
+        }
+        return cls.getName();
+    }
 
     /**
      * Method that will return true if any of <code>canCreateXxx</code> method
@@ -48,11 +68,12 @@
      * be created.
      */
     public boolean canInstantiate() {
-        return canCreateUsingDefault() || canCreateUsingDelegate()
-             || canCreateFromObjectWith() || canCreateFromString()
-             || canCreateFromInt() || canCreateFromLong()
-             || canCreateFromDouble() || canCreateFromBoolean();
-    }    
+        return canCreateUsingDefault()
+                || canCreateUsingDelegate() || canCreateUsingArrayDelegate()
+                || canCreateFromObjectWith() || canCreateFromString()
+                || canCreateFromInt() || canCreateFromLong()
+                || canCreateFromDouble() || canCreateFromBoolean();
+    }
 
     /**
      * Method that can be called to check whether a String-based creator
@@ -165,8 +186,8 @@
      * null or empty List.
      */
     public Object createUsingDefault(DeserializationContext ctxt) throws IOException {
-        throw ctxt.mappingException("Can not instantiate value of type %s; no default creator found",
-                getValueTypeDesc());
+        return ctxt.handleMissingInstantiator(getValueClass(), ctxt.getParser(),
+                "no default no-arguments constructor found");
     }
 
     /**
@@ -178,8 +199,34 @@
      * a non-empty List of arguments.
      */
     public Object createFromObjectWith(DeserializationContext ctxt, Object[] args) throws IOException {
-        throw ctxt.mappingException("Can not instantiate value of type %s with arguments",
-                getValueTypeDesc());
+        // sanity check; shouldn't really get called if no Creator specified
+        return ctxt.handleMissingInstantiator(getValueClass(), ctxt.getParser(),
+                "no creator with arguments specified");
+    }
+
+    /**
+     * Method that delegates to
+     * {@link #createFromObjectWith(DeserializationContext, Object[])} by
+     * default, but can be overridden if the application should have customized
+     * behavior with respect to missing properties.
+     *<p>
+     * The default implementation of this method uses
+     * {@link PropertyValueBuffer#getParameters(SettableBeanProperty[])} to read
+     * and validate all properties in bulk, possibly substituting defaults for
+     * missing properties or throwing exceptions for missing properties.  An
+     * overridden implementation of this method could, for example, use
+     * {@link PropertyValueBuffer#hasParameter(SettableBeanProperty)} and
+     * {@link PropertyValueBuffer#getParameter(SettableBeanProperty)} to safely
+     * read the present properties only, and to have some other behavior for the
+     * missing properties.
+     * 
+     * @since 2.8
+     */
+    public Object createFromObjectWith(DeserializationContext ctxt,
+            SettableBeanProperty[] props, PropertyValueBuffer buffer)
+        throws IOException
+    {
+        return createFromObjectWith(ctxt, buffer.getParameters(props));
     }
 
     /**
@@ -187,8 +234,8 @@
      * an intermediate "delegate" value to pass to createor method
      */
     public Object createUsingDelegate(DeserializationContext ctxt, Object delegate) throws IOException {
-        throw ctxt.mappingException("Can not instantiate value of type %s using delegate",
-                getValueTypeDesc());
+        return ctxt.handleMissingInstantiator(getValueClass(), ctxt.getParser(),
+                "no delegate creator specified");
     }
 
     /**
@@ -196,8 +243,8 @@
      * an intermediate "delegate" value to pass to createor method
      */
     public Object createUsingArrayDelegate(DeserializationContext ctxt, Object delegate) throws IOException {
-        throw ctxt.mappingException("Can not instantiate value of type %s using delegate",
-                getValueTypeDesc());
+        return ctxt.handleMissingInstantiator(getValueClass(), ctxt.getParser(),
+                "no array delegate creator specified");
     }
 
     /*
@@ -212,23 +259,27 @@
     }
 
     public Object createFromInt(DeserializationContext ctxt, int value) throws IOException {
-        throw ctxt.mappingException("Can not instantiate value of type %s from Integer number (%s, int)",
-                getValueTypeDesc(), value);
+        return ctxt.handleMissingInstantiator(getValueClass(), ctxt.getParser(),
+                "no int/Int-argument constructor/factory method to deserialize from Number value (%s)",
+                value);
     }
 
     public Object createFromLong(DeserializationContext ctxt, long value) throws IOException {
-        throw ctxt.mappingException("Can not instantiate value of type %s from Integer number (%s, long)",
-                getValueTypeDesc(), value);
+        return ctxt.handleMissingInstantiator(getValueClass(), ctxt.getParser(),
+                "no long/Long-argument constructor/factory method to deserialize from Number value (%s)",
+                value);
     }
 
     public Object createFromDouble(DeserializationContext ctxt, double value) throws IOException {
-        throw ctxt.mappingException("Can not instantiate value of type %s from Floating-point number (%s, double)",
-                getValueTypeDesc(), value);
+        return ctxt.handleMissingInstantiator(getValueClass(), ctxt.getParser(),
+                "no double/Double-argument constructor/factory method to deserialize from Number value (%s)",
+                value);
     }
-    
+
     public Object createFromBoolean(DeserializationContext ctxt, boolean value) throws IOException {
-        throw ctxt.mappingException("Can not instantiate value of type %s from Boolean value (%s)",
-                getValueTypeDesc(), value);
+        return ctxt.handleMissingInstantiator(getValueClass(), ctxt.getParser(),
+                "no boolean/Boolean-argument constructor/factory method to deserialize from boolean value (%s)",
+                value);
     }
 
     /*
@@ -296,7 +347,7 @@
      * @since 2.4 (demoted from <code>StdValueInstantiator</code>)
      */
     protected Object _createFromStringFallbacks(DeserializationContext ctxt, String value)
-            throws IOException, JsonProcessingException
+            throws IOException
     {
         /* 28-Sep-2011, tatu: Ok this is not clean at all; but since there are legacy
          *   systems that expect conversions in some cases, let's just add a minimal
@@ -317,7 +368,41 @@
                 return null;
             }
         }
-        throw ctxt.mappingException("Can not instantiate value of type %s from String value ('%s'); no single-String constructor/factory method",
-                getValueTypeDesc(), value);
+        return ctxt.handleMissingInstantiator(getValueClass(), ctxt.getParser(),
+                "no String-argument constructor/factory method to deserialize from String value ('%s')",
+                value);
+    }
+
+    /*
+    /**********************************************************
+    /* Standard Base implementation (since 2.8)
+    /**********************************************************
+     */
+
+    /**
+     * Partial {@link ValueInstantiator} implementation that is strongly recommended
+     * to be used instead of directly extending {@link ValueInstantiator} itself.
+     */
+    public static class Base extends ValueInstantiator
+    {
+        protected final Class<?> _valueType;
+
+        public Base(Class<?> type) {
+            _valueType = type;
+        }
+
+        public Base(JavaType type) {
+            _valueType = type.getRawClass();
+        }
+        
+        @Override
+        public String getValueTypeDesc() {
+            return _valueType.getName();
+        }
+
+        @Override
+        public Class<?> getValueClass() {
+            return _valueType;
+        }
     }
 }
diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/impl/BeanAsArrayBuilderDeserializer.java b/src/main/java/com/fasterxml/jackson/databind/deser/impl/BeanAsArrayBuilderDeserializer.java
index 1ca180b..dabe451 100644
--- a/src/main/java/com/fasterxml/jackson/databind/deser/impl/BeanAsArrayBuilderDeserializer.java
+++ b/src/main/java/com/fasterxml/jackson/databind/deser/impl/BeanAsArrayBuilderDeserializer.java
@@ -1,10 +1,9 @@
 package com.fasterxml.jackson.databind.deser.impl;
 
 import java.io.IOException;
-import java.util.HashSet;
+import java.util.Set;
 
 import com.fasterxml.jackson.core.*;
-
 import com.fasterxml.jackson.databind.*;
 import com.fasterxml.jackson.databind.deser.*;
 import com.fasterxml.jackson.databind.introspect.AnnotatedMethod;
@@ -59,19 +58,25 @@
     }
 
     @Override
-    public BeanAsArrayBuilderDeserializer withObjectIdReader(ObjectIdReader oir) {
+    public BeanDeserializerBase withObjectIdReader(ObjectIdReader oir) {
         return new BeanAsArrayBuilderDeserializer(_delegate.withObjectIdReader(oir),
                 _orderedProperties, _buildMethod);
     }
 
     @Override
-    public BeanAsArrayBuilderDeserializer withIgnorableProperties(HashSet<String> ignorableProps) {
+    public BeanDeserializerBase withIgnorableProperties(Set<String> ignorableProps) {
         return new BeanAsArrayBuilderDeserializer(_delegate.withIgnorableProperties(ignorableProps),
                 _orderedProperties, _buildMethod);
     }
 
     @Override
-    protected BeanAsArrayBuilderDeserializer asArrayDeserializer() {
+    public BeanDeserializerBase withBeanProperties(BeanPropertyMap props) {
+        return new BeanAsArrayBuilderDeserializer(_delegate.withBeanProperties(props),
+                _orderedProperties, _buildMethod);
+    }
+
+    @Override
+    protected BeanDeserializerBase asArrayDeserializer() {
         return this;
     }
 
@@ -87,11 +92,10 @@
         try {
             return _buildMethod.getMember().invoke(builder);
         } catch (Exception e) {
-            wrapInstantiationProblem(e, ctxt);
-            return null;
+            return wrapInstantiationProblem(e, ctxt);
         }
     }
-    
+
     @Override
     public Object deserialize(JsonParser p, DeserializationContext ctxt)
         throws IOException
@@ -128,8 +132,9 @@
         }
         // Ok; extra fields? Let's fail, unless ignoring extra props is fine
         if (!_ignoreAllUnknown) {
-            throw ctxt.mappingException("Unexpected JSON values; expected at most %d properties (in JSON Array)",
+            ctxt.reportMappingException("Unexpected JSON values; expected at most %d properties (in JSON Array)",
                     propCount);
+            // fall through
         }
         // otherwise, skip until end
         while (p.nextToken() != JsonToken.END_ARRAY) {
@@ -173,13 +178,15 @@
         
         // Ok; extra fields? Let's fail, unless ignoring extra props is fine
         if (!_ignoreAllUnknown) {
-            throw ctxt.mappingException("Unexpected JSON values; expected at most %d properties (in JSON Array)",
+            ctxt.reportWrongTokenException(p, JsonToken.END_ARRAY,
+                    "Unexpected JSON values; expected at most %d properties (in JSON Array)",
                     propCount);
+            // never gets here
         }
         // otherwise, skip until end
-        while (p.nextToken() != JsonToken.END_ARRAY) {
+        do {
             p.skipChildren();
-        }
+        } while (p.nextToken() != JsonToken.END_ARRAY);
         return finishBuild(ctxt, builder);
     }
 
@@ -207,7 +214,7 @@
         throws IOException
     {
         if (_nonStandardCreation) {
-            return _deserializeWithCreator(p, ctxt);
+            return deserializeFromObjectUsingNonDefault(p, ctxt);
         }
         Object builder = _valueInstantiator.createUsingDefault(ctxt);
         if (_injectables != null) {
@@ -241,8 +248,10 @@
         }
         // Ok; extra fields? Let's fail, unless ignoring extra props is fine
         if (!_ignoreAllUnknown) {
-            throw ctxt.mappingException("Unexpected JSON values; expected at most %d properties (in JSON Array)",
+            ctxt.reportWrongTokenException(p, JsonToken.END_ARRAY,
+                    "Unexpected JSON value(s); expected at most %d properties (in JSON Array)",
                     propCount);
+            // will never reach here as exception has been thrown
         }
         // otherwise, skip until end
         while (p.nextToken() != JsonToken.END_ARRAY) {
@@ -250,25 +259,6 @@
         }
         return builder;
     }
-    
-    protected Object _deserializeWithCreator(JsonParser p, DeserializationContext ctxt)
-        throws IOException
-    {        
-        if (_delegateDeserializer != null) {
-            return _valueInstantiator.createUsingDelegate(ctxt,
-                    _delegateDeserializer.deserialize(p, ctxt));
-        }
-        if (_propertyBasedCreator != null) {
-            return _deserializeUsingPropertyBased(p, ctxt);
-        }
-        // should only occur for abstract types...
-        if (_beanType.isAbstract()) {
-            throw JsonMappingException.from(p, "Can not instantiate abstract type "+_beanType
-                    +" (need to add/enable type information?)");
-        }
-        throw JsonMappingException.from(p, "No suitable constructor found for type "
-                +_beanType+": can not instantiate from JSON object (need to add/enable type information?)");
-    }
 
     /**
      * Method called to deserialize bean using "property-based creator":
@@ -324,9 +314,10 @@
                          *   supported (since ordering of elements may not be guaranteed);
                          *   but make explicitly non-supported for now.
                          */
-                        throw ctxt.mappingException("Can not support implicit polymorphic deserialization for POJOs-as-Arrays style: "
+                        ctxt.reportMappingException("Can not support implicit polymorphic deserialization for POJOs-as-Arrays style: "
                                 +"nominal type %s, actual type %s",
                                 _beanType.getRawClass().getName(), builder.getClass().getName());
+                        return null;
                     }
                 }
                 continue;
@@ -344,8 +335,7 @@
             try {
                 builder = creator.build(ctxt, buffer);
             } catch (Exception e) {
-                wrapInstantiationProblem(e, ctxt);
-                return null; // never gets here
+                return wrapInstantiationProblem(e, ctxt);
             }
         }
         return builder;
@@ -361,7 +351,8 @@
         throws IOException
     {
         // Let's start with failure
-        throw ctxt.mappingException("Can not deserialize a POJO (of type %s) from non-Array representation (token: %s): "
+        return ctxt.handleUnexpectedToken(handledType(), p.getCurrentToken(), p,
+                "Can not deserialize a POJO (of type %s) from non-Array representation (token: %s): "
                 +"type/property designed to be serialized as JSON Array",
                 _beanType.getRawClass().getName(),
                 p.getCurrentToken());
diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/impl/BeanAsArrayDeserializer.java b/src/main/java/com/fasterxml/jackson/databind/deser/impl/BeanAsArrayDeserializer.java
index 04869be..1cff5ca 100644
--- a/src/main/java/com/fasterxml/jackson/databind/deser/impl/BeanAsArrayDeserializer.java
+++ b/src/main/java/com/fasterxml/jackson/databind/deser/impl/BeanAsArrayDeserializer.java
@@ -1,11 +1,10 @@
 package com.fasterxml.jackson.databind.deser.impl;
 
 import java.io.IOException;
-import java.util.HashSet;
+import java.util.Set;
 
 import com.fasterxml.jackson.core.JsonParser;
 import com.fasterxml.jackson.core.JsonToken;
-
 import com.fasterxml.jackson.databind.*;
 import com.fasterxml.jackson.databind.deser.*;
 import com.fasterxml.jackson.databind.util.NameTransformer;
@@ -61,18 +60,24 @@
     }
 
     @Override
-    public BeanAsArrayDeserializer withObjectIdReader(ObjectIdReader oir) {
+    public BeanDeserializerBase withObjectIdReader(ObjectIdReader oir) {
         return new BeanAsArrayDeserializer(_delegate.withObjectIdReader(oir),
                 _orderedProperties);
     }
 
     @Override
-    public BeanAsArrayDeserializer withIgnorableProperties(HashSet<String> ignorableProps) {
+    public BeanDeserializerBase withIgnorableProperties(Set<String> ignorableProps) {
         return new BeanAsArrayDeserializer(_delegate.withIgnorableProperties(ignorableProps),
                 _orderedProperties);
     }
 
     @Override
+    public BeanDeserializerBase withBeanProperties(BeanPropertyMap props) {
+        return new BeanAsArrayDeserializer(_delegate.withBeanProperties(props),
+                _orderedProperties);
+    }
+    
+    @Override
     protected BeanDeserializerBase asArrayDeserializer() {
         return this;
     }
@@ -122,13 +127,15 @@
         }
         // Ok; extra fields? Let's fail, unless ignoring extra props is fine
         if (!_ignoreAllUnknown) {
-            throw ctxt.mappingException("Unexpected JSON values; expected at most %d properties (in JSON Array)",
+            ctxt.reportWrongTokenException(p, JsonToken.END_ARRAY,
+                    "Unexpected JSON values; expected at most %d properties (in JSON Array)",
                     propCount);
+            // never gets here
         }
         // otherwise, skip until end
-        while (p.nextToken() != JsonToken.END_ARRAY) {
+        do {
             p.skipChildren();
-        }
+        } while (p.nextToken() != JsonToken.END_ARRAY);
         return bean;
     }
 
@@ -169,17 +176,18 @@
         
         // Ok; extra fields? Let's fail, unless ignoring extra props is fine
         if (!_ignoreAllUnknown) {
-            throw ctxt.mappingException("Unexpected JSON values; expected at most %d properties (in JSON Array)",
+            ctxt.reportWrongTokenException(p, JsonToken.END_ARRAY,
+                    "Unexpected JSON values; expected at most %d properties (in JSON Array)",
                     propCount);
+            // never gets here
         }
         // otherwise, skip until end
-        while (p.nextToken() != JsonToken.END_ARRAY) {
+        do {
             p.skipChildren();
-        }
+        } while (p.nextToken() != JsonToken.END_ARRAY);
         return bean;
     }
 
-
     // needed since 2.1
     @Override
     public Object deserializeFromObject(JsonParser p, DeserializationContext ctxt)
@@ -187,7 +195,7 @@
     {
         return _deserializeFromNonArray(p, ctxt);
     }
-    
+
     /*
     /**********************************************************
     /* Helper methods, non-standard creation
@@ -202,7 +210,7 @@
         throws IOException
     {
         if (_nonStandardCreation) {
-            return _deserializeWithCreator(p, ctxt);
+            return deserializeFromObjectUsingNonDefault(p, ctxt);
         }
         final Object bean = _valueInstantiator.createUsingDefault(ctxt);
         // [databind#631]: Assign current value, to be accessible by custom serializers
@@ -238,33 +246,17 @@
         }
         // Ok; extra fields? Let's fail, unless ignoring extra props is fine
         if (!_ignoreAllUnknown) {
-            throw ctxt.mappingException("Unexpected JSON values; expected at most %d properties (in JSON Array)",
+            ctxt.reportWrongTokenException(p, JsonToken.END_ARRAY,
+                    "Unexpected JSON values; expected at most %d properties (in JSON Array)",
                     propCount);
+            // will never reach here as exception has been thrown
         }
         // otherwise, skip until end
-        while (p.nextToken() != JsonToken.END_ARRAY) {
+        do {
             p.skipChildren();
-        }
+        } while (p.nextToken() != JsonToken.END_ARRAY);
         return bean;
     }
-    
-    protected Object _deserializeWithCreator(JsonParser p, DeserializationContext ctxt)
-        throws IOException
-    {        
-        if (_delegateDeserializer != null) {
-            return _valueInstantiator.createUsingDelegate(ctxt, _delegateDeserializer.deserialize(p, ctxt));
-        }
-        if (_propertyBasedCreator != null) {
-            return _deserializeUsingPropertyBased(p, ctxt);
-        }
-        // should only occur for abstract types...
-        if (_beanType.isAbstract()) {
-            throw JsonMappingException.from(p, "Can not instantiate abstract type "+_beanType
-                    +" (need to add/enable type information?)");
-        }
-        throw JsonMappingException.from(p, "No suitable constructor found for type "
-                +_beanType+": can not instantiate from JSON object (need to add/enable type information?)");
-    }
 
     /**
      * Method called to deserialize bean using "property-based creator":
@@ -322,7 +314,7 @@
                          *   supported (since ordering of elements may not be guaranteed);
                          *   but make explicitly non-supported for now.
                          */
-                        throw ctxt.mappingException("Can not support implicit polymorphic deserialization for POJOs-as-Arrays style: "
+                        ctxt.reportMappingException("Can not support implicit polymorphic deserialization for POJOs-as-Arrays style: "
                                 +"nominal type %s, actual type %s",
                                 _beanType.getRawClass().getName(), bean.getClass().getName());
                     }
@@ -342,8 +334,7 @@
             try {
                 bean = creator.build(ctxt, buffer);
             } catch (Exception e) {
-                wrapInstantiationProblem(e, ctxt);
-                return null; // never gets here
+                return wrapInstantiationProblem(e, ctxt);
             }
         }
         return bean;
@@ -358,8 +349,8 @@
     protected Object _deserializeFromNonArray(JsonParser p, DeserializationContext ctxt)
         throws IOException
     {
-        // Let's start with failure
-        throw ctxt.mappingException("Can not deserialize a POJO (of type %s) from non-Array representation (token: %s): "
+        return ctxt.handleUnexpectedToken(handledType(), p.getCurrentToken(), p,
+                "Can not deserialize a POJO (of type %s) from non-Array representation (token: %s): "
                 +"type/property designed to be serialized as JSON Array",
                 _beanType.getRawClass().getName(),
                 p.getCurrentToken());
diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/impl/BeanPropertyMap.java b/src/main/java/com/fasterxml/jackson/databind/deser/impl/BeanPropertyMap.java
index e6c6a79..8031ee0 100644
--- a/src/main/java/com/fasterxml/jackson/databind/deser/impl/BeanPropertyMap.java
+++ b/src/main/java/com/fasterxml/jackson/databind/deser/impl/BeanPropertyMap.java
@@ -61,11 +61,38 @@
         _propsInOrder = props.toArray(new SettableBeanProperty[props.size()]);
         init(props);
     }
-    
+
+    /**
+     * @since 2.8
+     */
+    protected BeanPropertyMap(BeanPropertyMap base, boolean caseInsensitive)
+    {
+        _caseInsensitive = caseInsensitive;
+
+        // 16-May-2016, tatu: Alas, not enough to just change flag, need to re-init
+        //    as well.
+        _propsInOrder = Arrays.copyOf(base._propsInOrder, base._propsInOrder.length);
+        init(Arrays.asList(_propsInOrder));
+    }
+
+    /**
+     * Mutant factory method that constructs a new instance if desired case-insensitivity
+     * state differs from the state of this instance; if states are the same, returns
+     * <code>this</code>.
+     *
+     * @since 2.8
+     */
+    public BeanPropertyMap withCaseInsensitivity(boolean state) {
+        if (_caseInsensitive == state) {
+            return this;
+        }
+        return new BeanPropertyMap(this, state);
+    }
+
     protected void init(Collection<SettableBeanProperty> props)
     {
         _size = props.size();
-        
+
         // First: calculate size of primary hash area
         final int hashSize = findSize(_size);
         _hashMask = hashSize-1;
@@ -208,7 +235,7 @@
     }
 
     /**
-     * Factory method for constructing a map where all entries use given
+     * Mutant factory method for constructing a map where all entries use given
      * prefix
      */
     public BeanPropertyMap renameAll(NameTransformer transformer)
@@ -235,6 +262,36 @@
     }
 
     /**
+     * Mutant factory method that will use this instance as the base, and
+     * construct an instance that is otherwise same except for excluding
+     * properties with specified names.
+     *
+     * @since 2.8
+     */
+    public BeanPropertyMap withoutProperties(Collection<String> toExclude)
+    {
+        if (toExclude.isEmpty()) {
+            return this;
+        }
+        final int len = _propsInOrder.length;
+        ArrayList<SettableBeanProperty> newProps = new ArrayList<SettableBeanProperty>(len);
+
+        for (int i = 0; i < len; ++i) {
+            SettableBeanProperty prop = _propsInOrder[i];
+            // 01-May-2015, tatu: Not 100% sure if existing `null`s should be retained;
+            //   or, if entries to ignore should be retained as nulls. For now just
+            //   prune them out
+            if (prop != null) { // may contain holes, too, check.
+                if (!toExclude.contains(prop.getName())) {
+                    newProps.add(prop);
+                }
+            }
+        }
+        // should we try to re-index? Apparently no need
+        return new BeanPropertyMap(_caseInsensitive, newProps);
+    }
+    
+    /**
      * Specialized method that can be used to replace an existing entry
      * (note: entry MUST exist; otherwise exception is thrown) with
      * specified replacement.
@@ -316,7 +373,7 @@
         if (_caseInsensitive) {
             key = key.toLowerCase();
         }
-
+            
         // inlined `_hashCode(key)`
         int slot = key.hashCode() & _hashMask;
 //        int h = key.hashCode();
@@ -366,7 +423,8 @@
      * Specialized method for removing specified existing entry.
      * NOTE: entry MUST exist, otherwise an exception is thrown.
      */
-    public void remove(SettableBeanProperty propToRm) {
+    public void remove(SettableBeanProperty propToRm)
+    {
         ArrayList<SettableBeanProperty> props = new ArrayList<SettableBeanProperty>(_size);
         String key = getPropertyName(propToRm);
         boolean found = false;
@@ -377,7 +435,9 @@
                 continue;
             }
             if (!found) {
-                found = key.equals(prop.getName());
+                // 09-Jan-2017, tatu: Important: must check name slot and NOT property name,
+                //   as only former is lower-case in case-insensitive case
+                found = key.equals(_hashArea[i-1]);
                 if (found) {
                     // need to leave a hole here
                     _propsInOrder[_findFromOrdered(prop)] = null;
@@ -481,7 +541,7 @@
             if (!wrap || !(t instanceof JsonProcessingException)) {
                 throw (IOException) t;
             }
-        } else if (!wrap) { // [JACKSON-407] -- allow disabling wrapping for unchecked exceptions
+        } else if (!wrap) { // allow disabling wrapping for unchecked exceptions
             if (t instanceof RuntimeException) {
                 throw (RuntimeException) t;
             }
diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/impl/CreatorCollector.java b/src/main/java/com/fasterxml/jackson/databind/deser/impl/CreatorCollector.java
index a530e4b..2999341 100644
--- a/src/main/java/com/fasterxml/jackson/databind/deser/impl/CreatorCollector.java
+++ b/src/main/java/com/fasterxml/jackson/databind/deser/impl/CreatorCollector.java
@@ -1,7 +1,8 @@
 package com.fasterxml.jackson.databind.deser.impl;
 
-import java.io.IOException;
+import java.lang.reflect.AnnotatedElement;
 import java.lang.reflect.Member;
+import java.lang.reflect.Type;
 import java.util.*;
 
 import com.fasterxml.jackson.databind.*;
@@ -17,8 +18,7 @@
  * Container class for storing information on creators (based on annotations,
  * visibility), to be able to build actual instantiator later on.
  */
-public class CreatorCollector
-{
+public class CreatorCollector {
     // Since 2.5
     protected final static int C_DEFAULT = 0;
     protected final static int C_STRING = 1;
@@ -30,11 +30,9 @@
     protected final static int C_PROPS = 7;
     protected final static int C_ARRAY_DELEGATE = 8;
 
-    protected final static String[] TYPE_DESCS = new String[] {
-        "default",
-        "String", "int", "long", "double", "boolean",
-        "delegate", "property-based"
-    };
+    protected final static String[] TYPE_DESCS = new String[] { "default",
+            "from-String", "from-int", "from-long", "from-double",
+            "from-boolean", "delegate", "property-based" };
 
     /// Type of bean being created
     final protected BeanDescription _beanDesc;
@@ -45,7 +43,7 @@
      * @since 2.7
      */
     final protected boolean _forceAccess;
-    
+
     /**
      * Set of creators we have collected so far
      * 
@@ -54,8 +52,9 @@
     protected final AnnotatedWithParams[] _creators = new AnnotatedWithParams[9];
 
     /**
-     * Bitmask of creators that were explicitly marked as creators; false for auto-detected
-     * (ones included base on naming and/or visibility, not annotation)
+     * Bitmask of creators that were explicitly marked as creators; false for
+     * auto-detected (ones included base on naming and/or visibility, not
+     * annotation)
      * 
      * @since 2.5
      */
@@ -73,47 +72,37 @@
     protected AnnotatedParameter _incompleteParameter;
 
     /*
-    /**********************************************************
-    /* Life-cycle
-    /**********************************************************
+     * /********************************************************** /* Life-cycle
+     * /**********************************************************
      */
-    
-    public CreatorCollector(BeanDescription beanDesc, MapperConfig<?> config)
-    {
+
+    public CreatorCollector(BeanDescription beanDesc, MapperConfig<?> config) {
         _beanDesc = beanDesc;
         _canFixAccess = config.canOverrideAccessModifiers();
-        _forceAccess = config.isEnabled(MapperFeature.OVERRIDE_PUBLIC_ACCESS_MODIFIERS);
+        _forceAccess = config
+                .isEnabled(MapperFeature.OVERRIDE_PUBLIC_ACCESS_MODIFIERS);
     }
 
-    public ValueInstantiator constructValueInstantiator(DeserializationConfig config)
-    {
-        final JavaType delegateType = _computeDelegateType(_creators[C_DELEGATE], _delegateArgs);
-        final JavaType arrayDelegateType = _computeDelegateType(_creators[C_ARRAY_DELEGATE], _arrayDelegateArgs);
+    public ValueInstantiator constructValueInstantiator(
+            DeserializationConfig config) {
+        final JavaType delegateType = _computeDelegateType(
+                _creators[C_DELEGATE], _delegateArgs);
+        final JavaType arrayDelegateType = _computeDelegateType(
+                _creators[C_ARRAY_DELEGATE], _arrayDelegateArgs);
         final JavaType type = _beanDesc.getType();
 
-        // Any non-standard creator will prevent; with one exception: int-valued constructor
-        // that standard containers have can be ignored
-        if (!_hasNonDefaultCreator) {
-            /* 10-May-2014, tatu: If we have nothing special, and we are dealing with one
-             *   of "well-known" types, can create a non-reflection-based instantiator.
-             */
-            final Class<?> rawType = type.getRawClass();
-            if (rawType == Collection.class || rawType == List.class || rawType == ArrayList.class) {
-                return new Vanilla(Vanilla.TYPE_COLLECTION);
-            }
-            if (rawType == Map.class || rawType == LinkedHashMap.class) {
-                return new Vanilla(Vanilla.TYPE_MAP);
-            }
-            if (rawType == HashMap.class) {
-                return new Vanilla(Vanilla.TYPE_HASH_MAP);
-            }
-        }
-        
+        // 11-Jul-2016, tatu: Earlier optimization by replacing the whole
+        // instantiator did not
+        // work well, so let's replace by lower-level check:
+        AnnotatedWithParams defaultCtor = StdTypeConstructor
+                .tryToOptimize(_creators[C_DEFAULT]);
+
         StdValueInstantiator inst = new StdValueInstantiator(config, type);
-        inst.configureFromObjectSettings(_creators[C_DEFAULT],
-                _creators[C_DELEGATE], delegateType, _delegateArgs,
-                _creators[C_PROPS], _propertyBasedArgs);
-        inst.configureFromArraySettings(_creators[C_ARRAY_DELEGATE], arrayDelegateType, _arrayDelegateArgs);
+        inst.configureFromObjectSettings(defaultCtor, _creators[C_DELEGATE],
+                delegateType, _delegateArgs, _creators[C_PROPS],
+                _propertyBasedArgs);
+        inst.configureFromArraySettings(_creators[C_ARRAY_DELEGATE],
+                arrayDelegateType, _arrayDelegateArgs);
         inst.configureFromStringCreator(_creators[C_STRING]);
         inst.configureFromIntCreator(_creators[C_INT]);
         inst.configureFromLongCreator(_creators[C_LONG]);
@@ -122,45 +111,51 @@
         inst.configureIncompleteParameter(_incompleteParameter);
         return inst;
     }
-    
+
     /*
-    /**********************************************************
-    /* Setters
-    /**********************************************************
+     * /********************************************************** /* Setters
+     * /**********************************************************
      */
-    
+
     /**
-     * Method called to indicate the default creator: no-arguments
-     * constructor or factory method that is called to instantiate
-     * a value before populating it with data. Default creator is
-     * only used if no other creators are indicated.
+     * Method called to indicate the default creator: no-arguments constructor
+     * or factory method that is called to instantiate a value before populating
+     * it with data. Default creator is only used if no other creators are
+     * indicated.
      * 
-     * @param creator Creator method; no-arguments constructor or static
-     *   factory method.
+     * @param creator
+     *            Creator method; no-arguments constructor or static factory
+     *            method.
      */
     public void setDefaultCreator(AnnotatedWithParams creator) {
         _creators[C_DEFAULT] = _fixAccess(creator);
     }
-    
-    public void addStringCreator(AnnotatedWithParams creator, boolean explicit) {
+
+    public void addStringCreator(AnnotatedWithParams creator,
+            boolean explicit) {
         verifyNonDup(creator, C_STRING, explicit);
     }
+
     public void addIntCreator(AnnotatedWithParams creator, boolean explicit) {
         verifyNonDup(creator, C_INT, explicit);
     }
+
     public void addLongCreator(AnnotatedWithParams creator, boolean explicit) {
         verifyNonDup(creator, C_LONG, explicit);
     }
-    public void addDoubleCreator(AnnotatedWithParams creator, boolean explicit) {
+
+    public void addDoubleCreator(AnnotatedWithParams creator,
+            boolean explicit) {
         verifyNonDup(creator, C_DOUBLE, explicit);
     }
-    public void addBooleanCreator(AnnotatedWithParams creator, boolean explicit) {
+
+    public void addBooleanCreator(AnnotatedWithParams creator,
+            boolean explicit) {
         verifyNonDup(creator, C_BOOLEAN, explicit);
     }
 
-    public void addDelegatingCreator(AnnotatedWithParams creator, boolean explicit,
-            SettableBeanProperty[] injectables)
-    {
+    public void addDelegatingCreator(AnnotatedWithParams creator,
+            boolean explicit, SettableBeanProperty[] injectables) {
         if (creator.getParameterType(0).isCollectionLikeType()) {
             if (verifyNonDup(creator, C_ARRAY_DELEGATE, explicit)) {
                 _arrayDelegateArgs = injectables;
@@ -171,25 +166,26 @@
             }
         }
     }
-    
-    public void addPropertyCreator(AnnotatedWithParams creator, boolean explicit,
-            SettableBeanProperty[] properties)
-    {
+
+    public void addPropertyCreator(AnnotatedWithParams creator,
+            boolean explicit, SettableBeanProperty[] properties) {
         if (verifyNonDup(creator, C_PROPS, explicit)) {
             // Better ensure we have no duplicate names either...
             if (properties.length > 1) {
-                HashMap<String,Integer> names = new HashMap<String,Integer>();
+                HashMap<String, Integer> names = new HashMap<String, Integer>();
                 for (int i = 0, len = properties.length; i < len; ++i) {
                     String name = properties[i].getName();
-                    /* [Issue-13]: Need to consider Injectables, which may not have
-                     *   a name at all, and need to be skipped
-                     */
-                    if (name.length() == 0 && properties[i].getInjectableValueId() != null) {
+                    // Need to consider Injectables, which may not have
+                    // a name at all, and need to be skipped
+                    if (name.length() == 0
+                            && properties[i].getInjectableValueId() != null) {
                         continue;
                     }
                     Integer old = names.put(name, Integer.valueOf(i));
                     if (old != null) {
-                        throw new IllegalArgumentException("Duplicate creator property \""+name+"\" (index "+old+" vs "+i+")");
+                        throw new IllegalArgumentException(String.format(
+                                "Duplicate creator property \"%s\" (index %s vs %d)",
+                                name, old, i));
                     }
                 }
             }
@@ -204,42 +200,47 @@
     }
 
     // Bunch of methods deprecated in 2.5, to be removed from 2.6 or later
-    
+
     @Deprecated // since 2.5
     public void addStringCreator(AnnotatedWithParams creator) {
         addStringCreator(creator, false);
     }
+
     @Deprecated // since 2.5
     public void addIntCreator(AnnotatedWithParams creator) {
         addBooleanCreator(creator, false);
     }
+
     @Deprecated // since 2.5
     public void addLongCreator(AnnotatedWithParams creator) {
         addBooleanCreator(creator, false);
     }
+
     @Deprecated // since 2.5
     public void addDoubleCreator(AnnotatedWithParams creator) {
         addBooleanCreator(creator, false);
     }
+
     @Deprecated // since 2.5
     public void addBooleanCreator(AnnotatedWithParams creator) {
         addBooleanCreator(creator, false);
     }
 
     @Deprecated // since 2.5
-    public void addDelegatingCreator(AnnotatedWithParams creator, CreatorProperty[] injectables) {
+    public void addDelegatingCreator(AnnotatedWithParams creator,
+            CreatorProperty[] injectables) {
         addDelegatingCreator(creator, false, injectables);
     }
 
     @Deprecated // since 2.5
-    public void addPropertyCreator(AnnotatedWithParams creator, CreatorProperty[] properties) {
+    public void addPropertyCreator(AnnotatedWithParams creator,
+            CreatorProperty[] properties) {
         addPropertyCreator(creator, false, properties);
     }
 
     /*
-    /**********************************************************
-    /* Accessors
-    /**********************************************************
+     * /********************************************************** /* Accessors
+     * /**********************************************************
      */
 
     /**
@@ -262,16 +263,14 @@
     public boolean hasPropertyBasedCreator() {
         return _creators[C_PROPS] != null;
     }
-    
+
     /*
-    /**********************************************************
-    /* Helper methods
-    /**********************************************************
+     * /********************************************************** /* Helper
+     * methods /**********************************************************
      */
 
     private JavaType _computeDelegateType(AnnotatedWithParams creator,
-            SettableBeanProperty[] delegateArgs)
-    {
+            SettableBeanProperty[] delegateArgs) {
         if (!_hasNonDefaultCreator || (creator == null)) {
             return null;
         }
@@ -288,10 +287,10 @@
         return creator.getParameterType(ix);
     }
 
-    private <T extends AnnotatedMember> T _fixAccess(T member)
-    {
+    private <T extends AnnotatedMember> T _fixAccess(T member) {
         if (member != null && _canFixAccess) {
-            ClassUtil.checkAndFixAccess((Member) member.getAnnotated(), _forceAccess);
+            ClassUtil.checkAndFixAccess((Member) member.getAnnotated(),
+                    _forceAccess);
         }
         return member;
     }
@@ -326,11 +325,27 @@
                 Class<?> newType = newOne.getRawParameterType(0);
 
                 if (oldType == newType) {
-                    throw new IllegalArgumentException("Conflicting "+TYPE_DESCS[typeIndex]
-                            +" creators: already had explicitly marked "+oldOne+", encountered "+newOne);
+                    // 13-Jul-2016, tatu: One more thing to check; since Enum
+                    // classes always have
+                    // implicitly created `valueOf()`, let's resolve in favor of
+                    // other implicit
+                    // creator (`fromString()`)
+                    if (_isEnumValueOf(newOne)) {
+                        return false; // ignore
+                    }
+                    if (_isEnumValueOf(oldOne)) {
+                        ;
+                    } else {
+                        throw new IllegalArgumentException(String.format(
+                                "Conflicting %s creators: already had %s creator %s, encountered another: %s",
+                                TYPE_DESCS[typeIndex],
+                                explicit ? "explicitly marked"
+                                        : "implicitly discovered",
+                                oldOne, newOne));
+                    }
                 }
                 // otherwise, which one to choose?
-                if (newType.isAssignableFrom(oldType)) {
+                else if (newType.isAssignableFrom(oldType)) {
                     // new type more generic, use old
                     return false;
                 }
@@ -344,53 +359,179 @@
         return true;
     }
 
+    /**
+     * Helper method for recognizing `Enum.valueOf()` factory method
+     *
+     * @since 2.8.1
+     */
+    protected boolean _isEnumValueOf(AnnotatedWithParams creator) {
+        return creator.getDeclaringClass().isEnum()
+                && "valueOf".equals(creator.getName());
+    }
+
     /*
     /**********************************************************
     /* Helper class(es)
     /**********************************************************
      */
 
-    protected final static class Vanilla
-        extends ValueInstantiator
-        implements java.io.Serializable
-    {
+    /**
+     * Replacement for default constructor to use for a small set of
+     * "well-known" types.
+     * <p>
+     * Note: replaces earlier <code>Vanilla</code>
+     * <code>ValueInstantiator</code> implementation
+     *
+     * @since 2.8.1 (replacing earlier <code>Vanilla</code> instantiator
+     */
+    protected final static class StdTypeConstructor extends AnnotatedWithParams
+            implements java.io.Serializable {
         private static final long serialVersionUID = 1L;
 
-        public final static int TYPE_COLLECTION = 1;
-        public final static int TYPE_MAP = 2;
-        public final static int TYPE_HASH_MAP = 3;
+        public final static int TYPE_ARRAY_LIST = 1;
+        public final static int TYPE_HASH_MAP = 2;
+        public final static int TYPE_LINKED_HASH_MAP = 3;
+
+        private final AnnotatedWithParams _base;
 
         private final int _type;
-        
-        public Vanilla(int t) {
+
+        public StdTypeConstructor(AnnotatedWithParams base, int t) {
+            super(base, null);
+            _base = base;
             _type = t;
         }
-        
-        
-        @Override
-        public String getValueTypeDesc() {
-            switch (_type) {
-            case TYPE_COLLECTION: return ArrayList.class.getName();
-            case TYPE_MAP: return LinkedHashMap.class.getName();
-            case TYPE_HASH_MAP: return HashMap.class.getName();
+
+        public static AnnotatedWithParams tryToOptimize(
+                AnnotatedWithParams src) {
+            if (src != null) {
+                final Class<?> rawType = src.getDeclaringClass();
+                if (rawType == List.class || rawType == ArrayList.class) {
+                    return new StdTypeConstructor(src, TYPE_ARRAY_LIST);
+                }
+                if (rawType == LinkedHashMap.class) {
+                    return new StdTypeConstructor(src, TYPE_LINKED_HASH_MAP);
+                }
+                if (rawType == HashMap.class) {
+                    return new StdTypeConstructor(src, TYPE_HASH_MAP);
+                }
             }
-            return Object.class.getName();
+            return src;
+        }
+
+        protected final Object _construct() {
+            switch (_type) {
+            case TYPE_ARRAY_LIST:
+                return new ArrayList<Object>();
+            case TYPE_LINKED_HASH_MAP:
+                return new LinkedHashMap<String, Object>();
+            case TYPE_HASH_MAP:
+                return new HashMap<String, Object>();
+            }
+            throw new IllegalStateException("Unknown type " + _type);
         }
 
         @Override
-        public boolean canInstantiate() { return true; }
+        public int getParameterCount() {
+            return _base.getParameterCount();
+        }
 
         @Override
-        public boolean canCreateUsingDefault() {  return true; }
+        public Class<?> getRawParameterType(int index) {
+            return _base.getRawParameterType(index);
+        }
 
         @Override
-        public Object createUsingDefault(DeserializationContext ctxt) throws IOException {
-            switch (_type) {
-            case TYPE_COLLECTION: return new ArrayList<Object>();
-            case TYPE_MAP: return new LinkedHashMap<String,Object>();
-            case TYPE_HASH_MAP: return new HashMap<String,Object>();
-            }
-            throw new IllegalStateException("Unknown type "+_type);
+        public JavaType getParameterType(int index) {
+            return _base.getParameterType(index);
+        }
+
+        @Override
+        @Deprecated
+        public Type getGenericParameterType(int index) {
+            return _base.getGenericParameterType(index);
+        }
+
+        @Override
+        public Object call() throws Exception {
+            return _construct();
+        }
+
+        @Override
+        public Object call(Object[] args) throws Exception {
+            return _construct();
+        }
+
+        @Override
+        public Object call1(Object arg) throws Exception {
+            return _construct();
+        }
+
+        @Override
+        public Class<?> getDeclaringClass() {
+            return _base.getDeclaringClass();
+        }
+
+        @Override
+        public Member getMember() {
+            return _base.getMember();
+        }
+
+        @Override
+        public void setValue(Object pojo, Object value)
+                throws UnsupportedOperationException, IllegalArgumentException {
+            throw new UnsupportedOperationException();
+        }
+
+        @Override
+        public Object getValue(Object pojo)
+                throws UnsupportedOperationException, IllegalArgumentException {
+            throw new UnsupportedOperationException();
+        }
+
+        @Override
+        public Annotated withAnnotations(AnnotationMap fallback) {
+            throw new UnsupportedOperationException();
+        }
+
+        @Override
+        public AnnotatedElement getAnnotated() {
+            return _base.getAnnotated();
+        }
+
+        @Override
+        protected int getModifiers() {
+            return _base.getMember().getModifiers();
+        }
+
+        @Override
+        public String getName() {
+            return _base.getName();
+        }
+
+        @Override
+        public JavaType getType() {
+            return _base.getType();
+        }
+
+        @Override
+        public Class<?> getRawType() {
+            return _base.getRawType();
+        }
+
+        @Override
+        public boolean equals(Object o) {
+            return (o == this);
+        }
+
+        @Override
+        public int hashCode() {
+            return _base.hashCode();
+        }
+
+        @Override
+        public String toString() {
+            return _base.toString();
         }
     }
 }
diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/impl/ErrorThrowingDeserializer.java b/src/main/java/com/fasterxml/jackson/databind/deser/impl/ErrorThrowingDeserializer.java
new file mode 100644
index 0000000..97d43a6
--- /dev/null
+++ b/src/main/java/com/fasterxml/jackson/databind/deser/impl/ErrorThrowingDeserializer.java
@@ -0,0 +1,29 @@
+package com.fasterxml.jackson.databind.deser.impl;
+
+import java.io.IOException;
+
+import com.fasterxml.jackson.core.JsonParser;
+import com.fasterxml.jackson.databind.DeserializationContext;
+import com.fasterxml.jackson.databind.JsonDeserializer;
+
+/**
+ * A deserializer that stores an {@link Error} caught during constructing
+ * of the deserializer, which needs to be deferred and only during actual
+ * attempt to deserialize a value of given type.
+ * Note that null and empty values can be deserialized without error.
+ * 
+ * @since 2.9 Note: prior to this version was named <code>NoClassDefFoundDeserializer</code>
+ */
+public class ErrorThrowingDeserializer extends JsonDeserializer<Object>
+{
+    private final Error _cause;
+
+    public ErrorThrowingDeserializer(NoClassDefFoundError cause) {
+        _cause = cause;
+    }
+
+    @Override
+    public Object deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException {
+        throw _cause;
+    }
+}
diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/impl/ExternalTypeHandler.java b/src/main/java/com/fasterxml/jackson/databind/deser/impl/ExternalTypeHandler.java
index 26af9bc..4069f38 100644
--- a/src/main/java/com/fasterxml/jackson/databind/deser/impl/ExternalTypeHandler.java
+++ b/src/main/java/com/fasterxml/jackson/databind/deser/impl/ExternalTypeHandler.java
@@ -23,12 +23,12 @@
 
     private final String[] _typeIds;
     private final TokenBuffer[] _tokens;
-    
+
     protected ExternalTypeHandler(ExtTypedProperty[] properties,
             HashMap<String, Integer> nameToPropertyIndex,
             String[] typeIds, TokenBuffer[] tokens)
     {
-        _properties = properties;        
+        _properties = properties;
         _nameToPropertyIndex = nameToPropertyIndex;
         _typeIds = typeIds;
         _tokens = tokens;
@@ -42,7 +42,11 @@
         _typeIds = new String[len];
         _tokens = new TokenBuffer[len];
     }
-    
+
+    /**
+     * Method called to start collection process by creating non-blueprint
+     * instances.
+     */
     public ExternalTypeHandler start() {
         return new ExternalTypeHandler(this);
     }
@@ -53,7 +57,7 @@
      * containing POJO has similarly named property as the external type id;
      * otherwise {@link #handlePropertyValue} should be called instead.
      */
-    public boolean handleTypePropertyValue(JsonParser jp, DeserializationContext ctxt,
+    public boolean handleTypePropertyValue(JsonParser p, DeserializationContext ctxt,
             String propName, Object bean)
         throws IOException
     {
@@ -66,12 +70,12 @@
         if (!prop.hasTypePropertyName(propName)) {
             return false;
         }
-        String typeId = jp.getText();
+        String typeId = p.getText();
         // note: can NOT skip child values (should always be String anyway)
         boolean canDeserialize = (bean != null) && (_tokens[index] != null);
         // Minor optimization: deserialize properties as soon as we have all we need:
         if (canDeserialize) {
-            _deserializeAndSet(jp, ctxt, bean, index, typeId);
+            _deserializeAndSet(p, ctxt, bean, index, typeId);
             // clear stored data, to avoid deserializing+setting twice:
             _tokens[index] = null;
         } else {
@@ -79,7 +83,7 @@
         }
         return true;
     }
-    
+
     /**
      * Method called to ask handler to handle value of given property,
      * at point where parser points to the first token of the value.
@@ -153,15 +157,21 @@
                     }
                     // 26-Oct-2012, tatu: As per [databind#94], must allow use of 'defaultImpl'
                     if (!_properties[i].hasDefaultType()) {
-                        throw ctxt.mappingException("Missing external type id property '%s'",
+                        ctxt.reportMappingException("Missing external type id property '%s'",
                                 _properties[i].getTypePropertyName());                                
+                    } else  {
+                        typeId = _properties[i].getDefaultTypeId();
                     }
-                    typeId = _properties[i].getDefaultTypeId();
                 }
             } else if (_tokens[i] == null) {
                 SettableBeanProperty prop = _properties[i].getProperty();
-                throw ctxt.mappingException("Missing property '%s' for external type id '%s'",
-                        prop.getName(), _properties[i].getTypePropertyName());
+
+                if(prop.isRequired() ||
+                        ctxt.isEnabled(DeserializationFeature.FAIL_ON_MISSING_EXTERNAL_TYPE_ID_PROPERTY)) {
+                    ctxt.reportMappingException("Missing property '%s' for external type id '%s'",
+                            prop.getName(), _properties[i].getTypePropertyName());
+                }
+                return bean;
             }
             _deserializeAndSet(p, ctxt, bean, i, typeId);
         }
@@ -172,7 +182,7 @@
      * Variant called when creation of the POJO involves buffering of creator properties
      * as well as property-based creator.
      */
-    public Object complete(JsonParser jp, DeserializationContext ctxt,
+    public Object complete(JsonParser p, DeserializationContext ctxt,
             PropertyValueBuffer buffer, PropertyBasedCreator creator)
         throws IOException
     {
@@ -181,37 +191,47 @@
         Object[] values = new Object[len];
         for (int i = 0; i < len; ++i) {
             String typeId = _typeIds[i];
+            final ExtTypedProperty extProp = _properties[i];
+
             if (typeId == null) {
                 // let's allow missing both type and property (may already have been set, too)
                 if (_tokens[i] == null) {
                     continue;
                 }
                 // but not just one
-                // 26-Oct-2012, tatu: As per [Issue#94], must allow use of 'defaultImpl'
-                if (!_properties[i].hasDefaultType()) {
-                    throw ctxt.mappingException("Missing external type id property '%s'",
-                            _properties[i].getTypePropertyName());
+                // 26-Oct-2012, tatu: As per [databind#94], must allow use of 'defaultImpl'
+                if (!extProp.hasDefaultType()) {
+                    ctxt.reportMappingException("Missing external type id property '%s'",
+                            extProp.getTypePropertyName());
+                } else {
+                    typeId = extProp.getDefaultTypeId();
                 }
-                typeId = _properties[i].getDefaultTypeId();
             } else if (_tokens[i] == null) {
-                SettableBeanProperty prop = _properties[i].getProperty();
-                throw ctxt.mappingException("Missing property '%s' for external type id '%s'",
+                SettableBeanProperty prop = extProp.getProperty();
+                ctxt.reportMappingException("Missing property '%s' for external type id '%s'",
                         prop.getName(), _properties[i].getTypePropertyName());
             }
-            values[i] = _deserialize(jp, ctxt, i, typeId);
-        }
-        // second: fill in creator properties:
-        for (int i = 0; i < len; ++i) {
-            SettableBeanProperty prop = _properties[i].getProperty();
-            if (creator.findCreatorProperty(prop.getName()) != null) {
+            values[i] = _deserialize(p, ctxt, i, typeId);
+
+            final SettableBeanProperty prop = extProp.getProperty();
+            // also: if it's creator prop, fill in
+            if (prop.getCreatorIndex() >= 0) {
                 buffer.assignParameter(prop, values[i]);
+
+                // [databind#999] And maybe there's creator property for type id too?
+                SettableBeanProperty typeProp = extProp.getTypeProperty();
+                // for now, should only be needed for creator properties, too
+                if ((typeProp != null) && (typeProp.getCreatorIndex() >= 0)) {
+                    buffer.assignParameter(typeProp, typeId);
+                }
             }
         }
+
         Object bean = creator.build(ctxt, buffer);
         // third: assign non-creator properties
         for (int i = 0; i < len; ++i) {
             SettableBeanProperty prop = _properties[i].getProperty();
-            if (creator.findCreatorProperty(prop.getName()) == null) {
+            if (prop.getCreatorIndex() < 0) {
                 prop.set(bean, values[i]);
             }
         }
@@ -285,6 +305,30 @@
             _nameToPropertyIndex.put(typeDeser.getPropertyName(), index);
         }
 
+        /**
+         * Method called after all external properties have been assigned, to further
+         * link property with polymorphic value with possible property for type id
+         * itself. This is needed to support type ids as Creator properties.
+         *
+         * @since 2.8
+         */
+        public ExternalTypeHandler build(BeanPropertyMap otherProps) {
+            // 21-Jun-2016, tatu: as per [databind#999], may need to link type id property also
+            final int len = _properties.size();
+            ExtTypedProperty[] extProps = new ExtTypedProperty[len];
+            for (int i = 0; i < len; ++i) {
+                ExtTypedProperty extProp = _properties.get(i);
+                String typePropId = extProp.getTypePropertyName();
+                SettableBeanProperty typeProp = otherProps.find(typePropId);
+                if (typeProp != null) {
+                    extProp.linkTypeProperty(typeProp);
+                }
+                extProps[i] = extProp;
+            }
+            return new ExternalTypeHandler(extProps, _nameToPropertyIndex, null, null);
+        }
+
+        @Deprecated // since 2.8; may be removed as early as 2.9
         public ExternalTypeHandler build() {
             return new ExternalTypeHandler(_properties.toArray(new ExtTypedProperty[_properties.size()]),
                     _nameToPropertyIndex, null, null);
@@ -297,6 +341,11 @@
         private final TypeDeserializer _typeDeserializer;
         private final String _typePropertyName;
 
+        /**
+         * @since 2.8
+         */
+        private SettableBeanProperty _typeProperty;
+
         public ExtTypedProperty(SettableBeanProperty property, TypeDeserializer typeDeser)
         {
             _property = property;
@@ -304,6 +353,13 @@
             _typePropertyName = typeDeser.getPropertyName();
         }
 
+        /**
+         * @since 2.8
+         */
+        public void linkTypeProperty(SettableBeanProperty p) {
+            _typeProperty = p;
+        }
+
         public boolean hasTypePropertyName(String n) {
             return n.equals(_typePropertyName);
         }
@@ -330,5 +386,12 @@
         public SettableBeanProperty getProperty() {
             return _property;
         }
+
+        /**
+         * @since 2.8
+         */
+        public SettableBeanProperty getTypeProperty() {
+            return _typeProperty;
+        }
     }
 }
diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/impl/FailingDeserializer.java b/src/main/java/com/fasterxml/jackson/databind/deser/impl/FailingDeserializer.java
index e6a5a7e..a777bde 100644
--- a/src/main/java/com/fasterxml/jackson/databind/deser/impl/FailingDeserializer.java
+++ b/src/main/java/com/fasterxml/jackson/databind/deser/impl/FailingDeserializer.java
@@ -24,6 +24,7 @@
     
     @Override
     public Object deserialize(JsonParser jp, DeserializationContext ctxt) throws JsonMappingException{
-        throw ctxt.mappingException(_message);
+        ctxt.reportMappingException(_message);
+        return null;
     }
 }
diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/impl/FieldProperty.java b/src/main/java/com/fasterxml/jackson/databind/deser/impl/FieldProperty.java
index 15fca54..756dda2 100644
--- a/src/main/java/com/fasterxml/jackson/databind/deser/impl/FieldProperty.java
+++ b/src/main/java/com/fasterxml/jackson/databind/deser/impl/FieldProperty.java
@@ -12,6 +12,7 @@
 import com.fasterxml.jackson.databind.introspect.BeanPropertyDefinition;
 import com.fasterxml.jackson.databind.jsontype.TypeDeserializer;
 import com.fasterxml.jackson.databind.util.Annotations;
+import com.fasterxml.jackson.databind.util.ClassUtil;
 
 /**
  * This concrete sub-class implements property that is set
@@ -72,9 +73,18 @@
     
     @Override
     public FieldProperty withValueDeserializer(JsonDeserializer<?> deser) {
+        if (_valueDeserializer == deser) {
+            return this;
+        }
         return new FieldProperty(this, deser);
     }
-    
+
+    @Override
+    public void fixAccess(DeserializationConfig config) {
+        ClassUtil.checkAndFixAccess(_field,
+                config.isEnabled(MapperFeature.OVERRIDE_PUBLIC_ACCESS_MODIFIERS));
+    }
+
     /*
     /**********************************************************
     /* BeanProperty impl
@@ -125,7 +135,7 @@
         try {
             _field.set(instance, value);
         } catch (Exception e) {
-            // 15-Sep-2015, tatu: How coud we get a ref to JsonParser?
+            // 15-Sep-2015, tatu: How could we get a ref to JsonParser?
             _throwAsIOE(e, value);
         }
     }
@@ -136,7 +146,7 @@
         try {
             _field.set(instance, value);
         } catch (Exception e) {
-            // 15-Sep-2015, tatu: How coud we get a ref to JsonParser?
+            // 15-Sep-2015, tatu: How could we get a ref to JsonParser?
             _throwAsIOE(e, value);
         }
         return instance;
diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/impl/InnerClassProperty.java b/src/main/java/com/fasterxml/jackson/databind/deser/impl/InnerClassProperty.java
index 4a9ca99..cac8057 100644
--- a/src/main/java/com/fasterxml/jackson/databind/deser/impl/InnerClassProperty.java
+++ b/src/main/java/com/fasterxml/jackson/databind/deser/impl/InnerClassProperty.java
@@ -81,6 +81,9 @@
 
     @Override
     public InnerClassProperty withValueDeserializer(JsonDeserializer<?> deser) {
+        if (_valueDeserializer == deser) {
+            return this;
+        }
         return new InnerClassProperty(this, deser);
     }
 
@@ -93,6 +96,11 @@
     @Override
     public int getCreatorIndex() { return _delegate.getCreatorIndex(); }
     
+    @Override
+    public void fixAccess(DeserializationConfig config) {
+        _delegate.fixAccess(config);
+    }
+
     // // // BeanProperty impl
     
     @Override
diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/impl/ManagedReferenceProperty.java b/src/main/java/com/fasterxml/jackson/databind/deser/impl/ManagedReferenceProperty.java
index 028cc09..21b465a 100644
--- a/src/main/java/com/fasterxml/jackson/databind/deser/impl/ManagedReferenceProperty.java
+++ b/src/main/java/com/fasterxml/jackson/databind/deser/impl/ManagedReferenceProperty.java
@@ -6,10 +6,7 @@
 import java.util.Map;
 
 import com.fasterxml.jackson.core.JsonParser;
-
-import com.fasterxml.jackson.databind.DeserializationContext;
-import com.fasterxml.jackson.databind.JsonDeserializer;
-import com.fasterxml.jackson.databind.PropertyName;
+import com.fasterxml.jackson.databind.*;
 import com.fasterxml.jackson.databind.deser.SettableBeanProperty;
 import com.fasterxml.jackson.databind.introspect.AnnotatedMember;
 import com.fasterxml.jackson.databind.util.Annotations;
@@ -25,17 +22,17 @@
     private static final long serialVersionUID = 1L;
 
     protected final String _referenceName;
-    
+
     /**
      * Flag that indicates whether property to handle is a container type
      * (array, Collection, Map) or not.
      */
     protected final boolean _isContainer;
-    
+
     protected final SettableBeanProperty _managedProperty;
 
     protected final SettableBeanProperty _backProperty;
-    
+
     public ManagedReferenceProperty(SettableBeanProperty forward, String refName,
             SettableBeanProperty backward, Annotations contextAnnotations, boolean isContainer)
     {
@@ -69,18 +66,27 @@
     public ManagedReferenceProperty withName(PropertyName newName) {
         return new ManagedReferenceProperty(this, newName);
     }
-    
+
     @Override
     public ManagedReferenceProperty withValueDeserializer(JsonDeserializer<?> deser) {
+        if (_valueDeserializer == deser) {
+            return this;
+        }
         return new ManagedReferenceProperty(this, deser);
     }
-    
+ 
+    @Override
+    public void fixAccess(DeserializationConfig config) {
+        _managedProperty.fixAccess(config);
+        _backProperty.fixAccess(config);
+    }
+
     /*
     /**********************************************************
     /* BeanProperty impl
     /**********************************************************
      */
-    
+
     @Override
     public <A extends Annotation> A getAnnotation(Class<A> acls) {
         return _managedProperty.getAnnotation(acls);
diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/impl/MethodProperty.java b/src/main/java/com/fasterxml/jackson/databind/deser/impl/MethodProperty.java
index 86d8f9a..bf4e0fe 100644
--- a/src/main/java/com/fasterxml/jackson/databind/deser/impl/MethodProperty.java
+++ b/src/main/java/com/fasterxml/jackson/databind/deser/impl/MethodProperty.java
@@ -66,9 +66,18 @@
     
     @Override
     public MethodProperty withValueDeserializer(JsonDeserializer<?> deser) {
+        if (_valueDeserializer == deser) {
+            return this;
+        }
         return new MethodProperty(this, deser);
     }
-    
+
+    @Override
+    public void fixAccess(DeserializationConfig config) {
+        _annotated.fixAccess(
+                config.isEnabled(MapperFeature.OVERRIDE_PUBLIC_ACCESS_MODIFIERS));
+    }
+
     /*
     /**********************************************************
     /* BeanProperty impl
@@ -113,7 +122,7 @@
             return null;
         }
     }
-    
+
     @Override
     public final void set(Object instance, Object value) throws IOException
     {
diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/impl/NoClassDefFoundDeserializer.java b/src/main/java/com/fasterxml/jackson/databind/deser/impl/NoClassDefFoundDeserializer.java
deleted file mode 100644
index a094670..0000000
--- a/src/main/java/com/fasterxml/jackson/databind/deser/impl/NoClassDefFoundDeserializer.java
+++ /dev/null
@@ -1,30 +0,0 @@
-package com.fasterxml.jackson.databind.deser.impl;
-
-import java.io.IOException;
-
-import com.fasterxml.jackson.core.JsonParser;
-import com.fasterxml.jackson.databind.DeserializationContext;
-import com.fasterxml.jackson.databind.JsonDeserializer;
-
-/**
- * A deserializer that stores a {@link NoClassDefFoundError} error
- * and throws the stored exception when attempting to deserialize
- * a value. Null and empty values can be deserialized without error.
- * 
- * @since 2.5
- */
-public class NoClassDefFoundDeserializer<T> extends JsonDeserializer<T>
-{
-    private final NoClassDefFoundError _cause;
-
-    public NoClassDefFoundDeserializer(NoClassDefFoundError cause)
-    {
-        _cause = cause;
-    }
-
-    @Override
-    public T deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
-    {
-        throw _cause;
-    }
-}
diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/impl/NullProvider.java b/src/main/java/com/fasterxml/jackson/databind/deser/impl/NullProvider.java
deleted file mode 100644
index 24ec174..0000000
--- a/src/main/java/com/fasterxml/jackson/databind/deser/impl/NullProvider.java
+++ /dev/null
@@ -1,39 +0,0 @@
-package com.fasterxml.jackson.databind.deser.impl;
-
-import com.fasterxml.jackson.core.JsonProcessingException;
-import com.fasterxml.jackson.databind.DeserializationContext;
-import com.fasterxml.jackson.databind.DeserializationFeature;
-import com.fasterxml.jackson.databind.JavaType;
-
-/**
- * @deprecated
- */
-@Deprecated // since 2.6, remove in 2.7
-public final class NullProvider
-    implements java.io.Serializable
-{
-    private static final long serialVersionUID = 1L;
-
-    private final Object _nullValue;
-
-    private final boolean _isPrimitive;
-    
-    private final Class<?> _rawType;
-    
-    public NullProvider(JavaType type, Object nullValue)
-    {
-        _nullValue = nullValue;
-        _isPrimitive = type.isPrimitive();
-        _rawType = type.getRawClass();
-    }
-
-    public Object nullValue(DeserializationContext ctxt) throws JsonProcessingException
-    {
-        if (_isPrimitive && ctxt.isEnabled(DeserializationFeature.FAIL_ON_NULL_FOR_PRIMITIVES)) {
-            throw ctxt.mappingException("Can not map JSON null into type %s"
-                    +" (set DeserializationConfig.DeserializationFeature.FAIL_ON_NULL_FOR_PRIMITIVES to 'false' to allow)",
-                    _rawType.getName());                    
-        }
-        return _nullValue;
-    }
-}
\ No newline at end of file
diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/impl/ObjectIdReferenceProperty.java b/src/main/java/com/fasterxml/jackson/databind/deser/impl/ObjectIdReferenceProperty.java
index c77d756..2034d91 100644
--- a/src/main/java/com/fasterxml/jackson/databind/deser/impl/ObjectIdReferenceProperty.java
+++ b/src/main/java/com/fasterxml/jackson/databind/deser/impl/ObjectIdReferenceProperty.java
@@ -40,6 +40,9 @@
 
     @Override
     public SettableBeanProperty withValueDeserializer(JsonDeserializer<?> deser) {
+        if (_valueDeserializer == deser) {
+            return this;
+        }
         return new ObjectIdReferenceProperty(this, deser);
     }
 
@@ -49,6 +52,13 @@
     }
 
     @Override
+    public void fixAccess(DeserializationConfig config) {
+        if (_forward != null) {
+            _forward.fixAccess(config);
+        }
+    }
+
+    @Override
     public <A extends Annotation> A getAnnotation(Class<A> acls) {
         return _forward.getAnnotation(acls);
     }
diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/impl/ObjectIdValueProperty.java b/src/main/java/com/fasterxml/jackson/databind/deser/impl/ObjectIdValueProperty.java
index 4847c3c..4787fd0 100644
--- a/src/main/java/com/fasterxml/jackson/databind/deser/impl/ObjectIdValueProperty.java
+++ b/src/main/java/com/fasterxml/jackson/databind/deser/impl/ObjectIdValueProperty.java
@@ -47,6 +47,9 @@
 
     @Override
     public ObjectIdValueProperty withValueDeserializer(JsonDeserializer<?> deser) {
+        if (_valueDeserializer == deser) {
+            return this;
+        }
         return new ObjectIdValueProperty(this, deser);
     }
     
diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/impl/PropertyBasedCreator.java b/src/main/java/com/fasterxml/jackson/databind/deser/impl/PropertyBasedCreator.java
index f1d35ec..f0c4093 100644
--- a/src/main/java/com/fasterxml/jackson/databind/deser/impl/PropertyBasedCreator.java
+++ b/src/main/java/com/fasterxml/jackson/databind/deser/impl/PropertyBasedCreator.java
@@ -8,6 +8,7 @@
 
 import com.fasterxml.jackson.databind.DeserializationContext;
 import com.fasterxml.jackson.databind.JsonMappingException;
+import com.fasterxml.jackson.databind.MapperFeature;
 import com.fasterxml.jackson.databind.deser.SettableBeanProperty;
 import com.fasterxml.jackson.databind.deser.ValueInstantiator;
 
@@ -21,8 +22,18 @@
  */
 public final class PropertyBasedCreator
 {
+    /**
+     * Number of properties: usually same as size of {@link #_propertyLookup},
+     * but not necessarily, when we have unnamed injectable properties.
+     */
+    protected final int _propertyCount;
+
+    /**
+     * Helper object that knows how to actually construct the instance by
+     * invoking creator method with buffered arguments.
+     */
     protected final ValueInstantiator _valueInstantiator;
-    
+
     /**
      * Map that contains property objects for either constructor or factory
      * method (whichever one is null: one property for each
@@ -31,28 +42,27 @@
     protected final HashMap<String, SettableBeanProperty> _propertyLookup;
 
     /**
-     * Number of properties: usually same as size of {@link #_propertyLookup},
-     * but not necessarily, when we have unnamed injectable properties.
-     */
-    protected final int _propertyCount;
-
-    /**
      * Array that contains properties that expect value to inject, if any;
      * null if no injectable values are expected.
      */
     protected final SettableBeanProperty[] _allProperties;
-    
+
     /*
     /**********************************************************
     /* Construction, initialization
     /**********************************************************
      */
-    
+
     protected PropertyBasedCreator(ValueInstantiator valueInstantiator,
-            SettableBeanProperty[] creatorProps)
+            SettableBeanProperty[] creatorProps,
+            boolean caseInsensitive)
     {
         _valueInstantiator = valueInstantiator;
-        _propertyLookup = new HashMap<String, SettableBeanProperty>();
+        if (caseInsensitive) {
+            _propertyLookup = new CaseInsensitiveMap();
+        } else {
+            _propertyLookup = new HashMap<String, SettableBeanProperty>();
+        }
         final int len = creatorProps.length;
         _propertyCount = len;
         _allProperties = new SettableBeanProperty[len];
@@ -79,24 +89,17 @@
                 prop = prop.withValueDeserializer(ctxt.findContextualValueDeserializer(prop.getType(), prop));
             }
             creatorProps[i] = prop;
-        }        
-        return new PropertyBasedCreator(valueInstantiator, creatorProps);
+        }
+        return new PropertyBasedCreator(valueInstantiator, creatorProps,
+                ctxt.isEnabled(MapperFeature.ACCEPT_CASE_INSENSITIVE_PROPERTIES));
     }
 
-    // 05-May-2015, tatu: Does not seem to be used, commented out in 2.6
-    /*
-    public void assignDeserializer(SettableBeanProperty prop, JsonDeserializer<Object> deser) {
-        prop = prop.withValueDeserializer(deser);
-        _properties.put(prop.getName(), prop);
-    }
-    */
-    
     /*
     /**********************************************************
     /* Accessors
     /**********************************************************
      */
-    
+
     public Collection<SettableBeanProperty> properties() {
         return _propertyLookup.values();
     }
@@ -113,7 +116,7 @@
         }
         return null;
     }
-    
+
     /*
     /**********************************************************
     /* Building process
@@ -133,7 +136,7 @@
     public Object build(DeserializationContext ctxt, PropertyValueBuffer buffer) throws IOException
     {
         Object bean = _valueInstantiator.createFromObjectWith(ctxt,
-                buffer.getParameters(_allProperties));
+                _allProperties, buffer);
         // returning null isn't quite legal, but let's let caller deal with that
         if (bean != null) {
             // Object Id to handle?
@@ -146,4 +149,33 @@
         }
         return bean;
     }
+
+    /*
+    /**********************************************************
+    /* Helper classes
+    /**********************************************************
+     */
+
+    /**
+     * Simple override of standard {@link java.util.HashMap} to support
+     * case-insensitive access to creator properties.
+     *
+     * @since 2.8.5
+     */
+    static class CaseInsensitiveMap extends HashMap<String, SettableBeanProperty>
+    {
+        private static final long serialVersionUID = 1L;
+
+        @Override
+        public SettableBeanProperty get(Object key0) {
+            String key = (String) key0;
+            return super.get(key.toLowerCase());
+        }
+
+        @Override
+        public SettableBeanProperty put(String key, SettableBeanProperty value) {
+            key = key.toLowerCase();
+            return super.put(key, value);
+        }
+    }
 }
diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/impl/PropertyValueBuffer.java b/src/main/java/com/fasterxml/jackson/databind/deser/impl/PropertyValueBuffer.java
index 5ba7332..73238b2 100644
--- a/src/main/java/com/fasterxml/jackson/databind/deser/impl/PropertyValueBuffer.java
+++ b/src/main/java/com/fasterxml/jackson/databind/deser/impl/PropertyValueBuffer.java
@@ -82,10 +82,10 @@
     /**********************************************************
      */
     
-    public PropertyValueBuffer(JsonParser jp, DeserializationContext ctxt, int paramCount,
+    public PropertyValueBuffer(JsonParser p, DeserializationContext ctxt, int paramCount,
             ObjectIdReader oir)
     {
-        _parser = jp;
+        _parser = p;
         _context = ctxt;
         _paramsNeeded = paramCount;
         _objectIdReader = oir;
@@ -98,13 +98,54 @@
     }
 
     /**
+     * Returns {@code true} if the given property was seen in the JSON source by
+     * this buffer.
+     *
+     * @since 2.8
+     */
+    public final boolean hasParameter(SettableBeanProperty prop)
+    {
+        if (_paramsSeenBig == null) {
+            return ((_paramsSeen >> prop.getCreatorIndex()) & 1) == 1;
+        }
+        return _paramsSeenBig.get(prop.getCreatorIndex());
+    }
+
+    /**
+     * A variation of {@link #getParameters(SettableBeanProperty[])} that
+     * accepts a single property.  Whereas the plural form eagerly fetches and
+     * validates all properties, this method may be used (along with
+     * {@link #hasParameter(SettableBeanProperty)}) to let applications only
+     * fetch the properties defined in the JSON source itself, and to have some
+     * other customized behavior for missing properties.
+     *
+     * @since 2.8
+     */
+    public Object getParameter(SettableBeanProperty prop)
+        throws JsonMappingException
+    {
+        Object value;
+        if (hasParameter(prop)) {
+            value = _creatorParameters[prop.getCreatorIndex()];
+        } else {
+            value = _creatorParameters[prop.getCreatorIndex()] = _findMissing(prop);
+        }
+        if (value == null && _context.isEnabled(DeserializationFeature.FAIL_ON_NULL_CREATOR_PROPERTIES)) {
+            throw _context.mappingException(
+                "Null value for creator property '%s'; DeserializationFeature.FAIL_ON_NULL_FOR_CREATOR_PARAMETERS enabled",
+                prop.getName(), prop.getCreatorIndex());
+        }
+        return value;
+    }
+
+    /**
      * Method called to do necessary post-processing such as injection of values
      * and verification of values for required properties,
      * after either {@link #assignParameter(SettableBeanProperty, Object)}
      * returns <code>true</code> (to indicate all creator properties are found), or when
      * then whole JSON Object has been processed,
      */
-    protected Object[] getParameters(SettableBeanProperty[] props)
+    public Object[] getParameters(SettableBeanProperty[] props)
         throws JsonMappingException
     {
         // quick check to see if anything else is needed
@@ -125,6 +166,16 @@
                 }
             }
         }
+
+        if (_context.isEnabled(DeserializationFeature.FAIL_ON_NULL_CREATOR_PROPERTIES)) {
+            for (int ix = 0; ix < props.length; ++ix) {
+              if (_creatorParameters[ix] == null) {
+                  _context.reportMappingException("Null value for creator property '%s'; DeserializationFeature.FAIL_ON_NULL_FOR_CREATOR_PARAMETERS enabled",
+                          props[ix].getName(), props[ix].getCreatorIndex());
+              }
+            }
+        }
+
         return _creatorParameters;
     }
 
@@ -138,11 +189,11 @@
         }
         // Second: required?
         if (prop.isRequired()) {
-            throw _context.mappingException("Missing required creator property '%s' (index %d)",
+            _context.reportMappingException("Missing required creator property '%s' (index %d)",
                     prop.getName(), prop.getCreatorIndex());
         }
         if (_context.isEnabled(DeserializationFeature.FAIL_ON_MISSING_CREATOR_PROPERTIES)) {
-            throw _context.mappingException("Missing creator property '%s' (index %d); DeserializationFeature.FAIL_ON_MISSING_CREATOR_PROPERTIES enabled",
+            _context.reportMappingException("Missing creator property '%s' (index %d); DeserializationFeature.FAIL_ON_MISSING_CREATOR_PROPERTIES enabled",
                     prop.getName(), prop.getCreatorIndex());
         }
         // Third: default value
@@ -156,7 +207,6 @@
     /**********************************************************
      */
 
-
     /**
      * Helper method called to see if given non-creator property is the "id property";
      * and if so, handle appropriately.
@@ -187,9 +237,8 @@
                     return idProp.setAndReturn(bean, _idValue);
                 }
             } else {
-                // TODO: is this an error case?
-                throw ctxt.mappingException("No _idValue when handleIdValue called, on instance of %s",
-                        bean.getClass().getName());
+                // 07-Jun-2016, tatu: Trying to improve error messaging here...
+                ctxt.reportUnresolvedObjectId(_objectIdReader, bean);
             }
         }
         return bean;
@@ -200,6 +249,9 @@
     public boolean isComplete() { return _paramsNeeded <= 0; }
 
     /**
+     * Method called to buffer value for given property, as well as check whether
+     * we now have values for all (creator) properties that we expect to get values for.
+     *
      * @return True if we have received all creator parameters
      * 
      * @since 2.6
@@ -215,30 +267,21 @@
             if (old != newValue) {
                 _paramsSeen = newValue;
                 if (--_paramsNeeded <= 0) {
-                    return true;
+                    // 29-Nov-2016, tatu: But! May still require Object Id value
+                    return (_objectIdReader == null) || (_idValue != null);
                 }
             }
         } else {
             if (!_paramsSeenBig.get(ix)) {
                 _paramsSeenBig.set(ix);
                 if (--_paramsNeeded <= 0) {
-                    return true;
+                    // 29-Nov-2016, tatu: But! May still require Object Id value
                 }
             }
         }
         return false;
     }
-    
-    /**
-     * @deprecated Since 2.6
-     */
-    @Deprecated
-    public boolean assignParameter(int index, Object value) {
-        // !!! TODO: remove from 2.7
-        _creatorParameters[index] = value;
-        return false;
-    }
-    
+
     public void bufferProperty(SettableBeanProperty prop, Object value) {
         _buffered = new PropertyValue.Regular(_buffered, value, prop);
     }
@@ -251,4 +294,3 @@
         _buffered = new PropertyValue.Map(_buffered, value, key);
     }
 }
-
diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/impl/ReadableObjectId.java b/src/main/java/com/fasterxml/jackson/databind/deser/impl/ReadableObjectId.java
index a06d80c..6c3b804 100644
--- a/src/main/java/com/fasterxml/jackson/databind/deser/impl/ReadableObjectId.java
+++ b/src/main/java/com/fasterxml/jackson/databind/deser/impl/ReadableObjectId.java
@@ -9,6 +9,7 @@
 import com.fasterxml.jackson.annotation.ObjectIdResolver;
 import com.fasterxml.jackson.core.JsonLocation;
 import com.fasterxml.jackson.databind.DeserializationContext;
+import com.fasterxml.jackson.databind.JavaType;
 import com.fasterxml.jackson.databind.deser.UnresolvedForwardReference;
 
 /**
@@ -18,14 +19,9 @@
 public class ReadableObjectId
 {
     /**
-     * @deprecated Change visibility, if possible; prefer using {@link #resolve()}, which is able
-     *    to handle external id resolving mechanism.
+     * @since 2.8 (with this name, formerly `public Object item`)
      */
-    @Deprecated // at least since 2.5. Remove from 2.7
-    public Object item;
-
-    @Deprecated
-    public final Object id;
+    protected Object _item;
 
     protected final ObjectIdGenerator.IdKey _key;
 
@@ -33,15 +29,8 @@
 
     protected ObjectIdResolver _resolver;
 
-    @Deprecated // at least since 2.5. Remove from 2.7
-    public ReadableObjectId(Object id) {
-        this.id = id;
-        _key = null;
-    }
-
     public ReadableObjectId(ObjectIdGenerator.IdKey key) {
         _key = key;
-        id = key.key;
     }
 
     public void setResolver(ObjectIdResolver resolver) {
@@ -66,7 +55,8 @@
     public void bindItem(Object ob) throws IOException
     {
         _resolver.bindItem(_key, ob);
-        item = ob;
+        _item = ob;
+        Object id = _key.key;
         if (_referringProperties != null) {
             Iterator<Referring> it = _referringProperties.iterator();
             _referringProperties = null;
@@ -77,7 +67,7 @@
     }
 
     public Object resolve(){
-         return (item = _resolver.resolveId(_key));
+         return (_item = _resolver.resolveId(_key));
     }
 
     public boolean hasReferringProperties() {
@@ -144,6 +134,11 @@
             _beanType = beanType;
         }
 
+        public Referring(UnresolvedForwardReference ref, JavaType beanType) {
+            _reference = ref;
+            _beanType = beanType.getRawClass();
+        }
+
         public JsonLocation getLocation() { return _reference.getLocation(); }
         public Class<?> getBeanType() { return _beanType; }
 
diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/impl/SetterlessProperty.java b/src/main/java/com/fasterxml/jackson/databind/deser/impl/SetterlessProperty.java
index 4daaaed..8df84b6 100644
--- a/src/main/java/com/fasterxml/jackson/databind/deser/impl/SetterlessProperty.java
+++ b/src/main/java/com/fasterxml/jackson/databind/deser/impl/SetterlessProperty.java
@@ -33,7 +33,8 @@
     protected final Method _getter;
 
     public SetterlessProperty(BeanPropertyDefinition propDef, JavaType type,
-            TypeDeserializer typeDeser, Annotations contextAnnotations, AnnotatedMethod method) {
+            TypeDeserializer typeDeser, Annotations contextAnnotations, AnnotatedMethod method)
+    {
         super(propDef, type, typeDeser, contextAnnotations);
         _annotated = method;
         _getter = method.getAnnotated();
@@ -58,9 +59,18 @@
     
     @Override
     public SetterlessProperty withValueDeserializer(JsonDeserializer<?> deser) {
+        if (_valueDeserializer == deser) {
+            return this;
+        }
         return new SetterlessProperty(this, deser);
     }
-    
+
+    @Override
+    public void fixAccess(DeserializationConfig config) {
+        _annotated.fixAccess(
+                config.isEnabled(MapperFeature.OVERRIDE_PUBLIC_ACCESS_MODIFIERS));
+    }
+
     /*
     /**********************************************************
     /* BeanProperty impl
@@ -94,9 +104,10 @@
 
         // For [#501] fix we need to implement this but:
         if (_valueTypeDeserializer != null) {
-            throw JsonMappingException.from(p,
-                    "Problem deserializing 'setterless' property (\""+getName()+"\"): no way to handle typed deser with setterless yet");
-//            return _valueDeserializer.deserializeWithType(jp, ctxt, _valueTypeDeserializer);
+            ctxt.reportMappingException(
+                    "Problem deserializing 'setterless' property (\"%s\"): no way to handle typed deser with setterless yet",
+                    getName());
+//            return _valueDeserializer.deserializeWithType(p, ctxt, _valueTypeDeserializer);
         }
         
         // Ok: then, need to fetch Collection/Map to modify:
diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/impl/UnwrappedPropertyHandler.java b/src/main/java/com/fasterxml/jackson/databind/deser/impl/UnwrappedPropertyHandler.java
index 181c52a..890ff7b 100644
--- a/src/main/java/com/fasterxml/jackson/databind/deser/impl/UnwrappedPropertyHandler.java
+++ b/src/main/java/com/fasterxml/jackson/databind/deser/impl/UnwrappedPropertyHandler.java
@@ -51,15 +51,15 @@
     }
     
     @SuppressWarnings("resource")
-    public Object processUnwrapped(JsonParser originalParser, DeserializationContext ctxt, Object bean,
-            TokenBuffer buffered)
-        throws IOException, JsonProcessingException
+    public Object processUnwrapped(JsonParser originalParser, DeserializationContext ctxt,
+            Object bean, TokenBuffer buffered)
+        throws IOException
     {
         for (int i = 0, len = _properties.size(); i < len; ++i) {
             SettableBeanProperty prop = _properties.get(i);
-            JsonParser jp = buffered.asParser();
-            jp.nextToken();
-            prop.deserializeAndSet(jp, ctxt, bean);
+            JsonParser p = buffered.asParser();
+            p.nextToken();
+            prop.deserializeAndSet(p, ctxt, bean);
         }
         return bean;
     }
diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/std/AtomicReferenceDeserializer.java b/src/main/java/com/fasterxml/jackson/databind/deser/std/AtomicReferenceDeserializer.java
index eba75e1..8faa423 100644
--- a/src/main/java/com/fasterxml/jackson/databind/deser/std/AtomicReferenceDeserializer.java
+++ b/src/main/java/com/fasterxml/jackson/databind/deser/std/AtomicReferenceDeserializer.java
@@ -1,87 +1,54 @@
 package com.fasterxml.jackson.databind.deser.std;
 
-import java.io.IOException;
 import java.util.concurrent.atomic.AtomicReference;
 
-import com.fasterxml.jackson.core.*;
 import com.fasterxml.jackson.databind.*;
-import com.fasterxml.jackson.databind.deser.ContextualDeserializer;
 import com.fasterxml.jackson.databind.jsontype.TypeDeserializer;
 
 public class AtomicReferenceDeserializer
-    extends StdDeserializer<AtomicReference<?>>
-    implements ContextualDeserializer
+    extends ReferenceTypeDeserializer<AtomicReference<Object>>
 {
     private static final long serialVersionUID = 1L;
 
-    /**
-     * Type of value that we reference
+    /*
+    /**********************************************************
+    /* Life-cycle
+    /**********************************************************
      */
-    protected final JavaType _referencedType;
-    
-    protected final TypeDeserializer _valueTypeDeserializer;
 
-    protected final JsonDeserializer<?> _valueDeserializer;
-
-    /**
-     * @param referencedType Parameterization of this reference
-     */
-    public AtomicReferenceDeserializer(JavaType referencedType) {
-        this(referencedType, null, null);
+    @Deprecated // since 2.8
+    public AtomicReferenceDeserializer(JavaType fullType) {
+        this(fullType, null, null);
     }
 
-    public AtomicReferenceDeserializer(JavaType referencedType,
+    public AtomicReferenceDeserializer(JavaType fullType,
             TypeDeserializer typeDeser, JsonDeserializer<?> deser)
     {
-        super(AtomicReference.class);
-        _referencedType = referencedType;
-        _valueDeserializer = deser;
-        _valueTypeDeserializer = typeDeser;
+        super(fullType, typeDeser, deser);
     }
 
+    /*
+    /**********************************************************
+    /* Abstract method implementations
+    /**********************************************************
+     */
+
+    @Override
     public AtomicReferenceDeserializer withResolved(TypeDeserializer typeDeser, JsonDeserializer<?> valueDeser) {
-        if ((valueDeser == _valueDeserializer) && (typeDeser == _valueTypeDeserializer)) {
-            return this;
-        }
-        return new AtomicReferenceDeserializer(_referencedType, typeDeser, valueDeser);
+        return new AtomicReferenceDeserializer(_fullType, typeDeser, valueDeser);
     }
 
     @Override
-    public AtomicReference<?> getNullValue(DeserializationContext ctxt) {
-        return new AtomicReference<Object>();
-    }
-
-    @Deprecated // remove in 2.7
-    @Override
-    public AtomicReference<?> getNullValue() {
+    public AtomicReference<Object> getNullValue(DeserializationContext ctxt) {
         return new AtomicReference<Object>();
     }
 
     @Override
-    public JsonDeserializer<?> createContextual(DeserializationContext ctxt, BeanProperty property) throws JsonMappingException
-    {
-        JsonDeserializer<?> deser = _valueDeserializer;
-        TypeDeserializer typeDeser = _valueTypeDeserializer;
-        
-        if (deser == null) {
-            deser = ctxt.findContextualValueDeserializer(_referencedType, property);
-        } else { // otherwise directly assigned, probably not contextual yet:
-            deser = ctxt.handleSecondaryContextualization(deser, property, _referencedType);
-        }
-        if (typeDeser != null) {
-            typeDeser = typeDeser.forProperty(property);
-        }
-        return withResolved(typeDeser, deser);
-    }
-
-    @Override
-    public AtomicReference<?> deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
-        Object contents = (_valueTypeDeserializer == null)
-                ? _valueDeserializer.deserialize(p, ctxt)
-                : _valueDeserializer.deserializeWithType(p, ctxt, _valueTypeDeserializer);
+    public AtomicReference<Object> referenceValue(Object contents) {
         return new AtomicReference<Object>(contents);
     }
 
+    /*
     @Override
     public Object deserializeWithType(JsonParser p, DeserializationContext ctxt,
             TypeDeserializer typeDeser) throws IOException
@@ -105,4 +72,5 @@
         }
         return new AtomicReference<Object>(_valueTypeDeserializer.deserializeTypedFromAny(p, ctxt));
     }
+    */
 }
diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/std/CollectionDeserializer.java b/src/main/java/com/fasterxml/jackson/databind/deser/std/CollectionDeserializer.java
index 33d8878..c3cb45f 100644
--- a/src/main/java/com/fasterxml/jackson/databind/deser/std/CollectionDeserializer.java
+++ b/src/main/java/com/fasterxml/jackson/databind/deser/std/CollectionDeserializer.java
@@ -312,12 +312,12 @@
     }
 
     @Override
-    public Object deserializeWithType(JsonParser jp, DeserializationContext ctxt,
+    public Object deserializeWithType(JsonParser p, DeserializationContext ctxt,
             TypeDeserializer typeDeserializer)
         throws IOException
     {
         // In future could check current token... for now this should be enough:
-        return typeDeserializer.deserializeTypedFromArray(jp, ctxt);
+        return typeDeserializer.deserializeTypedFromArray(p, ctxt);
     }
 
     /**
@@ -325,6 +325,7 @@
      * throw an exception, or try to handle value as if member of implicit
      * array, depending on configuration.
      */
+    @SuppressWarnings("unchecked")
     protected final Collection<Object> handleNonArray(JsonParser p, DeserializationContext ctxt,
             Collection<Object> result)
         throws IOException
@@ -334,7 +335,7 @@
                 ((_unwrapSingle == null) &&
                         ctxt.isEnabled(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY));
         if (!canWrap) {
-            throw ctxt.mappingException(_collectionType.getRawClass());
+            return (Collection<Object>) ctxt.handleUnexpectedToken(_collectionType.getRawClass(), p);
         }
         JsonDeserializer<Object> valueDes = _valueDeserializer;
         final TypeDeserializer typeDeser = _valueTypeDeserializer;
diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/std/DateDeserializers.java b/src/main/java/com/fasterxml/jackson/databind/deser/std/DateDeserializers.java
index 239f2fd..4a840bc 100644
--- a/src/main/java/com/fasterxml/jackson/databind/deser/std/DateDeserializers.java
+++ b/src/main/java/com/fasterxml/jackson/databind/deser/std/DateDeserializers.java
@@ -6,10 +6,8 @@
 import java.util.*;
 
 import com.fasterxml.jackson.annotation.JsonFormat;
-
 import com.fasterxml.jackson.core.JsonParser;
 import com.fasterxml.jackson.core.JsonToken;
-
 import com.fasterxml.jackson.databind.BeanProperty;
 import com.fasterxml.jackson.databind.DeserializationContext;
 import com.fasterxml.jackson.databind.DeserializationFeature;
@@ -17,7 +15,6 @@
 import com.fasterxml.jackson.databind.JsonMappingException;
 import com.fasterxml.jackson.databind.annotation.JacksonStdImpl;
 import com.fasterxml.jackson.databind.deser.ContextualDeserializer;
-import com.fasterxml.jackson.databind.introspect.Annotated;
 import com.fasterxml.jackson.databind.util.StdDateFormat;
 
 /**
@@ -104,7 +101,8 @@
            throws JsonMappingException
         {
             if (property != null) {
-                JsonFormat.Value format = ctxt.getAnnotationIntrospector().findFormat((Annotated) property.getMember());
+                JsonFormat.Value format = findFormatOverrides(ctxt, property,
+                        this.handledType());
                 if (format != null) {
                     TimeZone tz = format.getTimeZone();
                     // First: fully custom pattern?
@@ -155,8 +153,8 @@
                         try {
                             return _customFormat.parse(str);
                         } catch (ParseException e) {
-                            throw new IllegalArgumentException("Failed to parse Date value '"+str
-                                    +"' (format: \""+_formatString+"\"): "+e.getMessage());
+                            return (java.util.Date) ctxt.handleWeirdStringValue(handledType(), str,
+                                    "expected format \"%s\"", _formatString);
                         }
                     }
                 }
@@ -166,8 +164,7 @@
                     final Date parsed = _parseDate(p, ctxt);
                     t = p.nextToken();
                     if (t != JsonToken.END_ARRAY) {
-                        throw ctxt.wrongTokenException(p, JsonToken.END_ARRAY, 
-                                "Attempted to unwrap single value array for single 'java.util.Date' value but there was more than a single value in the array");
+                        handleMissingEndArrayForSingle(p, ctxt);
                     }            
                     return parsed;            
                 }
@@ -181,7 +178,7 @@
     /* Deserializer implementations for Date types
     /**********************************************************
      */
-    
+
     @JacksonStdImpl
     public static class CalendarDeserializer extends DateBasedDeserializer<Calendar>
     {
@@ -230,7 +227,7 @@
                 }
                 return c;
             } catch (Exception e) {
-                throw ctxt.instantiationException(_calendarClass, e);
+                return (Calendar) ctxt.handleInstantiationProblem(_calendarClass, d, e);
             }
         }
     }
@@ -242,6 +239,7 @@
      * {@link DeserializationContext#parseDate} that this basic
      * deserializer calls.
      */
+    @JacksonStdImpl
     public static class DateDeserializer extends DateBasedDeserializer<Date>
     {
         public final static DateDeserializer instance = new DateDeserializer();
diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/std/EnumDeserializer.java b/src/main/java/com/fasterxml/jackson/databind/deser/std/EnumDeserializer.java
index a442b1e..c3ad93e 100644
--- a/src/main/java/com/fasterxml/jackson/databind/deser/std/EnumDeserializer.java
+++ b/src/main/java/com/fasterxml/jackson/databind/deser/std/EnumDeserializer.java
@@ -1,15 +1,13 @@
 package com.fasterxml.jackson.databind.deser.std;
 
 import java.io.IOException;
-import java.lang.reflect.Method;
 
 import com.fasterxml.jackson.core.*;
 import com.fasterxml.jackson.databind.*;
 import com.fasterxml.jackson.databind.annotation.JacksonStdImpl;
-import com.fasterxml.jackson.databind.deser.ContextualDeserializer;
-import com.fasterxml.jackson.databind.exc.InvalidFormatException;
+import com.fasterxml.jackson.databind.deser.SettableBeanProperty;
+import com.fasterxml.jackson.databind.deser.ValueInstantiator;
 import com.fasterxml.jackson.databind.introspect.AnnotatedMethod;
-import com.fasterxml.jackson.databind.jsontype.TypeDeserializer;
 import com.fasterxml.jackson.databind.util.ClassUtil;
 import com.fasterxml.jackson.databind.util.CompactStringObjectMap;
 import com.fasterxml.jackson.databind.util.EnumResolver;
@@ -24,10 +22,12 @@
 {
     private static final long serialVersionUID = 1L;
 
-    /**
-     * @since 2.6
-     */
     protected Object[] _enumsByIndex;
+    
+    /**
+     * @since 2.8
+     */
+    private final Enum<?> _enumDefaultValue;
 
     /**
      * @since 2.7.3
@@ -47,27 +47,57 @@
         super(byNameResolver.getEnumClass());
         _lookupByName = byNameResolver.constructLookup();
         _enumsByIndex = byNameResolver.getRawEnums();
+        _enumDefaultValue = byNameResolver.getDefaultValue();
+    }
+
+    /**
+     * @deprecated Since 2.8
+     */
+    @Deprecated
+    public static JsonDeserializer<?> deserializerForCreator(DeserializationConfig config,
+            Class<?> enumClass, AnnotatedMethod factory) {
+        return deserializerForCreator(config, enumClass, factory, null, null);
     }
 
     /**
      * Factory method used when Enum instances are to be deserialized
      * using a creator (static factory method)
      * 
-     * @return Deserializer based on given factory method, if type was suitable;
-     *  null if type can not be used
+     * @return Deserializer based on given factory method
+     *
+     * @since 2.8
      */
     public static JsonDeserializer<?> deserializerForCreator(DeserializationConfig config,
-            Class<?> enumClass, AnnotatedMethod factory)
+            Class<?> enumClass, AnnotatedMethod factory,
+            ValueInstantiator valueInstantiator, SettableBeanProperty[] creatorProps)
     {
-        // note: caller has verified there's just one arg; but we must verify its type
-        Class<?> paramClass = factory.getRawParameterType(0);
         if (config.canOverrideAccessModifiers()) {
             ClassUtil.checkAndFixAccess(factory.getMember(),
                     config.isEnabled(MapperFeature.OVERRIDE_PUBLIC_ACCESS_MODIFIERS));
         }
-        return new FactoryBasedDeserializer(enumClass, factory, paramClass);
+        return new FactoryBasedEnumDeserializer(enumClass, factory,
+                factory.getParameterType(0),
+                valueInstantiator, creatorProps);
     }
-    
+
+    /**
+     * Factory method used when Enum instances are to be deserialized
+     * using a zero-/no-args factory method
+     * 
+     * @return Deserializer based on given no-args factory method
+     *
+     * @since 2.8
+     */
+    public static JsonDeserializer<?> deserializerForNoArgsCreator(DeserializationConfig config,
+            Class<?> enumClass, AnnotatedMethod factory)
+    {
+        if (config.canOverrideAccessModifiers()) {
+            ClassUtil.checkAndFixAccess(factory.getMember(),
+                    config.isEnabled(MapperFeature.OVERRIDE_PUBLIC_ACCESS_MODIFIERS));
+        }
+        return new FactoryBasedEnumDeserializer(enumClass, factory);
+    }
+
     /*
     /**********************************************************
     /* Default JsonDeserializer implementation
@@ -89,7 +119,7 @@
         // Usually should just get string value:
         if (curr == JsonToken.VALUE_STRING || curr == JsonToken.FIELD_NAME) {
             CompactStringObjectMap lookup = ctxt.isEnabled(DeserializationFeature.READ_ENUMS_USING_TO_STRING)
-                    ? _getToStringLookup() : _lookupByName;
+                    ? _getToStringLookup(ctxt) : _lookupByName;
             final String name = p.getText();
             Object result = lookup.find(name);
             if (result == null) {
@@ -102,14 +132,21 @@
             // ... unless told not to do that
             int index = p.getIntValue();
             if (ctxt.isEnabled(DeserializationFeature.FAIL_ON_NUMBERS_FOR_ENUMS)) {
-                _failOnNumber(ctxt, p, index);
+                return ctxt.handleWeirdNumberValue(_enumClass(), index,
+                        "not allowed to deserialize Enum value out of number: disable DeserializationConfig.DeserializationFeature.FAIL_ON_NUMBERS_FOR_ENUMS to allow"
+                        );
             }
             if (index >= 0 && index < _enumsByIndex.length) {
                 return _enumsByIndex[index];
             }
+            if ((_enumDefaultValue != null)
+                    && ctxt.isEnabled(DeserializationFeature.READ_UNKNOWN_ENUM_VALUES_USING_DEFAULT_VALUE)) {
+                return _enumDefaultValue;
+            }
             if (!ctxt.isEnabled(DeserializationFeature.READ_UNKNOWN_ENUM_VALUES_AS_NULL)) {
-                throw ctxt.weirdNumberException(index, _enumClass(),
-                        "index value outside legal index range [0.."+(_enumsByIndex.length-1)+"]");
+                return ctxt.handleWeirdNumberValue(_enumClass(), index,
+                        "index value outside legal index range [0..%s]",
+                        _enumsByIndex.length-1);
             }
             return null;
         }
@@ -128,159 +165,59 @@
         name = name.trim();
         if (name.length() == 0) {
             if (ctxt.isEnabled(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT)) {
-                return null;
+                return getEmptyValue(ctxt);
             }
-        } else {
-            // [databind#149]: Allow use of 'String' indexes as well
+        } else if (!ctxt.isEnabled(DeserializationFeature.FAIL_ON_NUMBERS_FOR_ENUMS)) {
+            // [databind#149]: Allow use of 'String' indexes as well -- unless prohibited (as per above)
             char c = name.charAt(0);
             if (c >= '0' && c <= '9') {
                 try {
-                    int ix = Integer.parseInt(name);
-                    if (ctxt.isEnabled(DeserializationFeature.FAIL_ON_NUMBERS_FOR_ENUMS)) {
-                        _failOnNumber(ctxt, p, ix);
-                    }
-                    if (ix >= 0 && ix < _enumsByIndex.length) {
-                        return _enumsByIndex[ix];
+                    int index = Integer.parseInt(name);
+                    if (index >= 0 && index < _enumsByIndex.length) {
+                        return _enumsByIndex[index];
                     }
                 } catch (NumberFormatException e) {
                     // fine, ignore, was not an integer
                 }
             }
         }
+        if ((_enumDefaultValue != null)
+                && ctxt.isEnabled(DeserializationFeature.READ_UNKNOWN_ENUM_VALUES_USING_DEFAULT_VALUE)) {
+            return _enumDefaultValue;
+        }
         if (!ctxt.isEnabled(DeserializationFeature.READ_UNKNOWN_ENUM_VALUES_AS_NULL)) {
-            throw ctxt.weirdStringException(name, _enumClass(),
-                    "value not one of declared Enum instance names: "+lookup.keys());
+            return ctxt.handleWeirdStringValue(_enumClass(), name,
+                    "value not one of declared Enum instance names: %s", lookup.keys());
         }
         return null;
     }
 
     protected Object _deserializeOther(JsonParser p, DeserializationContext ctxt) throws IOException
     {
-        JsonToken curr = p.getCurrentToken();
         // [databind#381]
-        if (ctxt.isEnabled(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS)
-                && p.isExpectedStartArrayToken()) {
-            p.nextToken();
-            final Object parsed = deserialize(p, ctxt);
-            curr = p.nextToken();
-            if (curr != JsonToken.END_ARRAY) {
-                throw ctxt.wrongTokenException(p, JsonToken.END_ARRAY,
-                        "Attempted to unwrap single value array for single '" + _enumClass().getName() + "' value but there was more than a single value in the array");
-            }
-            return parsed;
+        if (p.hasToken(JsonToken.START_ARRAY)) {
+            return _deserializeFromArray(p, ctxt);
         }
-        throw ctxt.mappingException(_enumClass());
-    }
-
-    protected void _failOnNumber(DeserializationContext ctxt, JsonParser p, int index)
-        throws IOException
-    {
-        throw InvalidFormatException.from(p,
-                String.format("Not allowed to deserialize Enum value out of JSON number (%d): disable DeserializationConfig.DeserializationFeature.FAIL_ON_NUMBERS_FOR_ENUMS to allow",
-                        index),
-                        index, _enumClass());
+        return ctxt.handleUnexpectedToken(_enumClass(), p);
     }
 
     protected Class<?> _enumClass() {
         return handledType();
     }
 
-    protected CompactStringObjectMap _getToStringLookup()
+    protected CompactStringObjectMap _getToStringLookup(DeserializationContext ctxt)
     {
         CompactStringObjectMap lookup = _lookupByToString;
         // note: exact locking not needed; all we care for here is to try to
         // reduce contention for the initial resolution
         if (lookup == null) {
             synchronized (this) {
-                lookup = EnumResolver.constructUnsafeUsingToString(_enumClass())
-                        .constructLookup();
+                lookup = EnumResolver.constructUnsafeUsingToString(_enumClass(),
+                        ctxt.getAnnotationIntrospector())
+                    .constructLookup();
             }
             _lookupByToString = lookup;
         }
         return lookup;
     }
-
-    /*
-    /**********************************************************
-    /* Additional helper classes
-    /**********************************************************
-     */
-
-    /**
-     * Deserializer that uses a single-String static factory method
-     * for locating Enum values by String id.
-     */
-    protected static class FactoryBasedDeserializer
-        extends StdDeserializer<Object>
-        implements ContextualDeserializer
-    {
-        private static final long serialVersionUID = 1;
-
-        // Marker type; null if String expected; otherwise numeric wrapper
-        protected final Class<?> _inputType;
-        protected final Method _factory;
-        protected final JsonDeserializer<?> _deser;
-        
-        public FactoryBasedDeserializer(Class<?> cls, AnnotatedMethod f,
-                Class<?> inputType)
-        {
-            super(cls);
-            _factory = f.getAnnotated();
-            _inputType = inputType;
-            _deser = null;
-        }
-
-        protected FactoryBasedDeserializer(FactoryBasedDeserializer base,
-                JsonDeserializer<?> deser) {
-            super(base._valueClass);
-            _inputType = base._inputType;
-            _factory = base._factory;
-            _deser = deser;
-        }
-        
-        @Override
-        public JsonDeserializer<?> createContextual(DeserializationContext ctxt,
-                BeanProperty property)
-            throws JsonMappingException
-        {
-            if ((_deser == null) && (_inputType != String.class)) {
-                return new FactoryBasedDeserializer(this,
-                        ctxt.findContextualValueDeserializer(ctxt.constructType(_inputType), property));
-            }
-            return this;
-        }
-        
-        @Override
-        public Object deserialize(JsonParser p, DeserializationContext ctxt) throws IOException
-        {
-            Object value;
-            if (_deser != null) {
-                value = _deser.deserialize(p, ctxt);
-            } else {
-                JsonToken curr = p.getCurrentToken();
-                if (curr == JsonToken.VALUE_STRING || curr == JsonToken.FIELD_NAME) {
-                    value = p.getText();
-                } else {
-                    value = p.getValueAsString();
-                }
-            }
-            try {
-                return _factory.invoke(_valueClass, value);
-            } catch (Exception e) {
-                Throwable t = ClassUtil.getRootCause(e);
-                if (t instanceof IOException) {
-                    throw (IOException) t;
-                }
-                throw ctxt.instantiationException(_valueClass, t);
-            }
-        }
-
-        @Override
-        public Object deserializeWithType(JsonParser p, DeserializationContext ctxt, TypeDeserializer typeDeserializer) throws IOException {
-            if (_deser == null) { // String never has type info
-                return deserialize(p, ctxt);
-            }
-            return typeDeserializer.deserializeTypedFromAny(p, ctxt);
-        }
-    }
 }
diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/std/EnumMapDeserializer.java b/src/main/java/com/fasterxml/jackson/databind/deser/std/EnumMapDeserializer.java
index 6fd73c1..d227834 100644
--- a/src/main/java/com/fasterxml/jackson/databind/deser/std/EnumMapDeserializer.java
+++ b/src/main/java/com/fasterxml/jackson/databind/deser/std/EnumMapDeserializer.java
@@ -122,35 +122,36 @@
      */
     
     @Override
-    public EnumMap<?,?> deserialize(JsonParser jp, DeserializationContext ctxt)
+    public EnumMap<?,?> deserialize(JsonParser p, DeserializationContext ctxt)
         throws IOException
     {
         // Ok: must point to START_OBJECT
-        if (jp.getCurrentToken() != JsonToken.START_OBJECT) {
-            return _deserializeFromEmpty(jp, ctxt);
+        if (p.getCurrentToken() != JsonToken.START_OBJECT) {
+            return _deserializeFromEmpty(p, ctxt);
         }
         EnumMap result = constructMap();
         final JsonDeserializer<Object> valueDes = _valueDeserializer;
         final TypeDeserializer typeDeser = _valueTypeDeserializer;
 
-        while ((jp.nextToken()) == JsonToken.FIELD_NAME) {
-            String keyName = jp.getCurrentName(); // just for error message
+        while ((p.nextToken()) == JsonToken.FIELD_NAME) {
+            String keyName = p.getCurrentName(); // just for error message
             // but we need to let key deserializer handle it separately, nonetheless
             Enum<?> key = (Enum<?>) _keyDeserializer.deserializeKey(keyName, ctxt);
             if (key == null) {
                 if (!ctxt.isEnabled(DeserializationFeature.READ_UNKNOWN_ENUM_VALUES_AS_NULL)) {
-                    throw ctxt.weirdStringException(keyName, _enumClass, "value not one of declared Enum instance names for "
-                            +_mapType.getKeyType());
+                    return (EnumMap<?,?>) ctxt.handleWeirdStringValue(_enumClass, keyName,
+                            "value not one of declared Enum instance names for %s",
+                            _mapType.getKeyType());
                 }
                 /* 24-Mar-2012, tatu: Null won't work as a key anyway, so let's
                  *  just skip the entry then. But we must skip the value as well, if so.
                  */
-                jp.nextToken();
-                jp.skipChildren();
+                p.nextToken();
+                p.skipChildren();
                 continue;
             }
             // And then the value...
-            JsonToken t = jp.nextToken();
+            JsonToken t = p.nextToken();
             /* note: MUST check for nulls separately: deserializers will
              * not handle them (and maybe fail or return bogus data)
              */
@@ -160,9 +161,9 @@
                 if (t == JsonToken.VALUE_NULL) {
                     value = valueDes.getNullValue(ctxt);
                 } else if (typeDeser == null) {
-                    value =  valueDes.deserialize(jp, ctxt);
+                    value =  valueDes.deserialize(p, ctxt);
                 } else {
-                    value = valueDes.deserializeWithType(jp, ctxt, typeDeser);
+                    value = valueDes.deserializeWithType(p, ctxt, typeDeser);
                 }
             } catch (Exception e) {
                 wrapAndThrow(e, result, keyName);
diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/std/EnumSetDeserializer.java b/src/main/java/com/fasterxml/jackson/databind/deser/std/EnumSetDeserializer.java
index a20fa04..2136210 100644
--- a/src/main/java/com/fasterxml/jackson/databind/deser/std/EnumSetDeserializer.java
+++ b/src/main/java/com/fasterxml/jackson/databind/deser/std/EnumSetDeserializer.java
@@ -137,7 +137,7 @@
                  * deserializers)
                  */
                 if (t == JsonToken.VALUE_NULL) {
-                    throw ctxt.mappingException(_enumClass);
+                    return (EnumSet<?>) ctxt.handleUnexpectedToken(_enumClass, p);
                 }
                 Enum<?> value = _enumDeserializer.deserialize(p, ctxt);
                 /* 24-Mar-2012, tatu: As per [JACKSON-810], may actually get nulls;
@@ -177,13 +177,13 @@
                         ctxt.isEnabled(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY));
 
         if (!canWrap) {
-            throw ctxt.mappingException(EnumSet.class);
+            return (EnumSet<?>) ctxt.handleUnexpectedToken(EnumSet.class, p);
         }
 
         EnumSet result = constructSet();
         // First: since `null`s not allowed, slightly simpler...
         if (p.hasToken(JsonToken.VALUE_NULL)) {
-            throw ctxt.mappingException(_enumClass);
+            return (EnumSet<?>) ctxt.handleUnexpectedToken(_enumClass, p);
         }
         try {
             Enum<?> value = _enumDeserializer.deserialize(p, ctxt);
diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/std/FactoryBasedEnumDeserializer.java b/src/main/java/com/fasterxml/jackson/databind/deser/std/FactoryBasedEnumDeserializer.java
new file mode 100644
index 0000000..a6839f2
--- /dev/null
+++ b/src/main/java/com/fasterxml/jackson/databind/deser/std/FactoryBasedEnumDeserializer.java
@@ -0,0 +1,218 @@
+package com.fasterxml.jackson.databind.deser.std;
+
+import java.io.IOException;
+import java.lang.reflect.InvocationTargetException;
+
+import com.fasterxml.jackson.core.JsonParser;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.core.JsonToken;
+import com.fasterxml.jackson.databind.BeanProperty;
+import com.fasterxml.jackson.databind.DeserializationContext;
+import com.fasterxml.jackson.databind.DeserializationFeature;
+import com.fasterxml.jackson.databind.JavaType;
+import com.fasterxml.jackson.databind.JsonDeserializer;
+import com.fasterxml.jackson.databind.JsonMappingException;
+import com.fasterxml.jackson.databind.deser.ContextualDeserializer;
+import com.fasterxml.jackson.databind.deser.SettableBeanProperty;
+import com.fasterxml.jackson.databind.deser.ValueInstantiator;
+import com.fasterxml.jackson.databind.deser.impl.PropertyBasedCreator;
+import com.fasterxml.jackson.databind.deser.impl.PropertyValueBuffer;
+import com.fasterxml.jackson.databind.introspect.AnnotatedMethod;
+import com.fasterxml.jackson.databind.jsontype.TypeDeserializer;
+import com.fasterxml.jackson.databind.util.ClassUtil;
+
+/**
+ * Deserializer that uses a single-String static factory method
+ * for locating Enum values by String id.
+ * 
+ * @since 2.8 (as stand-alone class; was static inner class of {@link EnumDeserializer}
+ */
+class FactoryBasedEnumDeserializer
+    extends StdDeserializer<Object>
+    implements ContextualDeserializer
+{
+    private static final long serialVersionUID = 1;
+
+    // Marker type; null if String expected; otherwise numeric wrapper
+    protected final JavaType _inputType;
+    protected final boolean _hasArgs;
+    protected final AnnotatedMethod _factory;
+    protected final JsonDeserializer<?> _deser;
+    protected final ValueInstantiator _valueInstantiator;
+    protected final SettableBeanProperty[] _creatorProps;
+
+    /**
+     * Lazily instantiated property-based creator.
+     *
+     * @since 2.8
+     */
+    private transient PropertyBasedCreator _propCreator;
+    
+    public FactoryBasedEnumDeserializer(Class<?> cls, AnnotatedMethod f, JavaType paramType,
+            ValueInstantiator valueInstantiator, SettableBeanProperty[] creatorProps)
+    {
+        super(cls);
+        _factory = f;
+        _hasArgs = true;
+        // We'll skip case of `String`, as well as no type (zero-args): 
+        _inputType = paramType.hasRawClass(String.class) ? null : paramType;
+        _deser = null;
+        _valueInstantiator = valueInstantiator;
+        _creatorProps = creatorProps;
+    }
+
+    /**
+     * @since 2.8
+     */
+    public FactoryBasedEnumDeserializer(Class<?> cls, AnnotatedMethod f)
+    {
+        super(cls);
+        _factory = f;
+        _hasArgs = false;
+        _inputType = null;
+        _deser = null;
+        _valueInstantiator = null;
+        _creatorProps = null;
+    }
+
+    protected FactoryBasedEnumDeserializer(FactoryBasedEnumDeserializer base,
+            JsonDeserializer<?> deser) {
+        super(base._valueClass);
+        _inputType = base._inputType;
+        _factory = base._factory;
+        _hasArgs = base._hasArgs;
+        _valueInstantiator = base._valueInstantiator;
+        _creatorProps = base._creatorProps;
+
+        _deser = deser;
+    }
+
+    @Override
+    public JsonDeserializer<?> createContextual(DeserializationContext ctxt,
+            BeanProperty property)
+        throws JsonMappingException
+    {
+        if ((_deser == null) && (_inputType != null) && (_creatorProps == null)) {
+            return new FactoryBasedEnumDeserializer(this,
+                    ctxt.findContextualValueDeserializer(_inputType, property));
+        }
+        return this;
+    }
+
+    @Override
+    public Object deserialize(JsonParser p, DeserializationContext ctxt) throws IOException
+    {
+        Object value = null;
+        if (_deser != null) {
+            value = _deser.deserialize(p, ctxt);
+        } else if (_hasArgs) {
+            JsonToken curr = p.getCurrentToken();
+            //There can be a JSON object passed for deserializing an Enum,
+            //the below case handles it.
+            if (curr == JsonToken.VALUE_STRING || curr == JsonToken.FIELD_NAME) {
+                value = p.getText();
+            } else if ((_creatorProps != null) && p.isExpectedStartObjectToken()) {
+                if (_propCreator == null) {
+                    _propCreator = PropertyBasedCreator.construct(ctxt, _valueInstantiator, _creatorProps);
+                }
+                p.nextToken();
+                return deserializeEnumUsingPropertyBased(p, ctxt, _propCreator);
+            } else {
+                value = p.getValueAsString();
+            }
+        } else { // zero-args; just skip whatever value there may be
+            p.skipChildren();
+            try {
+                return _factory.call();
+            } catch (Exception e) {
+                Throwable t = ClassUtil.throwRootCauseIfIOE(e);
+                return ctxt.handleInstantiationProblem(_valueClass, null, t);
+            }
+        }
+        try {
+            return _factory.callOnWith(_valueClass, value);
+        } catch (Exception e) {
+            Throwable t = ClassUtil.throwRootCauseIfIOE(e);
+            // [databind#1642]
+            if (ctxt.isEnabled(DeserializationFeature.READ_UNKNOWN_ENUM_VALUES_AS_NULL)
+                    && (t instanceof IllegalArgumentException)) {
+                return null;
+            }
+            return ctxt.handleInstantiationProblem(_valueClass, value, t);
+        }
+    }
+
+    @Override
+    public Object deserializeWithType(JsonParser p, DeserializationContext ctxt, TypeDeserializer typeDeserializer) throws IOException {
+        if (_deser == null) { // String never has type info
+            return deserialize(p, ctxt);
+        }
+        return typeDeserializer.deserializeTypedFromAny(p, ctxt);
+    }
+    
+    // Method to deserialize the Enum using property based methodology
+    protected Object deserializeEnumUsingPropertyBased(final JsonParser p, final DeserializationContext ctxt,
+    		final PropertyBasedCreator creator) throws IOException
+    {
+        PropertyValueBuffer buffer = creator.startBuilding(p, ctxt, null);
+    
+        JsonToken t = p.getCurrentToken();
+        for (; t == JsonToken.FIELD_NAME; t = p.nextToken()) {
+            String propName = p.getCurrentName();
+            p.nextToken(); // to point to value
+    
+            SettableBeanProperty creatorProp = creator.findCreatorProperty(propName);
+            if (creatorProp != null) {
+                buffer.assignParameter(creatorProp, _deserializeWithErrorWrapping(p, ctxt, creatorProp));
+                continue;
+            }
+            if (buffer.readIdProperty(propName)) {
+                continue;
+            }
+        }
+        return creator.build(ctxt, buffer);
+    }
+
+    // ************ Got the below methods from BeanDeserializer ********************//
+
+    protected final Object _deserializeWithErrorWrapping(JsonParser p, DeserializationContext ctxt,
+    		SettableBeanProperty prop) throws IOException {
+    	try {
+    		return prop.deserialize(p, ctxt);
+    	} catch (Exception e) {
+    		wrapAndThrow(e, _valueClass.getClass(), prop.getName(), ctxt);
+    		// never gets here, unless caller declines to throw an exception
+    		return null;
+    	}
+    }
+
+    public void wrapAndThrow(Throwable t, Object bean, String fieldName, DeserializationContext ctxt)
+    		throws IOException
+    {
+        throw JsonMappingException.wrapWithPath(throwOrReturnThrowable(t, ctxt), bean, fieldName);
+    }
+
+    private Throwable throwOrReturnThrowable(Throwable t, DeserializationContext ctxt) throws IOException
+    {
+        while (t instanceof InvocationTargetException && t.getCause() != null) {
+            t = t.getCause();
+        }
+        // Errors to be passed as is
+        if (t instanceof Error) {
+            throw (Error) t;
+        }
+        boolean wrap = (ctxt == null) || ctxt.isEnabled(DeserializationFeature.WRAP_EXCEPTIONS);
+    	    // Ditto for IOExceptions; except we may want to wrap JSON
+    	    // exceptions
+    	    if (t instanceof IOException) {
+    	        if (!wrap || !(t instanceof JsonProcessingException)) {
+    	            throw (IOException) t;
+    	        }
+    	    } else if (!wrap) {
+    	        if (t instanceof RuntimeException) {
+    	            throw (RuntimeException) t;
+    	        }
+    	    }
+    	    return t;
+    }
+}
\ No newline at end of file
diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/std/FromStringDeserializer.java b/src/main/java/com/fasterxml/jackson/databind/deser/std/FromStringDeserializer.java
index e27d6a9..0d01e78 100644
--- a/src/main/java/com/fasterxml/jackson/databind/deser/std/FromStringDeserializer.java
+++ b/src/main/java/com/fasterxml/jackson/databind/deser/std/FromStringDeserializer.java
@@ -3,6 +3,7 @@
 import java.io.*;
 import java.net.InetAddress;
 import java.net.InetSocketAddress;
+import java.net.MalformedURLException;
 import java.net.URI;
 import java.net.URL;
 import java.nio.charset.Charset;
@@ -12,8 +13,8 @@
 import java.util.regex.Pattern;
 
 import com.fasterxml.jackson.core.*;
+import com.fasterxml.jackson.core.util.VersionUtil;
 import com.fasterxml.jackson.databind.DeserializationContext;
-import com.fasterxml.jackson.databind.DeserializationFeature;
 import com.fasterxml.jackson.databind.JavaType;
 import com.fasterxml.jackson.databind.JsonMappingException;
 import com.fasterxml.jackson.databind.exc.InvalidFormatException;
@@ -40,6 +41,7 @@
             TimeZone.class,
             InetAddress.class,
             InetSocketAddress.class,
+            StringBuilder.class,
         };
     }
     
@@ -84,6 +86,8 @@
             kind = Std.STD_INET_ADDRESS;
         } else if (rawType == InetSocketAddress.class) {
             kind = Std.STD_INET_SOCKET_ADDRESS;
+        } else if (rawType == StringBuilder.class) {
+            kind = Std.STD_STRING_BUILDER;
         } else {
             return null;
         }
@@ -100,16 +104,6 @@
     @Override
     public T deserialize(JsonParser p, DeserializationContext ctxt) throws IOException
     {
-        // Issue#381
-        if (p.getCurrentToken() == JsonToken.START_ARRAY && ctxt.isEnabled(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS)) {
-            p.nextToken();
-            final T value = deserialize(p, ctxt);
-            if (p.nextToken() != JsonToken.END_ARRAY) {
-                throw ctxt.wrongTokenException(p, JsonToken.END_ARRAY, 
-                                "Attempted to unwrap single value array for single '" + _valueClass.getName() + "' value but there was more than a single value in the array");
-            }
-            return value;
-        }
         // 22-Sep-2012, tatu: For 2.1, use this new method, may force coercion:
         String text = p.getValueAsString();
         if (text != null) { // has String representation
@@ -119,12 +113,14 @@
             }
             Exception cause = null;
             try {
-                T result = _deserialize(text, ctxt);
-                if (result != null) {
-                    return result;
-                }
+                // 19-May-2017, tatu: Used to require non-null result (assuming `null`
+                //    indicated error; but that seems wrong. Should be able to return
+                //    `null` as value.
+                return _deserialize(text, ctxt);
             } catch (IllegalArgumentException iae) {
                 cause = iae;
+            } catch (MalformedURLException me) {
+                cause = me;
             }
             String msg = "not a valid textual representation";
             if (cause != null) {
@@ -133,6 +129,7 @@
                     msg = msg + ", problem: "+m2;
                 }
             }
+            // 05-May-2016, tatu: Unlike most usage, this seems legit, so...
             JsonMappingException e = ctxt.weirdStringException(text, _valueClass, msg);
             if (cause != null) {
                 e.initCause(cause);
@@ -140,7 +137,12 @@
             throw e;
             // nothing to do here, yet? We'll fail anyway
         }
-        if (p.getCurrentToken() == JsonToken.VALUE_EMBEDDED_OBJECT) {
+        JsonToken t = p.getCurrentToken();
+        // [databind#381]
+        if (t == JsonToken.START_ARRAY) {
+            return _deserializeFromArray(p, ctxt);
+        }
+        if (t == JsonToken.VALUE_EMBEDDED_OBJECT) {
             // Trivial cases; null to null, instance of type itself returned as is
             Object ob = p.getEmbeddedObject();
             if (ob == null) {
@@ -151,15 +153,16 @@
             }
             return _deserializeEmbedded(ob, ctxt);
         }
-        throw ctxt.mappingException(_valueClass);
+        return (T) ctxt.handleUnexpectedToken(_valueClass, p);
     }
         
     protected abstract T _deserialize(String value, DeserializationContext ctxt) throws IOException;
 
     protected T _deserializeEmbedded(Object ob, DeserializationContext ctxt) throws IOException {
         // default impl: error out
-        throw ctxt.mappingException("Don't know how to convert embedded Object of type %s into %s",
+        ctxt.reportMappingException("Don't know how to convert embedded Object of type %s into %s",
                 ob.getClass().getName(), _valueClass.getName());
+        return null;
     }
 
     protected T _deserializeFromEmptyString() throws IOException {
@@ -194,6 +197,7 @@
         public final static int STD_TIME_ZONE = 10;
         public final static int STD_INET_ADDRESS = 11;
         public final static int STD_INET_SOCKET_ADDRESS = 12;
+        public final static int STD_STRING_BUILDER = 13;
 
         protected final int _kind;
         
@@ -216,7 +220,8 @@
                 try {
                     return ctxt.findClass(value);
                 } catch (Exception e) {
-                    throw ctxt.instantiationException(_valueClass, ClassUtil.getRootCause(e));
+                    return ctxt.handleInstantiationProblem(_valueClass, value,
+                            ClassUtil.getRootCause(e));
                 }
             case STD_JAVA_TYPE:
                 return ctxt.getTypeFactory().constructFromCanonical(value);
@@ -261,18 +266,20 @@
                     int j = value.indexOf(':', i);
                     int port = j > -1 ? Integer.parseInt(value.substring(j + 1)) : 0;
                     return new InetSocketAddress(value.substring(0, i + 1), port);
-                } else {
-                    int ix = value.indexOf(':');
-                    if (ix >= 0 && value.indexOf(':', ix + 1) < 0) {
-                        // host:port
-                        int port = Integer.parseInt(value.substring(ix+1));
-                        return new InetSocketAddress(value.substring(0, ix), port);
-                    }
-                    // host or unbracketed IPv6, without port number
-                    return new InetSocketAddress(value, 0);
                 }
+                int ix = value.indexOf(':');
+                if (ix >= 0 && value.indexOf(':', ix + 1) < 0) {
+                    // host:port
+                    int port = Integer.parseInt(value.substring(ix+1));
+                    return new InetSocketAddress(value.substring(0, ix), port);
+                }
+                // host or unbracketed IPv6, without port number
+                return new InetSocketAddress(value, 0);
+            case STD_STRING_BUILDER:
+                return new StringBuilder(value);
             }
-            throw new IllegalArgumentException();
+            VersionUtil.throwInternal();
+            return null;
         }
 
         @Override
@@ -285,10 +292,12 @@
             if (_kind == STD_LOCALE) {
                 return Locale.ROOT;
             }
+            if (_kind == STD_STRING_BUILDER) {
+                return new StringBuilder();
+            }
             return super._deserializeFromEmptyString();
         }
 
-
         protected int _firstHyphenOrUnderscore(String str)
         {
             for (int i = 0, end = str.length(); i < end; ++i) {
diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/std/JsonLocationInstantiator.java b/src/main/java/com/fasterxml/jackson/databind/deser/std/JsonLocationInstantiator.java
index c5aaa99..be32d08 100644
--- a/src/main/java/com/fasterxml/jackson/databind/deser/std/JsonLocationInstantiator.java
+++ b/src/main/java/com/fasterxml/jackson/databind/deser/std/JsonLocationInstantiator.java
@@ -15,13 +15,13 @@
  * {@link ValueInstantiator} (not that explicit one would be very
  * hard but...)
  */
-public class JsonLocationInstantiator extends ValueInstantiator
+public class JsonLocationInstantiator
+    extends ValueInstantiator.Base
 {
-    @Override
-    public String getValueTypeDesc() {
-        return JsonLocation.class.getName();
+    public JsonLocationInstantiator() {
+        super(JsonLocation.class);
     }
-    
+
     @Override
     public boolean canCreateFromObjectWith() { return true; }
     
diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/std/JsonNodeDeserializer.java b/src/main/java/com/fasterxml/jackson/databind/deser/std/JsonNodeDeserializer.java
index ac705c6..05b0562 100644
--- a/src/main/java/com/fasterxml/jackson/databind/deser/std/JsonNodeDeserializer.java
+++ b/src/main/java/com/fasterxml/jackson/databind/deser/std/JsonNodeDeserializer.java
@@ -102,7 +102,7 @@
             if (p.hasToken(JsonToken.END_OBJECT)) {
                 return ctxt.getNodeFactory().objectNode();
             }
-            throw ctxt.mappingException(ObjectNode.class);
+            return (ObjectNode) ctxt.handleUnexpectedToken(ObjectNode.class, p);
          }
     }
         
@@ -123,7 +123,7 @@
             if (p.isExpectedStartArrayToken()) {
                 return deserializeArray(p, ctxt, ctxt.getNodeFactory());
             }
-            throw ctxt.mappingException(ArrayNode.class);
+            return (ArrayNode) ctxt.handleUnexpectedToken(ArrayNode.class, p);
         }
     }
 }
@@ -164,6 +164,7 @@
     /**********************************************************
      */
 
+    @Deprecated // since 2.8
     protected void _reportProblem(JsonParser p, String msg) throws JsonMappingException {
         throw JsonMappingException.from(p, msg);
     }
@@ -187,9 +188,10 @@
             JsonNode oldValue, JsonNode newValue)
         throws JsonProcessingException
     {
-        // [Issue#237]: Report an error if asked to do so:
+        // [databind#237]: Report an error if asked to do so:
         if (ctxt.isEnabled(DeserializationFeature.FAIL_ON_READING_DUP_TREE_KEY)) {
-            _reportProblem(p, "Duplicate field '"+fieldName+"' for ObjectNode: not allowed when FAIL_ON_READING_DUP_TREE_KEY enabled");
+            ctxt.reportMappingException("Duplicate field '%s' for ObjectNode: not allowed when FAIL_ON_READING_DUP_TREE_KEY enabled",
+                    fieldName);
         }
     }
 
@@ -212,7 +214,7 @@
                 return node;
             }
             if (t != JsonToken.FIELD_NAME) {
-                throw ctxt.mappingException(handledType(), p.getCurrentToken());
+                return (ObjectNode) ctxt.handleUnexpectedToken(handledType(), p);
             }
             key = p.getCurrentName();
         }
@@ -265,9 +267,6 @@
         ArrayNode node = nodeFactory.arrayNode();
         while (true) {
             JsonToken t = p.nextToken();
-            if (t == null) {
-                throw ctxt.mappingException("Unexpected end-of-input when binding data into ArrayNode");
-            }
             switch (t.id()) {
             case JsonTokenId.ID_START_OBJECT:
                 node.add(deserializeObject(p, ctxt, nodeFactory));
@@ -333,8 +332,8 @@
         //case END_OBJECT:
         //case END_ARRAY:
         default:
-            throw ctxt.mappingException(handledType());
         }
+        return (JsonNode) ctxt.handleUnexpectedToken(handledType(), p);
     }
 
     protected final JsonNode _fromInt(JsonParser p, DeserializationContext ctxt,
@@ -366,8 +365,19 @@
             final JsonNodeFactory nodeFactory) throws IOException
     {
         JsonParser.NumberType nt = p.getNumberType();
-        if (nt == JsonParser.NumberType.BIG_DECIMAL
-            || ctxt.isEnabled(DeserializationFeature.USE_BIG_DECIMAL_FOR_FLOATS)) {
+        if (nt == JsonParser.NumberType.BIG_DECIMAL) {
+            return nodeFactory.numberNode(p.getDecimalValue());
+        }
+        if (ctxt.isEnabled(DeserializationFeature.USE_BIG_DECIMAL_FOR_FLOATS)) {
+            // 20-May-2016, tatu: As per [databind#1028], need to be careful
+            //   (note: JDK 1.8 would have `Double.isFinite()`)
+            // 21-Aug-2016, tatu: Not optimal, really, because this may result in
+            //   value getting parsed twice. But has to do for now, to resolve
+            //  [databind#1315]
+            double d = p.getDoubleValue();
+            if (Double.isInfinite(d) || Double.isNaN(d)) {
+                return nodeFactory.numberNode(d);
+            }
             return nodeFactory.numberNode(p.getDecimalValue());
         }
         if (nt == JsonParser.NumberType.FLOAT) {
@@ -379,7 +389,6 @@
     protected final JsonNode _fromEmbedded(JsonParser p, DeserializationContext ctxt,
             JsonNodeFactory nodeFactory) throws IOException
     {
-        // [JACKSON-796]
         Object ob = p.getEmbeddedObject();
         if (ob == null) { // should this occur?
             return nodeFactory.nullNode();
diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/std/MapDeserializer.java b/src/main/java/com/fasterxml/jackson/databind/deser/std/MapDeserializer.java
index 23599ff..c1d8719 100644
--- a/src/main/java/com/fasterxml/jackson/databind/deser/std/MapDeserializer.java
+++ b/src/main/java/com/fasterxml/jackson/databind/deser/std/MapDeserializer.java
@@ -3,6 +3,7 @@
 import java.io.IOException;
 import java.util.*;
 
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
 import com.fasterxml.jackson.core.*;
 import com.fasterxml.jackson.databind.*;
 import com.fasterxml.jackson.databind.annotation.JacksonStdImpl;
@@ -83,7 +84,7 @@
 
     // // Any properties to ignore if seen?
     
-    protected HashSet<String> _ignorableProperties;
+    protected Set<String> _ignorableProperties;
 
     /*
     /**********************************************************
@@ -131,7 +132,7 @@
     protected MapDeserializer(MapDeserializer src,
             KeyDeserializer keyDeser, JsonDeserializer<Object> valueDeser,
             TypeDeserializer valueTypeDeser,
-            HashSet<String> ignorable)
+            Set<String> ignorable)
     {
         super(src._mapType);
         _mapType = src._mapType;
@@ -154,7 +155,7 @@
     @SuppressWarnings("unchecked")
     protected MapDeserializer withResolved(KeyDeserializer keyDeser,
             TypeDeserializer valueTypeDeser, JsonDeserializer<?> valueDeser,
-            HashSet<String> ignorable)
+            Set<String> ignorable)
     {
         
         if ((_keyDeserializer == keyDeser) && (_valueDeserializer == valueDeser)
@@ -188,6 +189,11 @@
             null : ArrayBuilders.arrayToSet(ignorable);
     }
 
+    public void setIgnorableProperties(Set<String> ignorable) {
+        _ignorableProperties = (ignorable == null || ignorable.size() == 0) ?
+                null : ignorable;
+    }
+
     /*
     /**********************************************************
     /* Validation, post-processing (ResolvableDeserializer)
@@ -198,18 +204,28 @@
     public void resolve(DeserializationContext ctxt) throws JsonMappingException
     {
         // May need to resolve types for delegate- and/or property-based creators:
-        if (_valueInstantiator.canCreateUsingDelegate()) {
-            JavaType delegateType = _valueInstantiator.getDelegateType(ctxt.getConfig());
-            if (delegateType == null) {
-                throw new IllegalArgumentException("Invalid delegate-creator definition for "+_mapType
-                        +": value instantiator ("+_valueInstantiator.getClass().getName()
-                        +") returned true for 'canCreateUsingDelegate()', but null for 'getDelegateType()'");
+        if (_valueInstantiator != null) {
+            if (_valueInstantiator.canCreateUsingDelegate()) {
+                JavaType delegateType = _valueInstantiator.getDelegateType(ctxt.getConfig());
+                if (delegateType == null) {
+                    throw new IllegalArgumentException("Invalid delegate-creator definition for "+_mapType
+                            +": value instantiator ("+_valueInstantiator.getClass().getName()
+                            +") returned true for 'canCreateUsingDelegate()', but null for 'getDelegateType()'");
+                }
+                /* Theoretically should be able to get CreatorProperty for delegate
+                 * parameter to pass; but things get tricky because DelegateCreator
+                 * may contain injectable values. So, for now, let's pass nothing.
+                 */
+                _delegateDeserializer = findDeserializer(ctxt, delegateType, null);
+            } else if (_valueInstantiator.canCreateUsingArrayDelegate()) {
+                JavaType delegateType = _valueInstantiator.getArrayDelegateType(ctxt.getConfig());
+                if (delegateType == null) {
+                    throw new IllegalArgumentException("Invalid delegate-creator definition for "+_mapType
+                            +": value instantiator ("+_valueInstantiator.getClass().getName()
+                            +") returned true for 'canCreateUsingDelegate()', but null for 'getArrayDelegateType()'");
+                }
+                _delegateDeserializer = findDeserializer(ctxt, delegateType, null);
             }
-            /* Theoretically should be able to get CreatorProperty for delegate
-             * parameter to pass; but things get tricky because DelegateCreator
-             * may contain injectable values. So, for now, let's pass nothing.
-             */
-            _delegateDeserializer = findDeserializer(ctxt, delegateType, null);
         }
         if (_valueInstantiator.canCreateFromObjectWith()) {
             SettableBeanProperty[] creatorProps = _valueInstantiator.getFromObjectArguments(ctxt.getConfig());
@@ -250,16 +266,19 @@
         if (vtd != null) {
             vtd = vtd.forProperty(property);
         }
-        HashSet<String> ignored = _ignorableProperties;
+        Set<String> ignored = _ignorableProperties;
         AnnotationIntrospector intr = ctxt.getAnnotationIntrospector();
         if (intr != null && property != null) {
             AnnotatedMember member = property.getMember();
             if (member != null) {
-                String[] moreToIgnore = intr.findPropertiesToIgnore(member, false);
-                if (moreToIgnore != null) {
-                    ignored = (ignored == null) ? new HashSet<String>() : new HashSet<String>(ignored);
-                    for (String str : moreToIgnore) {
-                        ignored.add(str);
+                JsonIgnoreProperties.Value ignorals = intr.findPropertyIgnorals(member);
+                if (ignorals != null) {
+                    Set<String> ignoresToAdd = ignorals.findIgnoredForDeserialization();
+                    if (!ignoresToAdd.isEmpty()) {
+                        ignored = (ignored == null) ? new HashSet<String>() : new HashSet<String>(ignored);
+                        for (String str : ignoresToAdd) {
+                            ignored.add(str);
+                        }
                     }
                 }
             }
@@ -325,7 +344,8 @@
                     _delegateDeserializer.deserialize(p, ctxt));
         }
         if (!_hasDefaultCreator) {
-            throw ctxt.instantiationException(getMapClass(), "No default constructor found");
+            return (Map<Object,Object> ) ctxt.handleMissingInstantiator(getMapClass(), p,
+                    "no default constructor found");
         }
         // Ok: must point to START_OBJECT, FIELD_NAME or END_OBJECT
         JsonToken t = p.getCurrentToken();
@@ -339,13 +359,14 @@
         }
         final Map<Object,Object> result = (Map<Object,Object>) _valueInstantiator.createUsingDefault(ctxt);
         if (_standardStringKey) {
-            _readAndBindStringMap(p, ctxt, result);
+            _readAndBindStringKeyMap(p, ctxt, result);
             return result;
         }
         _readAndBind(p, ctxt, result);
         return result;
     }
 
+    @SuppressWarnings("unchecked")
     @Override
     public Map<Object,Object> deserialize(JsonParser p, DeserializationContext ctxt,
             Map<Object,Object> result)
@@ -357,10 +378,10 @@
         // Ok: must point to START_OBJECT or FIELD_NAME
         JsonToken t = p.getCurrentToken();
         if (t != JsonToken.START_OBJECT && t != JsonToken.FIELD_NAME) {
-            throw ctxt.mappingException(getMapClass());
+            return (Map<Object,Object>) ctxt.handleUnexpectedToken(getMapClass(), p);
         }
         if (_standardStringKey) {
-            _readAndBindStringMap(p, ctxt, result);
+            _readAndBindStringKeyMap(p, ctxt, result);
             return result;
         }
         _readAndBind(p, ctxt, result);
@@ -415,7 +436,7 @@
                 return;
             }
             if (t != JsonToken.FIELD_NAME) {
-                throw ctxt.mappingException(_mapType.getRawClass(), p.getCurrentToken());
+                ctxt.reportWrongTokenException(p, JsonToken.FIELD_NAME, null);
             }
             keyStr = p.getCurrentName();
         }
@@ -456,7 +477,7 @@
      * {@link java.lang.String}s, and there is no custom deserialized
      * specified.
      */
-    protected final void _readAndBindStringMap(JsonParser p, DeserializationContext ctxt,
+    protected final void _readAndBindStringKeyMap(JsonParser p, DeserializationContext ctxt,
             Map<Object,Object> result) throws IOException
     {
         final JsonDeserializer<Object> valueDes = _valueDeserializer;
@@ -476,7 +497,7 @@
                 return;
             }
             if (t != JsonToken.FIELD_NAME) {
-                throw ctxt.mappingException(_mapType.getRawClass(), p.getCurrentToken());
+                ctxt.reportWrongTokenException(p, JsonToken.FIELD_NAME, null);
             }
             key = p.getCurrentName();
         }
@@ -656,7 +677,7 @@
      * The resolved object associated with {@link #key} comes before the values in
      * {@link #next}.
      */
-    final static class MapReferring extends Referring {
+    static class MapReferring extends Referring {
         private final MapReferringAccumulator _parent;
 
         public final Map<Object, Object> next = new LinkedHashMap<Object, Object>();
diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/std/MapEntryDeserializer.java b/src/main/java/com/fasterxml/jackson/databind/deser/std/MapEntryDeserializer.java
index 5e03d52..7899712 100644
--- a/src/main/java/com/fasterxml/jackson/databind/deser/std/MapEntryDeserializer.java
+++ b/src/main/java/com/fasterxml/jackson/databind/deser/std/MapEntryDeserializer.java
@@ -167,74 +167,78 @@
     /**********************************************************
      */
 
+    @SuppressWarnings("unchecked")
     @Override
-    public Map.Entry<Object,Object> deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
+    public Map.Entry<Object,Object> deserialize(JsonParser p, DeserializationContext ctxt) throws IOException
     {
         // Ok: must point to START_OBJECT, FIELD_NAME or END_OBJECT
-        JsonToken t = jp.getCurrentToken();
+        JsonToken t = p.getCurrentToken();
         if (t != JsonToken.START_OBJECT && t != JsonToken.FIELD_NAME && t != JsonToken.END_OBJECT) {
-            // [JACKSON-620] (empty) String may be ok however:
+            // String may be ok however:
             // slightly redundant (since String was passed above), but
-            return _deserializeFromEmpty(jp, ctxt);
+            return _deserializeFromEmpty(p, ctxt);
         }
         if (t == JsonToken.START_OBJECT) {
-            t = jp.nextToken();
+            t = p.nextToken();
         }
         if (t != JsonToken.FIELD_NAME) {
             if (t == JsonToken.END_OBJECT) {
-                throw ctxt.mappingException("Can not deserialize a Map.Entry out of empty JSON Object");
+                ctxt.reportMappingException("Can not deserialize a Map.Entry out of empty JSON Object");
+                return null;
             }
-            throw ctxt.mappingException(handledType(), t);
+            return (Map.Entry<Object,Object>) ctxt.handleUnexpectedToken(handledType(), p);
         }
-        
+
         final KeyDeserializer keyDes = _keyDeserializer;
         final JsonDeserializer<Object> valueDes = _valueDeserializer;
         final TypeDeserializer typeDeser = _valueTypeDeserializer;
 
-        final String keyStr = jp.getCurrentName();
+        final String keyStr = p.getCurrentName();
         Object key = keyDes.deserializeKey(keyStr, ctxt);
         Object value = null;
         // And then the value...
-        t = jp.nextToken();
+        t = p.nextToken();
         try {
             // Note: must handle null explicitly here; value deserializers won't
             if (t == JsonToken.VALUE_NULL) {
                 value = valueDes.getNullValue(ctxt);
             } else if (typeDeser == null) {
-                value = valueDes.deserialize(jp, ctxt);
+                value = valueDes.deserialize(p, ctxt);
             } else {
-                value = valueDes.deserializeWithType(jp, ctxt, typeDeser);
+                value = valueDes.deserializeWithType(p, ctxt, typeDeser);
             }
         } catch (Exception e) {
             wrapAndThrow(e, Map.Entry.class, keyStr);
         }
 
         // Close, but also verify that we reached the END_OBJECT
-        t = jp.nextToken();
+        t = p.nextToken();
         if (t != JsonToken.END_OBJECT) {
             if (t == JsonToken.FIELD_NAME) { // most likely
-                throw ctxt.mappingException("Problem binding JSON into Map.Entry: more than one entry in JSON (second field: '"+jp.getCurrentName()+"')");
+                ctxt.reportMappingException("Problem binding JSON into Map.Entry: more than one entry in JSON (second field: '"+p.getCurrentName()+"')");
+            } else {
+                // how would this occur?
+                ctxt.reportMappingException("Problem binding JSON into Map.Entry: unexpected content after JSON Object entry: "+t);
             }
-            // how would this occur?
-            throw ctxt.mappingException("Problem binding JSON into Map.Entry: unexpected content after JSON Object entry: "+t);
+            return null;
         }
         return new AbstractMap.SimpleEntry<Object,Object>(key, value);
     }
 
     @Override
-    public Map.Entry<Object,Object> deserialize(JsonParser jp, DeserializationContext ctxt,
+    public Map.Entry<Object,Object> deserialize(JsonParser p, DeserializationContext ctxt,
             Map.Entry<Object,Object> result) throws IOException
     {
         throw new IllegalStateException("Can not update Map.Entry values");
     }
 
     @Override
-    public Object deserializeWithType(JsonParser jp, DeserializationContext ctxt,
+    public Object deserializeWithType(JsonParser p, DeserializationContext ctxt,
             TypeDeserializer typeDeserializer)
         throws IOException, JsonProcessingException
     {
         // In future could check current token... for now this should be enough:
-        return typeDeserializer.deserializeTypedFromObject(jp, ctxt);
+        return typeDeserializer.deserializeTypedFromObject(p, ctxt);
     }
 
     /*
diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/std/NumberDeserializers.java b/src/main/java/com/fasterxml/jackson/databind/deser/std/NumberDeserializers.java
index b8ade5b..e545d6b 100644
--- a/src/main/java/com/fasterxml/jackson/databind/deser/std/NumberDeserializers.java
+++ b/src/main/java/com/fasterxml/jackson/databind/deser/std/NumberDeserializers.java
@@ -132,7 +132,7 @@
         public final T getNullValue(DeserializationContext ctxt) throws JsonMappingException
         {
             if (_primitive && ctxt.isEnabled(DeserializationFeature.FAIL_ON_NULL_FOR_PRIMITIVES)) {
-                throw ctxt.mappingException(
+                ctxt.reportMappingException(
                         "Can not map JSON null into type %s (set DeserializationConfig.DeserializationFeature.FAIL_ON_NULL_FOR_PRIMITIVES to 'false' to allow)",
                         handledType().toString());
             }
@@ -140,17 +140,11 @@
         }
 
         @Override
-        @Deprecated // remove in 2.7
-        public final T getNullValue() {
-            return _nullValue;
-        }
-
-        @Override
         public T getEmptyValue(DeserializationContext ctxt) throws JsonMappingException {
             // [databind#1095]: Should not allow coercion from into null from Empty String
             // either, if `null` not allowed
             if (_primitive && ctxt.isEnabled(DeserializationFeature.FAIL_ON_NULL_FOR_PRIMITIVES)) {
-                throw ctxt.mappingException(
+                ctxt.reportMappingException(
                         "Can not map Empty String as null into type %s (set DeserializationConfig.DeserializationFeature.FAIL_ON_NULL_FOR_PRIMITIVES to 'false' to allow)",
                         handledType().toString());
             }
@@ -177,7 +171,7 @@
         {
             super(cls, nvl);
         }
-        
+
         @Override
         public Boolean deserialize(JsonParser j, DeserializationContext ctxt) throws IOException
         {
@@ -275,18 +269,10 @@
                 }               
                 break;
             case JsonTokenId.ID_START_ARRAY:
-                if (ctxt.isEnabled(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS)) {
-                    p.nextToken();
-                    final Character C = deserialize(p, ctxt);
-                    if (p.nextToken() != JsonToken.END_ARRAY) {
-                        throw ctxt.wrongTokenException(p, JsonToken.END_ARRAY, 
-                                "Attempted to unwrap single value array for single '" + _valueClass.getName() + "' value but there was more than a single value in the array"
-                                );
-                    }
-                    return C;
-                }
+                return _deserializeFromArray(p, ctxt);
+            default:
             }
-            throw ctxt.mappingException(_valueClass, p.getCurrentToken());
+            return (Character) ctxt.handleUnexpectedToken(_valueClass, p);
         }
     }
 
@@ -437,7 +423,7 @@
                 if (ctxt.isEnabled(DeserializationFeature.USE_BIG_DECIMAL_FOR_FLOATS)) {
                     return p.getDecimalValue();
                 }
-                return Double.valueOf(p.getDoubleValue());
+                return p.getNumberValue();
 
             case JsonTokenId.ID_STRING:
                 /* Textual values are more difficult... not parsing itself, but figuring
@@ -477,23 +463,14 @@
                     }
                     return Long.valueOf(value);
                 } catch (IllegalArgumentException iae) {
-                    throw ctxt.weirdStringException(text, _valueClass, "not a valid number");
+                    return ctxt.handleWeirdStringValue(_valueClass, text,
+                            "not a valid number");
                 }
             case JsonTokenId.ID_START_ARRAY:
-                if (ctxt.isEnabled(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS)) {
-                    p.nextToken();
-                    final Object value = deserialize(p, ctxt);
-                    if (p.nextToken() != JsonToken.END_ARRAY) {
-                        throw ctxt.wrongTokenException(p, JsonToken.END_ARRAY, 
-                                "Attempted to unwrap single value array for single '" + _valueClass.getName() + "' value but there was more than a single value in the array"
-                                );
-                    }
-                    return value;
-                }
-                break;
+                return _deserializeFromArray(p, ctxt);
             }
             // Otherwise, no can do:
-            throw ctxt.mappingException(_valueClass, p.getCurrentToken());
+            return ctxt.handleUnexpectedToken(_valueClass, p);
         }
 
         /**
@@ -557,17 +534,7 @@
                 }
                 return p.getDecimalValue().toBigInteger();
             case JsonTokenId.ID_START_ARRAY:
-                if (ctxt.isEnabled(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS)) {
-                    p.nextToken();
-                    final BigInteger value = deserialize(p, ctxt);
-                    if (p.nextToken() != JsonToken.END_ARRAY) {
-                        throw ctxt.wrongTokenException(p, JsonToken.END_ARRAY,
-                            "Attempted to unwrap single value array for single 'BigInteger' value but there was more than a single value in the array"
-                        );
-                    }
-                    return value;
-                }
-                break;
+                return _deserializeFromArray(p, ctxt);
             case JsonTokenId.ID_STRING: // let's do implicit re-parse
                 String text = p.getText().trim();
                 if (text.length() == 0) {
@@ -576,11 +543,12 @@
                 try {
                     return new BigInteger(text);
                 } catch (IllegalArgumentException iae) {
-                    throw ctxt.weirdStringException(text, _valueClass, "not a valid representation");
+                    return (BigInteger) ctxt.handleWeirdStringValue(_valueClass, text,
+                            "not a valid representation");
                 }
             }
             // String is ok too, can easily convert; otherwise, no can do:
-            throw ctxt.mappingException(_valueClass, p.getCurrentToken());
+            return (BigInteger) ctxt.handleUnexpectedToken(_valueClass, p);
         }
     }
     
@@ -609,23 +577,14 @@
                 try {
                     return new BigDecimal(text);
                 } catch (IllegalArgumentException iae) {
-                    throw ctxt.weirdStringException(text, _valueClass, "not a valid representation");
+                    return (BigDecimal) ctxt.handleWeirdStringValue(_valueClass, text,
+                            "not a valid representation");
                 }
             case JsonTokenId.ID_START_ARRAY:
-                if (ctxt.isEnabled(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS)) {
-                    p.nextToken();
-                    final BigDecimal value = deserialize(p, ctxt);
-                    if (p.nextToken() != JsonToken.END_ARRAY) {
-                        throw ctxt.wrongTokenException(p, JsonToken.END_ARRAY,
-                            "Attempted to unwrap single value array for single 'BigDecimal' value but there was more than a single value in the array"
-                        );
-                    }
-                    return value;
-                }
-                break;
+                return _deserializeFromArray(p, ctxt);
             }
             // Otherwise, no can do:
-            throw ctxt.mappingException(_valueClass, p.getCurrentToken());
+            return (BigDecimal) ctxt.handleUnexpectedToken(_valueClass, p);
         }
     }
 }
diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/std/ObjectArrayDeserializer.java b/src/main/java/com/fasterxml/jackson/databind/deser/std/ObjectArrayDeserializer.java
index 1a3b747..101217b 100644
--- a/src/main/java/com/fasterxml/jackson/databind/deser/std/ObjectArrayDeserializer.java
+++ b/src/main/java/com/fasterxml/jackson/databind/deser/std/ObjectArrayDeserializer.java
@@ -147,7 +147,7 @@
         // Important: do NOT cache if polymorphic values, or ones with custom deserializer
         return (_elementDeserializer == null) && (_elementTypeDeserializer == null);
     }
-    
+
     /*
     /**********************************************************
     /* ContainerDeserializerBase API
@@ -266,12 +266,13 @@
                         ctxt.isEnabled(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY));
         if (!canWrap) {
             // One exception; byte arrays are generally serialized as base64, so that should be handled
-            if (p.getCurrentToken() == JsonToken.VALUE_STRING
+            JsonToken t = p.getCurrentToken();
+            if (t == JsonToken.VALUE_STRING
                     // note: not `byte[]`, but `Byte[]` -- former is primitive array
                     && _elementClass == Byte.class) {
                 return deserializeFromBase64(p, ctxt);
             }
-            throw ctxt.mappingException(_arrayType.getRawClass());
+            return (Object[]) ctxt.handleUnexpectedToken(_arrayType.getRawClass(), p);
         }
         JsonToken t = p.getCurrentToken();
         Object value;
diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/std/PrimitiveArrayDeserializers.java b/src/main/java/com/fasterxml/jackson/databind/deser/std/PrimitiveArrayDeserializers.java
index 6e7b4f8..4221b30 100644
--- a/src/main/java/com/fasterxml/jackson/databind/deser/std/PrimitiveArrayDeserializers.java
+++ b/src/main/java/com/fasterxml/jackson/databind/deser/std/PrimitiveArrayDeserializers.java
@@ -98,7 +98,8 @@
          */
         return typeDeserializer.deserializeTypedFromArray(p, ctxt);
     }
-    
+
+    @SuppressWarnings("unchecked")
     protected T handleNonArray(JsonParser p, DeserializationContext ctxt) throws IOException
     {
         // [JACKSON-620] Empty String can become null...
@@ -114,12 +115,12 @@
         if (canWrap) {
             return handleSingleElementUnwrapped(p, ctxt);
         }
-        throw ctxt.mappingException(_valueClass);
+        return (T) ctxt.handleUnexpectedToken(_valueClass, p);
     }
 
     protected abstract T handleSingleElementUnwrapped(JsonParser p,
             DeserializationContext ctxt) throws IOException;
-    
+
     /*
     /********************************************************
     /* Actual deserializers: efficient String[], char[] deserializers
@@ -165,12 +166,16 @@
                 // Let's actually build as a String, then get chars
                 StringBuilder sb = new StringBuilder(64);
                 while ((t = p.nextToken()) != JsonToken.END_ARRAY) {
-                    if (t != JsonToken.VALUE_STRING) {
-                        throw ctxt.mappingException(Character.TYPE);
+                    String str;
+                    if (t == JsonToken.VALUE_STRING) {
+                        str = p.getText();
+                    } else {
+                        CharSequence cs = (CharSequence) ctxt.handleUnexpectedToken(Character.TYPE, p);
+                        str = cs.toString();
                     }
-                    String str = p.getText();
                     if (str.length() != 1) {
-                        throw JsonMappingException.from(p, "Can not convert a JSON String of length "+str.length()+" into a char element of char array");
+                        ctxt.reportMappingException("Can not convert a JSON String of length %d into a char element of char array",
+                                str.length());
                     }
                     sb.append(str.charAt(0));
                 }
@@ -192,14 +197,14 @@
                 }
                 // not recognized, just fall through
             }
-            throw ctxt.mappingException(_valueClass);
+            return (char[]) ctxt.handleUnexpectedToken(_valueClass, p);
         }
 
         @Override
         protected char[] handleSingleElementUnwrapped(JsonParser p,
                 DeserializationContext ctxt) throws IOException {
-            // not sure how this should work so just return `null` so:
-            throw ctxt.mappingException(_valueClass);
+            // not sure how this should work...
+            return (char[]) ctxt.handleUnexpectedToken(_valueClass, p);
         }
     }
 
@@ -311,11 +316,13 @@
                         // should we catch overflow exceptions?
                         value = p.getByteValue();
                     } else {
-                        // [JACKSON-79]: should probably accept nulls as 0
-                        if (t != JsonToken.VALUE_NULL) {
-                            throw ctxt.mappingException(_valueClass.getComponentType());
+                        // should probably accept nulls as 0
+                        if (t == JsonToken.VALUE_NULL) {
+                            value = (byte) 0;
+                        } else {
+                            Number n = (Number) ctxt.handleUnexpectedToken(_valueClass.getComponentType(), p);
+                            value = n.byteValue();
                         }
-                        value = (byte) 0;
                     }
                     if (ix >= chunk.length) {
                         chunk = builder.appendCompletedChunk(chunk, ix);
@@ -340,10 +347,11 @@
                 value = p.getByteValue();
             } else {
                 // should probably accept nulls as 'false'
-                if (t != JsonToken.VALUE_NULL) {
-                    throw ctxt.mappingException(_valueClass.getComponentType());
+                if (t == JsonToken.VALUE_NULL) {
+                    return null;
                 }
-                value = (byte) 0;
+                Number n = (Number) ctxt.handleUnexpectedToken(_valueClass.getComponentType(), p);
+                value = n.byteValue();
             }
             return new byte[] { value };
         }
diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/std/ReferenceTypeDeserializer.java b/src/main/java/com/fasterxml/jackson/databind/deser/std/ReferenceTypeDeserializer.java
new file mode 100644
index 0000000..65876df
--- /dev/null
+++ b/src/main/java/com/fasterxml/jackson/databind/deser/std/ReferenceTypeDeserializer.java
@@ -0,0 +1,138 @@
+package com.fasterxml.jackson.databind.deser.std;
+
+import java.io.IOException;
+
+import com.fasterxml.jackson.core.JsonParser;
+import com.fasterxml.jackson.core.JsonToken;
+
+import com.fasterxml.jackson.databind.*;
+import com.fasterxml.jackson.databind.deser.ContextualDeserializer;
+import com.fasterxml.jackson.databind.deser.ValueInstantiator;
+import com.fasterxml.jackson.databind.jsontype.TypeDeserializer;
+import com.fasterxml.jackson.databind.type.ReferenceType;
+
+/**
+ * Base deserializer implementation for properties {@link ReferenceType} values.
+ * Implements most of functionality, only leaving couple of abstract
+ * methods for sub-classes to implement
+ *
+ * @since 2.8
+ */
+public abstract class ReferenceTypeDeserializer<T>
+    extends StdDeserializer<T>
+    implements ContextualDeserializer
+{
+    private static final long serialVersionUID = 1L;
+    
+    /**
+     * Full type of property (or root value) for which this deserializer
+     * has been constructed and contextualized.
+     */
+    protected final JavaType _fullType;
+    
+    protected final TypeDeserializer _valueTypeDeserializer;
+    
+    protected final JsonDeserializer<?> _valueDeserializer;
+
+    /*
+    /**********************************************************
+    /* Life-cycle
+    /**********************************************************
+     */
+
+    public ReferenceTypeDeserializer(JavaType fullType,
+            TypeDeserializer typeDeser, JsonDeserializer<?> deser)
+    {
+        super(fullType);
+        _fullType = fullType;
+        _valueDeserializer = deser;
+        _valueTypeDeserializer = typeDeser;
+    }
+
+    // NOTE: for forwards-compatibility; added in 2.8.5 since 2.9.0 has it
+    public ReferenceTypeDeserializer(JavaType fullType, ValueInstantiator inst,
+            TypeDeserializer typeDeser, JsonDeserializer<?> deser) {
+        this(fullType, typeDeser, deser);
+    }
+
+    @Override
+    public JsonDeserializer<?> createContextual(DeserializationContext ctxt, BeanProperty property) throws JsonMappingException
+    {
+        JsonDeserializer<?> deser = _valueDeserializer;
+        if (deser == null) {
+            deser = ctxt.findContextualValueDeserializer(_fullType.getReferencedType(), property);
+        } else { // otherwise directly assigned, probably not contextual yet:
+            deser = ctxt.handleSecondaryContextualization(deser, property, _fullType.getReferencedType());            
+        }
+        TypeDeserializer typeDeser = _valueTypeDeserializer;
+        if (typeDeser != null) {
+            typeDeser = typeDeser.forProperty(property);
+        }
+        if ((deser == _valueDeserializer) && (typeDeser == _valueTypeDeserializer)) {
+            return this;
+        }
+        return withResolved(typeDeser, deser);
+    }
+
+    /*
+    /**********************************************************
+    /* Abstract methods for sub-classes to implement
+    /**********************************************************
+     */
+
+    protected abstract ReferenceTypeDeserializer<T> withResolved(TypeDeserializer typeDeser, JsonDeserializer<?> valueDeser);
+
+    @Override
+    public abstract T getNullValue(DeserializationContext ctxt);
+
+    public abstract T referenceValue(Object contents);
+    
+    /*
+    /**********************************************************
+    /* Overridden accessors
+    /**********************************************************
+     */
+
+    @Override
+    public JavaType getValueType() { return _fullType; }
+
+    /*
+    /**********************************************************
+    /* Deserialization
+    /**********************************************************
+     */
+    
+    @Override
+    public T deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
+        Object contents = (_valueTypeDeserializer == null)
+                ? _valueDeserializer.deserialize(p, ctxt)
+                : _valueDeserializer.deserializeWithType(p, ctxt, _valueTypeDeserializer);
+        return referenceValue(contents);
+    }
+
+    @Override
+    public Object deserializeWithType(JsonParser p, DeserializationContext ctxt,
+            TypeDeserializer typeDeserializer) throws IOException
+    {
+        final JsonToken t = p.getCurrentToken();
+        if (t == JsonToken.VALUE_NULL) { // can this actually happen?
+            return getNullValue(ctxt);
+        }
+        // 22-Oct-2015, tatu: This handling is probably not needed (or is wrong), but
+        //   could be result of older (pre-2.7) Jackson trying to serialize natural types.
+        //  Because of this, let's allow for now, unless proven problematic
+        /*
+        if ((t != null) && t.isScalarValue()) {
+            return deserialize(p, ctxt);
+        }
+        */
+        // 19-Apr-2016, tatu: Alas, due to there typically really being anything for Reference wrapper
+        //   itself, need to just ignore `typeDeser`, use TypeDeserializer we do have for contents
+        //   and it might just work.
+
+        if (_valueTypeDeserializer == null) {
+            return deserialize(p, ctxt);
+        }
+        return referenceValue(_valueTypeDeserializer.deserializeTypedFromAny(p, ctxt));
+    }
+}
diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/std/StackTraceElementDeserializer.java b/src/main/java/com/fasterxml/jackson/databind/deser/std/StackTraceElementDeserializer.java
index 6dc16a3..a5decbe 100644
--- a/src/main/java/com/fasterxml/jackson/databind/deser/std/StackTraceElementDeserializer.java
+++ b/src/main/java/com/fasterxml/jackson/databind/deser/std/StackTraceElementDeserializer.java
@@ -7,7 +7,6 @@
 
 import com.fasterxml.jackson.databind.DeserializationContext;
 import com.fasterxml.jackson.databind.DeserializationFeature;
-import com.fasterxml.jackson.databind.JsonMappingException;
 
 public class StackTraceElementDeserializer
     extends StdScalarDeserializer<StackTraceElement>
@@ -17,46 +16,65 @@
     public StackTraceElementDeserializer() { super(StackTraceElement.class); }
 
     @Override
-    public StackTraceElement deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
+    public StackTraceElement deserialize(JsonParser p, DeserializationContext ctxt) throws IOException
     {
-        JsonToken t = jp.getCurrentToken();
+        JsonToken t = p.getCurrentToken();
         // Must get an Object
         if (t == JsonToken.START_OBJECT) {
             String className = "", methodName = "", fileName = "";
+            // Java 9 adds couple more things
+            String moduleName = null, moduleVersion = null;
             int lineNumber = -1;
 
-            while ((t = jp.nextValue()) != JsonToken.END_OBJECT) {
-                String propName = jp.getCurrentName();
+            while ((t = p.nextValue()) != JsonToken.END_OBJECT) {
+                String propName = p.getCurrentName();
+                // TODO: with Java 8, convert to switch
                 if ("className".equals(propName)) {
-                    className = jp.getText();
+                    className = p.getText();
                 } else if ("fileName".equals(propName)) {
-                    fileName = jp.getText();
+                    fileName = p.getText();
                 } else if ("lineNumber".equals(propName)) {
                     if (t.isNumeric()) {
-                        lineNumber = jp.getIntValue();
+                        lineNumber = p.getIntValue();
                     } else {
-                        throw JsonMappingException.from(jp, "Non-numeric token ("+t+") for property 'lineNumber'");
+                        lineNumber = _parseIntPrimitive(p, ctxt);
                     }
                 } else if ("methodName".equals(propName)) {
-                    methodName = jp.getText();
+                    methodName = p.getText();
                 } else if ("nativeMethod".equals(propName)) {
                     // no setter, not passed via constructor: ignore
+                } else if ("moduleName".equals(propName)) {
+                    moduleName = p.getText();
+                } else if ("moduleVersion".equals(propName)) {
+                    moduleVersion = p.getText();
                 } else {
-                    handleUnknownProperty(jp, ctxt, _valueClass, propName);
+                    handleUnknownProperty(p, ctxt, _valueClass, propName);
                 }
             }
-            return new StackTraceElement(className, methodName, fileName, lineNumber);
+            return constructValue(ctxt, className, methodName, fileName, lineNumber,
+                    moduleName, moduleVersion);
         } else if (t == JsonToken.START_ARRAY && ctxt.isEnabled(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS)) {
-            jp.nextToken();
-            final StackTraceElement value = deserialize(jp, ctxt);
-            if (jp.nextToken() != JsonToken.END_ARRAY) {
-                throw ctxt.wrongTokenException(jp, JsonToken.END_ARRAY,
-                        "Attempted to unwrap single value array for single 'java.lang.StackTraceElement' value but there was more than a single value in the array"
-                    );
+            p.nextToken();
+            final StackTraceElement value = deserialize(p, ctxt);
+            if (p.nextToken() != JsonToken.END_ARRAY) {
+                handleMissingEndArrayForSingle(p, ctxt);
             }
             return value;
         }
-            
-        throw ctxt.mappingException(_valueClass, t);
+        return (StackTraceElement) ctxt.handleUnexpectedToken(_valueClass, p);
     }
-}
\ No newline at end of file
+
+    /**
+     * Overridable factory method used for constructing {@link StackTraceElement}s.
+     *
+     * @since 2.8
+     */
+    protected StackTraceElement constructValue(DeserializationContext ctxt,
+            String className, String methodName, String fileName, int lineNumber,
+            String moduleName, String moduleVersion)
+    {
+        // 21-May-2016, tatu: With Java 9, need to use different constructor, probably
+        //   via different module, and throw exception here if extra args passed
+        return new StackTraceElement(className, methodName, fileName, lineNumber);
+    }
+}
diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/std/StdDelegatingDeserializer.java b/src/main/java/com/fasterxml/jackson/databind/deser/std/StdDelegatingDeserializer.java
index 4f9cd74..9876124 100644
--- a/src/main/java/com/fasterxml/jackson/databind/deser/std/StdDelegatingDeserializer.java
+++ b/src/main/java/com/fasterxml/jackson/databind/deser/std/StdDelegatingDeserializer.java
@@ -104,6 +104,8 @@
     /**********************************************************
      */
 
+    // Note: unlikely to get called since most likely instances explicitly constructed;
+    // if so, caller must ensure delegating deserializer is properly resolve()d.
     @Override
     public void resolve(DeserializationContext ctxt)
         throws JsonMappingException
diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/std/StdDeserializer.java b/src/main/java/com/fasterxml/jackson/databind/deser/std/StdDeserializer.java
index 7848985..70d7417 100644
--- a/src/main/java/com/fasterxml/jackson/databind/deser/std/StdDeserializer.java
+++ b/src/main/java/com/fasterxml/jackson/databind/deser/std/StdDeserializer.java
@@ -5,7 +5,6 @@
 
 import com.fasterxml.jackson.annotation.JsonFormat;
 import com.fasterxml.jackson.core.*;
-import com.fasterxml.jackson.core.JsonParser.NumberType;
 import com.fasterxml.jackson.core.io.NumberInput;
 import com.fasterxml.jackson.databind.*;
 import com.fasterxml.jackson.databind.annotation.JacksonStdImpl;
@@ -116,8 +115,9 @@
      * this method if they are to handle type information.
      */
     @Override
-    public Object deserializeWithType(JsonParser jp, DeserializationContext ctxt, TypeDeserializer typeDeserializer) throws IOException {
-        return typeDeserializer.deserializeTypedFromAny(jp, ctxt);
+    public Object deserializeWithType(JsonParser p, DeserializationContext ctxt,
+            TypeDeserializer typeDeserializer) throws IOException {
+        return typeDeserializer.deserializeTypedFromAny(p, ctxt);
     }
     
     /*
@@ -128,25 +128,21 @@
     /**********************************************************
      */
 
-    protected final boolean _parseBooleanPrimitive(JsonParser jp, DeserializationContext ctxt) throws IOException
+    protected final boolean _parseBooleanPrimitive(JsonParser p, DeserializationContext ctxt) throws IOException
     {
-        JsonToken t = jp.getCurrentToken();
+        JsonToken t = p.getCurrentToken();
         if (t == JsonToken.VALUE_TRUE) return true;
         if (t == JsonToken.VALUE_FALSE) return false;
         if (t == JsonToken.VALUE_NULL) return false;
 
-        // [JACKSON-78]: should accept ints too, (0 == false, otherwise true)
+        // should accept ints too, (0 == false, otherwise true)
         if (t == JsonToken.VALUE_NUMBER_INT) {
-            // 11-Jan-2012, tatus: May be outside of int...
-            if (jp.getNumberType() == NumberType.INT) {
-                return (jp.getIntValue() != 0);
-            }
-            return _parseBooleanFromOther(jp, ctxt);
+            return _parseBooleanFromInt(p, ctxt);
         }
         // And finally, let's allow Strings to be converted too
         if (t == JsonToken.VALUE_STRING) {
-            String text = jp.getText().trim();
-            // [#422]: Allow aliases
+            String text = p.getText().trim();
+            // [databind#422]: Allow aliases
             if ("true".equals(text) || "True".equals(text)) {
                 return true;
             }
@@ -156,21 +152,22 @@
             if (_hasTextualNull(text)) {
                 return false;
             }
-            throw ctxt.weirdStringException(text, _valueClass, "only \"true\" or \"false\" recognized");
+            Boolean b = (Boolean) ctxt.handleWeirdStringValue(_valueClass, text,
+                    "only \"true\" or \"false\" recognized");
+            return (b == null) ? false : b.booleanValue();
         }
         // [databind#381]
         if (t == JsonToken.START_ARRAY && ctxt.isEnabled(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS)) {
-            jp.nextToken();
-            final boolean parsed = _parseBooleanPrimitive(jp, ctxt);
-            t = jp.nextToken();
+            p.nextToken();
+            final boolean parsed = _parseBooleanPrimitive(p, ctxt);
+            t = p.nextToken();
             if (t != JsonToken.END_ARRAY) {
-                throw ctxt.wrongTokenException(jp, JsonToken.END_ARRAY, 
-                        "Attempted to unwrap single value array for single 'boolean' value but there was more than a single value in the array");
+                handleMissingEndArrayForSingle(p, ctxt);
             }            
             return parsed;            
         }
         // Otherwise, no can do:
-        throw ctxt.mappingException(_valueClass, t);
+        return ((Boolean) ctxt.handleUnexpectedToken(_valueClass, p)).booleanValue();
     }
 
     protected final Boolean _parseBoolean(JsonParser p, DeserializationContext ctxt)
@@ -183,13 +180,9 @@
         if (t == JsonToken.VALUE_FALSE) {
             return Boolean.FALSE;
         }
-        // [JACKSON-78]: should accept ints too, (0 == false, otherwise true)
+        // should accept ints too, (0 == false, otherwise true)
         if (t == JsonToken.VALUE_NUMBER_INT) {
-            // 11-Jan-2012, tatus: May be outside of int...
-            if (p.getNumberType() == NumberType.INT) {
-                return (p.getIntValue() == 0) ? Boolean.FALSE : Boolean.TRUE;
-            }
-            return Boolean.valueOf(_parseBooleanFromOther(p, ctxt));
+            return Boolean.valueOf(_parseBooleanFromInt(p, ctxt));
         }
         if (t == JsonToken.VALUE_NULL) {
             return (Boolean) getNullValue(ctxt);
@@ -197,7 +190,7 @@
         // And finally, let's allow Strings to be converted too
         if (t == JsonToken.VALUE_STRING) {
             String text = p.getText().trim();
-            // [#422]: Allow aliases
+            // [databind#422]: Allow aliases
             if ("true".equals(text) || "True".equals(text)) {
                 return Boolean.TRUE;
             }
@@ -210,35 +203,41 @@
             if (_hasTextualNull(text)) {
                 return (Boolean) getNullValue(ctxt);
             }
-            throw ctxt.weirdStringException(text, _valueClass, "only \"true\" or \"false\" recognized");
+            return (Boolean) ctxt.handleWeirdStringValue(_valueClass, text,
+                    "only \"true\" or \"false\" recognized");
         }
-        // Issue#381
+        // [databind#381]
         if (t == JsonToken.START_ARRAY && ctxt.isEnabled(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS)) {
             p.nextToken();
             final Boolean parsed = _parseBoolean(p, ctxt);
             t = p.nextToken();
             if (t != JsonToken.END_ARRAY) {
-                throw ctxt.wrongTokenException(p, JsonToken.END_ARRAY, 
-                        "Attempted to unwrap single value array for single 'Boolean' value but there was more than a single value in the array");
+                handleMissingEndArrayForSingle(p, ctxt);
             }            
             return parsed;            
         }
         // Otherwise, no can do:
-        throw ctxt.mappingException(_valueClass, t);
+        return (Boolean) ctxt.handleUnexpectedToken(_valueClass, p);
     }
 
-    protected final boolean _parseBooleanFromOther(JsonParser p, DeserializationContext ctxt)
-            throws IOException
+    protected boolean _parseBooleanFromInt(JsonParser p, DeserializationContext ctxt)
+        throws IOException
     {
-        if (p.getNumberType() == NumberType.LONG) {
-            return (p.getLongValue() == 0L) ? Boolean.FALSE : Boolean.TRUE;
-        }
-        // no really good logic; let's actually resort to textual comparison
-        String str = p.getText();
-        if ("0.0".equals(str) || "0".equals(str)) {
-            return Boolean.FALSE;
-        }
-        return Boolean.TRUE;
+        // 13-Oct-2016, tatu: As per [databind#1324], need to be careful wrt
+        //    degenerate case of huge integers, legal in JSON.
+        //  ... this is, on the other hand, probably wrong/sub-optimal for non-JSON
+        //  input. For now, no rea
+
+        // Anyway, note that since we know it's valid (JSON) integer, it can't have
+        // extra whitespace to trim.
+        return !"0".equals(p.getText());
+    }
+
+    @Deprecated // since 2.8.4
+    protected boolean _parseBooleanFromOther(JsonParser p, DeserializationContext ctxt)
+        throws IOException
+    {
+        return _parseBooleanFromInt(p, ctxt);
     }
 
     protected Byte _parseByte(JsonParser p, DeserializationContext ctxt)
@@ -261,12 +260,15 @@
                 }
                 value = NumberInput.parseInt(text);
             } catch (IllegalArgumentException iae) {
-                throw ctxt.weirdStringException(text, _valueClass, "not a valid Byte value");
+                return (Byte) ctxt.handleWeirdStringValue(_valueClass, text,
+                        "not a valid Byte value");
             }
             // So far so good: but does it fit?
             // as per [JACKSON-804], allow range up to 255, inclusive
             if (value < Byte.MIN_VALUE || value > 255) {
-                throw ctxt.weirdStringException(text, _valueClass, "overflow, value can not be represented as 8-bit value");
+                return (Byte) ctxt.handleWeirdStringValue(_valueClass, text,
+                        "overflow, value can not be represented as 8-bit value");
+                // fall-through for deferred fails
             }
             return Byte.valueOf((byte) value);
         }
@@ -279,18 +281,17 @@
         if (t == JsonToken.VALUE_NULL) {
             return (Byte) getNullValue(ctxt);
         }
-        // Issue#381
+        // [databind#381]
         if (t == JsonToken.START_ARRAY && ctxt.isEnabled(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS)) {
             p.nextToken();
             final Byte parsed = _parseByte(p, ctxt);
             t = p.nextToken();
             if (t != JsonToken.END_ARRAY) {
-                throw ctxt.wrongTokenException(p, JsonToken.END_ARRAY, 
-                        "Attempted to unwrap single value array for single 'Byte' value but there was more than a single value in the array");
+                handleMissingEndArrayForSingle(p, ctxt);
             }            
             return parsed;            
         }
-        throw ctxt.mappingException(_valueClass, t);
+        return (Byte) ctxt.handleUnexpectedToken(_valueClass, p);
     }
     
     protected Short _parseShort(JsonParser p, DeserializationContext ctxt)
@@ -313,11 +314,13 @@
                 }
                 value = NumberInput.parseInt(text);
             } catch (IllegalArgumentException iae) {
-                throw ctxt.weirdStringException(text, _valueClass, "not a valid Short value");
+                return (Short) ctxt.handleWeirdStringValue(_valueClass, text,
+                        "not a valid Short value");
             }
             // So far so good: but does it fit?
             if (value < Short.MIN_VALUE || value > Short.MAX_VALUE) {
-                throw ctxt.weirdStringException(text, _valueClass, "overflow, value can not be represented as 16-bit value");
+                return (Short) ctxt.handleWeirdStringValue(_valueClass, text,
+                        "overflow, value can not be represented as 16-bit value");
             }
             return Short.valueOf((short) value);
         }
@@ -330,28 +333,28 @@
         if (t == JsonToken.VALUE_NULL) {
             return (Short) getNullValue(ctxt);
         }
-        // Issue#381
+        // [databind#381]
         if (t == JsonToken.START_ARRAY && ctxt.isEnabled(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS)) {
             p.nextToken();
             final Short parsed = _parseShort(p, ctxt);
             t = p.nextToken();
             if (t != JsonToken.END_ARRAY) {
-                throw ctxt.wrongTokenException(p, JsonToken.END_ARRAY, 
-                        "Attempted to unwrap single value array for single 'Short' value but there was more than a single value in the array");
+                handleMissingEndArrayForSingle(p, ctxt);
             }            
             return parsed;            
         }
-        throw ctxt.mappingException(_valueClass, t);
+        return (Short) ctxt.handleUnexpectedToken(_valueClass, p);
     }
 
-    protected final short _parseShortPrimitive(JsonParser jp, DeserializationContext ctxt)
+    protected final short _parseShortPrimitive(JsonParser p, DeserializationContext ctxt)
         throws IOException
     {
-        int value = _parseIntPrimitive(jp, ctxt);
+        int value = _parseIntPrimitive(p, ctxt);
         // So far so good: but does it fit?
         if (value < Short.MIN_VALUE || value > Short.MAX_VALUE) {
-            throw ctxt.weirdStringException(String.valueOf(value),
-                    _valueClass, "overflow, value can not be represented as 16-bit value");
+            Number v = (Number) ctxt.handleWeirdStringValue(_valueClass, String.valueOf(value),
+                    "overflow, value can not be represented as 16-bit value");
+            return (v == null) ? (short) 0 : v.shortValue();
         }
         return (short) value;
     }
@@ -373,8 +376,10 @@
                 if (len > 9) {
                     long l = Long.parseLong(text);
                     if (l < Integer.MIN_VALUE || l > Integer.MAX_VALUE) {
-                        throw ctxt.weirdStringException(text, _valueClass,
-                            "Overflow: numeric value ("+text+") out of range of int ("+Integer.MIN_VALUE+" - "+Integer.MAX_VALUE+")");
+                        Number v = (Number) ctxt.handleWeirdStringValue(_valueClass, text,
+                            "Overflow: numeric value (%s) out of range of int (%d -%d)",
+                            text, Integer.MIN_VALUE, Integer.MAX_VALUE);
+                        return (v == null) ? 0 : v.intValue();
                     }
                     return (int) l;
                 }
@@ -383,7 +388,9 @@
                 }
                 return NumberInput.parseInt(text);
             } catch (IllegalArgumentException iae) {
-                throw ctxt.weirdStringException(text, _valueClass, "not a valid int value");
+                Number v = (Number) ctxt.handleWeirdStringValue(_valueClass, text,
+                        "not a valid int value");
+                return (v == null) ? 0 : v.intValue();
             }
         }
         if (t == JsonToken.VALUE_NUMBER_FLOAT) {
@@ -400,13 +407,12 @@
             final int parsed = _parseIntPrimitive(p, ctxt);
             t = p.nextToken();
             if (t != JsonToken.END_ARRAY) {
-                throw ctxt.wrongTokenException(p, JsonToken.END_ARRAY, 
-                        "Attempted to unwrap single value array for single 'int' value but there was more than a single value in the array");
+                handleMissingEndArrayForSingle(p, ctxt);
             }            
             return parsed;            
         }
         // Otherwise, no can do:
-        throw ctxt.mappingException(_valueClass, t);
+        return ((Number) ctxt.handleUnexpectedToken(_valueClass, p)).intValue();
     }
 
     protected final Integer _parseInteger(JsonParser p, DeserializationContext ctxt)
@@ -431,8 +437,9 @@
                 if (len > 9) {
                     long l = Long.parseLong(text);
                     if (l < Integer.MIN_VALUE || l > Integer.MAX_VALUE) {
-                        throw ctxt.weirdStringException(text, _valueClass,
+                        return (Integer) ctxt.handleWeirdStringValue(_valueClass, text,
                             "Overflow: numeric value ("+text+") out of range of Integer ("+Integer.MIN_VALUE+" - "+Integer.MAX_VALUE+")");
+                        // fall-through
                     }
                     return Integer.valueOf((int) l);
                 }
@@ -441,8 +448,10 @@
                 }
                 return Integer.valueOf(NumberInput.parseInt(text));
             } catch (IllegalArgumentException iae) {
-                throw ctxt.weirdStringException(text, _valueClass, "not a valid Integer value");
+                return (Integer) ctxt.handleWeirdStringValue(_valueClass, text,
+                        "not a valid Integer value");
             }
+            // fall-through
         case JsonTokenId.ID_NULL:
             return (Integer) getNullValue(ctxt);
         case JsonTokenId.ID_START_ARRAY:
@@ -450,15 +459,14 @@
                 p.nextToken();
                 final Integer parsed = _parseInteger(p, ctxt);
                 if (p.nextToken() != JsonToken.END_ARRAY) {
-                    throw ctxt.wrongTokenException(p, JsonToken.END_ARRAY, 
-                            "Attempted to unwrap single value array for single 'Integer' value but there was more than a single value in the array");
+                    handleMissingEndArrayForSingle(p, ctxt);
                 }            
                 return parsed;            
             }
             break;
         }
         // Otherwise, no can do:
-        throw ctxt.mappingException(_valueClass, p.getCurrentToken());
+        return (Integer) ctxt.handleUnexpectedToken(_valueClass, p);
     }
 
     protected final Long _parseLong(JsonParser p, DeserializationContext ctxt) throws IOException
@@ -485,7 +493,9 @@
             try {
                 return Long.valueOf(NumberInput.parseLong(text));
             } catch (IllegalArgumentException iae) { }
-            throw ctxt.weirdStringException(text, _valueClass, "not a valid Long value");
+            return (Long) ctxt.handleWeirdStringValue(_valueClass, text,
+                    "not a valid Long value");
+            // fall-through
         case JsonTokenId.ID_NULL:
             return (Long) getNullValue(ctxt);
         case JsonTokenId.ID_START_ARRAY:
@@ -494,15 +504,14 @@
                 final Long parsed = _parseLong(p, ctxt);
                 JsonToken t = p.nextToken();
                 if (t != JsonToken.END_ARRAY) {
-                    throw ctxt.wrongTokenException(p, JsonToken.END_ARRAY, 
-                            "Attempted to unwrap single value array for single 'Long' value but there was more than a single value in the array");
+                    handleMissingEndArrayForSingle(p, ctxt);
                 }            
                 return parsed;            
             }
             break;
         }
         // Otherwise, no can do:
-        throw ctxt.mappingException(_valueClass, p.getCurrentToken());
+        return (Long) ctxt.handleUnexpectedToken(_valueClass, p);
     }
 
     protected final long _parseLongPrimitive(JsonParser p, DeserializationContext ctxt)
@@ -524,37 +533,40 @@
             try {
                 return NumberInput.parseLong(text);
             } catch (IllegalArgumentException iae) { }
-            throw ctxt.weirdStringException(text, _valueClass, "not a valid long value");
+            {
+                Number v = (Number) ctxt.handleWeirdStringValue(_valueClass, text,
+                        "not a valid long value");
+                return (v == null) ? 0 : v.longValue();
+            }
         case JsonTokenId.ID_NULL:
             return 0L;
         case JsonTokenId.ID_START_ARRAY:
             if (ctxt.isEnabled(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS)) {
-            p.nextToken();
-            final long parsed = _parseLongPrimitive(p, ctxt);
-            JsonToken t = p.nextToken();
-            if (t != JsonToken.END_ARRAY) {
-                throw ctxt.wrongTokenException(p, JsonToken.END_ARRAY, 
-                        "Attempted to unwrap single value array for single 'long' value but there was more than a single value in the array");
-            }            
-            return parsed;
+                p.nextToken();
+                final long parsed = _parseLongPrimitive(p, ctxt);
+                JsonToken t = p.nextToken();
+                if (t != JsonToken.END_ARRAY) {
+                    handleMissingEndArrayForSingle(p, ctxt);
+                }
+                return parsed;
             }
             break;
         }
-        throw ctxt.mappingException(_valueClass, p.getCurrentToken());
+        return ((Number) ctxt.handleUnexpectedToken(_valueClass, p)).longValue();
     }
-    
-    protected final Float _parseFloat(JsonParser jp, DeserializationContext ctxt)
+
+    protected final Float _parseFloat(JsonParser p, DeserializationContext ctxt)
         throws IOException
     {
         // We accept couple of different types; obvious ones first:
-        JsonToken t = jp.getCurrentToken();
+        JsonToken t = p.getCurrentToken();
         
         if (t == JsonToken.VALUE_NUMBER_INT || t == JsonToken.VALUE_NUMBER_FLOAT) { // coercing should work too
-            return jp.getFloatValue();
+            return p.getFloatValue();
         }
         // And finally, let's allow Strings to be converted too
         if (t == JsonToken.VALUE_STRING) {
-            String text = jp.getText().trim();
+            String text = p.getText().trim();
             if (text.length() == 0) {
                 return (Float) getEmptyValue(ctxt);
             }
@@ -581,36 +593,35 @@
             try {
                 return Float.parseFloat(text);
             } catch (IllegalArgumentException iae) { }
-            throw ctxt.weirdStringException(text, _valueClass, "not a valid Float value");
+            return (Float) ctxt.handleWeirdStringValue(_valueClass, text,
+                    "not a valid Float value");
         }
         if (t == JsonToken.VALUE_NULL) {
             return (Float) getNullValue(ctxt);
         }
-        // Issue#381
         if (t == JsonToken.START_ARRAY && ctxt.isEnabled(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS)) {
-            jp.nextToken();
-            final Float parsed = _parseFloat(jp, ctxt);
-            t = jp.nextToken();
+            p.nextToken();
+            final Float parsed = _parseFloat(p, ctxt);
+            t = p.nextToken();
             if (t != JsonToken.END_ARRAY) {
-                throw ctxt.wrongTokenException(jp, JsonToken.END_ARRAY, 
-                        "Attempted to unwrap single value array for single 'Byte' value but there was more than a single value in the array");
+                handleMissingEndArrayForSingle(p, ctxt);
             }            
             return parsed;            
         }
         // Otherwise, no can do:
-        throw ctxt.mappingException(_valueClass, t);
+        return (Float) ctxt.handleUnexpectedToken(_valueClass, p);
     }
-    
-    protected final float _parseFloatPrimitive(JsonParser jp, DeserializationContext ctxt)
+
+    protected final float _parseFloatPrimitive(JsonParser p, DeserializationContext ctxt)
         throws IOException
     {
-        JsonToken t = jp.getCurrentToken();
+        JsonToken t = p.getCurrentToken();
 
         if (t == JsonToken.VALUE_NUMBER_INT || t == JsonToken.VALUE_NUMBER_FLOAT) { // coercing should work too
-            return jp.getFloatValue();
+            return p.getFloatValue();
         }
         if (t == JsonToken.VALUE_STRING) {
-            String text = jp.getText().trim();
+            String text = p.getText().trim();
             if (text.length() == 0 || _hasTextualNull(text)) {
                 return 0.0f;
             }
@@ -632,36 +643,36 @@
             try {
                 return Float.parseFloat(text);
             } catch (IllegalArgumentException iae) { }
-            throw ctxt.weirdStringException(text, _valueClass, "not a valid float value");
+            Number v = (Number) ctxt.handleWeirdStringValue(_valueClass, text,
+                    "not a valid float value");
+            return (v == null) ? 0 : v.floatValue();
         }
         if (t == JsonToken.VALUE_NULL) {
             return 0.0f;
         }
-        // Issue#381
         if (t == JsonToken.START_ARRAY && ctxt.isEnabled(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS)) {
-            jp.nextToken();
-            final float parsed = _parseFloatPrimitive(jp, ctxt);
-            t = jp.nextToken();
+            p.nextToken();
+            final float parsed = _parseFloatPrimitive(p, ctxt);
+            t = p.nextToken();
             if (t != JsonToken.END_ARRAY) {
-                throw ctxt.wrongTokenException(jp, JsonToken.END_ARRAY, 
-                        "Attempted to unwrap single value array for single 'float' value but there was more than a single value in the array");
+                handleMissingEndArrayForSingle(p, ctxt);
             }            
             return parsed;            
         }
         // Otherwise, no can do:
-        throw ctxt.mappingException(_valueClass, t);
+        return ((Number) ctxt.handleUnexpectedToken(_valueClass, p)).floatValue();
     }
 
-    protected final Double _parseDouble(JsonParser jp, DeserializationContext ctxt)
+    protected final Double _parseDouble(JsonParser p, DeserializationContext ctxt)
         throws IOException
     {
-        JsonToken t = jp.getCurrentToken();
+        JsonToken t = p.getCurrentToken();
         
         if (t == JsonToken.VALUE_NUMBER_INT || t == JsonToken.VALUE_NUMBER_FLOAT) { // coercing should work too
-            return jp.getDoubleValue();
+            return p.getDoubleValue();
         }
         if (t == JsonToken.VALUE_STRING) {
-            String text = jp.getText().trim();
+            String text = p.getText().trim();
             if (text.length() == 0) {
                 return (Double) getEmptyValue(ctxt);
             }
@@ -688,37 +699,37 @@
             try {
                 return parseDouble(text);
             } catch (IllegalArgumentException iae) { }
-            throw ctxt.weirdStringException(text, _valueClass, "not a valid Double value");
+            return (Double) ctxt.handleWeirdStringValue(_valueClass, text,
+                    "not a valid Double value");
         }
         if (t == JsonToken.VALUE_NULL) {
             return (Double) getNullValue(ctxt);
         }
         if (t == JsonToken.START_ARRAY && ctxt.isEnabled(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS)) {
-            jp.nextToken();
-            final Double parsed = _parseDouble(jp, ctxt);
-            t = jp.nextToken();
+            p.nextToken();
+            final Double parsed = _parseDouble(p, ctxt);
+            t = p.nextToken();
             if (t != JsonToken.END_ARRAY) {
-                throw ctxt.wrongTokenException(jp, JsonToken.END_ARRAY, 
-                        "Attempted to unwrap single value array for single 'Double' value but there was more than a single value in the array");
+                handleMissingEndArrayForSingle(p, ctxt);
             }            
             return parsed;            
         }
-            // Otherwise, no can do:
-        throw ctxt.mappingException(_valueClass, t);
+        // Otherwise, no can do:
+        return (Double) ctxt.handleUnexpectedToken(_valueClass, p);
     }
 
-    protected final double _parseDoublePrimitive(JsonParser jp, DeserializationContext ctxt)
+    protected final double _parseDoublePrimitive(JsonParser p, DeserializationContext ctxt)
         throws IOException
     {
         // We accept couple of different types; obvious ones first:
-        JsonToken t = jp.getCurrentToken();
+        JsonToken t = p.getCurrentToken();
         
         if (t == JsonToken.VALUE_NUMBER_INT || t == JsonToken.VALUE_NUMBER_FLOAT) { // coercing should work too
-            return jp.getDoubleValue();
+            return p.getDoubleValue();
         }
         // And finally, let's allow Strings to be converted too
         if (t == JsonToken.VALUE_STRING) {
-            String text = jp.getText().trim();
+            String text = p.getText().trim();
             if (text.length() == 0 || _hasTextualNull(text)) {
                 return 0.0;
             }
@@ -742,24 +753,25 @@
             try {
                 return parseDouble(text);
             } catch (IllegalArgumentException iae) { }
-            throw ctxt.weirdStringException(text, _valueClass, "not a valid double value");
+            Number v = (Number) ctxt.handleWeirdStringValue(_valueClass, text, 
+                    "not a valid double value");
+            return (v == null) ? 0 : v.doubleValue();
         }
         if (t == JsonToken.VALUE_NULL) {
             return 0.0;
         }
-        // Issue#381
+        // [databind#381]
         if (t == JsonToken.START_ARRAY && ctxt.isEnabled(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS)) {
-            jp.nextToken();
-            final double parsed = _parseDoublePrimitive(jp, ctxt);
-            t = jp.nextToken();
+            p.nextToken();
+            final double parsed = _parseDoublePrimitive(p, ctxt);
+            t = p.nextToken();
             if (t != JsonToken.END_ARRAY) {
-                throw ctxt.wrongTokenException(jp, JsonToken.END_ARRAY, 
-                        "Attempted to unwrap single value array for single 'Byte' value but there was more than a single value in the array");
+                handleMissingEndArrayForSingle(p, ctxt);
             }            
             return parsed;            
         }
-            // Otherwise, no can do:
-        throw ctxt.mappingException(_valueClass, t);
+        // Otherwise, no can do:
+        return ((Number) ctxt.handleUnexpectedToken(_valueClass, p)).doubleValue();
     }
 
     protected java.util.Date _parseDate(JsonParser p, DeserializationContext ctxt)
@@ -773,36 +785,40 @@
             return (java.util.Date) getNullValue(ctxt);
         }
         if (t == JsonToken.VALUE_STRING) {
-            String value = null;
-            try {
-                // As per [JACKSON-203], take empty Strings to mean
-                value = p.getText().trim();
-                if (value.length() == 0) {
-                    return (Date) getEmptyValue(ctxt);
-                }
-                if (_hasTextualNull(value)) {
-                    return (java.util.Date) getNullValue(ctxt);
-                }
-                return ctxt.parseDate(value);
-            } catch (IllegalArgumentException iae) {
-                throw ctxt.weirdStringException(value, _valueClass,
-                        "not a valid representation (error: "+iae.getMessage()+")");
-            }
+            return _parseDate(p.getText().trim(), ctxt);
         }
         // [databind#381]
-        if (t == JsonToken.START_ARRAY) {
-            if (ctxt.isEnabled(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS)) {
-                p.nextToken();
-                final Date parsed = _parseDate(p, ctxt);
-                t = p.nextToken();
-                if (t != JsonToken.END_ARRAY) {
-                    throw ctxt.wrongTokenException(p, JsonToken.END_ARRAY, 
-                            "Attempted to unwrap single value array for single 'java.util.Date' value but there was more than a single value in the array");
-                }            
-                return parsed;
-            }
+        if (t == JsonToken.START_ARRAY && ctxt.isEnabled(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS)) {
+            p.nextToken();
+            final Date parsed = _parseDate(p, ctxt);
+            t = p.nextToken();
+            if (t != JsonToken.END_ARRAY) {
+                handleMissingEndArrayForSingle(p, ctxt);
+            }            
+            return parsed;            
         }
-        throw ctxt.mappingException(_valueClass, t);
+        return (java.util.Date)  ctxt.handleUnexpectedToken(_valueClass, p);
+    }
+
+    /**
+     * @since 2.8
+     */
+    protected java.util.Date _parseDate(String value, DeserializationContext ctxt)
+        throws IOException
+    {
+        try {
+            // Take empty Strings to mean 'empty' Value, usually 'null':
+            if (value.length() == 0) {
+                return (Date) getEmptyValue(ctxt);
+            }
+            if (_hasTextualNull(value)) {
+                return (java.util.Date) getNullValue(ctxt);
+            }
+            return ctxt.parseDate(value);
+        } catch (IllegalArgumentException iae) {
+            return (java.util.Date) ctxt.handleWeirdStringValue(_valueClass, value,
+                    "not a valid representation (error: %s)", iae.getMessage());
+        }
     }
 
     /**
@@ -831,12 +847,11 @@
             return p.getText();
         }
         // [databind#381]
-        if (t == JsonToken.START_ARRAY && ctxt.isEnabled(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS)) {
+        if ((t == JsonToken.START_ARRAY) && ctxt.isEnabled(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS)) {
             p.nextToken();
             final String parsed = _parseString(p, ctxt);
             if (p.nextToken() != JsonToken.END_ARRAY) {
-                throw ctxt.wrongTokenException(p, JsonToken.END_ARRAY, 
-                        "Attempted to unwrap single value array for single 'String' value but there was more than a single value in the array");
+                handleMissingEndArrayForSingle(p, ctxt);
             }            
             return parsed;            
         }
@@ -844,7 +859,7 @@
         if (value != null) {
             return value;
         }
-        throw ctxt.mappingException(String.class, p.getCurrentToken());
+        return (String) ctxt.handleUnexpectedToken(String.class, p);
     }
 
     /**
@@ -853,29 +868,30 @@
      * 
      * @since 2.5
      */
-    protected T _deserializeFromEmpty(JsonParser jp, DeserializationContext ctxt)
+    @SuppressWarnings("unchecked")
+    protected T _deserializeFromEmpty(JsonParser p, DeserializationContext ctxt)
         throws IOException
     {
-        JsonToken t = jp.getCurrentToken();
+        JsonToken t = p.getCurrentToken();
         if (t == JsonToken.START_ARRAY) {
             if (ctxt.isEnabled(DeserializationFeature.ACCEPT_EMPTY_ARRAY_AS_NULL_OBJECT)) {
-                t = jp.nextToken();
+                t = p.nextToken();
                 if (t == JsonToken.END_ARRAY) {
                     return null;
                 }
-                throw ctxt.mappingException(handledType(), JsonToken.START_ARRAY);
+                return (T) ctxt.handleUnexpectedToken(handledType(), p);
             }
         } else if (t == JsonToken.VALUE_STRING) {
             if (ctxt.isEnabled(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT)) {
-                String str = jp.getText().trim();
+                String str = p.getText().trim();
                 if (str.isEmpty()) {
                     return null;
                 }
             }
         }
-        throw ctxt.mappingException(handledType());
+        return (T) ctxt.handleUnexpectedToken(handledType(), p);
     }
-    
+
     /**
      * Helper method called to determine if we are seeing String value of
      * "null", and, further, that it should be coerced to null just like
@@ -1058,12 +1074,8 @@
      * Bean property. Method can deal with the problem as it sees fit (ignore,
      * throw exception); but if it does return, it has to skip the matching
      * Json content parser has.
-     *<p>
-     * NOTE: method signature was changed in version 1.5; explicit JsonParser
-     * <b>must</b> be passed since it may be something other than what
-     * context has. Prior versions did not include the first parameter.
      *
-     * @param jp Parser that points to value of the unknown property
+     * @param p Parser that points to value of the unknown property
      * @param ctxt Context for deserialization; allows access to the parser,
      *    error reporting functionality
      * @param instanceOrClass Instance that is being populated by this
@@ -1071,29 +1083,36 @@
      *   If null, will assume type is what {@link #getValueClass} returns.
      * @param propName Name of the property that can not be mapped
      */
-    protected void handleUnknownProperty(JsonParser jp, DeserializationContext ctxt, Object instanceOrClass, String propName)
+    protected void handleUnknownProperty(JsonParser p, DeserializationContext ctxt, Object instanceOrClass, String propName)
         throws IOException
     {
         if (instanceOrClass == null) {
             instanceOrClass = handledType();
         }
         // Maybe we have configured handler(s) to take care of it?
-        if (ctxt.handleUnknownProperty(jp, this, instanceOrClass, propName)) {
+        if (ctxt.handleUnknownProperty(p, this, instanceOrClass, propName)) {
             return;
         }
-        // Nope, not handled. Potentially that's a problem...
-        ctxt.reportUnknownProperty(instanceOrClass, propName, this);
-
         /* But if we do get this far, need to skip whatever value we
-         * are pointing to now.
+         * are pointing to now (although handler is likely to have done that already)
          */
-        jp.skipChildren();
+        p.skipChildren();
     }
 
-    protected void _failDoubleToIntCoercion(JsonParser jp, DeserializationContext ctxt,
+    protected void handleMissingEndArrayForSingle(JsonParser p, DeserializationContext ctxt)
+        throws IOException
+    {
+        ctxt.reportWrongTokenException(p, JsonToken.END_ARRAY, 
+"Attempted to unwrap single value array for single '%s' value but there was more than a single value in the array",
+handledType().getName());
+        // 05-May-2016, tatu: Should recover somehow (maybe skip until END_ARRAY);
+        //     but for now just fall through
+    }
+
+    protected void _failDoubleToIntCoercion(JsonParser p, DeserializationContext ctxt,
             String type) throws IOException
     {
-        throw ctxt.mappingException("Can not coerce a floating-point value ('%s') into %s; enable `DeserializationFeature.ACCEPT_FLOAT_AS_INT` to allow",
-                        jp.getValueAsString(), type);
+        ctxt.reportMappingException("Can not coerce a floating-point value ('%s') into %s; enable `DeserializationFeature.ACCEPT_FLOAT_AS_INT` to allow",
+                        p.getValueAsString(), type);
     }
 }
diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/std/StdKeyDeserializer.java b/src/main/java/com/fasterxml/jackson/databind/deser/std/StdKeyDeserializer.java
index 8bddce4..de6b23b 100644
--- a/src/main/java/com/fasterxml/jackson/databind/deser/std/StdKeyDeserializer.java
+++ b/src/main/java/com/fasterxml/jackson/databind/deser/std/StdKeyDeserializer.java
@@ -3,14 +3,12 @@
 import java.io.IOException;
 import java.lang.reflect.Constructor;
 import java.lang.reflect.Method;
+import java.net.MalformedURLException;
 import java.net.URI;
 import java.net.URL;
-import java.util.Calendar;
-import java.util.Currency;
-import java.util.Date;
-import java.util.Locale;
-import java.util.UUID;
+import java.util.*;
 
+import com.fasterxml.jackson.core.JsonParser;
 import com.fasterxml.jackson.core.JsonProcessingException;
 import com.fasterxml.jackson.core.io.NumberInput;
 import com.fasterxml.jackson.databind.*;
@@ -18,6 +16,7 @@
 import com.fasterxml.jackson.databind.introspect.AnnotatedMethod;
 import com.fasterxml.jackson.databind.util.ClassUtil;
 import com.fasterxml.jackson.databind.util.EnumResolver;
+import com.fasterxml.jackson.databind.util.TokenBuffer;
 
 /**
  * Default {@link KeyDeserializer} implementation used for most {@link java.util.Map}
@@ -114,7 +113,7 @@
         }
         return new StdKeyDeserializer(kind, raw);
     }
-    
+
     @Override
     public Object deserializeKey(String key, DeserializationContext ctxt)
         throws IOException
@@ -128,12 +127,13 @@
                 return result;
             }
         } catch (Exception re) {
-            throw ctxt.weirdKeyException(_keyClass, key, "not a valid representation: "+re.getMessage());
+            return ctxt.handleWeirdKey(_keyClass, key, "not a valid representation, problem: (%s) %s",
+                    re.getClass().getName(), re.getMessage());
         }
         if (_keyClass.isEnum() && ctxt.getConfig().isEnabled(DeserializationFeature.READ_UNKNOWN_ENUM_VALUES_AS_NULL)) {
             return null;
         }
-        throw ctxt.weirdKeyException(_keyClass, key, "not a valid representation");
+        return ctxt.handleWeirdKey(_keyClass, key, "not a valid representation");
     }
 
     public Class<?> getKeyClass() { return _keyClass; }
@@ -148,13 +148,13 @@
             if ("false".equals(key)) {
                 return Boolean.FALSE;
             }
-            throw ctxt.weirdKeyException(_keyClass, key, "value not 'true' or 'false'");
+            return ctxt.handleWeirdKey(_keyClass, key, "value not 'true' or 'false'");
         case TYPE_BYTE:
             {
                 int value = _parseInt(key);
-                // as per [JACKSON-804], allow range up to 255, inclusive
+                // allow range up to 255, inclusive (to support "unsigned" byte)
                 if (value < Byte.MIN_VALUE || value > 255) {
-                    throw ctxt.weirdKeyException(_keyClass, key, "overflow, value can not be represented as 8-bit value");
+                    return ctxt.handleWeirdKey(_keyClass, key, "overflow, value can not be represented as 8-bit value");
                 }
                 return Byte.valueOf((byte) value);
             }
@@ -162,7 +162,8 @@
             {
                 int value = _parseInt(key);
                 if (value < Short.MIN_VALUE || value > Short.MAX_VALUE) {
-                    throw ctxt.weirdKeyException(_keyClass, key, "overflow, value can not be represented as 16-bit value");
+                    return ctxt.handleWeirdKey(_keyClass, key, "overflow, value can not be represented as 16-bit value");
+                    // fall-through and truncate if need be
                 }
                 return Short.valueOf((short) value);
             }
@@ -170,7 +171,7 @@
             if (key.length() == 1) {
                 return Character.valueOf(key.charAt(0));
             }
-            throw ctxt.weirdKeyException(_keyClass, key, "can only convert 1-character Strings");
+            return ctxt.handleWeirdKey(_keyClass, key, "can only convert 1-character Strings");
         case TYPE_INT:
             return _parseInt(key);
 
@@ -186,13 +187,13 @@
             try {
                 return _deser._deserialize(key, ctxt);
             } catch (IOException e) {
-                throw ctxt.weirdKeyException(_keyClass, key, "unable to parse key as locale");
+                return ctxt.handleWeirdKey(_keyClass, key, "unable to parse key as locale");
             }
         case TYPE_CURRENCY:
             try {
                 return _deser._deserialize(key, ctxt);
             } catch (IOException e) {
-                throw ctxt.weirdKeyException(_keyClass, key, "unable to parse key as currency");
+                return ctxt.handleWeirdKey(_keyClass, key, "unable to parse key as currency");
             }
         case TYPE_DATE:
             return ctxt.parseDate(key);
@@ -200,19 +201,32 @@
             java.util.Date date = ctxt.parseDate(key);
             return (date == null)  ? null : ctxt.constructCalendar(date);
         case TYPE_UUID:
-            return UUID.fromString(key);
+            try {
+                return UUID.fromString(key);
+            } catch (Exception e) {
+                return ctxt.handleWeirdKey(_keyClass, key, "problem: %s", e.getMessage());
+            }
         case TYPE_URI:
-            return URI.create(key);
+            try {
+                return URI.create(key);
+            } catch (Exception e) {
+                return ctxt.handleWeirdKey(_keyClass, key, "problem: %s", e.getMessage());
+            }
         case TYPE_URL:
-            return new URL(key);
+            try {
+                return new URL(key);
+            } catch (MalformedURLException e) {
+                return ctxt.handleWeirdKey(_keyClass, key, "problem: %s", e.getMessage());
+            }
         case TYPE_CLASS:
             try {
                 return ctxt.findClass(key);
             } catch (Exception e) {
-                throw ctxt.weirdKeyException(_keyClass, key, "unable to parse key as Class");
+                return ctxt.handleWeirdKey(_keyClass, key, "unable to parse key as Class");
             }
+        default:
+            throw new IllegalStateException("Internal error: unknown key type "+_keyClass);
         }
-        return null;
     }
 
     /*
@@ -291,23 +305,28 @@
             _delegate = deser;
         }
 
+        @SuppressWarnings("resource")
         @Override
         public final Object deserializeKey(String key, DeserializationContext ctxt)
-            throws IOException, JsonProcessingException
+            throws IOException
         {
             if (key == null) { // is this even legal call?
                 return null;
             }
+            TokenBuffer tb = new TokenBuffer(ctxt.getParser(), ctxt);
+            tb.writeString(key);
             try {
                 // Ugh... should not have to give parser which may or may not be correct one...
-                Object result = _delegate.deserialize(ctxt.getParser(), ctxt);
+                JsonParser p = tb.asParser();
+                p.nextToken();
+                Object result = _delegate.deserialize(p, ctxt);
                 if (result != null) {
                     return result;
                 }
+                return ctxt.handleWeirdKey(_keyClass, key, "not a valid representation");
             } catch (Exception re) {
-                throw ctxt.weirdKeyException(_keyClass, key, "not a valid representation: "+re.getMessage());
+                return ctxt.handleWeirdKey(_keyClass, key, "not a valid representation: %s", re.getMessage());
             }
-            throw ctxt.weirdKeyException(_keyClass, key, "not a valid representation");
         }
 
         public Class<?> getKeyClass() { return _keyClass; }
@@ -337,7 +356,7 @@
         }
 
         @Override
-        public Object _parse(String key, DeserializationContext ctxt) throws JsonMappingException
+        public Object _parse(String key, DeserializationContext ctxt) throws IOException
         {
             if (_factory != null) {
                 try {
@@ -347,21 +366,23 @@
                 }
             }
             EnumResolver res = ctxt.isEnabled(DeserializationFeature.READ_ENUMS_USING_TO_STRING)
-                    ? _getToStringResolver() : _byNameResolver;
+                    ? _getToStringResolver(ctxt) : _byNameResolver;
             Enum<?> e = res.findEnum(key);
             if ((e == null) && !ctxt.getConfig().isEnabled(DeserializationFeature.READ_UNKNOWN_ENUM_VALUES_AS_NULL)) {
-                throw ctxt.weirdKeyException(_keyClass, key, "not one of values excepted for Enum class: "
-                        +res.getEnumIds());
+                return ctxt.handleWeirdKey(_keyClass, key, "not one of values excepted for Enum class: %s",
+                        res.getEnumIds());
+                // fall-through if problems are collected, not immediately thrown
             }
             return e;
         }
 
-        private EnumResolver _getToStringResolver()
+        private EnumResolver _getToStringResolver(DeserializationContext ctxt)
         {
             EnumResolver res = _byToStringResolver;
             if (res == null) {
                 synchronized (this) {
-                    res = EnumResolver.constructUnsafeUsingToString(_byNameResolver.getEnumClass());
+                    res = EnumResolver.constructUnsafeUsingToString(_byNameResolver.getEnumClass(),
+                            ctxt.getAnnotationIntrospector());
                 }
             }
             return res;
diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/std/StdScalarDeserializer.java b/src/main/java/com/fasterxml/jackson/databind/deser/std/StdScalarDeserializer.java
index 889bd62..f75d101 100644
--- a/src/main/java/com/fasterxml/jackson/databind/deser/std/StdScalarDeserializer.java
+++ b/src/main/java/com/fasterxml/jackson/databind/deser/std/StdScalarDeserializer.java
@@ -4,6 +4,7 @@
 
 import com.fasterxml.jackson.core.*;
 import com.fasterxml.jackson.databind.DeserializationContext;
+import com.fasterxml.jackson.databind.DeserializationFeature;
 import com.fasterxml.jackson.databind.JavaType;
 import com.fasterxml.jackson.databind.jsontype.TypeDeserializer;
 
@@ -13,6 +14,11 @@
  */
 public abstract class StdScalarDeserializer<T> extends StdDeserializer<T>
 {
+    // @since 2.8.8
+    protected final static int FEATURES_ACCEPT_ARRAYS =
+            DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS.getMask() |
+            DeserializationFeature.ACCEPT_EMPTY_ARRAY_AS_NULL_OBJECT.getMask();
+
     private static final long serialVersionUID = 1L;
 
     protected StdScalarDeserializer(Class<?> vc) { super(vc); }
@@ -22,7 +28,32 @@
     protected StdScalarDeserializer(StdScalarDeserializer<?> src) { super(src); }
     
     @Override
-    public Object deserializeWithType(JsonParser jp, DeserializationContext ctxt, TypeDeserializer typeDeserializer) throws IOException {
-        return typeDeserializer.deserializeTypedFromScalar(jp, ctxt);
+    public Object deserializeWithType(JsonParser p, DeserializationContext ctxt, TypeDeserializer typeDeserializer) throws IOException {
+        return typeDeserializer.deserializeTypedFromScalar(p, ctxt);
+    }
+
+    protected T _deserializeFromArray(JsonParser p, DeserializationContext ctxt) throws IOException
+    {
+        JsonToken t;
+        if (ctxt.hasSomeOfFeatures(FEATURES_ACCEPT_ARRAYS)) {
+            t = p.nextToken();
+            if (t == JsonToken.END_ARRAY) {
+                if (ctxt.isEnabled(DeserializationFeature.ACCEPT_EMPTY_ARRAY_AS_NULL_OBJECT)) {
+                    return getNullValue(ctxt);
+                }
+            }
+            if (ctxt.isEnabled(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS)) {
+                final T parsed = deserialize(p, ctxt);
+                if (p.nextToken() != JsonToken.END_ARRAY) {
+                    handleMissingEndArrayForSingle(p, ctxt);
+                }
+                return parsed;            
+            }
+        } else {
+            t = p.getCurrentToken();
+        }
+        @SuppressWarnings("unchecked")
+        T result = (T) ctxt.handleUnexpectedToken(_valueClass, t, p, null);
+        return result;
     }
 }
diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/std/StdValueInstantiator.java b/src/main/java/com/fasterxml/jackson/databind/deser/std/StdValueInstantiator.java
index b833fe9..9705770 100644
--- a/src/main/java/com/fasterxml/jackson/databind/deser/std/StdValueInstantiator.java
+++ b/src/main/java/com/fasterxml/jackson/databind/deser/std/StdValueInstantiator.java
@@ -27,6 +27,11 @@
      */
     protected final String _valueTypeDesc;
 
+    /**
+     * @since 2.8
+     */
+    protected final Class<?> _valueClass;
+
     // // // Default (no-args) construction
 
     /**
@@ -69,12 +74,18 @@
     /**********************************************************
      */
 
+    /**
+     * @deprecated Since 2.7 use constructor that takes {@link JavaType} instead
+     */
+    @Deprecated
     public StdValueInstantiator(DeserializationConfig config, Class<?> valueType) {
         _valueTypeDesc = (valueType == null) ? "UNKNOWN TYPE" : valueType.getName();
+        _valueClass = (valueType == null) ? Object.class : valueType;
     }
 
     public StdValueInstantiator(DeserializationConfig config, JavaType valueType) {
         _valueTypeDesc = (valueType == null) ? "UNKNOWN TYPE" : valueType.toString();
+        _valueClass = (valueType == null) ? Object.class : valueType.getRawClass();
     }
 
     /**
@@ -84,6 +95,7 @@
     protected StdValueInstantiator(StdValueInstantiator src)
     {
         _valueTypeDesc = src._valueTypeDesc;
+        _valueClass = src._valueClass;
 
         _defaultCreator = src._defaultCreator;
 
@@ -166,7 +178,12 @@
     public String getValueTypeDesc() {
         return _valueTypeDesc;
     }
-    
+
+    @Override
+    public Class<?> getValueClass() {
+        return _valueClass;
+    }
+
     @Override
     public boolean canCreateFromString() {
         return (_fromStringCreator != null);
@@ -191,7 +208,7 @@
     public boolean canCreateFromBoolean() {
         return (_fromBooleanCreator != null);
     }
-    
+
     @Override
     public boolean canCreateUsingDefault() {
         return (_defaultCreator != null);
@@ -199,20 +216,29 @@
 
     @Override
     public boolean canCreateUsingDelegate() {
-        return _delegateType != null;
+        return (_delegateType != null);
     }
 
     @Override
     public boolean canCreateUsingArrayDelegate() {
-        return _arrayDelegateType != null;
+        return (_arrayDelegateType != null);
     }
-    
+
     @Override
     public boolean canCreateFromObjectWith() {
         return (_withArgsCreator != null);
     }
 
     @Override
+    public boolean canInstantiate() {
+        return canCreateUsingDefault()
+                || canCreateUsingDelegate() || canCreateUsingArrayDelegate()
+                || canCreateFromObjectWith() || canCreateFromString()
+                || canCreateFromInt() || canCreateFromLong()
+                || canCreateFromDouble() || canCreateFromBoolean();
+    }
+
+    @Override
     public JavaType getDelegateType(DeserializationConfig config) {
         return _delegateType;
     }
@@ -237,25 +263,27 @@
     public Object createUsingDefault(DeserializationContext ctxt) throws IOException
     {
         if (_defaultCreator == null) { // sanity-check; caller should check
-            throw new IllegalStateException("No default constructor for "+getValueTypeDesc());
+            return super.createUsingDefault(ctxt);
         }
         try {
             return _defaultCreator.call();
         } catch (Throwable t) {
-            throw rewrapCtorProblem(ctxt, t);
+            return ctxt.handleInstantiationProblem(_defaultCreator.getDeclaringClass(),
+                    null, rewrapCtorProblem(ctxt, t));
         }
     }
-    
+
     @Override
     public Object createFromObjectWith(DeserializationContext ctxt, Object[] args) throws IOException
     {
         if (_withArgsCreator == null) { // sanity-check; caller should check
-            throw new IllegalStateException("No with-args constructor for "+getValueTypeDesc());
+            return super.createFromObjectWith(ctxt, args);
         }
         try {
             return _withArgsCreator.call(args);
         } catch (Throwable t) {
-            throw rewrapCtorProblem(ctxt, t);
+            return ctxt.handleInstantiationProblem(_withArgsCreator.getDeclaringClass(),
+                    args, rewrapCtorProblem(ctxt, t));
         }
     }
 
@@ -298,41 +326,49 @@
         try {
             return _fromStringCreator.call1(value);
         } catch (Throwable t) {
-            throw rewrapCtorProblem(ctxt, t);
+            return ctxt.handleInstantiationProblem(_fromStringCreator.getDeclaringClass(),
+                    value, rewrapCtorProblem(ctxt, t));
         }
     }
     
     @Override
     public Object createFromInt(DeserializationContext ctxt, int value) throws IOException
     {
-        try {
-            // First: "native" int methods work best:
-            if (_fromIntCreator != null) {
-                return _fromIntCreator.call1(Integer.valueOf(value));
+        // First: "native" int methods work best:
+        if (_fromIntCreator != null) {
+            Object arg = Integer.valueOf(value);
+            try {
+                return _fromIntCreator.call1(arg);
+            } catch (Throwable t0) {
+                return ctxt.handleInstantiationProblem(_fromIntCreator.getDeclaringClass(),
+                        arg, rewrapCtorProblem(ctxt, t0));
             }
-            // but if not, can do widening conversion
-            if (_fromLongCreator != null) {
-                return _fromLongCreator.call1(Long.valueOf(value));
-            }
-        } catch (Throwable t) {
-            throw rewrapCtorProblem(ctxt, t);
         }
-        throw ctxt.mappingException("Can not instantiate value of type %s from Integral number (%s); no single-int-arg constructor/factory method",
-                getValueTypeDesc(), value);
+        // but if not, can do widening conversion
+        if (_fromLongCreator != null) {
+            Object arg = Long.valueOf(value);
+            try {
+                return _fromLongCreator.call1(arg);
+            } catch (Throwable t0) {
+                return ctxt.handleInstantiationProblem(_fromLongCreator.getDeclaringClass(),
+                        arg, rewrapCtorProblem(ctxt, t0));
+            }
+        }
+        return super.createFromInt(ctxt, value);
     }
 
     @Override
     public Object createFromLong(DeserializationContext ctxt, long value) throws IOException
     {
         if (_fromLongCreator == null) {
-            throw ctxt.mappingException("Can not instantiate value of type %s"
-                    +" from Long integral number (%s); no single-long-arg constructor/factory method",
-                    getValueTypeDesc(), value);
+            return super.createFromLong(ctxt, value);
         }
+        Object arg = Long.valueOf(value);
         try {
-            return _fromLongCreator.call1(Long.valueOf(value));
-        } catch (Throwable t) {
-            throw rewrapCtorProblem(ctxt, t);
+            return _fromLongCreator.call1(arg);
+        } catch (Throwable t0) {
+            return ctxt.handleInstantiationProblem(_fromLongCreator.getDeclaringClass(),
+                    arg, rewrapCtorProblem(ctxt, t0));
         }
     }
 
@@ -340,14 +376,14 @@
     public Object createFromDouble(DeserializationContext ctxt, double value) throws IOException
     {
         if (_fromDoubleCreator == null) {
-            throw ctxt.mappingException("Can not instantiate value of type %s"
-                    +" from Floating-point number (%s); no one-double/Double-arg constructor/factory method",
-                    getValueTypeDesc(), value);
+            return super.createFromDouble(ctxt, value);
         }
+        Object arg = Double.valueOf(value);
         try {
-            return _fromDoubleCreator.call1(Double.valueOf(value));
-        } catch (Throwable t) {
-            throw rewrapCtorProblem(ctxt, t);
+            return _fromDoubleCreator.call1(arg);
+        } catch (Throwable t0) {
+            return ctxt.handleInstantiationProblem(_fromDoubleCreator.getDeclaringClass(),
+                    arg, rewrapCtorProblem(ctxt, t0));
         }
     }
 
@@ -355,14 +391,14 @@
     public Object createFromBoolean(DeserializationContext ctxt, boolean value) throws IOException
     {
         if (_fromBooleanCreator == null) {
-            throw ctxt.mappingException("Can not instantiate value of type %s"
-                    +" from Boolean value (%s); no single-boolean/Boolean-arg constructor/factory method",
-                    getValueTypeDesc(), value);
+            return super.createFromBoolean(ctxt, value);
         }
+        final Boolean arg = Boolean.valueOf(value);
         try {
-            return _fromBooleanCreator.call1(Boolean.valueOf(value));
-        } catch (Throwable t) {
-            throw rewrapCtorProblem(ctxt, t);
+            return _fromBooleanCreator.call1(arg);
+        } catch (Throwable t0) {
+            return ctxt.handleInstantiationProblem(_fromBooleanCreator.getDeclaringClass(),
+                    arg, rewrapCtorProblem(ctxt, t0));
         }
     }
     
@@ -433,9 +469,7 @@
                 return (JsonMappingException) curr;
             }
         }
-        String msg = String.format("Instantiation of %s value failed (%s): %s",
-                getValueTypeDesc(), t.getClass().getName(), t.getMessage());
-        return JsonMappingException.from(ctxt.getParser(), msg, t);
+        return ctxt.instantiationException(getValueClass(), t);
     }
 
     /**
@@ -448,9 +482,7 @@
         if (t instanceof JsonMappingException) {
             return (JsonMappingException) t;
         }
-        String msg = String.format("Instantiation of %s value failed (%s): %s",
-                getValueTypeDesc(), t.getClass().getName(), t.getMessage());
-        return JsonMappingException.from(ctxt.getParser(), msg, t);
+        return ctxt.instantiationException(getValueClass(), t);
     }
 
     /**
diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/std/StringArrayDeserializer.java b/src/main/java/com/fasterxml/jackson/databind/deser/std/StringArrayDeserializer.java
index a4b0fe2..38f319f 100644
--- a/src/main/java/com/fasterxml/jackson/databind/deser/std/StringArrayDeserializer.java
+++ b/src/main/java/com/fasterxml/jackson/databind/deser/std/StringArrayDeserializer.java
@@ -184,6 +184,6 @@
                 return null;
             }
         }
-        throw ctxt.mappingException(_valueClass);
+        return (String[]) ctxt.handleUnexpectedToken(_valueClass, p);
     }
 }
diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/std/StringCollectionDeserializer.java b/src/main/java/com/fasterxml/jackson/databind/deser/std/StringCollectionDeserializer.java
index b093dfc..0ef9714 100644
--- a/src/main/java/com/fasterxml/jackson/databind/deser/std/StringCollectionDeserializer.java
+++ b/src/main/java/com/fasterxml/jackson/databind/deser/std/StringCollectionDeserializer.java
@@ -249,6 +249,7 @@
      * throw an exception, or try to handle value as if member of implicit
      * array, depending on configuration.
      */
+    @SuppressWarnings("unchecked")
     private final Collection<String> handleNonArray(JsonParser p, DeserializationContext ctxt, Collection<String> result) throws IOException
     {
         // implicit arrays from single values?
@@ -256,7 +257,7 @@
                 ((_unwrapSingle == null) &&
                         ctxt.isEnabled(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY));
         if (!canWrap) {
-            throw ctxt.mappingException(_collectionType.getRawClass());
+            return (Collection<String>) ctxt.handleUnexpectedToken(_collectionType.getRawClass(), p);
         }
         // Strings are one of "native" (intrinsic) types, so there's never type deserializer involved
         JsonDeserializer<String> valueDes = _valueDeserializer;
diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/std/StringDeserializer.java b/src/main/java/com/fasterxml/jackson/databind/deser/std/StringDeserializer.java
index c420536..5082b74 100644
--- a/src/main/java/com/fasterxml/jackson/databind/deser/std/StringDeserializer.java
+++ b/src/main/java/com/fasterxml/jackson/databind/deser/std/StringDeserializer.java
@@ -13,6 +13,11 @@
 {
     private static final long serialVersionUID = 1L;
 
+    // @since 2.8.8
+    protected final static int FEATURES_ACCEPT_ARRAYS =
+            DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS.getMask() |
+            DeserializationFeature.ACCEPT_EMPTY_ARRAY_AS_NULL_OBJECT.getMask();
+    
     /**
      * @since 2.2
      */
@@ -32,14 +37,8 @@
         }
         JsonToken t = p.getCurrentToken();
         // [databind#381]
-        if ((t == JsonToken.START_ARRAY) && ctxt.isEnabled(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS)) {
-            p.nextToken();
-            final String parsed = _parseString(p, ctxt);
-            if (p.nextToken() != JsonToken.END_ARRAY) {
-                throw ctxt.wrongTokenException(p, JsonToken.END_ARRAY, 
-                        "Attempted to unwrap single value array for single 'String' value but there was more than a single value in the array");
-            }            
-            return parsed;            
+        if (t == JsonToken.START_ARRAY) {
+            return _deserializeFromArray(p, ctxt);
         }
         // need to gracefully handle byte[] data, as base64
         if (t == JsonToken.VALUE_EMBEDDED_OBJECT) {
@@ -58,7 +57,7 @@
         if (text != null) {
             return text;
         }
-        throw ctxt.mappingException(_valueClass, p.getCurrentToken());
+        return (String) ctxt.handleUnexpectedToken(_valueClass, p);
     }
 
     // Since we can never have type info ("natural type"; String, Boolean, Integer, Double):
@@ -67,4 +66,28 @@
     public String deserializeWithType(JsonParser p, DeserializationContext ctxt, TypeDeserializer typeDeserializer) throws IOException {
         return deserialize(p, ctxt);
     }
+
+    // @since 2.8.8
+    protected String _deserializeFromArray(JsonParser p, DeserializationContext ctxt) throws IOException
+    {
+        JsonToken t;
+        if (ctxt.hasSomeOfFeatures(FEATURES_ACCEPT_ARRAYS)) {
+            t = p.nextToken();
+            if (t == JsonToken.END_ARRAY) {
+                if (ctxt.isEnabled(DeserializationFeature.ACCEPT_EMPTY_ARRAY_AS_NULL_OBJECT)) {
+                    return getNullValue(ctxt);
+                }
+            }
+            if (ctxt.isEnabled(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS)) {
+                final String parsed = _parseString(p, ctxt);
+                if (p.nextToken() != JsonToken.END_ARRAY) {
+                    handleMissingEndArrayForSingle(p, ctxt);
+                }
+                return parsed;            
+            }
+        } else {
+            t = p.getCurrentToken();
+        }
+        return (String) ctxt.handleUnexpectedToken(_valueClass, t, p, null);
+    }
 }
diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/std/ThrowableDeserializer.java b/src/main/java/com/fasterxml/jackson/databind/deser/std/ThrowableDeserializer.java
index afd5f8b..0906ad5 100644
--- a/src/main/java/com/fasterxml/jackson/databind/deser/std/ThrowableDeserializer.java
+++ b/src/main/java/com/fasterxml/jackson/databind/deser/std/ThrowableDeserializer.java
@@ -38,7 +38,7 @@
     protected ThrowableDeserializer(BeanDeserializer src, NameTransformer unwrapper) {
         super(src, unwrapper);
     }
-    
+
     @Override
     public JsonDeserializer<Object> unwrappingDeserializer(NameTransformer unwrapper) {
         if (getClass() != ThrowableDeserializer.class) {
@@ -51,7 +51,6 @@
         return new ThrowableDeserializer(this, unwrapper);
     }
 
-    
     /*
     /************************************************************
     /* Overridden methods
@@ -70,15 +69,15 @@
                     _delegateDeserializer.deserialize(p, ctxt));
         }
         if (_beanType.isAbstract()) { // for good measure, check this too
-            throw JsonMappingException.from(p, "Can not instantiate abstract type "+_beanType
-                    +" (need to add/enable type information?)");
+            return ctxt.handleMissingInstantiator(handledType(), p,
+                    "abstract type (need to add/enable type information?)");
         }
         boolean hasStringCreator = _valueInstantiator.canCreateFromString();
         boolean hasDefaultCtor = _valueInstantiator.canCreateUsingDefault();
         // and finally, verify we do have single-String arg constructor (if no @JsonCreator)
         if (!hasStringCreator && !hasDefaultCtor) {
-            throw JsonMappingException.from(p,"Can not deserialize Throwable of type "+_beanType
-                    +" without having a default contructor, a single-String-arg constructor; or explicit @JsonCreator");
+            return ctxt.handleMissingInstantiator(handledType(), p,
+                    "Throwable needs a default contructor, a single-String-arg constructor; or explicit @JsonCreator");
         }
         
         Object throwable = null;
diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/std/UUIDDeserializer.java b/src/main/java/com/fasterxml/jackson/databind/deser/std/UUIDDeserializer.java
index 5fa5e11..797569e 100644
--- a/src/main/java/com/fasterxml/jackson/databind/deser/std/UUIDDeserializer.java
+++ b/src/main/java/com/fasterxml/jackson/databind/deser/std/UUIDDeserializer.java
@@ -39,7 +39,7 @@
                 byte[] stuff = Base64Variants.getDefaultVariant().decode(id);
                 return _fromBytes(stuff, ctxt);
             }
-            _badFormat(id, ctxt);
+            return _badFormat(id, ctxt);
         }
 
         // verify hyphens first:
@@ -73,27 +73,25 @@
         return null; // never gets here
     }
 
-    private void _badFormat(String uuidStr, DeserializationContext ctxt)
-        throws JsonMappingException
+    private UUID _badFormat(String uuidStr, DeserializationContext ctxt)
+        throws IOException
     {
-        throw InvalidFormatException.from(ctxt.getParser(),
-                String.format("UUID has to be represented by standard 36-char representation: input String '%s'",
-                        uuidStr),
-                uuidStr, handledType());
+        return (UUID) ctxt.handleWeirdStringValue(handledType(), uuidStr,
+                "UUID has to be represented by standard 36-char representation");
     }
-    
-    static int intFromChars(String str, int index, DeserializationContext ctxt) throws JsonMappingException {
+
+    int intFromChars(String str, int index, DeserializationContext ctxt) throws JsonMappingException {
         return (byteFromChars(str, index, ctxt) << 24)
                 + (byteFromChars(str, index+2, ctxt) << 16)
                 + (byteFromChars(str, index+4, ctxt) << 8)
                 + byteFromChars(str, index+6, ctxt);
     }
     
-    static int shortFromChars(String str, int index, DeserializationContext ctxt) throws JsonMappingException {
+    int shortFromChars(String str, int index, DeserializationContext ctxt) throws JsonMappingException {
         return (byteFromChars(str, index, ctxt) << 8) + byteFromChars(str, index+2, ctxt);
     }
     
-    static int byteFromChars(String str, int index, DeserializationContext ctxt) throws JsonMappingException
+    int byteFromChars(String str, int index, DeserializationContext ctxt) throws JsonMappingException
     {
         final char c1 = str.charAt(index);
         final char c2 = str.charAt(index+1);
@@ -110,11 +108,13 @@
         return _badChar(str, index+1, ctxt, c2);
     }
 
-    static int _badChar(String uuidStr, int index, DeserializationContext ctxt, char c) throws JsonMappingException {
-        String msg = String.format(
-"Non-hex character '%c' (value 0x%s), not valid for UUID String: input String '%s'",
-        c, Integer.toHexString(c), uuidStr);
-        throw InvalidFormatException.from(ctxt.getParser(), msg, uuidStr, UUID.class);
+    int _badChar(String uuidStr, int index, DeserializationContext ctxt, char c) throws JsonMappingException {
+        // 15-May-2016, tatu: Ideally should not throw, but call `handleWeirdStringValue`...
+        //   however, control flow is gnarly here, so for now just throw
+        throw ctxt.weirdStringException(uuidStr, handledType(),
+                String.format(
+                "Non-hex character '%c' (value 0x%s), not valid for UUID String",
+                c, Integer.toHexString(c)));
     }
 
     private UUID _fromBytes(byte[] bytes, DeserializationContext ctxt) throws JsonMappingException {
diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/std/UntypedObjectDeserializer.java b/src/main/java/com/fasterxml/jackson/databind/deser/std/UntypedObjectDeserializer.java
index c962214..7f4e220 100644
--- a/src/main/java/com/fasterxml/jackson/databind/deser/std/UntypedObjectDeserializer.java
+++ b/src/main/java/com/fasterxml/jackson/databind/deser/std/UntypedObjectDeserializer.java
@@ -255,13 +255,12 @@
             if (_numberDeserializer != null) {
                 return _numberDeserializer.deserialize(p, ctxt);
             }
-            /* [JACKSON-72]: need to allow overriding the behavior regarding
-             *   which type to use
-             */
+            // Need to allow overriding the behavior regarding which type to use
             if (ctxt.isEnabled(DeserializationFeature.USE_BIG_DECIMAL_FOR_FLOATS)) {
                 return p.getDecimalValue();
             }
-            return p.getDoubleValue();
+            // as per [databind#1453] should not assume Double but:
+            return p.getNumberValue();
 
         case JsonTokenId.ID_TRUE:
             return Boolean.TRUE;
@@ -274,7 +273,7 @@
 //        case JsonTokenId.ID_END_ARRAY: // invalid
         default:
         }
-        throw ctxt.mappingException(Object.class);
+        return ctxt.handleUnexpectedToken(Object.class, p);
     }
 
     @Override
@@ -319,7 +318,7 @@
             if (ctxt.isEnabled(DeserializationFeature.USE_BIG_DECIMAL_FOR_FLOATS)) {
                 return p.getDecimalValue();
             }
-            return Double.valueOf(p.getDoubleValue());
+            return p.getNumberValue();
 
         case JsonTokenId.ID_TRUE:
             return Boolean.TRUE;
@@ -330,7 +329,7 @@
             return null;
         default:
         }
-        throw ctxt.mappingException(Object.class);
+        return ctxt.handleUnexpectedToken(Object.class, p);
     }
 
     /*
@@ -338,24 +337,24 @@
     /* Internal methods
     /**********************************************************
      */
-    
+
     /**
      * Method called to map a JSON Array into a Java value.
      */
-    protected Object mapArray(JsonParser jp, DeserializationContext ctxt) throws IOException
+    protected Object mapArray(JsonParser p, DeserializationContext ctxt) throws IOException
     {
         // Minor optimization to handle small lists (default size for ArrayList is 10)
-        if (jp.nextToken()  == JsonToken.END_ARRAY) {
+        if (p.nextToken()  == JsonToken.END_ARRAY) {
             return new ArrayList<Object>(2);
         }
-        Object value = deserialize(jp, ctxt);
-        if (jp.nextToken()  == JsonToken.END_ARRAY) {
+        Object value = deserialize(p, ctxt);
+        if (p.nextToken()  == JsonToken.END_ARRAY) {
             ArrayList<Object> l = new ArrayList<Object>(2);
             l.add(value);
             return l;
         }
-        Object value2 = deserialize(jp, ctxt);
-        if (jp.nextToken()  == JsonToken.END_ARRAY) {
+        Object value2 = deserialize(p, ctxt);
+        if (p.nextToken()  == JsonToken.END_ARRAY) {
             ArrayList<Object> l = new ArrayList<Object>(2);
             l.add(value);
             l.add(value2);
@@ -368,14 +367,14 @@
         values[ptr++] = value2;
         int totalSize = ptr;
         do {
-            value = deserialize(jp, ctxt);
+            value = deserialize(p, ctxt);
             ++totalSize;
             if (ptr >= values.length) {
                 values = buffer.appendCompletedChunk(values);
                 ptr = 0;
             }
             values[ptr++] = value;
-        } while (jp.nextToken() != JsonToken.END_ARRAY);
+        } while (p.nextToken() != JsonToken.END_ARRAY);
         // let's create full array then
         ArrayList<Object> result = new ArrayList<Object>(totalSize);
         buffer.completeAndClearBuffer(values, ptr, result);
@@ -397,7 +396,7 @@
             key1 = p.getCurrentName();
         } else {
             if (t != JsonToken.END_OBJECT) {
-                throw ctxt.mappingException(handledType(), p.getCurrentToken());
+                return ctxt.handleUnexpectedToken(handledType(), p);
             }
             key1 = null;
         }
@@ -444,23 +443,23 @@
     /**
      * Method called to map a JSON Array into a Java Object array (Object[]).
      */
-    protected Object[] mapArrayToArray(JsonParser jp, DeserializationContext ctxt) throws IOException
+    protected Object[] mapArrayToArray(JsonParser p, DeserializationContext ctxt) throws IOException
     {
         // Minor optimization to handle small lists (default size for ArrayList is 10)
-        if (jp.nextToken()  == JsonToken.END_ARRAY) {
+        if (p.nextToken()  == JsonToken.END_ARRAY) {
             return NO_OBJECTS;
         }
         ObjectBuffer buffer = ctxt.leaseObjectBuffer();
         Object[] values = buffer.resetAndStart();
         int ptr = 0;
         do {
-            Object value = deserialize(jp, ctxt);
+            Object value = deserialize(p, ctxt);
             if (ptr >= values.length) {
                 values = buffer.appendCompletedChunk(values);
                 ptr = 0;
             }
             values[ptr++] = value;
-        } while (jp.nextToken() != JsonToken.END_ARRAY);
+        } while (p.nextToken() != JsonToken.END_ARRAY);
         return buffer.completeAndClearBuffer(values, ptr);
     }
 
@@ -523,7 +522,7 @@
                 if (ctxt.isEnabled(DeserializationFeature.USE_BIG_DECIMAL_FOR_FLOATS)) {
                     return p.getDecimalValue();
                 }
-                return Double.valueOf(p.getDoubleValue());
+                return p.getNumberValue();
 
             case JsonTokenId.ID_TRUE:
                 return Boolean.TRUE;
@@ -540,58 +539,58 @@
 
             //case JsonTokenId.ID_END_ARRAY: // invalid
             default:
-                throw ctxt.mappingException(Object.class);
             }
+            return ctxt.handleUnexpectedToken(Object.class, p);
         }
 
         @Override
-        public Object deserializeWithType(JsonParser jp, DeserializationContext ctxt, TypeDeserializer typeDeserializer) throws IOException
+        public Object deserializeWithType(JsonParser p, DeserializationContext ctxt, TypeDeserializer typeDeserializer) throws IOException
         {
-            switch (jp.getCurrentTokenId()) {
+            switch (p.getCurrentTokenId()) {
             case JsonTokenId.ID_START_ARRAY:
             case JsonTokenId.ID_START_OBJECT:
             case JsonTokenId.ID_FIELD_NAME:
-                return typeDeserializer.deserializeTypedFromAny(jp, ctxt);
+                return typeDeserializer.deserializeTypedFromAny(p, ctxt);
 
             case JsonTokenId.ID_STRING:
-                return jp.getText();
+                return p.getText();
 
             case JsonTokenId.ID_NUMBER_INT:
                 if (ctxt.isEnabled(DeserializationFeature.USE_BIG_INTEGER_FOR_INTS)) {
-                    return jp.getBigIntegerValue();
+                    return p.getBigIntegerValue();
                 }
-                return jp.getNumberValue();
+                return p.getNumberValue();
 
             case JsonTokenId.ID_NUMBER_FLOAT:
                 if (ctxt.isEnabled(DeserializationFeature.USE_BIG_DECIMAL_FOR_FLOATS)) {
-                    return jp.getDecimalValue();
+                    return p.getDecimalValue();
                 }
-                return Double.valueOf(jp.getDoubleValue());
+                return p.getNumberValue();
 
             case JsonTokenId.ID_TRUE:
                 return Boolean.TRUE;
             case JsonTokenId.ID_FALSE:
                 return Boolean.FALSE;
             case JsonTokenId.ID_EMBEDDED_OBJECT:
-                return jp.getEmbeddedObject();
+                return p.getEmbeddedObject();
 
             case JsonTokenId.ID_NULL: // should not get this far really but...
                 return null;
             default:
-                throw ctxt.mappingException(Object.class);
             }
+            return ctxt.handleUnexpectedToken(Object.class, p);
         }
 
-        protected Object mapArray(JsonParser jp, DeserializationContext ctxt) throws IOException
+        protected Object mapArray(JsonParser p, DeserializationContext ctxt) throws IOException
         {
-            Object value = deserialize(jp, ctxt);
-            if (jp.nextToken()  == JsonToken.END_ARRAY) {
+            Object value = deserialize(p, ctxt);
+            if (p.nextToken()  == JsonToken.END_ARRAY) {
                 ArrayList<Object> l = new ArrayList<Object>(2);
                 l.add(value);
                 return l;
             }
-            Object value2 = deserialize(jp, ctxt);
-            if (jp.nextToken()  == JsonToken.END_ARRAY) {
+            Object value2 = deserialize(p, ctxt);
+            if (p.nextToken()  == JsonToken.END_ARRAY) {
                 ArrayList<Object> l = new ArrayList<Object>(2);
                 l.add(value);
                 l.add(value2);
@@ -604,14 +603,14 @@
             values[ptr++] = value2;
             int totalSize = ptr;
             do {
-                value = deserialize(jp, ctxt);
+                value = deserialize(p, ctxt);
                 ++totalSize;
                 if (ptr >= values.length) {
                     values = buffer.appendCompletedChunk(values);
                     ptr = 0;
                 }
                 values[ptr++] = value;
-            } while (jp.nextToken() != JsonToken.END_ARRAY);
+            } while (p.nextToken() != JsonToken.END_ARRAY);
             // let's create full array then
             ArrayList<Object> result = new ArrayList<Object>(totalSize);
             buffer.completeAndClearBuffer(values, ptr, result);
@@ -658,18 +657,18 @@
         /**
          * Method called to map a JSON Array into a Java Object array (Object[]).
          */
-        protected Object[] mapArrayToArray(JsonParser jp, DeserializationContext ctxt) throws IOException {
+        protected Object[] mapArrayToArray(JsonParser p, DeserializationContext ctxt) throws IOException {
             ObjectBuffer buffer = ctxt.leaseObjectBuffer();
             Object[] values = buffer.resetAndStart();
             int ptr = 0;
             do {
-                Object value = deserialize(jp, ctxt);
+                Object value = deserialize(p, ctxt);
                 if (ptr >= values.length) {
                     values = buffer.appendCompletedChunk(values);
                     ptr = 0;
                 }
                 values[ptr++] = value;
-            } while (jp.nextToken() != JsonToken.END_ARRAY);
+            } while (p.nextToken() != JsonToken.END_ARRAY);
             return buffer.completeAndClearBuffer(values, ptr);
         }
     }
diff --git a/src/main/java/com/fasterxml/jackson/databind/exc/InvalidTypeIdException.java b/src/main/java/com/fasterxml/jackson/databind/exc/InvalidTypeIdException.java
new file mode 100644
index 0000000..8b05215
--- /dev/null
+++ b/src/main/java/com/fasterxml/jackson/databind/exc/InvalidTypeIdException.java
@@ -0,0 +1,53 @@
+package com.fasterxml.jackson.databind.exc;
+
+import com.fasterxml.jackson.core.JsonParser;
+import com.fasterxml.jackson.databind.JavaType;
+import com.fasterxml.jackson.databind.JsonMappingException;
+
+/**
+ * Exception thrown when resolution of a type id fails.
+ *
+ * @since 2.8
+ */
+public class InvalidTypeIdException extends JsonMappingException
+{
+    private static final long serialVersionUID = 1L; // silly Eclipse, warnings
+
+    /**
+     * Basetype for which subtype was to be resolved
+     */
+    protected final JavaType _baseType;
+
+    /**
+     * Type id that failed to be resolved to a subtype
+     */
+    protected final String _typeId;
+
+    /*
+    /**********************************************************
+    /* Life-cycle
+    /**********************************************************
+     */
+
+    public InvalidTypeIdException(JsonParser p, String msg,
+            JavaType baseType, String typeId)
+    {
+        super(p, msg);
+        _baseType = baseType;
+        _typeId = typeId;
+    }
+
+    public static InvalidTypeIdException from(JsonParser p, String msg,
+            JavaType baseType, String typeId) {
+        return new InvalidTypeIdException(p, msg, baseType, typeId);
+    }
+
+    /*
+    /**********************************************************
+    /* Accessors
+    /**********************************************************
+     */
+
+    public JavaType getBaseType() { return _baseType; }
+    public String getTypeId() { return _typeId; }
+}
diff --git a/src/main/java/com/fasterxml/jackson/databind/ext/CoreXMLDeserializers.java b/src/main/java/com/fasterxml/jackson/databind/ext/CoreXMLDeserializers.java
index 0e0fe4d..64a06d8 100644
--- a/src/main/java/com/fasterxml/jackson/databind/ext/CoreXMLDeserializers.java
+++ b/src/main/java/com/fasterxml/jackson/databind/ext/CoreXMLDeserializers.java
@@ -65,7 +65,7 @@
      * javax.xml types {@link QName}, {@link Duration} and {@link XMLGregorianCalendar}.
      * Combined into a single class to eliminate bunch of one-off implementation
      * classes, to reduce resulting jar size (mostly).
-     * 
+     *
      * @since 2.4
      */
     public static class Std extends FromStringDeserializer<Object>
@@ -80,36 +80,56 @@
         }
 
         @Override
-        public Object deserialize(JsonParser jp, DeserializationContext ctxt)
-            throws IOException, JsonProcessingException
+        public Object deserialize(JsonParser p, DeserializationContext ctxt)
+            throws IOException
         {
-            // For most types, use super impl; but not for GregorianCalendar
+            // For most types, use super impl; but GregorianCalendar also allows
+            // integer value (timestamp), which needs separate handling
             if (_kind == TYPE_G_CALENDAR) {
-                Date d = _parseDate(jp, ctxt);
-                if (d == null) {
-                    return null;
+                if (p.hasToken(JsonToken.VALUE_NUMBER_INT)) {
+                    return _gregorianFromDate(ctxt, _parseDate(p, ctxt));
                 }
-                GregorianCalendar calendar = new GregorianCalendar();
-                calendar.setTime(d);
-                TimeZone tz = ctxt.getTimeZone();
-                if (tz != null) {
-                    calendar.setTimeZone(tz);
-                }
-                return _dataTypeFactory.newXMLGregorianCalendar(calendar);
             }
-            return super.deserialize(jp, ctxt);
+            return super.deserialize(p, ctxt);
         }
 
         @Override
-        protected Object _deserialize(String value, DeserializationContext ctxt) throws IllegalArgumentException
+        protected Object _deserialize(String value, DeserializationContext ctxt)
+            throws IOException
         {
             switch (_kind) {
             case TYPE_DURATION:
                 return _dataTypeFactory.newDuration(value);
             case TYPE_QNAME:
                 return QName.valueOf(value);
+            case TYPE_G_CALENDAR:
+                Date d;
+                try {
+                    d = _parseDate(value, ctxt);
+                }
+                catch (JsonMappingException e) {
+                    // try to parse from native XML Schema 1.0 lexical representation String,
+                    // which includes time-only formats not handled by parseXMLGregorianCalendarFromJacksonFormat(...)
+                    return _dataTypeFactory.newXMLGregorianCalendar(value);
+                }
+                return _gregorianFromDate(ctxt, d);
             }
             throw new IllegalStateException();
         }
+
+        protected XMLGregorianCalendar _gregorianFromDate(DeserializationContext ctxt,
+                Date d)
+        {
+            if (d == null) {
+                return null;
+            }
+            GregorianCalendar calendar = new GregorianCalendar();
+            calendar.setTime(d);
+            TimeZone tz = ctxt.getTimeZone();
+            if (tz != null) {
+                calendar.setTimeZone(tz);
+            }
+            return _dataTypeFactory.newXMLGregorianCalendar(calendar);
+        }
     }
 }
diff --git a/src/main/java/com/fasterxml/jackson/databind/ext/DOMDeserializer.java b/src/main/java/com/fasterxml/jackson/databind/ext/DOMDeserializer.java
index 78b1a00..74bc18d 100644
--- a/src/main/java/com/fasterxml/jackson/databind/ext/DOMDeserializer.java
+++ b/src/main/java/com/fasterxml/jackson/databind/ext/DOMDeserializer.java
@@ -35,6 +35,9 @@
             parserFactory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
         } catch(ParserConfigurationException pce) {
             // not much point to do anything; could log but...
+        } catch (Error e) {
+            // 14-Jul-2016, tatu: Not sure how or why, but during code coverage runs
+            //   (via Cobertura) we get `java.lang.AbstractMethodError` so... ignore that too
         }
         DEFAULT_PARSER_FACTORY = parserFactory;
     }
diff --git a/src/main/java/com/fasterxml/jackson/databind/ext/Java7Support.java b/src/main/java/com/fasterxml/jackson/databind/ext/Java7Support.java
new file mode 100644
index 0000000..5edf8a0
--- /dev/null
+++ b/src/main/java/com/fasterxml/jackson/databind/ext/Java7Support.java
@@ -0,0 +1,48 @@
+package com.fasterxml.jackson.databind.ext;
+
+import com.fasterxml.jackson.databind.JsonDeserializer;
+import com.fasterxml.jackson.databind.JsonSerializer;
+import com.fasterxml.jackson.databind.PropertyName;
+import com.fasterxml.jackson.databind.introspect.Annotated;
+import com.fasterxml.jackson.databind.introspect.AnnotatedParameter;
+
+/**
+ * To support Java7-incomplete platforms, we will offer support for JDK 7
+ * annotations through this class, loaded dynamically; if loading fails,
+ * support will be missing. This class is the non-JDK-7-dependent API,
+ * and {@link Java7SupportImpl} is JDK7-dependent implementation of
+ * functionality.
+ */
+public abstract class Java7Support
+{
+    private final static Java7Support IMPL;
+    
+    static {
+        Java7Support impl = null;
+        try {
+            Class<?> cls = Class.forName("com.fasterxml.jackson.databind.ext.Java7SupportImpl");
+            impl = (Java7Support) cls.newInstance();
+        } catch (Throwable t) {
+            // 24-Nov-2015, tatu: Should we log or not?
+            java.util.logging.Logger.getLogger(Java7Support.class.getName())
+                .warning("Unable to load JDK7 types (annotations, java.nio.file.Path): no Java7 support added");
+        }
+        IMPL = impl;
+    }
+
+    public static Java7Support instance() {
+        return IMPL;
+    }
+    
+    public abstract Boolean findTransient(Annotated a);
+
+    public abstract Boolean hasCreatorAnnotation(Annotated a);
+
+    public abstract PropertyName findConstructorName(AnnotatedParameter p);
+
+    public abstract Class<?> getClassJavaNioFilePath();
+
+    public abstract JsonDeserializer<?> getDeserializerForJavaNioFilePath(Class<?> rawType);
+
+    public abstract JsonSerializer<?> getSerializerForJavaNioFilePath(Class<?> rawType);
+}
diff --git a/src/main/java/com/fasterxml/jackson/databind/ext/Java7SupportImpl.java b/src/main/java/com/fasterxml/jackson/databind/ext/Java7SupportImpl.java
new file mode 100644
index 0000000..4546d03
--- /dev/null
+++ b/src/main/java/com/fasterxml/jackson/databind/ext/Java7SupportImpl.java
@@ -0,0 +1,86 @@
+package com.fasterxml.jackson.databind.ext;
+
+import java.beans.ConstructorProperties;
+import java.beans.Transient;
+import java.nio.file.Path;
+
+import com.fasterxml.jackson.databind.JsonDeserializer;
+import com.fasterxml.jackson.databind.JsonSerializer;
+import com.fasterxml.jackson.databind.PropertyName;
+import com.fasterxml.jackson.databind.introspect.Annotated;
+import com.fasterxml.jackson.databind.introspect.AnnotatedParameter;
+import com.fasterxml.jackson.databind.introspect.AnnotatedWithParams;
+
+/**
+ * @since 2.8
+ */
+public class Java7SupportImpl extends Java7Support
+{
+    @SuppressWarnings("unused") // compiler warns, just needed side-effects
+    private final Class<?> _bogus;
+
+    public Java7SupportImpl() {
+        // Trigger loading of annotations that only JDK 7 has...
+        Class<?> cls = Transient.class;
+        cls = ConstructorProperties.class;
+        _bogus = cls;
+    }
+
+    @Override
+    public Class<?> getClassJavaNioFilePath() {
+        return Path.class;
+    }
+
+    @Override
+    public JsonDeserializer<?> getDeserializerForJavaNioFilePath(Class<?> rawType) {
+        if (rawType == Path.class) {
+            return new NioPathDeserializer();
+        }
+        return null;
+    }
+
+    @Override
+    public JsonSerializer<?> getSerializerForJavaNioFilePath(Class<?> rawType) {
+        if (Path.class.isAssignableFrom(rawType)) {
+            return new NioPathSerializer();
+        }
+        return null;
+    }
+
+    @Override
+    public Boolean findTransient(Annotated a) {
+        Transient t = a.getAnnotation(Transient.class);
+        if (t != null) {
+            return t.value();
+        }
+        return null;
+    }
+
+    @Override
+    public Boolean hasCreatorAnnotation(Annotated a) {
+        ConstructorProperties props = a.getAnnotation(ConstructorProperties.class);
+        // 08-Nov-2015, tatu: One possible check would be to ensure there is at least
+        //    one name iff constructor has arguments. But seems unnecessary for now.
+        if (props != null) {
+            return Boolean.TRUE;
+        }
+        return null;
+    }
+
+    @Override
+    public PropertyName findConstructorName(AnnotatedParameter p)
+    {
+        AnnotatedWithParams ctor = p.getOwner();
+        if (ctor != null) {
+            ConstructorProperties props = ctor.getAnnotation(ConstructorProperties.class);
+            if (props != null) {
+                String[] names = props.value();
+                int ix = p.getIndex();
+                if (ix < names.length) {
+                    return PropertyName.construct(names[ix]);
+                }
+            }
+        }
+        return null;
+    }
+}
diff --git a/src/main/java/com/fasterxml/jackson/databind/ext/NioPathDeserializer.java b/src/main/java/com/fasterxml/jackson/databind/ext/NioPathDeserializer.java
new file mode 100644
index 0000000..48a39eb
--- /dev/null
+++ b/src/main/java/com/fasterxml/jackson/databind/ext/NioPathDeserializer.java
@@ -0,0 +1,41 @@
+package com.fasterxml.jackson.databind.ext;
+
+import java.io.IOException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+
+import com.fasterxml.jackson.core.JsonParser;
+import com.fasterxml.jackson.core.JsonToken;
+import com.fasterxml.jackson.databind.DeserializationContext;
+import com.fasterxml.jackson.databind.deser.std.StdScalarDeserializer;
+
+/**
+ * @since 2.8
+ */
+public class NioPathDeserializer extends StdScalarDeserializer<Path>
+{
+    private static final long serialVersionUID = 1;
+
+    public NioPathDeserializer() { super(Path.class); }
+
+    @Override
+    public Path deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
+        if (!p.hasToken(JsonToken.VALUE_STRING)) {
+            return (Path) ctxt.handleUnexpectedToken(Path.class, p);
+        }
+        final String value = p.getText();
+        // If someone gives us an input with no : at all, treat as local path, instead of failing
+        // with invalid URI.
+        if (value.indexOf(':') < 0) {
+            return Paths.get(value);
+        }
+        try {
+            URI uri = new URI(value);
+            return Paths.get(uri);
+        } catch (URISyntaxException e) {
+            return (Path) ctxt.handleInstantiationProblem(handledType(), value, e);
+        }
+    }
+}
diff --git a/src/main/java/com/fasterxml/jackson/databind/ext/NioPathSerializer.java b/src/main/java/com/fasterxml/jackson/databind/ext/NioPathSerializer.java
new file mode 100644
index 0000000..1abfab5
--- /dev/null
+++ b/src/main/java/com/fasterxml/jackson/databind/ext/NioPathSerializer.java
@@ -0,0 +1,25 @@
+
+package com.fasterxml.jackson.databind.ext;
+
+import java.io.IOException;
+import java.nio.file.Path;
+
+import com.fasterxml.jackson.core.JsonGenerator;
+import com.fasterxml.jackson.databind.SerializerProvider;
+import com.fasterxml.jackson.databind.ser.std.StdScalarSerializer;
+
+/**
+ * @since 2.8
+ */
+public class NioPathSerializer extends StdScalarSerializer<Path>
+{
+    private static final long serialVersionUID = 1;
+
+    public NioPathSerializer() { super(Path.class); }
+
+    @Override
+    public void serialize(Path value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
+        // write the Path as a URI, always.
+        gen.writeString(value.toUri().toString());
+    }
+}
diff --git a/src/main/java/com/fasterxml/jackson/databind/ext/OptionalHandlerFactory.java b/src/main/java/com/fasterxml/jackson/databind/ext/OptionalHandlerFactory.java
index 3206598..0f49a22 100644
--- a/src/main/java/com/fasterxml/jackson/databind/ext/OptionalHandlerFactory.java
+++ b/src/main/java/com/fasterxml/jackson/databind/ext/OptionalHandlerFactory.java
@@ -6,7 +6,6 @@
 import com.fasterxml.jackson.databind.*;
 import com.fasterxml.jackson.databind.deser.Deserializers;
 import com.fasterxml.jackson.databind.ser.Serializers;
-import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
 
 /**
  * Helper class used for isolating details of handling optional+external types
@@ -40,8 +39,6 @@
     private final static String DESERIALIZER_FOR_DOM_DOCUMENT = "com.fasterxml.jackson.databind.ext.DOMDeserializer$DocumentDeserializer";
     private final static String DESERIALIZER_FOR_DOM_NODE = "com.fasterxml.jackson.databind.ext.DOMDeserializer$NodeDeserializer";
 
-    private final static String DESERIALIZER_FOR_PATH = "com.fasterxml.jackson.databind.ext.PathDeserializer";
-
     // // Since 2.7, we will assume DOM classes are always found, both due to JDK 1.6 minimum
     // // and because Android (and presumably GAE) have these classes
 
@@ -55,8 +52,8 @@
             doc = org.w3c.dom.Document.class;
         } catch (Exception e) {
             // not optimal but will do
-            Logger.getLogger("com.fasterxml.jackson.databind.ext.OptionalHandlerFactory")
-                .log(Level.INFO, "Could not load DOM `Node` and/or `Document` classes: ignoring");
+            Logger.getLogger(OptionalHandlerFactory.class.getName())
+                .log(Level.INFO, "Could not load DOM `Node` and/or `Document` classes: no DOM support");
         }
         CLASS_DOM_NODE = node;
         CLASS_DOM_DOCUMENT = doc;
@@ -65,17 +62,14 @@
     // // But Java7 type(s) may or may not be; dynamic lookup should be fine, still
     // // (note: also assume it comes from JDK so that ClassLoader issues with OSGi
     // // can, I hope, be avoided?)
-    
-    private final static Class<?> CLASS_JAVA7_PATH;
+
+    private static final Java7Support _jdk7Helper;
     static {
-        Class<?> cls = null;
+        Java7Support x = null;
         try {
-            cls = Class.forName("java.nio.file.Path");
-        } catch (Exception e) {
-            Logger.getLogger("com.fasterxml.jackson.databind.ext.OptionalHandlerFactory")
-                .log(Level.INFO, "Could not load Java7 `java.nio.file.Path` class: ignoring");
-        }
-        CLASS_JAVA7_PATH = cls;
+            x = Java7Support.instance();
+        } catch (Throwable t) { }
+        _jdk7Helper = x;
     }
     
     public final static OptionalHandlerFactory instance = new OptionalHandlerFactory();
@@ -93,8 +87,11 @@
     {
         final Class<?> rawType = type.getRawClass();
 
-        if ((CLASS_JAVA7_PATH != null) && CLASS_JAVA7_PATH.isAssignableFrom(rawType)) {
-            return ToStringSerializer.instance;
+        if (_jdk7Helper != null) {
+            JsonSerializer<?> ser = _jdk7Helper.getSerializerForJavaNioFilePath(rawType);
+            if (ser != null) {
+                return ser;
+            }
         }
         if ((CLASS_DOM_NODE != null) && CLASS_DOM_NODE.isAssignableFrom(rawType)) {
             return (JsonSerializer<?>) instantiate(SERIALIZER_FOR_DOM_NODE);
@@ -120,8 +117,11 @@
     {
         final Class<?> rawType = type.getRawClass();
 
-        if ((CLASS_JAVA7_PATH != null) && CLASS_JAVA7_PATH.isAssignableFrom(rawType)) {
-            return (JsonDeserializer<?>) instantiate(DESERIALIZER_FOR_PATH);
+        if (_jdk7Helper != null) {
+            JsonDeserializer<?> deser = _jdk7Helper.getDeserializerForJavaNioFilePath(rawType);
+            if (deser != null) {
+                return deser;
+            }
         }
         if ((CLASS_DOM_NODE != null) && CLASS_DOM_NODE.isAssignableFrom(rawType)) {
             return (JsonDeserializer<?>) instantiate(DESERIALIZER_FOR_DOM_NODE);
diff --git a/src/main/java/com/fasterxml/jackson/databind/ext/PathDeserializer.java b/src/main/java/com/fasterxml/jackson/databind/ext/PathDeserializer.java
deleted file mode 100644
index 7b910db..0000000
--- a/src/main/java/com/fasterxml/jackson/databind/ext/PathDeserializer.java
+++ /dev/null
@@ -1,29 +0,0 @@
-package com.fasterxml.jackson.databind.ext;
-
-import java.io.IOException;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-
-import com.fasterxml.jackson.core.JsonParser;
-import com.fasterxml.jackson.core.JsonToken;
-import com.fasterxml.jackson.databind.DeserializationContext;
-import com.fasterxml.jackson.databind.deser.std.StdScalarDeserializer;
-
-public class PathDeserializer extends StdScalarDeserializer<Path>
-{
-    private static final long serialVersionUID = 1;
-
-    public PathDeserializer() { super(Path.class); }
-    
-    @Override
-    public Path deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
-        JsonToken t= p.getCurrentToken();
-        if (t != null) {
-            if (t.isScalarValue()) {
-                return Paths.get(p.getValueAsString());
-            }
-            // 16-Oct-2015: should we perhaps allow JSON Arrays (of Strings) as well?
-        }
-        throw ctxt.mappingException(Path.class, t);
-    }
-}
diff --git a/src/main/java/com/fasterxml/jackson/databind/introspect/Annotated.java b/src/main/java/com/fasterxml/jackson/databind/introspect/Annotated.java
index 90ed524..2d7c064 100644
--- a/src/main/java/com/fasterxml/jackson/databind/introspect/Annotated.java
+++ b/src/main/java/com/fasterxml/jackson/databind/introspect/Annotated.java
@@ -63,7 +63,7 @@
     public abstract JavaType getType();
 
     /**
-     * @deprecated Since 2.7 Use {@link #getType()} instead. To be removed from 2.8.
+     * @deprecated Since 2.7 Use {@link #getType()} instead. To be removed from 2.9
      */
     @Deprecated
     public final JavaType getType(TypeBindings bogus) {
@@ -77,7 +77,7 @@
      * as a result use of this method was deprecated in Jackson 2.7: see
      * {@link #getType} for replacement.
      *
-     * @deprecated Since 2.7 should instead use {@link #getType()}. To be removed from 2.8
+     * @deprecated Since 2.7 should instead use {@link #getType()}. To be removed from 2.9
      */
     @Deprecated
     public Type getGenericType() {
diff --git a/src/main/java/com/fasterxml/jackson/databind/introspect/AnnotatedClass.java b/src/main/java/com/fasterxml/jackson/databind/introspect/AnnotatedClass.java
index 5faa7ba..109c4c7 100644
--- a/src/main/java/com/fasterxml/jackson/databind/introspect/AnnotatedClass.java
+++ b/src/main/java/com/fasterxml/jackson/databind/introspect/AnnotatedClass.java
@@ -88,7 +88,7 @@
      * Combined list of Jackson annotations that the class has,
      * including inheritable ones from super classes and interfaces
      */
-    protected AnnotationMap _classAnnotations;
+    final protected AnnotationMap _classAnnotations;
 
     /**
      * Flag to indicate whether creator information has been resolved
@@ -124,6 +124,14 @@
      */
     protected List<AnnotatedField> _fields;
 
+    /**
+     * Lazily determined property to see if this is a non-static inner
+     * class.
+     *
+     * @since 2.8.7
+     */
+    protected transient Boolean _nonStaticInnerClass;
+
     /*
     /**********************************************************
     /* Life-cycle
@@ -136,8 +144,7 @@
      */
     private AnnotatedClass(JavaType type, Class<?> rawType, TypeBindings bindings,
             List<JavaType> superTypes,
-            AnnotationIntrospector aintr, MixInResolver mir, TypeFactory tf,
-            AnnotationMap classAnnotations)
+            AnnotationIntrospector aintr, MixInResolver mir, TypeFactory tf)
     {
         _type = type;
         _class = rawType;
@@ -148,13 +155,24 @@
         _mixInResolver = mir;
         _primaryMixIn = (_mixInResolver == null) ? null
             : _mixInResolver.findMixInClassFor(_class);
-        _classAnnotations = classAnnotations;
+        _classAnnotations = _resolveClassAnnotations();
+    }
+
+    private AnnotatedClass(AnnotatedClass base, AnnotationMap clsAnn) {
+        _type = base._type;
+        _class = base._class;
+        _bindings = base._bindings;
+        _superTypes = base._superTypes;
+        _annotationIntrospector = base._annotationIntrospector;
+        _typeFactory = base._typeFactory;
+        _mixInResolver = base._mixInResolver;
+        _primaryMixIn = base._primaryMixIn;
+        _classAnnotations = clsAnn;
     }
 
     @Override
     public AnnotatedClass withAnnotations(AnnotationMap ann) {
-        return new AnnotatedClass(_type, _class, _bindings, _superTypes,
-                _annotationIntrospector, _mixInResolver, _typeFactory, ann);
+        return new AnnotatedClass(this, ann);
     }
 
     /**
@@ -170,7 +188,7 @@
         Class<?> raw = type.getRawClass();
         return new AnnotatedClass(type, raw, type.getBindings(),
                 ClassUtil.findSuperTypes(type, null, false), intr,
-                (MixInResolver) config, config.getTypeFactory(), null);
+                (MixInResolver) config, config.getTypeFactory());
     }
 
     /**
@@ -184,7 +202,7 @@
         Class<?> raw = type.getRawClass();
         return new AnnotatedClass(type, raw, type.getBindings(),
                 ClassUtil.findSuperTypes(type, null, false),
-                intr, mir, config.getTypeFactory(), null);
+                intr, mir, config.getTypeFactory());
     }
     
     /**
@@ -196,12 +214,12 @@
     {
         if (config == null) {
             return new AnnotatedClass(null, cls, TypeBindings.emptyBindings(),
-                    Collections.<JavaType>emptyList(), null, null, null, null);
+                    Collections.<JavaType>emptyList(), null, null, null);
         }
         AnnotationIntrospector intr = config.isAnnotationProcessingEnabled()
                 ? config.getAnnotationIntrospector() : null;
         return new AnnotatedClass(null, cls, TypeBindings.emptyBindings(),
-                Collections.<JavaType>emptyList(), intr, (MixInResolver) config, config.getTypeFactory(), null);
+                Collections.<JavaType>emptyList(), intr, (MixInResolver) config, config.getTypeFactory());
     }
 
     public static AnnotatedClass constructWithoutSuperTypes(Class<?> cls, MapperConfig<?> config,
@@ -209,12 +227,12 @@
     {
         if (config == null) {
             return new AnnotatedClass(null, cls, TypeBindings.emptyBindings(),
-                    Collections.<JavaType>emptyList(), null, null, null, null);
+                    Collections.<JavaType>emptyList(), null, null, null);
         }
         AnnotationIntrospector intr = config.isAnnotationProcessingEnabled()
                 ? config.getAnnotationIntrospector() : null;
         return new AnnotatedClass(null, cls, TypeBindings.emptyBindings(),
-                Collections.<JavaType>emptyList(), intr, mir, config.getTypeFactory(), null);
+                Collections.<JavaType>emptyList(), intr, mir, config.getTypeFactory());
     }
 
     /*
@@ -245,17 +263,17 @@
 
     @Override
     public <A extends Annotation> A getAnnotation(Class<A> acls) {
-        return _classAnnotations().get(acls);
+        return _classAnnotations.get(acls);
     }
 
     @Override
     public boolean hasAnnotation(Class<?> acls) {
-        return _classAnnotations().has(acls);
+        return _classAnnotations.has(acls);
     }
 
     @Override
     public boolean hasOneOf(Class<? extends Annotation>[] annoClasses) {
-        return _classAnnotations().hasOneOf(annoClasses);
+        return _classAnnotations.hasOneOf(annoClasses);
     }
 
     @Override
@@ -265,12 +283,12 @@
 
     @Override
     public Iterable<Annotation> annotations() {
-        return _classAnnotations().annotations();
+        return _classAnnotations.annotations();
     }
     
     @Override
     protected AnnotationMap getAllAnnotations() {
-        return _classAnnotations();
+        return _classAnnotations;
     }
 
     @Override
@@ -285,11 +303,11 @@
      */
 
     public Annotations getAnnotations() {
-        return _classAnnotations();
+        return _classAnnotations;
     }
 
     public boolean hasAnnotations() {
-        return _classAnnotations().size() > 0;
+        return _classAnnotations.size() > 0;
     }
 
     public AnnotatedConstructor getDefaultConstructor()
@@ -355,32 +373,24 @@
         return _fields;
     }
 
+    /**
+     * @since 2.9
+     */
+    public boolean isNonStaticInnerClass()
+    {
+        Boolean B = _nonStaticInnerClass;
+        if (B == null) {
+            _nonStaticInnerClass = B = ClassUtil.isNonStaticInnerClass(_class);
+        }
+        return B.booleanValue();
+    }
+
     /*
     /**********************************************************
     /* Public API, main-level resolution methods
     /**********************************************************
      */
 
-    private AnnotationMap _classAnnotations() {
-        AnnotationMap anns = _classAnnotations;
-        if (anns == null) {
-            // 06-Dec-2015, tatu: yes, double-locking, typically not a good choice.
-            //  But for typical usage pattern here (and with JVM 7 and above) is
-            //  a reasonable choice to avoid non-common but existing race condition
-            //  from root name lookup style usage
-            // Also note that race condition stems from caching only used for loading
-            // where just class annotations are needed
-            synchronized (this) {
-                anns = _classAnnotations;
-                if (anns == null) {
-                    anns = _resolveClassAnnotations();
-                    _classAnnotations = anns;
-                }
-            }
-        }
-        return anns;
-    }
-
     /**
      * Initialization method that will recursively collect Jackson
      * annotations for this class and all super classes and
@@ -424,24 +434,33 @@
      */
     private void resolveCreators()
     {
-        // Then see which constructors we have
-        List<AnnotatedConstructor> constructors = null;
-        ClassUtil.Ctor[] declaredCtors = ClassUtil.getConstructors(_class);
         // Constructor also always members of this class
         TypeResolutionContext typeContext = this; 
 
-        // 30-Apr-2016, tatu: [databind#1215]: Actually, while true, this does
-        //   NOT apply to context since sub-class may have type bindings
-//        TypeResolutionContext typeContext = new TypeResolutionContext.Basic(_typeFactory, _type.getBindings());
-        for (ClassUtil.Ctor ctor : declaredCtors) {
-            if (_isIncludableConstructor(ctor.getConstructor())) {
-                if (ctor.getParamCount() == 0) {
-                    _defaultConstructor = _constructDefaultConstructor(ctor, typeContext);
-                } else {
-                    if (constructors == null) {
-                        constructors = new ArrayList<AnnotatedConstructor>(Math.max(10, declaredCtors.length));
+    // 30-Apr-2016, tatu: [databind#1215]: Actually, while true, this does
+    //   NOT apply to context since sub-class may have type bindings
+//    TypeResolutionContext typeContext = new TypeResolutionContext.Basic(_typeFactory, _type.getBindings());
+
+        // Then see which constructors we have
+        List<AnnotatedConstructor> constructors = null;
+
+        // 18-Jun-2016, tatu: Enum constructors will never be useful (unlike
+        //    possibly static factory methods); but they can be royal PITA
+        //    due to some oddities by JVM; see:
+        //    [https://github.com/FasterXML/jackson-module-parameter-names/issues/35]
+        //    for more. So, let's just skip them.
+        if (!_type.isEnumType()) {
+            ClassUtil.Ctor[] declaredCtors = ClassUtil.getConstructors(_class);
+            for (ClassUtil.Ctor ctor : declaredCtors) {
+                if (_isIncludableConstructor(ctor.getConstructor())) {
+                    if (ctor.getParamCount() == 0) {
+                        _defaultConstructor = _constructDefaultConstructor(ctor, typeContext);
+                    } else {
+                        if (constructors == null) {
+                            constructors = new ArrayList<AnnotatedConstructor>(Math.max(10, declaredCtors.length));
+                        }
+                        constructors.add(_constructNonDefaultConstructor(ctor, typeContext));
                     }
-                    constructors.add(_constructNonDefaultConstructor(ctor, typeContext));
                 }
             }
         }
@@ -457,7 +476,6 @@
             }
         }
 
-
         /* And then... let's remove all constructors that are deemed
          * ignorable after all annotations have been properly collapsed.
          */
diff --git a/src/main/java/com/fasterxml/jackson/databind/introspect/AnnotatedConstructor.java b/src/main/java/com/fasterxml/jackson/databind/introspect/AnnotatedConstructor.java
index 93f0876..a5e81ad 100644
--- a/src/main/java/com/fasterxml/jackson/databind/introspect/AnnotatedConstructor.java
+++ b/src/main/java/com/fasterxml/jackson/databind/introspect/AnnotatedConstructor.java
@@ -19,7 +19,7 @@
      * @since 2.1
      */
     protected Serialization _serialization;
-    
+
     /*
     /**********************************************************
     /* Life-cycle
diff --git a/src/main/java/com/fasterxml/jackson/databind/introspect/AnnotatedMember.java b/src/main/java/com/fasterxml/jackson/databind/introspect/AnnotatedMember.java
index 03388e8..423f209 100644
--- a/src/main/java/com/fasterxml/jackson/databind/introspect/AnnotatedMember.java
+++ b/src/main/java/com/fasterxml/jackson/databind/introspect/AnnotatedMember.java
@@ -133,9 +133,12 @@
      * @since 2.7
      */
     public final void fixAccess(boolean force) {
-        ClassUtil.checkAndFixAccess(getMember(), force);
+        Member m = getMember();
+        if (m != null) { // may be null for virtual members
+            ClassUtil.checkAndFixAccess(m, force);
+        }
     }
-    
+
     /**
      * @deprecated Since 2.7 use {@link #fixAccess(boolean)} instead
      */
diff --git a/src/main/java/com/fasterxml/jackson/databind/introspect/AnnotatedMethod.java b/src/main/java/com/fasterxml/jackson/databind/introspect/AnnotatedMethod.java
index 8ec3737..e7d75ac 100644
--- a/src/main/java/com/fasterxml/jackson/databind/introspect/AnnotatedMethod.java
+++ b/src/main/java/com/fasterxml/jackson/databind/introspect/AnnotatedMethod.java
@@ -77,8 +77,8 @@
 
     /**
      * For methods, this returns declared return type, which is only
-     * useful with getters (setters do not return anything; hence "void"
-     * type is returned here)
+     * useful with getters (setters do not return anything; hence `Void`
+     * would be returned here)
      */
     @Override
     public JavaType getType() {
@@ -121,7 +121,15 @@
     public final Object call1(Object arg) throws Exception {
         return _method.invoke(null, arg);
     }
-    
+
+    public final Object callOn(Object pojo) throws Exception {
+        return _method.invoke(pojo);
+    }
+
+    public final Object callOnWith(Object pojo, Object... args) throws Exception {
+        return _method.invoke(pojo, args);
+    }
+
     /*
     /********************************************************
     /* AnnotatedMember impl
@@ -192,7 +200,7 @@
                     +getFullName()+": "+e.getMessage(), e);
         }
     }
-    
+
     /*
     /*****************************************************
     /* Extended API, generic
@@ -203,7 +211,7 @@
         return getDeclaringClass().getName() + "#" + getName() + "("
             +getParameterCount()+" params)";
     }
-    
+
     public Class<?>[] getRawParameterTypes()
     {
         if (_paramClasses == null) {
diff --git a/src/main/java/com/fasterxml/jackson/databind/introspect/AnnotatedWithParams.java b/src/main/java/com/fasterxml/jackson/databind/introspect/AnnotatedWithParams.java
index a176f7d..8cf5a79 100644
--- a/src/main/java/com/fasterxml/jackson/databind/introspect/AnnotatedWithParams.java
+++ b/src/main/java/com/fasterxml/jackson/databind/introspect/AnnotatedWithParams.java
@@ -33,6 +33,14 @@
     }
 
     /**
+     * @since 2.8.1
+     */
+    protected AnnotatedWithParams(AnnotatedWithParams base, AnnotationMap[] paramAnnotations) {
+        super(base);
+        _paramAnnotations = paramAnnotations;
+    }
+
+    /**
      * Method called to override a method parameter annotation,
      * usually due to a mix-in
      * annotation masking or overriding an annotation 'real' method
@@ -60,33 +68,6 @@
 
     /*
     /**********************************************************
-    /* Helper methods for subclasses
-    /**********************************************************
-     */
-
-    /*
-    protected JavaType getType(TypeBindings bindings, TypeVariable<?>[] typeParams)
-    {
-        // [JACKSON-468] Need to consider local type binding declarations too...
-        if (typeParams != null && typeParams.length > 0) {
-            bindings = bindings.childInstance();
-            for (TypeVariable<?> var : typeParams) {
-                String name = var.getName();
-                // to prevent infinite loops, need to first add placeholder ("<T extends Enum<T>>" etc)
-                bindings._addPlaceholder(name);
-                // About only useful piece of information is the lower bound (which is at least Object.class)
-                Type lowerBound = var.getBounds()[0];
-                JavaType type = (lowerBound == null) ? TypeFactory.unknownType()
-                        : bindings.resolveType(lowerBound);
-                bindings.addBinding(var.getName(), type);
-            }
-        }
-        return bindings.resolveType(getGenericType());
-    }
-    */
-
-    /*
-    /**********************************************************
     /* Extended API
     /**********************************************************
      */
@@ -116,7 +97,7 @@
     public abstract JavaType getParameterType(int index);
 
     /**
-     * @deprecated Since 2.7, remove in 2.8
+     * @deprecated Since 2.7, remove in 2.9
      */
     @Deprecated
     public abstract Type getGenericParameterType(int index);
diff --git a/src/main/java/com/fasterxml/jackson/databind/introspect/AnnotationIntrospectorPair.java b/src/main/java/com/fasterxml/jackson/databind/introspect/AnnotationIntrospectorPair.java
index a7bfa3f..97e5edc 100644
--- a/src/main/java/com/fasterxml/jackson/databind/introspect/AnnotationIntrospectorPair.java
+++ b/src/main/java/com/fasterxml/jackson/databind/introspect/AnnotationIntrospectorPair.java
@@ -7,6 +7,7 @@
 
 import com.fasterxml.jackson.annotation.JsonCreator;
 import com.fasterxml.jackson.annotation.JsonFormat;
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
 import com.fasterxml.jackson.annotation.JsonInclude;
 import com.fasterxml.jackson.annotation.JsonProperty;
 import com.fasterxml.jackson.core.Version;
@@ -114,6 +115,18 @@
     }
 
     @Override
+    public JsonIgnoreProperties.Value findPropertyIgnorals(Annotated a)
+    {
+        JsonIgnoreProperties.Value v2 = _secondary.findPropertyIgnorals(a);
+        JsonIgnoreProperties.Value v1 = _primary.findPropertyIgnorals(a);
+
+        if (v2 == null) { // shouldn't occur but
+            return v1;
+        }
+        return v2.withOverrides(v1);
+    }
+    
+    @Override
     @Deprecated // since 2.6
     public String[] findPropertiesToIgnore(Annotated ac) {
         String[] result = _primary.findPropertiesToIgnore(ac);
@@ -124,6 +137,7 @@
     }
 
     @Override
+    @Deprecated // since 2.8
     public String[] findPropertiesToIgnore(Annotated ac, boolean forSerialization) {
         String[] result = _primary.findPropertiesToIgnore(ac, forSerialization);
         if (result == null) {
@@ -133,6 +147,7 @@
     }
 
     @Override
+    @Deprecated // since 2.8
     public Boolean findIgnoreUnknownProperties(AnnotatedClass ac)
     {
         Boolean result = _primary.findIgnoreUnknownProperties(ac);
@@ -552,8 +567,9 @@
     public boolean hasAsValueAnnotation(AnnotatedMethod am) {
         return _primary.hasAsValueAnnotation(am) || _secondary.hasAsValueAnnotation(am);
     }
-    
+
     @Override
+    @Deprecated
     public String findEnumValue(Enum<?> value) {
         String r = _primary.findEnumValue(value);
         return (r == null) ? _secondary.findEnumValue(value) : r;
@@ -566,7 +582,13 @@
         names = _primary.findEnumValues(enumType, enumValues, names);
         return names;
     }
-    
+
+    @Override
+    public Enum<?> findDefaultEnumValue(Class<Enum<?>> enumCls) {
+        Enum<?> en = _primary.findDefaultEnumValue(enumCls);
+        return (en == null) ? _secondary.findDefaultEnumValue(enumCls) : en;
+    }
+
     // // // Deserialization: general annotations
 
     @Override
diff --git a/src/main/java/com/fasterxml/jackson/databind/introspect/BasicBeanDescription.java b/src/main/java/com/fasterxml/jackson/databind/introspect/BasicBeanDescription.java
index 494e9c0..fd2f0d4 100644
--- a/src/main/java/com/fasterxml/jackson/databind/introspect/BasicBeanDescription.java
+++ b/src/main/java/com/fasterxml/jackson/databind/introspect/BasicBeanDescription.java
@@ -6,6 +6,7 @@
 
 import com.fasterxml.jackson.annotation.JsonFormat;
 import com.fasterxml.jackson.annotation.JsonInclude;
+
 import com.fasterxml.jackson.databind.*;
 import com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder;
 import com.fasterxml.jackson.databind.cfg.HandlerInstantiator;
@@ -22,9 +23,6 @@
  * use cases for that, nor is such usage tested or supported.
  * Separation from API is mostly to isolate some implementation details
  * here and keep API simple.
- *<p>
- * Note that since 2.6 this class has been a thin shell around
- * {@link POJOPropertiesCollector}, which handles most of actual work.
  */
 public class BasicBeanDescription extends BeanDescription
 {
@@ -49,12 +47,6 @@
      * Information collected about the class introspected.
      */
     final protected AnnotatedClass _classInfo;
-    
-    /**
-     * We may need type bindings for the bean type. If so, we'll
-     * construct it lazily
-     */
-    protected TypeBindings _bindings;
 
     /*
     /**********************************************************
@@ -71,7 +63,7 @@
      * Details of Object Id to include, if any
      */
     protected ObjectIdInfo _objectIdInfo;
-    
+
     /*
     /**********************************************************
     /* Life-cycle
@@ -84,7 +76,12 @@
         super(type);
         _propCollector = coll;
         _config = coll.getConfig();
-        _annotationIntrospector = (_config == null) ? null : _config.getAnnotationIntrospector();
+        // NOTE: null config only for some pre-constructed types
+        if (_config == null) {
+            _annotationIntrospector = null;
+        } else {
+            _annotationIntrospector = _config.getAnnotationIntrospector();
+        }
         _classInfo = classDef;
     }
 
@@ -98,7 +95,12 @@
         super(type);
         _propCollector = null;
         _config = config;
-        _annotationIntrospector = (_config == null) ? null : _config.getAnnotationIntrospector();
+        // NOTE: null config only for some pre-constructed types
+        if (_config == null) {
+            _annotationIntrospector = null;
+        } else {
+            _annotationIntrospector = _config.getAnnotationIntrospector();
+        }
         _classInfo = classDef;
         _properties = props;
     }
@@ -250,6 +252,7 @@
     }
 
     @Override
+    @Deprecated // since 2.8
     public JavaType resolveType(java.lang.reflect.Type jdkType) {
         if (jdkType == null) {
             return null;
@@ -339,10 +342,24 @@
     @Override
     public JsonFormat.Value findExpectedFormat(JsonFormat.Value defValue)
     {
+        // 15-Apr-2016, tatu: Let's check both per-type defaults and annotations; per-type
+        //   defaults having higher precedence, so start with that
         if (_annotationIntrospector != null) {
             JsonFormat.Value v = _annotationIntrospector.findFormat(_classInfo);
             if (v != null) {
-                return v;
+                if (defValue == null) {
+                    defValue = v;
+                } else {
+                    defValue = defValue.withOverrides(v);
+                }
+            }
+        }
+        JsonFormat.Value v = _config.getDefaultPropertyFormat(_classInfo.getRawType());
+        if (v != null) {
+            if (defValue == null) {
+                defValue = v;
+            } else {
+                defValue = defValue.withOverrides(v);
             }
         }
         return defValue;
@@ -374,7 +391,7 @@
         if (_annotationIntrospector != null) {
             JsonInclude.Value incl = _annotationIntrospector.findPropertyInclusion(_classInfo);
             if (incl != null) {
-                return defValue.withOverrides(incl);
+                return (defValue == null) ? incl : defValue.withOverrides(incl);
             }
         }
         return defValue;
@@ -404,13 +421,30 @@
     }
 
     @Override
+    public AnnotatedMember findAnySetterField() throws IllegalArgumentException {
+        AnnotatedMember anySetter = (_propCollector == null) ? null : _propCollector.getAnySetterField();
+		if (anySetter != null) {
+			/*
+			 * For now let's require a Map; in future can add support for other
+			 * types like perhaps Iterable<Map.Entry>?
+			 */
+			Class<?> type = anySetter.getRawType();
+			if (!Map.class.isAssignableFrom(type)) {
+				throw new IllegalArgumentException("Invalid 'any-setter' annotation on field " + anySetter.getName()
+				        + "(): type is not instance of java.util.Map");
+			}
+		}
+		return anySetter;
+	}
+
+    @Override
     public Map<String,AnnotatedMember> findBackReferenceProperties()
     {
         HashMap<String,AnnotatedMember> result = null;
 //        boolean hasIgnored = (_ignoredPropertyNames != null);
 
         for (BeanPropertyDefinition property : _properties()) {
-            /* 23-Sep-2014, tatu: As per [Databind#426], we _should_ try to avoid
+            /* 23-Sep-2014, tatu: As per [databind#426], we _should_ try to avoid
              *   calling accessor, as it triggers exception from seeming conflict.
              *   But the problem is that _ignoredPropertyNames here only contains
              *   ones ignored on per-property annotations, but NOT class annotations...
@@ -487,7 +521,8 @@
     {
         // So, of all single-arg static methods:
         for (AnnotatedMethod am : _classInfo.getStaticMethods()) {
-            if (isFactoryMethod(am)) {
+            // 24-Oct-2016, tatu: Better ensure it only takes 1 arg, no matter what
+            if (isFactoryMethod(am) && am.getParameterCount() == 1) {
                 // And must take one of expected arg types (or supertype)
                 Class<?> actualArgType = am.getRawParameterType(0);
                 for (Class<?> expArgType : expArgTypes) {
@@ -504,14 +539,12 @@
     protected boolean isFactoryMethod(AnnotatedMethod am)
     {
         /* First: return type must be compatible with the introspected class
-         * (i.e. allowed to be sub-class, although usually is the same
-         * class)
+         * (i.e. allowed to be sub-class, although usually is the same class)
          */
         Class<?> rt = am.getRawReturnType();
         if (!getBeanClass().isAssignableFrom(rt)) {
             return false;
         }
-
         /* Also: must be a recognized factory method, meaning:
          * (a) marked with @JsonCreator annotation, or
          * (b) "valueOf" (at this point, need not be public)
@@ -520,12 +553,15 @@
             return true;
         }
         final String name = am.getName();
+        // 24-Oct-2016, tatu: As per [databind#1429] must ensure takes exactly one arg
         if ("valueOf".equals(name)) {
-            return true;
+            if (am.getParameterCount() == 1) {
+                return true;
+            }
         }
-        // [Issue#208] Also accept "fromString()", if takes String or CharSequence
+        // [databind#208] Also accept "fromString()", if takes String or CharSequence
         if ("fromString".equals(name)) {
-            if (1 == am.getParameterCount()) {
+            if (am.getParameterCount() == 1) {
                 Class<?> cls = am.getRawParameterType(0);
                 if (cls == String.class || CharSequence.class.isAssignableFrom(cls)) {
                     return true;
@@ -536,50 +572,9 @@
     }
 
     /**
-     * @deprecated Since 2.4, use <code>findCreatorParameterNames()</code> instead.
+     * @deprecated since 2.8
      */
-    @Deprecated
-    public List<String> findCreatorPropertyNames()
-    {
-        List<PropertyName> params = findCreatorParameterNames();
-        if (params.isEmpty()) {
-    		    return Collections.emptyList();
-        }
-        List<String> result = new ArrayList<String>(params.size());
-        for (PropertyName name : params) {
-    		    result.add(name.getSimpleName());
-        }
-        return result;
-    }
-    
-    /**
-     * @deprecated Since 2.5, does not seem to be used at all.
-     */
-    @Deprecated
-    public List<PropertyName> findCreatorParameterNames()
-    {
-        for (int i = 0; i < 2; ++i) {
-            List<? extends AnnotatedWithParams> l = (i == 0)
-                ? getConstructors() : getFactoryMethods();
-            for (AnnotatedWithParams creator : l) {
-                int argCount = creator.getParameterCount();
-                if (argCount < 1) continue;
-                PropertyName name = _findCreatorPropertyName(creator.getParameter(0));
-                if (name == null || name.isEmpty()) {
-                    continue;
-                }
-                List<PropertyName> names = new ArrayList<PropertyName>();
-                names.add(name);
-                for (int p = 1; p < argCount; ++p) {
-                    name = _findCreatorPropertyName(creator.getParameter(p));
-                    names.add(name);
-                }
-                return names;
-            }
-        }
-        return Collections.emptyList();
-    }
-
+    @Deprecated // since 2.8, not used at least since 2.7
     protected PropertyName _findCreatorPropertyName(AnnotatedParameter param)
     {
         PropertyName name = _annotationIntrospector.findNameForDeserialization(param);
diff --git a/src/main/java/com/fasterxml/jackson/databind/introspect/BeanPropertyDefinition.java b/src/main/java/com/fasterxml/jackson/databind/introspect/BeanPropertyDefinition.java
index 0a85b30..4039230 100644
--- a/src/main/java/com/fasterxml/jackson/databind/introspect/BeanPropertyDefinition.java
+++ b/src/main/java/com/fasterxml/jackson/databind/introspect/BeanPropertyDefinition.java
@@ -230,6 +230,8 @@
     /**
      * Method used to check if this property has specific inclusion override
      * associated with it or not.
+     * It should NOT check for any default settings (global, per-type, or
+     * containing POJO settings)
      * 
      * @since 2.5
      */
diff --git a/src/main/java/com/fasterxml/jackson/databind/introspect/ConcreteBeanPropertyBase.java b/src/main/java/com/fasterxml/jackson/databind/introspect/ConcreteBeanPropertyBase.java
index 99de5d0..7ea742b 100644
--- a/src/main/java/com/fasterxml/jackson/databind/introspect/ConcreteBeanPropertyBase.java
+++ b/src/main/java/com/fasterxml/jackson/databind/introspect/ConcreteBeanPropertyBase.java
@@ -28,9 +28,9 @@
     /**
      * Lazily accessed value for per-property format override definition.
      * 
-     * @since 2.6
+     * @since 2.8
      */
-    protected transient JsonFormat.Value _format;
+    protected transient JsonFormat.Value _propertyFormat;
 
     protected ConcreteBeanPropertyBase(PropertyMetadata md) {
         _metadata = (md == null) ? PropertyMetadata.STD_REQUIRED_OR_OPTIONAL : md;
@@ -38,7 +38,7 @@
 
     protected ConcreteBeanPropertyBase(ConcreteBeanPropertyBase src) {
         _metadata = src._metadata;
-        _format = src._format;
+        _propertyFormat = src._propertyFormat;
     }
 
     @Override
@@ -53,17 +53,15 @@
     @Override
     @Deprecated
     public final JsonFormat.Value findFormatOverrides(AnnotationIntrospector intr) {
-        JsonFormat.Value f = _format;
-        if (f == null) { // not yet looked up, do that
-            if (intr != null) {
-                AnnotatedMember member = getMember();
-                if (member != null) {
-                    f = intr.findFormat(member);
-                }
+        JsonFormat.Value f = null;
+        if (intr != null) {
+            AnnotatedMember member = getMember();
+            if (member != null) {
+                f = intr.findFormat(member);
             }
-            if (f == null) {
-                f = EMPTY_FORMAT;
-            }
+        }
+        if (f == null) {
+            f = EMPTY_FORMAT;
         }
         return f;
     }
@@ -71,18 +69,27 @@
     @Override
     public JsonFormat.Value findPropertyFormat(MapperConfig<?> config, Class<?> baseType)
     {
-        // 08-Oct-2015, tatu: Unlike with Format, let's not cache locally here, for now?
-        JsonFormat.Value v0 = config.getDefaultPropertyFormat(baseType);
-        AnnotationIntrospector intr = config.getAnnotationIntrospector();
-        AnnotatedMember member = getMember();
-        if ((intr == null) || (member == null)) {
-            return v0;
-        }
-        JsonFormat.Value v = intr.findFormat(member);
+        // 15-Apr-2016, tatu: Let's calculate lazily, retain; assumption being however that
+        //    baseType is always the same
+        JsonFormat.Value v = _propertyFormat;
         if (v == null) {
-            return v0;
+            JsonFormat.Value v1 = config.getDefaultPropertyFormat(baseType);
+            JsonFormat.Value v2 = null;
+            AnnotationIntrospector intr = config.getAnnotationIntrospector();
+            if (intr != null) {
+                AnnotatedMember member = getMember();
+                if (member != null) {
+                    v2 = intr.findFormat(member);
+                }
+            }
+            if (v1 == null) {
+                v = (v2 == null) ? EMPTY_FORMAT : v2;
+            } else {
+                v = (v2 == null) ? v1 : v1.withOverrides(v2);
+            }
+            _propertyFormat = v;
         }
-        return v0.withOverrides(v);
+        return v;
     }
 
     @Override
diff --git a/src/main/java/com/fasterxml/jackson/databind/introspect/JacksonAnnotationIntrospector.java b/src/main/java/com/fasterxml/jackson/databind/introspect/JacksonAnnotationIntrospector.java
index f2bc1ca..8417aa3 100644
--- a/src/main/java/com/fasterxml/jackson/databind/introspect/JacksonAnnotationIntrospector.java
+++ b/src/main/java/com/fasterxml/jackson/databind/introspect/JacksonAnnotationIntrospector.java
@@ -1,7 +1,5 @@
 package com.fasterxml.jackson.databind.introspect;
 
-import java.beans.ConstructorProperties;
-import java.beans.Transient;
 import java.lang.annotation.Annotation;
 import java.lang.reflect.Field;
 import java.util.*;
@@ -12,6 +10,7 @@
 import com.fasterxml.jackson.databind.annotation.*;
 import com.fasterxml.jackson.databind.cfg.HandlerInstantiator;
 import com.fasterxml.jackson.databind.cfg.MapperConfig;
+import com.fasterxml.jackson.databind.ext.Java7Support;
 import com.fasterxml.jackson.databind.jsontype.NamedType;
 import com.fasterxml.jackson.databind.jsontype.TypeIdResolver;
 import com.fasterxml.jackson.databind.jsontype.TypeResolverBuilder;
@@ -57,17 +56,15 @@
         JsonManagedReference.class
     };
 
-    private static final Java7Support _jdk7Helper;
+    // NOTE: loading of Java7 dependencies is encapsulated by handlers in Java7Support,
+    //  here we do not really need any handling; but for extra-safety use try-catch
+    private static final Java7Support _java7Helper;
     static {
         Java7Support x = null;
         try {
-            x = Java7Support.class.newInstance();
-        } catch (Throwable t) {
-            // 24-Nov-2015, tatu: Should we log or not?
-            java.util.logging.Logger.getLogger(JacksonAnnotationIntrospector.class.getName())
-                .warning("Unable to load JDK7 annotation types; will have to skip");
-        }
-        _jdk7Helper = x;
+            x = Java7Support.instance();
+        } catch (Throwable t) { }
+        _java7Helper = x;
     }
     
     /**
@@ -175,6 +172,7 @@
      * explicit serialized name
      */
     @Override
+    @Deprecated
     public String findEnumValue(Enum<?> value)
     {
         // 11-Jun-2015, tatu: As per [databind#677], need to allow explicit naming.
@@ -233,6 +231,20 @@
         return names;
     }
 
+    /**
+     * Finds the Enum value that should be considered the default value, if possible.
+     * <p>
+     * This implementation relies on {@link JsonEnumDefaultValue} annotation to determine the default value if present.
+     *
+     * @param enumCls The Enum class to scan for the default value.
+     * @return null if none found or it's not possible to determine one.
+     * @since 2.8
+     */
+    @Override
+    public Enum<?> findDefaultEnumValue(Class<Enum<?>> enumCls) {
+        return ClassUtil.findFirstAnnotatedEnumValue(enumCls, JsonEnumDefaultValue.class);
+    }
+
     /*
     /**********************************************************
     /* General class annotations
@@ -253,36 +265,43 @@
         return PropertyName.construct(ann.value(), ns);
     }
 
-    @Override
-    @Deprecated // since 2.6, remove from 2.7 or later
-    public String[] findPropertiesToIgnore(Annotated ac) {
-        JsonIgnoreProperties ignore = _findAnnotation(ac, JsonIgnoreProperties.class);
-        return (ignore == null) ? null : ignore.value();
+    @Override // since 2.8
+    public JsonIgnoreProperties.Value findPropertyIgnorals(Annotated a)
+    {
+        JsonIgnoreProperties v = _findAnnotation(a, JsonIgnoreProperties.class);
+        if (v == null) {
+            // could alternatively return `Value.empty()`?
+            return null;
+        }
+        return JsonIgnoreProperties.Value.from(v);
     }
-
+    
     @Override // since 2.6
-    public String[] findPropertiesToIgnore(Annotated ac, boolean forSerialization) {
-        JsonIgnoreProperties ignore = _findAnnotation(ac, JsonIgnoreProperties.class);
-        if (ignore == null) {
+    @Deprecated // since 2.8
+    public String[] findPropertiesToIgnore(Annotated a, boolean forSerialization) {
+        JsonIgnoreProperties.Value v = findPropertyIgnorals(a);
+        if (v == null) {
             return null;
         }
         // 13-May-2015, tatu: As per [databind#95], allow read-only/write-only props
         if (forSerialization) {
-            if (ignore.allowGetters()) {
+            if (v.getAllowGetters()) {
                 return null;
             }
         } else {
-            if (ignore.allowSetters()) {
+            if (v.getAllowSetters()) {
                 return null;
             }
         }
-        return ignore.value();
+        Set<String> ignored = v.getIgnored();
+        return ignored.toArray(new String[ignored.size()]);
     }
-    
+
     @Override
-    public Boolean findIgnoreUnknownProperties(AnnotatedClass ac) {
-        JsonIgnoreProperties ignore = _findAnnotation(ac, JsonIgnoreProperties.class);
-        return (ignore == null) ? null : ignore.ignoreUnknown();
+    @Deprecated // since 2.8
+    public Boolean findIgnoreUnknownProperties(AnnotatedClass a) {
+        JsonIgnoreProperties.Value v = findPropertyIgnorals(a);
+        return (v == null) ? null : v.getIgnoreUnknown();
     }
 
     @Override
@@ -858,7 +877,7 @@
         }
         // now, then, we need a placeholder for member (no real Field/Method):
         AnnotatedMember member = new VirtualAnnotatedMember(ac, ac.getRawType(),
-                attrName, type.getRawClass());
+                attrName, type);
         // and with that and property definition
         SimpleBeanPropertyDefinition propDef = SimpleBeanPropertyDefinition.construct(config,
                 member, propName, metadata, attr.include());
@@ -876,7 +895,7 @@
         JavaType type = config.constructType(prop.type());
         // now, then, we need a placeholder for member (no real Field/Method):
         AnnotatedMember member = new VirtualAnnotatedMember(ac, ac.getRawType(),
-                propName.getSimpleName(), type.getRawClass());
+                propName.getSimpleName(), type);
         // and with that and property definition
         SimpleBeanPropertyDefinition propDef = SimpleBeanPropertyDefinition.construct(config,
                 member, propName, metadata, prop.include());
@@ -1066,7 +1085,7 @@
         }
         return null;
     }
-    
+
     @Override
     public boolean hasAnySetterAnnotation(AnnotatedMethod am)
     {
@@ -1089,9 +1108,8 @@
     @Override
     public boolean hasCreatorAnnotation(Annotated a)
     {
-        /* No dedicated disabling; regular @JsonIgnore used
-         * if needs to be ignored (and if so, is handled prior
-         * to this method getting called)
+        /* No dedicated disabling; regular @JsonIgnore used if needs to be
+         * ignored (and if so, is handled prior to this method getting called)
          */
          JsonCreator ann = _findAnnotation(a, JsonCreator.class);
          if (ann != null) {
@@ -1101,8 +1119,8 @@
          //    may or may not consider it a creator
          if (_cfgConstructorPropertiesImpliesCreator ) {
              if (a instanceof AnnotatedConstructor) {
-                 if (_jdk7Helper != null) {
-                     Boolean b = _jdk7Helper.hasCreatorAnnotation(a);
+                 if (_java7Helper != null) {
+                     Boolean b = _java7Helper.hasCreatorAnnotation(a);
                      if (b != null) {
                          return b.booleanValue();
                      }
@@ -1130,8 +1148,8 @@
         if (ann != null) {
             return ann.value();
         }
-        if (_jdk7Helper != null) {
-            Boolean b = _jdk7Helper.findTransient(a);
+        if (_java7Helper != null) {
+            Boolean b = _java7Helper.findTransient(a);
             if (b != null) {
                 return b.booleanValue();
             }
@@ -1168,8 +1186,8 @@
             AnnotatedWithParams ctor = p.getOwner();
 
             if (ctor != null) {
-                if (_jdk7Helper != null) {
-                    PropertyName name = _jdk7Helper.findConstructorName(p);
+                if (_java7Helper != null) {
+                    PropertyName name = _java7Helper.findConstructorName(p);
                     if (name != null) {
                         return name;
                     }
@@ -1263,57 +1281,4 @@
     /* Helper classes
     /**********************************************************
      */
-
-    /**
-     * To support Java7-incomplete platforms, we will offer support for JDK 7
-     * annotations through this class, loaded dynamically; if loading fails,
-     * support will be missing.
-     */
-    private static class Java7Support
-    {
-        @SuppressWarnings("unused") // compiler warns, just needed side-effects
-        private final Class<?> _bogus;
-
-        @SuppressWarnings("unused") // compiler warns; called via Reflection
-        public Java7Support() {
-            // Trigger loading of annotations that only JDK 7 has...
-            Class<?> cls = Transient.class;
-            cls = ConstructorProperties.class;
-            _bogus = cls;
-        }
-        
-        public Boolean findTransient(Annotated a) {
-            Transient t = a.getAnnotation(Transient.class);
-            if (t != null) {
-                return t.value();
-            }
-            return null;
-        }
-
-        public Boolean hasCreatorAnnotation(Annotated a) {
-            ConstructorProperties props = a.getAnnotation(ConstructorProperties.class);
-            // 08-Nov-2015, tatu: One possible check would be to ensure there is at least
-            //    one name iff constructor has arguments. But seems unnecessary for now.
-            if (props != null) {
-                return Boolean.TRUE;
-            }
-            return null;
-        }
-
-        public PropertyName findConstructorName(AnnotatedParameter p)
-        {
-            AnnotatedWithParams ctor = p.getOwner();
-            if (ctor != null) {
-                ConstructorProperties props = ctor.getAnnotation(ConstructorProperties.class);
-                if (props != null) {
-                    String[] names = props.value();
-                    int ix = p.getIndex();
-                    if (ix < names.length) {
-                        return PropertyName.construct(names[ix]);
-                    }
-                }
-            }
-            return null;
-        }
-    }
 }
diff --git a/src/main/java/com/fasterxml/jackson/databind/introspect/POJOPropertiesCollector.java b/src/main/java/com/fasterxml/jackson/databind/introspect/POJOPropertiesCollector.java
index dd4733f..fd6a613 100644
--- a/src/main/java/com/fasterxml/jackson/databind/introspect/POJOPropertiesCollector.java
+++ b/src/main/java/com/fasterxml/jackson/databind/introspect/POJOPropertiesCollector.java
@@ -3,6 +3,8 @@
 import java.lang.reflect.Modifier;
 import java.util.*;
 
+import com.fasterxml.jackson.annotation.JsonAnySetter;
+import com.fasterxml.jackson.annotation.JsonProperty.Access;
 import com.fasterxml.jackson.databind.*;
 import com.fasterxml.jackson.databind.cfg.HandlerInstantiator;
 import com.fasterxml.jackson.databind.cfg.MapperConfig;
@@ -83,6 +85,8 @@
     protected LinkedList<AnnotatedMember> _anyGetters;
 
     protected LinkedList<AnnotatedMethod> _anySetters;
+    
+    protected LinkedList<AnnotatedMember> _anySetterField;
 
     /**
      * Method(s) marked with 'JsonValue' annotation
@@ -127,7 +131,7 @@
                     _config.getDefaultVisibilityChecker());
         }
     }
-    
+
     /*
     /**********************************************************
     /* Public API
@@ -194,6 +198,21 @@
         }        
         return null;
     }
+    
+    public AnnotatedMember getAnySetterField()
+    {
+        if (!_collected) {
+            collectAll();
+        }
+        if (_anySetterField != null) {
+            if (_anySetterField.size() > 1) {
+                reportProblem("Multiple 'any-Setters' defined ("+_anySetters.get(0)+" vs "
+                        +_anySetterField.get(1)+")");
+            }
+            return _anySetterField.getFirst();
+        }
+        return null;
+    }
 
     public AnnotatedMethod getAnySetterMethod()
     {
@@ -282,7 +301,11 @@
         // First: gather basic data
         _addFields(props);
         _addMethods(props);
-        _addCreators(props);
+        // 25-Jan-2016, tatu: Avoid introspecting (constructor-)creators for non-static
+        //    inner classes, see [databind#1502]
+        if (!_classDef.isNonStaticInnerClass()) {
+            _addCreators(props);
+        }
         _addInjectables(props);
 
         // Remove ignored properties, first; this MUST precede annotation merging
@@ -293,7 +316,6 @@
         for (POJOPropertyBuilder property : props.values()) {
             property.mergeAnnotations(_forSerialization);
         }
-        
         // and then remove unneeded accessors (wrt read-only, read-write)
         _removeUnwantedAccessor(props);
 
@@ -324,7 +346,6 @@
         // well, almost last: there's still ordering...
         _sortProperties(props);
         _properties = props;
-
         _collected = true;
     }
 
@@ -367,7 +388,8 @@
             } else {
                 pn = ai.findNameForDeserialization(f);
             }
-            boolean nameExplicit = (pn != null);
+            boolean hasName = (pn != null);
+            boolean nameExplicit = hasName;
 
             if (nameExplicit && pn.isEmpty()) { // empty String meaning "use default name", here just means "same as field name"
                 pn = _propNameFromSimple(implName);
@@ -383,9 +405,13 @@
 
             // 13-May-2015, tatu: Moved from earlier place (AnnotatedClass) in 2.6
             if (f.isTransient()) {
-                visible = false;
-                if (transientAsIgnoral) {
-                    ignored = true;
+                // 20-May-2016, tatu: as per [databind#1184] explicit annotation should override
+                //    "default" `transient`
+                if (!hasName) {
+                    visible = false;
+                    if (transientAsIgnoral) {
+                        ignored = true;
+                    }
                 }
             }
             /* [databind#190]: this is the place to prune final fields, if they are not
@@ -396,6 +422,14 @@
             if (pruneFinalFields && (pn == null) && !ignored && Modifier.isFinal(f.getModifiers())) {
                 continue;
             }
+
+            //if field has annotation @JsonAnySetter
+            if(f.hasAnnotation(JsonAnySetter.class)) {
+            	if (_anySetterField == null) {
+            		_anySetterField = new LinkedList<AnnotatedMember>();
+            	}
+            	_anySetterField.add(f);
+            }
             _property(props, implName).addField(f, pn, nameExplicit, visible, ignored);
         }
     }
@@ -406,22 +440,23 @@
     protected void _addCreators(Map<String, POJOPropertyBuilder> props)
     {
         // can be null if annotation processing is disabled...
-        if (_annotationIntrospector != null) {
-            for (AnnotatedConstructor ctor : _classDef.getConstructors()) {
-                if (_creatorProperties == null) {
-                    _creatorProperties = new LinkedList<POJOPropertyBuilder>();
-                }
-                for (int i = 0, len = ctor.getParameterCount(); i < len; ++i) {
-                    _addCreatorParam(props, ctor.getParameter(i));
-                }
+        if (_annotationIntrospector == null) {
+            return;
+        }
+        for (AnnotatedConstructor ctor : _classDef.getConstructors()) {
+            if (_creatorProperties == null) {
+                _creatorProperties = new LinkedList<POJOPropertyBuilder>();
             }
-            for (AnnotatedMethod factory : _classDef.getStaticMethods()) {
-                if (_creatorProperties == null) {
-                    _creatorProperties = new LinkedList<POJOPropertyBuilder>();
-                }
-                for (int i = 0, len = factory.getParameterCount(); i < len; ++i) {
-                    _addCreatorParam(props, factory.getParameter(i));
-                }
+            for (int i = 0, len = ctor.getParameterCount(); i < len; ++i) {
+                _addCreatorParam(props, ctor.getParameter(i));
+            }
+        }
+        for (AnnotatedMethod factory : _classDef.getStaticMethods()) {
+            if (_creatorProperties == null) {
+                _creatorProperties = new LinkedList<POJOPropertyBuilder>();
+            }
+            for (int i = 0, len = factory.getParameterCount(); i < len; ++i) {
+                _addCreatorParam(props, factory.getParameter(i));
             }
         }
     }
@@ -656,7 +691,6 @@
     protected void _removeUnwantedProperties(Map<String, POJOPropertyBuilder> props)
     {
         Iterator<POJOPropertyBuilder> it = props.values().iterator();
-
         while (it.hasNext()) {
             POJOPropertyBuilder prop = it.next();
 
@@ -694,10 +728,14 @@
 
         while (it.hasNext()) {
             POJOPropertyBuilder prop = it.next();
-            prop.removeNonVisible(inferMutators);
+            // 26-Jan-2017, tatu: [databind#935]: need to denote removal of
+            Access acc = prop.removeNonVisible(inferMutators);
+            if (!_forSerialization && (acc == Access.READ_ONLY)) {
+                _collectIgnorals(prop.getName());
+            }
         }
     }
-        
+
     /**
      * Helper method called to add explicitly ignored properties to a list
      * of known ignored properties; this helps in proper reporting of
@@ -886,8 +924,8 @@
     {
         // Then how about explicit ordering?
         AnnotationIntrospector intr = _annotationIntrospector;
-        boolean sort;
         Boolean alpha = (intr == null) ? null : intr.findSerializationSortAlphabetically((Annotated) _classDef);
+        boolean sort;
         
         if (alpha == null) {
             sort = _config.shouldSortPropertiesAlphabetically();
@@ -917,7 +955,7 @@
         if (propertyOrder != null) {
             for (String name : propertyOrder) {
                 POJOPropertyBuilder w = all.get(name);
-                if (w == null) { // also, as per [JACKSON-268], we will allow use of "implicit" names
+                if (w == null) { // will also allow use of "implicit" names for sorting
                     for (POJOPropertyBuilder prop : props.values()) {
                         if (name.equals(prop.getInternalName())) {
                             w = prop;
@@ -951,7 +989,12 @@
                 cr = _creatorProperties;
             }
             for (POJOPropertyBuilder prop : cr) {
-                ordered.put(prop.getName(), prop);
+                // 16-Jan-2016, tatu: Related to [databind#1317], make sure not to accidentally
+                //    add back pruned creator properties!
+                String name = prop.getName();
+                if (all.containsKey(name)) {
+                    ordered.put(name, prop);
+                }
             }
         }
         // And finally whatever is left (trying to put again will not change ordering)
diff --git a/src/main/java/com/fasterxml/jackson/databind/introspect/POJOPropertyBuilder.java b/src/main/java/com/fasterxml/jackson/databind/introspect/POJOPropertyBuilder.java
index 62bcb5e..7cee780 100644
--- a/src/main/java/com/fasterxml/jackson/databind/introspect/POJOPropertyBuilder.java
+++ b/src/main/java/com/fasterxml/jackson/databind/introspect/POJOPropertyBuilder.java
@@ -40,9 +40,9 @@
     protected final PropertyName _internalName;
 
     protected Linked<AnnotatedField> _fields;
-    
+
     protected Linked<AnnotatedParameter> _ctorParameters;
-    
+
     protected Linked<AnnotatedMethod> _getters;
 
     protected Linked<AnnotatedMethod> _setters;
@@ -167,7 +167,11 @@
         return _anyExplicits(_fields)
                 || _anyExplicits(_getters)
                 || _anyExplicits(_setters)
-                || _anyExplicits(_ctorParameters)
+                // 16-Jan-2016, tatu: Creator names are special, in that name should exist too;
+                //   reason for this is [databind#1317]. Let's hope this works well, may need
+                //   to tweak further if this lowers visibility
+//                || _anyExplicits(_ctorParameters)
+                || _anyExplicitNames(_ctorParameters)
                 ;
     }
 
@@ -316,9 +320,9 @@
                     continue;
                 }
             }
-            
-            throw new IllegalArgumentException("Conflicting setter definitions for property \""+getName()+"\": "
-                    +curr.value.getFullName()+" vs "+next.value.getFullName());
+            throw new IllegalArgumentException(String.format(
+ "Conflicting setter definitions for property \"%s\": %s vs %s",
+ getName(), curr.value.getFullName(), next.value.getFullName()));
         }
         // One more thing; to avoid having to do it again...
         _setters = curr.withoutNext();
@@ -496,17 +500,16 @@
             return (desc == null) ? PropertyMetadata.STD_REQUIRED_OR_OPTIONAL
                     : PropertyMetadata.STD_REQUIRED_OR_OPTIONAL.withDescription(desc);
         }
-        return PropertyMetadata.construct(b.booleanValue(), desc, idx, def);
+        return PropertyMetadata.construct(b, desc, idx, def);
     }
 
     protected Boolean _findRequired() {
-        Boolean b = fromMemberAnnotations(new WithMember<Boolean>() {
+       return fromMemberAnnotations(new WithMember<Boolean>() {
             @Override
             public Boolean withMember(AnnotatedMember member) {
                 return _annotationIntrospector.hasRequiredMarker(member);
             }
         });
-        return b;
     }
     
     protected String _findDescription() {
@@ -552,14 +555,14 @@
 
     @Override
     public JsonInclude.Value findInclusion() {
-        if (_annotationIntrospector != null) {
-            AnnotatedMember a = getAccessor();
-            JsonInclude.Value v =  _annotationIntrospector.findPropertyInclusion(a);
-            if (v != null) {
-                return v;
-            }
-        }
-        return JsonInclude.Value.empty();
+        AnnotatedMember a = getAccessor();
+        // 16-Apr-2106, tatu: Let's include per-type default inclusion too
+        // 17-Aug-2016, tatu: Do NOT include global, or per-type defaults, because
+        //    not all of this information (specifically, enclosing type's settings)
+        //    is available here
+        JsonInclude.Value v = (_annotationIntrospector == null) ?
+                null : _annotationIntrospector.findPropertyInclusion(a);
+        return (v == null) ? JsonInclude.Value.empty() : v;
     }
 
     public JsonProperty.Access findAccess() {
@@ -638,7 +641,7 @@
      * @param inferMutators Whether mutators can be "pulled in" by visible
      *    accessors or not. 
      */
-    public void removeNonVisible(boolean inferMutators)
+    public JsonProperty.Access removeNonVisible(boolean inferMutators)
     {
         /* 07-Jun-2015, tatu: With 2.6, we will allow optional definition
          *  of explicit access type for property; if not "AUTO", it will
@@ -668,7 +671,7 @@
             }
             break;
         default:
-        case AUTO: // the default case: base it imply on visibility
+        case AUTO: // the default case: base it on visibility
             _getters = _removeNonVisible(_getters);
             _ctorParameters = _removeNonVisible(_ctorParameters);
     
@@ -677,6 +680,7 @@
                 _setters = _removeNonVisible(_setters);
             }
         }
+        return acc;
     }
 
     /**
diff --git a/src/main/java/com/fasterxml/jackson/databind/introspect/VirtualAnnotatedMember.java b/src/main/java/com/fasterxml/jackson/databind/introspect/VirtualAnnotatedMember.java
index 06713d9..13038f0 100644
--- a/src/main/java/com/fasterxml/jackson/databind/introspect/VirtualAnnotatedMember.java
+++ b/src/main/java/com/fasterxml/jackson/databind/introspect/VirtualAnnotatedMember.java
@@ -17,7 +17,10 @@
 
     protected final Class<?> _declaringClass;
 
-    protected final Class<?> _rawType;
+    /**
+     * @since 2.8 with this signature; had <code>_rawType</code> earlier
+     */
+    protected final JavaType _type;
 
     protected final String _name;
 
@@ -28,14 +31,23 @@
      */
 
     public VirtualAnnotatedMember(TypeResolutionContext typeContext, Class<?> declaringClass,
-            String name, Class<?> rawType)
+            String name, JavaType type)
     {
         super(typeContext, /* AnnotationMap*/ null);
         _declaringClass = declaringClass;
-        _rawType = rawType;
+        _type = type;
         _name = name;
     }
 
+    /**
+     * @deprecated Since 2.8
+     */
+    @Deprecated
+    public VirtualAnnotatedMember(TypeResolutionContext typeContext, Class<?> declaringClass,
+            String name, Class<?> rawType) {
+        this(typeContext, declaringClass, name, typeContext.resolveType(rawType));
+    }
+
     @Override
     public Annotated withAnnotations(AnnotationMap fallback) {
         return this;
@@ -58,12 +70,12 @@
 
     @Override
     public Class<?> getRawType() {
-        return _rawType;
+        return _type.getRawClass();
     }
 
     @Override
     public JavaType getType() {
-        return _typeContext.resolveType(_rawType);
+        return _type;
     }
 
     /*
diff --git a/src/main/java/com/fasterxml/jackson/databind/introspect/VisibilityChecker.java b/src/main/java/com/fasterxml/jackson/databind/introspect/VisibilityChecker.java
index 0a55496..0e2d0ad 100644
--- a/src/main/java/com/fasterxml/jackson/databind/introspect/VisibilityChecker.java
+++ b/src/main/java/com/fasterxml/jackson/databind/introspect/VisibilityChecker.java
@@ -241,11 +241,11 @@
         {
             Std curr = this;
             if (ann != null) {
-        	    curr = curr.withGetterVisibility(ann.getterVisibility());
-        	    curr = curr.withIsGetterVisibility(ann.isGetterVisibility());
-                    curr  = curr.withSetterVisibility(ann.setterVisibility());
-                    curr = curr.withCreatorVisibility(ann.creatorVisibility());
-                    curr = curr.withFieldVisibility(ann.fieldVisibility());
+                curr = curr.withGetterVisibility(ann.getterVisibility());
+                curr = curr.withIsGetterVisibility(ann.isGetterVisibility());
+                curr  = curr.withSetterVisibility(ann.setterVisibility());
+                curr = curr.withCreatorVisibility(ann.creatorVisibility());
+                curr = curr.withFieldVisibility(ann.fieldVisibility());
             }
             return curr;
         }
diff --git a/src/main/java/com/fasterxml/jackson/databind/jsontype/SubtypeResolver.java b/src/main/java/com/fasterxml/jackson/databind/jsontype/SubtypeResolver.java
index 71eeab1..e4953ca 100644
--- a/src/main/java/com/fasterxml/jackson/databind/jsontype/SubtypeResolver.java
+++ b/src/main/java/com/fasterxml/jackson/databind/jsontype/SubtypeResolver.java
@@ -120,9 +120,11 @@
      *   instead.
      */
     @Deprecated
-    public abstract Collection<NamedType> collectAndResolveSubtypes(AnnotatedMember property,
-            MapperConfig<?> config, AnnotationIntrospector ai, JavaType baseType);
-    
+    public Collection<NamedType> collectAndResolveSubtypes(AnnotatedMember property,
+            MapperConfig<?> config, AnnotationIntrospector ai, JavaType baseType) {
+        return collectAndResolveSubtypesByClass(config, property, baseType);
+    }
+
     /**
      * @deprecated Since 2.6 Use either
      *   {@link #collectAndResolveSubtypesByClass(MapperConfig, AnnotatedClass)}
@@ -130,6 +132,8 @@
      *   instead.
      */
     @Deprecated
-    public abstract Collection<NamedType> collectAndResolveSubtypes(AnnotatedClass baseType,
-            MapperConfig<?> config, AnnotationIntrospector ai);
+    public Collection<NamedType> collectAndResolveSubtypes(AnnotatedClass baseType,
+            MapperConfig<?> config, AnnotationIntrospector ai) {
+        return collectAndResolveSubtypesByClass(config, baseType);
+    }
 }
diff --git a/src/main/java/com/fasterxml/jackson/databind/jsontype/TypeIdResolver.java b/src/main/java/com/fasterxml/jackson/databind/jsontype/TypeIdResolver.java
index 5ea8386..a7e7e94 100644
--- a/src/main/java/com/fasterxml/jackson/databind/jsontype/TypeIdResolver.java
+++ b/src/main/java/com/fasterxml/jackson/databind/jsontype/TypeIdResolver.java
@@ -1,5 +1,7 @@
 package com.fasterxml.jackson.databind.jsontype;
 
+import java.io.IOException;
+
 import com.fasterxml.jackson.annotation.JsonTypeInfo;
 import com.fasterxml.jackson.databind.DatabindContext;
 import com.fasterxml.jackson.databind.JavaType;
@@ -42,7 +44,7 @@
     /* Conversions between types and type ids
     /**********************************************************
      */
-    
+
     /**
      * Method called to serialize type of the type of given value
      * as a String to include in serialized JSON content.
@@ -65,19 +67,12 @@
      */
     public String idFromBaseType();
 
-    // !!! TODO: remove from 2.8
-    /**
-     * @deprecated since 2.5; call {@link #typeFromId(DatabindContext, String)} instead
-     */
-    @Deprecated // since 2.5
-    public JavaType typeFromId(String id);
-
     /**
      * Method called to resolve type from given type identifier.
      * 
-     * @since 2.5 -- but since 2.3 has existed in {@link com.fasterxml.jackson.databind.jsontype.impl.TypeIdResolverBase}
+     * @since 2.5 (throws clause added in 2.8)
      */
-    public JavaType typeFromId(DatabindContext context, String id);
+    public JavaType typeFromId(DatabindContext context, String id) throws IOException;
 
     /**
      * Method called for error-reporting and diagnostics purposes.
@@ -85,7 +80,7 @@
      * @since 2.7 -- but since 2.5 has existed in {@link com.fasterxml.jackson.databind.jsontype.impl.TypeIdResolverBase}
      */
     public String getDescForKnownTypeIds();
-    
+
     /*
     /**********************************************************
     /* Accessors for metadata
diff --git a/src/main/java/com/fasterxml/jackson/databind/jsontype/TypeSerializer.java b/src/main/java/com/fasterxml/jackson/databind/jsontype/TypeSerializer.java
index 3e5373e..09f4be9 100644
--- a/src/main/java/com/fasterxml/jackson/databind/jsontype/TypeSerializer.java
+++ b/src/main/java/com/fasterxml/jackson/databind/jsontype/TypeSerializer.java
@@ -73,9 +73,9 @@
      * 
      * @param value Value that will be serialized, for which type information is
      *   to be written
-     * @param gen Generator to use for writing type information
+     * @param g Generator to use for writing type information
      */
-    public abstract void writeTypePrefixForScalar(Object value, JsonGenerator gen) throws IOException;
+    public abstract void writeTypePrefixForScalar(Object value, JsonGenerator g) throws IOException;
 
     /**
      * Method called to write initial part of type information for given
@@ -86,9 +86,9 @@
      * 
      * @param value Value that will be serialized, for which type information is
      *   to be written
-     * @param gen Generator to use for writing type information
+     * @param g Generator to use for writing type information
      */
-    public abstract void writeTypePrefixForObject(Object value, JsonGenerator gen) throws IOException;
+    public abstract void writeTypePrefixForObject(Object value, JsonGenerator g) throws IOException;
 
     /**
      * Method called to write initial part of type information for given
@@ -99,17 +99,17 @@
      * 
      * @param value Value that will be serialized, for which type information is
      *   to be written
-     * @param gen Generator to use for writing type information
+     * @param g Generator to use for writing type information
      */
-    public abstract void writeTypePrefixForArray(Object value, JsonGenerator gen) throws IOException;
-    
+    public abstract void writeTypePrefixForArray(Object value, JsonGenerator g) throws IOException;
+
     /**
      * Method called after value has been serialized, to close any scopes opened
      * by earlier matching call to {@link #writeTypePrefixForScalar}.
      * Actual action to take may depend on various factors, but has to match with
      * action {@link #writeTypePrefixForScalar} did (close array or object; or do nothing).
      */
-    public abstract void writeTypeSuffixForScalar(Object value, JsonGenerator gen) throws IOException;
+    public abstract void writeTypeSuffixForScalar(Object value, JsonGenerator g) throws IOException;
 
     /**
      * Method called after value has been serialized, to close any scopes opened
@@ -117,7 +117,7 @@
      * It needs to write closing END_OBJECT marker, and any other decoration
      * that needs to be matched.
      */
-    public abstract void writeTypeSuffixForObject(Object value, JsonGenerator gen) throws IOException;
+    public abstract void writeTypeSuffixForObject(Object value, JsonGenerator g) throws IOException;
 
     /**
      * Method called after value has been serialized, to close any scopes opened
@@ -125,15 +125,15 @@
      * It needs to write closing END_ARRAY marker, and any other decoration
      * that needs to be matched.
      */
-    public abstract void writeTypeSuffixForArray(Object value, JsonGenerator gen) throws IOException;
+    public abstract void writeTypeSuffixForArray(Object value, JsonGenerator g) throws IOException;
 
     /**
      * Alternative version of the prefix-for-scalar method, which is given
      * actual type to use (instead of using exact type of the value); typically
      * a super type of actual value type
      */
-    public void writeTypePrefixForScalar(Object value, JsonGenerator gen, Class<?> type) throws IOException {
-        writeTypePrefixForScalar(value, gen);
+    public void writeTypePrefixForScalar(Object value, JsonGenerator g, Class<?> type) throws IOException {
+        writeTypePrefixForScalar(value, g);
     }
 
     /**
@@ -141,8 +141,8 @@
      * actual type to use (instead of using exact type of the value); typically
      * a super type of actual value type
      */
-    public void writeTypePrefixForObject(Object value, JsonGenerator gen, Class<?> type) throws IOException {
-        writeTypePrefixForObject(value, gen);
+    public void writeTypePrefixForObject(Object value, JsonGenerator g, Class<?> type) throws IOException {
+        writeTypePrefixForObject(value, g);
     }
 
     /**
@@ -150,8 +150,8 @@
      * actual type to use (instead of using exact type of the value); typically
      * a super type of actual value type
      */
-    public void writeTypePrefixForArray(Object value, JsonGenerator gen, Class<?> type) throws IOException {
-        writeTypePrefixForArray(value, gen);
+    public void writeTypePrefixForArray(Object value, JsonGenerator g, Class<?> type) throws IOException {
+        writeTypePrefixForArray(value, g);
     }
 
     /*
@@ -170,11 +170,11 @@
      * 
      * @param value Value that will be serialized, for which type information is
      *   to be written
-     * @param gen Generator to use for writing type information
+     * @param g Generator to use for writing type information
      * @param typeId Exact type id to use
      */
-    public abstract void writeCustomTypePrefixForScalar(Object value, JsonGenerator gen, String typeId) throws IOException;
-    
+    public abstract void writeCustomTypePrefixForScalar(Object value, JsonGenerator g, String typeId) throws IOException;
+
     /**
      * Method called to write initial part of type information for given
      * value, when it will be output as JSON Object value (not as JSON
@@ -185,16 +185,16 @@
      * 
      * @param value Value that will be serialized, for which type information is
      *   to be written
-     * @param gen Generator to use for writing type information
+     * @param g Generator to use for writing type information
      * @param typeId Exact type id to use
      */
-    public abstract void writeCustomTypePrefixForObject(Object value, JsonGenerator gen, String typeId) throws IOException;
+    public abstract void writeCustomTypePrefixForObject(Object value, JsonGenerator g, String typeId) throws IOException;
     
-    public abstract void writeCustomTypePrefixForArray(Object value, JsonGenerator gen, String typeId) throws IOException;
+    public abstract void writeCustomTypePrefixForArray(Object value, JsonGenerator g, String typeId) throws IOException;
 
-    public abstract void writeCustomTypeSuffixForScalar(Object value, JsonGenerator gen, String typeId) throws IOException;
+    public abstract void writeCustomTypeSuffixForScalar(Object value, JsonGenerator g, String typeId) throws IOException;
 
-    public abstract void writeCustomTypeSuffixForObject(Object value, JsonGenerator gen, String typeId) throws IOException;
+    public abstract void writeCustomTypeSuffixForObject(Object value, JsonGenerator g, String typeId) throws IOException;
 
-    public abstract void writeCustomTypeSuffixForArray(Object value, JsonGenerator gen, String typeId) throws IOException;
+    public abstract void writeCustomTypeSuffixForArray(Object value, JsonGenerator g, String typeId) throws IOException;
 }
diff --git a/src/main/java/com/fasterxml/jackson/databind/jsontype/impl/AsArrayTypeDeserializer.java b/src/main/java/com/fasterxml/jackson/databind/jsontype/impl/AsArrayTypeDeserializer.java
index f5fdb2b..4172c17 100644
--- a/src/main/java/com/fasterxml/jackson/databind/jsontype/impl/AsArrayTypeDeserializer.java
+++ b/src/main/java/com/fasterxml/jackson/databind/jsontype/impl/AsArrayTypeDeserializer.java
@@ -23,8 +23,11 @@
 {
     private static final long serialVersionUID = 1L;
 
+    /**
+     * @since 2.8
+     */
     public AsArrayTypeDeserializer(JavaType bt, TypeIdResolver idRes,
-            String typePropertyName, boolean typeIdVisible, Class<?> defaultImpl)
+            String typePropertyName, boolean typeIdVisible, JavaType defaultImpl)
     {
         super(bt, idRes, typePropertyName, typeIdVisible, defaultImpl);
     }
@@ -104,39 +107,49 @@
             tb.writeStartObject(); // recreate START_OBJECT
             tb.writeFieldName(_typePropertyName);
             tb.writeString(typeId);
-            p = JsonParserSequence.createFlattened(tb.asParser(p), p);
+            // 02-Jul-2016, tatu: Depending on for JsonParserSequence is initialized it may
+            //   try to access current token; ensure there isn't one
+            p.clearCurrentToken();
+            p = JsonParserSequence.createFlattened(false, tb.asParser(p), p);
             p.nextToken();
         }
         Object value = deser.deserialize(p, ctxt);
         // And then need the closing END_ARRAY
         if (hadStartArray && p.nextToken() != JsonToken.END_ARRAY) {
-            throw ctxt.wrongTokenException(p, JsonToken.END_ARRAY,
+            ctxt.reportWrongTokenException(p, JsonToken.END_ARRAY,
                     "expected closing END_ARRAY after type information and deserialized value");
+            // 05-May-2016, tatu: Not 100% what to do if exception is stored for
+            //     future, and not thrown immediately: should probably skip until END_ARRAY
+
+            // ... but for now, fall through
         }
         return value;
     }    
     
-    protected String _locateTypeId(JsonParser jp, DeserializationContext ctxt) throws IOException
+    protected String _locateTypeId(JsonParser p, DeserializationContext ctxt) throws IOException
     {
-        if (!jp.isExpectedStartArrayToken()) {
+        if (!p.isExpectedStartArrayToken()) {
             // Need to allow even more customized handling, if something unexpected seen...
             // but should there be a way to limit this to likely success cases?
             if (_defaultImpl != null) {
                 return _idResolver.idFromBaseType();
             }
-            throw ctxt.wrongTokenException(jp, JsonToken.START_ARRAY, "need JSON Array to contain As.WRAPPER_ARRAY type information for class "+baseTypeName());
+             ctxt.reportWrongTokenException(p, JsonToken.START_ARRAY,
+                     "need JSON Array to contain As.WRAPPER_ARRAY type information for class "+baseTypeName());
+             return null;
         }
         // And then type id as a String
-        JsonToken t = jp.nextToken();
+        JsonToken t = p.nextToken();
         if (t == JsonToken.VALUE_STRING) {
-            String result = jp.getText();
-            jp.nextToken();
+            String result = p.getText();
+            p.nextToken();
             return result;
         }
         if (_defaultImpl != null) {
             return _idResolver.idFromBaseType();
         }
-        throw ctxt.wrongTokenException(jp, JsonToken.VALUE_STRING, "need JSON String that contains type id (for subtype of "+baseTypeName()+")");
+        ctxt.reportWrongTokenException(p, JsonToken.VALUE_STRING, "need JSON String that contains type id (for subtype of "+baseTypeName()+")");
+        return null;
     }
 
     /**
diff --git a/src/main/java/com/fasterxml/jackson/databind/jsontype/impl/AsArrayTypeSerializer.java b/src/main/java/com/fasterxml/jackson/databind/jsontype/impl/AsArrayTypeSerializer.java
index 0291296..adde36e 100644
--- a/src/main/java/com/fasterxml/jackson/databind/jsontype/impl/AsArrayTypeSerializer.java
+++ b/src/main/java/com/fasterxml/jackson/databind/jsontype/impl/AsArrayTypeSerializer.java
@@ -20,7 +20,7 @@
 
     @Override
     public AsArrayTypeSerializer forProperty(BeanProperty prop) {
-        return (_property == prop) ? this : new AsArrayTypeSerializer(this._idResolver, prop);
+        return (_property == prop) ? this : new AsArrayTypeSerializer(_idResolver, prop);
     }
     
     @Override
@@ -33,88 +33,88 @@
      */
     
     @Override
-    public void writeTypePrefixForObject(Object value, JsonGenerator jgen) throws IOException {
+    public void writeTypePrefixForObject(Object value, JsonGenerator g) throws IOException {
         final String typeId = idFromValue(value);
         // NOTE: can not always avoid writing type id, even if null
-        if (jgen.canWriteTypeId()) {
+        if (g.canWriteTypeId()) {
             if (typeId != null) {
-                jgen.writeTypeId(typeId);
+                g.writeTypeId(typeId);
             }
         } else {
-            jgen.writeStartArray();
-            jgen.writeString(typeId);
+            g.writeStartArray();
+            g.writeString(typeId);
         }
-        jgen.writeStartObject();
+        g.writeStartObject();
     }
 
     @Override
-    public void writeTypePrefixForObject(Object value, JsonGenerator jgen, Class<?> type) throws IOException {
+    public void writeTypePrefixForObject(Object value, JsonGenerator g, Class<?> type) throws IOException {
         final String typeId = idFromValueAndType(value, type);
         // NOTE: can not always avoid writing type id, even if null
-        if (jgen.canWriteTypeId()) {
+        if (g.canWriteTypeId()) {
             if (typeId != null) {
-                jgen.writeTypeId(typeId);
+                g.writeTypeId(typeId);
             }
         } else {
-            jgen.writeStartArray();
-            jgen.writeString(typeId);
+            g.writeStartArray();
+            g.writeString(typeId);
         }
-        jgen.writeStartObject();
+        g.writeStartObject();
     }
     
     @Override
-    public void writeTypePrefixForArray(Object value, JsonGenerator jgen) throws IOException {
+    public void writeTypePrefixForArray(Object value, JsonGenerator g) throws IOException {
         final String typeId = idFromValue(value);
-        if (jgen.canWriteTypeId()) {
+        if (g.canWriteTypeId()) {
             if (typeId != null) {
-                jgen.writeTypeId(typeId);
+                g.writeTypeId(typeId);
             }
         } else {
-            jgen.writeStartArray();
-            jgen.writeString(typeId);
+            g.writeStartArray();
+            g.writeString(typeId);
         }
-        jgen.writeStartArray();
+        g.writeStartArray();
     }
 
     @Override
-    public void writeTypePrefixForArray(Object value, JsonGenerator jgen, Class<?> type) throws IOException {
+    public void writeTypePrefixForArray(Object value, JsonGenerator g, Class<?> type) throws IOException {
         final String typeId = idFromValueAndType(value, type);
-        if (jgen.canWriteTypeId()) {
+        if (g.canWriteTypeId()) {
             if (typeId != null) {
-                jgen.writeTypeId(typeId);
+                g.writeTypeId(typeId);
             }
         } else {
-            jgen.writeStartArray();
-            jgen.writeString(typeId);
+            g.writeStartArray();
+            g.writeString(typeId);
         }
-        jgen.writeStartArray();
+        g.writeStartArray();
     }
     
     @Override
-    public void writeTypePrefixForScalar(Object value, JsonGenerator jgen) throws IOException {
+    public void writeTypePrefixForScalar(Object value, JsonGenerator g) throws IOException {
         final String typeId = idFromValue(value);
-        if (jgen.canWriteTypeId()) {
+        if (g.canWriteTypeId()) {
             if (typeId != null) {
-                jgen.writeTypeId(typeId);
+                g.writeTypeId(typeId);
             }
         } else {
             // only need the wrapper array
-            jgen.writeStartArray();
-            jgen.writeString(typeId);
+            g.writeStartArray();
+            g.writeString(typeId);
         }
     }
 
     @Override
-    public void writeTypePrefixForScalar(Object value, JsonGenerator jgen, Class<?> type) throws IOException {
+    public void writeTypePrefixForScalar(Object value, JsonGenerator g, Class<?> type) throws IOException {
         final String typeId = idFromValueAndType(value, type);
-        if (jgen.canWriteTypeId()) {
+        if (g.canWriteTypeId()) {
             if (typeId != null) {
-                jgen.writeTypeId(typeId);
+                g.writeTypeId(typeId);
             }
         } else {
             // only need the wrapper array
-            jgen.writeStartArray();
-            jgen.writeString(typeId);
+            g.writeStartArray();
+            g.writeString(typeId);
         }
     }
 
@@ -125,27 +125,27 @@
      */
     
     @Override
-    public void writeTypeSuffixForObject(Object value, JsonGenerator jgen) throws IOException {
-        jgen.writeEndObject();
-        if (!jgen.canWriteTypeId()) {
-            jgen.writeEndArray();
+    public void writeTypeSuffixForObject(Object value, JsonGenerator g) throws IOException {
+        g.writeEndObject();
+        if (!g.canWriteTypeId()) {
+            g.writeEndArray();
         }
     }
 
     @Override
-    public void writeTypeSuffixForArray(Object value, JsonGenerator jgen) throws IOException {
+    public void writeTypeSuffixForArray(Object value, JsonGenerator g) throws IOException {
         // first array caller needs to close, then wrapper array
-        jgen.writeEndArray();
-        if (!jgen.canWriteTypeId()) {
-            jgen.writeEndArray();
+        g.writeEndArray();
+        if (!g.canWriteTypeId()) {
+            g.writeEndArray();
         }
     }
 
     @Override
-    public void writeTypeSuffixForScalar(Object value, JsonGenerator jgen) throws IOException {
-        if (!jgen.canWriteTypeId()) {
+    public void writeTypeSuffixForScalar(Object value, JsonGenerator g) throws IOException {
+        if (!g.canWriteTypeId()) {
             // just the wrapper array to close
-            jgen.writeEndArray();
+            g.writeEndArray();
         }
     }
     
@@ -156,61 +156,61 @@
      */
 
     @Override
-    public void writeCustomTypePrefixForObject(Object value, JsonGenerator jgen, String typeId) throws IOException {
-        if (jgen.canWriteTypeId()) {
+    public void writeCustomTypePrefixForObject(Object value, JsonGenerator g, String typeId) throws IOException {
+        if (g.canWriteTypeId()) {
             if (typeId != null) {
-                jgen.writeTypeId(typeId);
+                g.writeTypeId(typeId);
             }
         } else {
-            jgen.writeStartArray();
-            jgen.writeString(typeId);
+            g.writeStartArray();
+            g.writeString(typeId);
         }
-        jgen.writeStartObject();
+        g.writeStartObject();
     }
     
     @Override
-    public void writeCustomTypePrefixForArray(Object value, JsonGenerator jgen, String typeId) throws IOException {
-        if (jgen.canWriteTypeId()) {
+    public void writeCustomTypePrefixForArray(Object value, JsonGenerator g, String typeId) throws IOException {
+        if (g.canWriteTypeId()) {
             if (typeId != null) {
-                jgen.writeTypeId(typeId);
+                g.writeTypeId(typeId);
             }
         } else {
-            jgen.writeStartArray();
-            jgen.writeString(typeId);
+            g.writeStartArray();
+            g.writeString(typeId);
         }
-        jgen.writeStartArray();
+        g.writeStartArray();
     }
 
     @Override
-    public void writeCustomTypePrefixForScalar(Object value, JsonGenerator jgen, String typeId) throws IOException {
-        if (jgen.canWriteTypeId()) {
+    public void writeCustomTypePrefixForScalar(Object value, JsonGenerator g, String typeId) throws IOException {
+        if (g.canWriteTypeId()) {
             if (typeId != null) {
-                jgen.writeTypeId(typeId);
+                g.writeTypeId(typeId);
             }
         } else {
-            jgen.writeStartArray();
-            jgen.writeString(typeId);
+            g.writeStartArray();
+            g.writeString(typeId);
         }
     }
 
     @Override
-    public void writeCustomTypeSuffixForObject(Object value, JsonGenerator jgen, String typeId) throws IOException {
-        if (!jgen.canWriteTypeId()) {
-            writeTypeSuffixForObject(value, jgen); // standard impl works fine
+    public void writeCustomTypeSuffixForObject(Object value, JsonGenerator g, String typeId) throws IOException {
+        if (!g.canWriteTypeId()) {
+            writeTypeSuffixForObject(value, g); // standard impl works fine
         }
     }
 
     @Override
-    public void writeCustomTypeSuffixForArray(Object value, JsonGenerator jgen, String typeId) throws IOException {
-        if (!jgen.canWriteTypeId()) {
-            writeTypeSuffixForArray(value, jgen); // standard impl works fine
+    public void writeCustomTypeSuffixForArray(Object value, JsonGenerator g, String typeId) throws IOException {
+        if (!g.canWriteTypeId()) {
+            writeTypeSuffixForArray(value, g); // standard impl works fine
         }
     }
 
     @Override
-    public void writeCustomTypeSuffixForScalar(Object value, JsonGenerator jgen, String typeId) throws IOException {
-        if (!jgen.canWriteTypeId()) {
-            writeTypeSuffixForScalar(value, jgen); // standard impl works fine
+    public void writeCustomTypeSuffixForScalar(Object value, JsonGenerator g, String typeId) throws IOException {
+        if (!g.canWriteTypeId()) {
+            writeTypeSuffixForScalar(value, g); // standard impl works fine
         }
     }
 }
diff --git a/src/main/java/com/fasterxml/jackson/databind/jsontype/impl/AsExistingPropertyTypeSerializer.java b/src/main/java/com/fasterxml/jackson/databind/jsontype/impl/AsExistingPropertyTypeSerializer.java
index 1fc5983..fd10302 100644
--- a/src/main/java/com/fasterxml/jackson/databind/jsontype/impl/AsExistingPropertyTypeSerializer.java
+++ b/src/main/java/com/fasterxml/jackson/databind/jsontype/impl/AsExistingPropertyTypeSerializer.java
@@ -11,52 +11,52 @@
 /**
  * Type serializer used with {@link As#EXISTING_PROPERTY} inclusion mechanism.
  * Expects type information to be a well-defined property on all sub-classes.
- * 
- * @author fleeman (modeled after code by tatus)
  */
 public class AsExistingPropertyTypeSerializer
     extends AsPropertyTypeSerializer
 {
 
-    public AsExistingPropertyTypeSerializer(TypeIdResolver idRes, BeanProperty property, String propName)
+    public AsExistingPropertyTypeSerializer(TypeIdResolver idRes,
+            BeanProperty property, String propName)
     {
         super(idRes, property, propName);
     }
 
     @Override
     public AsExistingPropertyTypeSerializer forProperty(BeanProperty prop) {
-        return (_property == prop) ? this : new AsExistingPropertyTypeSerializer(this._idResolver, prop, this._typePropertyName);
+        return (_property == prop) ? this :
+            new AsExistingPropertyTypeSerializer(_idResolver, prop, _typePropertyName);
     }
     
     @Override
     public As getTypeInclusion() { return As.EXISTING_PROPERTY; }
     
     @Override
-    public void writeTypePrefixForObject(Object value, JsonGenerator jgen) throws IOException
+    public void writeTypePrefixForObject(Object value, JsonGenerator gen) throws IOException
     {
         final String typeId = idFromValue(value);
-        if ((typeId != null) && jgen.canWriteTypeId()) {
-            jgen.writeTypeId(typeId);
+        if ((typeId != null) && gen.canWriteTypeId()) {
+            gen.writeTypeId(typeId);
         }
-        jgen.writeStartObject();
+        gen.writeStartObject();
     }
 
     @Override
-    public void writeTypePrefixForObject(Object value, JsonGenerator jgen, Class<?> type) throws IOException
+    public void writeTypePrefixForObject(Object value, JsonGenerator gen, Class<?> type) throws IOException
     {
         final String typeId = idFromValueAndType(value, type);
-        if ((typeId != null) && jgen.canWriteTypeId()) {
-            jgen.writeTypeId(typeId);
+        if ((typeId != null) && gen.canWriteTypeId()) {
+            gen.writeTypeId(typeId);
         }
-        jgen.writeStartObject();
+        gen.writeStartObject();
     }
     
     @Override
-    public void writeCustomTypePrefixForObject(Object value, JsonGenerator jgen, String typeId) throws IOException
+    public void writeCustomTypePrefixForObject(Object value, JsonGenerator gen, String typeId) throws IOException
     {
-        if ((typeId != null) && jgen.canWriteTypeId()) {
-            jgen.writeTypeId(typeId);
+        if ((typeId != null) && gen.canWriteTypeId()) {
+            gen.writeTypeId(typeId);
         }
-        jgen.writeStartObject();
+        gen.writeStartObject();
     }
 }
diff --git a/src/main/java/com/fasterxml/jackson/databind/jsontype/impl/AsExternalTypeDeserializer.java b/src/main/java/com/fasterxml/jackson/databind/jsontype/impl/AsExternalTypeDeserializer.java
index 3bd4539..c6b8d49 100644
--- a/src/main/java/com/fasterxml/jackson/databind/jsontype/impl/AsExternalTypeDeserializer.java
+++ b/src/main/java/com/fasterxml/jackson/databind/jsontype/impl/AsExternalTypeDeserializer.java
@@ -19,13 +19,17 @@
 {
     private static final long serialVersionUID = 1L;
 
+    /**
+     * @since 2.8
+     */
     public AsExternalTypeDeserializer(JavaType bt, TypeIdResolver idRes,
-            String typePropertyName, boolean typeIdVisible, Class<?> defaultImpl)
+            String typePropertyName, boolean typeIdVisible, JavaType defaultImpl)
     {
         super(bt, idRes, typePropertyName, typeIdVisible, defaultImpl);
     }
 
-    public AsExternalTypeDeserializer(AsExternalTypeDeserializer src, BeanProperty property) {
+    public AsExternalTypeDeserializer(AsExternalTypeDeserializer src,
+            BeanProperty property) {
         super(src, property);
     }
     
diff --git a/src/main/java/com/fasterxml/jackson/databind/jsontype/impl/AsPropertyTypeDeserializer.java b/src/main/java/com/fasterxml/jackson/databind/jsontype/impl/AsPropertyTypeDeserializer.java
index 101d842..daf3271 100644
--- a/src/main/java/com/fasterxml/jackson/databind/jsontype/impl/AsPropertyTypeDeserializer.java
+++ b/src/main/java/com/fasterxml/jackson/databind/jsontype/impl/AsPropertyTypeDeserializer.java
@@ -24,14 +24,20 @@
 
     protected final As _inclusion;
 
+    /**
+     * @since 2.8
+     */
     public AsPropertyTypeDeserializer(JavaType bt, TypeIdResolver idRes,
-            String typePropertyName, boolean typeIdVisible, Class<?> defaultImpl)
+            String typePropertyName, boolean typeIdVisible, JavaType defaultImpl)
     {
         this(bt, idRes, typePropertyName, typeIdVisible, defaultImpl, As.PROPERTY);
     }
     
+    /**
+     * @since 2.8
+     */
     public AsPropertyTypeDeserializer(JavaType bt, TypeIdResolver idRes,
-            String typePropertyName, boolean typeIdVisible, Class<?> defaultImpl,
+            String typePropertyName, boolean typeIdVisible, JavaType defaultImpl,
             As inclusion)
     {
         super(bt, idRes, typePropertyName, typeIdVisible, defaultImpl);
@@ -112,7 +118,10 @@
             tb.writeString(typeId);
         }
         if (tb != null) { // need to put back skipped properties?
-            p = JsonParserSequence.createFlattened(tb.asParser(p), p);
+            // 02-Jul-2016, tatu: Depending on for JsonParserSequence is initialized it may
+            //   try to access current token; ensure there isn't one
+            p.clearCurrentToken();
+            p = JsonParserSequence.createFlattened(false, tb.asParser(p), p);
         }
         // Must point to the next value; tb had no current, jp pointed to VALUE_STRING:
         p.nextToken(); // to skip past String value
@@ -122,7 +131,8 @@
     
     // off-lined to keep main method lean and mean...
     @SuppressWarnings("resource")
-    protected Object _deserializeTypedUsingDefaultImpl(JsonParser p, DeserializationContext ctxt, TokenBuffer tb) throws IOException
+    protected Object _deserializeTypedUsingDefaultImpl(JsonParser p, DeserializationContext ctxt,
+            TokenBuffer tb) throws IOException
     {
         // As per [JACKSON-614], may have default implementation to use
         JsonDeserializer<Object> deser = _findDefaultImplDeserializer(ctxt);
@@ -141,11 +151,20 @@
             return result;
         }
         // or, something for which "as-property" won't work, changed into "wrapper-array" type:
-        if (p.getCurrentToken() == JsonToken.START_ARRAY) {
+        if (p.isExpectedStartArrayToken()) {
             return super.deserializeTypedFromAny(p, ctxt);
         }
-        throw ctxt.wrongTokenException(p, JsonToken.FIELD_NAME,
+        if (p.hasToken(JsonToken.VALUE_STRING)) {
+            if (ctxt.isEnabled(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT)) {
+                String str = p.getText().trim();
+                if (str.isEmpty()) {
+                    return null;
+                }
+            }
+        }
+        ctxt.reportWrongTokenException(p, JsonToken.FIELD_NAME,
                 "missing property '"+_typePropertyName+"' that is to contain type id  (for class "+baseTypeName()+")");
+        return null;
     }
 
     /* Also need to re-route "unknown" version. Need to think
diff --git a/src/main/java/com/fasterxml/jackson/databind/jsontype/impl/AsWrapperTypeDeserializer.java b/src/main/java/com/fasterxml/jackson/databind/jsontype/impl/AsWrapperTypeDeserializer.java
index 8904b73..02f26ca 100644
--- a/src/main/java/com/fasterxml/jackson/databind/jsontype/impl/AsWrapperTypeDeserializer.java
+++ b/src/main/java/com/fasterxml/jackson/databind/jsontype/impl/AsWrapperTypeDeserializer.java
@@ -23,8 +23,11 @@
 {
     private static final long serialVersionUID = 1L;
 
+    /**
+     * @since 2.8
+     */
     public AsWrapperTypeDeserializer(JavaType bt, TypeIdResolver idRes,
-            String typePropertyName, boolean typeIdVisible, Class<?> defaultImpl)
+            String typePropertyName, boolean typeIdVisible, JavaType defaultImpl)
     {
         super(bt, idRes, typePropertyName, typeIdVisible, defaultImpl);
     }
@@ -90,11 +93,11 @@
         if (t == JsonToken.START_OBJECT) {
             // should always get field name, but just in case...
             if (p.nextToken() != JsonToken.FIELD_NAME) {
-                throw ctxt.wrongTokenException(p, JsonToken.FIELD_NAME,
+                ctxt.reportWrongTokenException(p, JsonToken.FIELD_NAME,
                         "need JSON String that contains type id (for subtype of "+baseTypeName()+")");
             }
         } else if (t != JsonToken.FIELD_NAME) {
-            throw ctxt.wrongTokenException(p, JsonToken.START_OBJECT,
+            ctxt.reportWrongTokenException(p, JsonToken.START_OBJECT,
                     "need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName());
         }
         final String typeId = p.getText();
@@ -108,14 +111,17 @@
             tb.writeStartObject(); // recreate START_OBJECT
             tb.writeFieldName(_typePropertyName);
             tb.writeString(typeId);
-            p = JsonParserSequence.createFlattened(tb.asParser(p), p);
+            // 02-Jul-2016, tatu: Depending on for JsonParserSequence is initialized it may
+            //   try to access current token; ensure there isn't one
+            p.clearCurrentToken();
+            p = JsonParserSequence.createFlattened(false, tb.asParser(p), p);
             p.nextToken();
         }
         
         Object value = deser.deserialize(p, ctxt);
         // And then need the closing END_OBJECT
         if (p.nextToken() != JsonToken.END_OBJECT) {
-            throw ctxt.wrongTokenException(p, JsonToken.END_OBJECT,
+            ctxt.reportWrongTokenException(p, JsonToken.END_OBJECT,
                     "expected closing END_OBJECT after type information and deserialized value");
         }
         return value;
diff --git a/src/main/java/com/fasterxml/jackson/databind/jsontype/impl/AsWrapperTypeSerializer.java b/src/main/java/com/fasterxml/jackson/databind/jsontype/impl/AsWrapperTypeSerializer.java
index 647d031..feab592 100644
--- a/src/main/java/com/fasterxml/jackson/databind/jsontype/impl/AsWrapperTypeSerializer.java
+++ b/src/main/java/com/fasterxml/jackson/databind/jsontype/impl/AsWrapperTypeSerializer.java
@@ -24,7 +24,7 @@
 
     @Override
     public AsWrapperTypeSerializer forProperty(BeanProperty prop) {
-        return (_property == prop) ? this : new AsWrapperTypeSerializer(this._idResolver, prop);
+        return (_property == prop) ? this : new AsWrapperTypeSerializer(_idResolver, prop);
     }
     
     @Override
diff --git a/src/main/java/com/fasterxml/jackson/databind/jsontype/impl/ClassNameIdResolver.java b/src/main/java/com/fasterxml/jackson/databind/jsontype/impl/ClassNameIdResolver.java
index 0dd48d2..2b3da1a 100644
--- a/src/main/java/com/fasterxml/jackson/databind/jsontype/impl/ClassNameIdResolver.java
+++ b/src/main/java/com/fasterxml/jackson/databind/jsontype/impl/ClassNameIdResolver.java
@@ -1,13 +1,10 @@
 package com.fasterxml.jackson.databind.jsontype.impl;
 
+import java.io.IOException;
 import java.util.*;
 
 import com.fasterxml.jackson.annotation.JsonTypeInfo;
-import com.fasterxml.jackson.databind.DatabindContext;
-import com.fasterxml.jackson.databind.DeserializationConfig;
-import com.fasterxml.jackson.databind.DeserializationFeature;
-import com.fasterxml.jackson.databind.JavaType;
-import com.fasterxml.jackson.databind.cfg.MapperConfig;
+import com.fasterxml.jackson.databind.*;
 import com.fasterxml.jackson.databind.type.TypeFactory;
 import com.fasterxml.jackson.databind.util.ClassUtil;
 
@@ -19,6 +16,8 @@
 public class ClassNameIdResolver
     extends TypeIdResolverBase
 {
+    private final static String JAVA_UTIL_PKG = "java.util.";
+
     public ClassNameIdResolver(JavaType baseType, TypeFactory typeFactory) {
         super(baseType, typeFactory);
     }
@@ -32,51 +31,52 @@
     
     @Override
     public String idFromValue(Object value) {
-        return _idFrom(value, value.getClass());
+        return _idFrom(value, value.getClass(), _typeFactory);
     }
 
     @Override
     public String idFromValueAndType(Object value, Class<?> type) {
-        return _idFrom(value, type);
-    }
-
-    @Deprecated // since 2.3
-    @Override
-    public JavaType typeFromId(String id) {
-        return _typeFromId(id, null);
+        return _idFrom(value, type, _typeFactory);
     }
 
     @Override
-    public JavaType typeFromId(DatabindContext context, String id) {
+    public JavaType typeFromId(DatabindContext context, String id) throws IOException {
         return _typeFromId(id, context);
     }
 
-    protected JavaType _typeFromId(String id, DatabindContext ctxt)
+    protected JavaType _typeFromId(String id, DatabindContext ctxt) throws IOException
     {
         /* 30-Jan-2010, tatu: Most ids are basic class names; so let's first
          *    check if any generics info is added; and only then ask factory
          *    to do translation when necessary
          */
-        TypeFactory tf = (ctxt == null) ? _typeFactory : ctxt.getTypeFactory();
+        TypeFactory tf = ctxt.getTypeFactory();
         if (id.indexOf('<') > 0) {
-            JavaType t = tf.constructFromCanonical(id);
             // note: may want to try combining with specialization (esp for EnumMap)?
+            // 17-Aug-2017, tatu: As per [databind#1735] need to ensure assignment
+            //    compatibility -- needed later anyway, and not doing so may open
+            //    security issues.
+            JavaType t = tf.constructFromCanonical(id);
+            if (!t.isTypeOrSubTypeOf(_baseType.getRawClass())) {
+                // Probably cleaner to have a method in `TypeFactory` but can't add in patch
+                throw new IllegalArgumentException(String.format(
+                        "Class %s not subtype of %s", t.getRawClass().getName(), _baseType));
+            }
             return t;
         }
         Class<?> cls;
         try {
             cls =  tf.findClass(id);
         } catch (ClassNotFoundException e) {
-            // 24-May-2016, tatu: Ok, this is supremely ugly, from multiple persepctives.
-            //    But fixes [databind#1098], so has to do for now.
-            MapperConfig<?> cfg = ctxt.getConfig();
-            if (cfg instanceof DeserializationConfig) {
-                DeserializationConfig dc = (DeserializationConfig) cfg;
-                if (!dc.isEnabled(DeserializationFeature.FAIL_ON_INVALID_SUBTYPE)) {
-                    return null;
-                }
+            // 24-May-2016, tatu: Ok, this is pretty ugly, but we should always get
+            //   DeserializationContext, just playing it safe
+            if (ctxt instanceof DeserializationContext) {
+                DeserializationContext dctxt = (DeserializationContext) ctxt;
+                // First: we may have problem handlers that can deal with it?
+                return dctxt.handleUnknownTypeId(_baseType, id, this, "no such class found");
             }
-            throw new IllegalArgumentException("Invalid type id '"+id+"' (for id type 'Id.class'): no such class found");
+            // ... meaning that we really should never get here.
+            return null;
         } catch (Exception e) {
             throw new IllegalArgumentException("Invalid type id '"+id+"' (for id type 'Id.class'): "+e.getMessage(), e);
         }
@@ -88,8 +88,8 @@
     /* Internal methods
     /**********************************************************
      */
-    
-    protected final String _idFrom(Object value, Class<?> cls)
+
+    protected String _idFrom(Object value, Class<?> cls, TypeFactory typeFactory)
     {
         // Need to ensure that "enum subtypes" work too
         if (Enum.class.isAssignableFrom(cls)) {
@@ -98,8 +98,8 @@
             }
         }
         String str = cls.getName();
-        if (str.startsWith("java.util")) {
-            // 25-Jan-2009, tatu: There are some internal classes that we can not access as is.
+        if (str.startsWith(JAVA_UTIL_PKG)) {
+            // 25-Jan-2009, tatu: There are some internal classes that we cannot access as is.
             //     We need better mechanism; for now this has to do...
 
             // Enum sets and maps are problematic since we MUST know type of
@@ -108,27 +108,27 @@
             if (value instanceof EnumSet<?>) { // Regular- and JumboEnumSet...
                 Class<?> enumClass = ClassUtil.findEnumType((EnumSet<?>) value);
                 // not optimal: but EnumSet is not a customizable type so this is sort of ok
-               str = _typeFactory.constructCollectionType(EnumSet.class, enumClass).toCanonical();
+               str = typeFactory.constructCollectionType(EnumSet.class, enumClass).toCanonical();
             } else if (value instanceof EnumMap<?,?>) {
                 Class<?> enumClass = ClassUtil.findEnumType((EnumMap<?,?>) value);
                 Class<?> valueClass = Object.class;
                 // not optimal: but EnumMap is not a customizable type so this is sort of ok
-                str = _typeFactory.constructMapType(EnumMap.class, enumClass, valueClass).toCanonical();
+                str = typeFactory.constructMapType(EnumMap.class, enumClass, valueClass).toCanonical();
             } else {
-                String end = str.substring(9);
-                if ((end.startsWith(".Arrays$") || end.startsWith(".Collections$"))
-                       && str.indexOf("List") >= 0) {
-                    /* 17-Feb-2010, tatus: Another such case: result of
-                     *    Arrays.asList() is named like so in Sun JDK...
-                     *   Let's just plain old ArrayList in its place
-                     * NOTE: chances are there are plenty of similar cases
-                     * for other wrappers... (immutable, singleton, synced etc)
-                     */
-                    str = "java.util.ArrayList";
+                // 17-Feb-2010, tatus: Another such case: result of Arrays.asList() is
+                // named like so in Sun JDK... Let's just plain old ArrayList in its place.
+                // ... also, other similar cases exist...
+                String suffix = str.substring(JAVA_UTIL_PKG.length());
+                if (isJavaUtilCollectionClass(suffix, "List")) {
+                    str = ArrayList.class.getName();
+                } else if (isJavaUtilCollectionClass(suffix, "Map")){
+                    str = HashMap.class.getName();
+                } else if (isJavaUtilCollectionClass(suffix, "Set")){
+                    str = HashSet.class.getName();
                 }
             }
         } else if (str.indexOf('$') >= 0) {
-            /* Other special handling may be needed for inner classes, [JACKSON-584].
+            /* Other special handling may be needed for inner classes,
              * The best way to handle would be to find 'hidden' constructor; pass parent
              * value etc (which is actually done for non-anonymous static classes!),
              * but that is just not possible due to various things. So, we will instead
@@ -137,10 +137,8 @@
              */
             Class<?> outer = ClassUtil.getOuterClass(cls);
             if (outer != null) {
-                /* one more check: let's actually not worry if the declared
-                 * static type is non-static as well; if so, deserializer does
-                 * have a chance at figuring it all out.
-                 */
+                // one more check: let's actually not worry if the declared static type is
+                // non-static as well; if so, deserializer does have a chance at figuring it all out.
                 Class<?> staticType = _baseType.getRawClass();
                 if (ClassUtil.getOuterClass(staticType) == null) {
                     // Is this always correct? Seems like it should be...
@@ -156,4 +154,17 @@
     public String getDescForKnownTypeIds() {
         return "class name used as type id";
     }
+
+    private static boolean isJavaUtilCollectionClass(String clz, String type)
+    {
+        if (clz.startsWith("Collections$")) {
+            // 02-Jan-2017, tatu: As per [databind#1868], may need to leave Unmodifiable variants as is
+            return (clz.indexOf(type) > 0)
+                    && !clz.contains("Unmodifiable");
+        }
+        if (clz.startsWith("Arrays$")) {
+            return (clz.indexOf(type) > 0);
+        }
+        return false;
+    }
 }
diff --git a/src/main/java/com/fasterxml/jackson/databind/jsontype/impl/MinimalClassNameIdResolver.java b/src/main/java/com/fasterxml/jackson/databind/jsontype/impl/MinimalClassNameIdResolver.java
index 5ff070f..d208c30 100644
--- a/src/main/java/com/fasterxml/jackson/databind/jsontype/impl/MinimalClassNameIdResolver.java
+++ b/src/main/java/com/fasterxml/jackson/databind/jsontype/impl/MinimalClassNameIdResolver.java
@@ -1,5 +1,7 @@
 package com.fasterxml.jackson.databind.jsontype.impl;
 
+import java.io.IOException;
+
 import com.fasterxml.jackson.annotation.JsonTypeInfo;
 import com.fasterxml.jackson.databind.DatabindContext;
 import com.fasterxml.jackson.databind.JavaType;
@@ -49,7 +51,7 @@
     }
 
     @Override
-    protected JavaType _typeFromId(String id, DatabindContext ctxt)
+    protected JavaType _typeFromId(String id, DatabindContext ctxt) throws IOException
     {
         if (id.startsWith(".")) {
             StringBuilder sb = new StringBuilder(id.length() + _basePackageName.length());
diff --git a/src/main/java/com/fasterxml/jackson/databind/jsontype/impl/StdSubtypeResolver.java b/src/main/java/com/fasterxml/jackson/databind/jsontype/impl/StdSubtypeResolver.java
index be39306..0158215 100644
--- a/src/main/java/com/fasterxml/jackson/databind/jsontype/impl/StdSubtypeResolver.java
+++ b/src/main/java/com/fasterxml/jackson/databind/jsontype/impl/StdSubtypeResolver.java
@@ -97,7 +97,7 @@
     {
         final AnnotationIntrospector ai = config.getAnnotationIntrospector();
         HashMap<NamedType, NamedType> subtypes = new HashMap<NamedType, NamedType>();
-        // [JACKSON-257] then consider registered subtypes (which have precedence over annotations)
+        // then consider registered subtypes (which have precedence over annotations)
         if (_registeredSubtypes != null) {
             Class<?> rawBase = type.getRawType();
             for (NamedType subtype : _registeredSubtypes) {
@@ -183,28 +183,6 @@
 
     /*
     /**********************************************************
-    /* Deprecated method overrides
-    /**********************************************************
-     */
-
-    @Override
-    @Deprecated
-    public Collection<NamedType> collectAndResolveSubtypes(AnnotatedMember property,
-        MapperConfig<?> config, AnnotationIntrospector ai, JavaType baseType)
-    {
-        return collectAndResolveSubtypesByClass(config, property, baseType);
-    }
-
-    @Override
-    @Deprecated
-    public Collection<NamedType> collectAndResolveSubtypes(AnnotatedClass type,
-            MapperConfig<?> config, AnnotationIntrospector ai)
-    {
-        return collectAndResolveSubtypesByClass(config, type);
-    }
-
-    /*
-    /**********************************************************
     /* Internal methods
     /**********************************************************
      */
diff --git a/src/main/java/com/fasterxml/jackson/databind/jsontype/impl/StdTypeResolverBuilder.java b/src/main/java/com/fasterxml/jackson/databind/jsontype/impl/StdTypeResolverBuilder.java
index 1372a67..e5a3e4d 100644
--- a/src/main/java/com/fasterxml/jackson/databind/jsontype/impl/StdTypeResolverBuilder.java
+++ b/src/main/java/com/fasterxml/jackson/databind/jsontype/impl/StdTypeResolverBuilder.java
@@ -3,13 +3,11 @@
 import java.util.Collection;
 
 import com.fasterxml.jackson.annotation.JsonTypeInfo;
+
 import com.fasterxml.jackson.databind.*;
+import com.fasterxml.jackson.databind.annotation.NoClass;
 import com.fasterxml.jackson.databind.cfg.MapperConfig;
-import com.fasterxml.jackson.databind.jsontype.NamedType;
-import com.fasterxml.jackson.databind.jsontype.TypeDeserializer;
-import com.fasterxml.jackson.databind.jsontype.TypeIdResolver;
-import com.fasterxml.jackson.databind.jsontype.TypeResolverBuilder;
-import com.fasterxml.jackson.databind.jsontype.TypeSerializer;
+import com.fasterxml.jackson.databind.jsontype.*;
 
 /**
  * Default {@link TypeResolverBuilder} implementation.
@@ -71,6 +69,11 @@
             JavaType baseType, Collection<NamedType> subtypes)
     {
         if (_idType == JsonTypeInfo.Id.NONE) { return null; }
+        // 03-Oct-2016, tatu: As per [databind#1395] better prevent use for primitives,
+        //    regardless of setting
+        if (baseType.isPrimitive()) {
+            return null;
+        }
         TypeIdResolver idRes = idResolver(config, baseType, subtypes, true, false);
         switch (_includeAs) {
         case WRAPPER_ARRAY:
@@ -99,24 +102,49 @@
             JavaType baseType, Collection<NamedType> subtypes)
     {
         if (_idType == JsonTypeInfo.Id.NONE) { return null; }
+        // 03-Oct-2016, tatu: As per [databind#1395] better prevent use for primitives,
+        //    regardless of setting
+        if (baseType.isPrimitive()) {
+            return null;
+        }
 
         TypeIdResolver idRes = idResolver(config, baseType, subtypes, false, true);
-        
+
+        JavaType defaultImpl;
+
+        if (_defaultImpl == null) {
+            defaultImpl = null;
+        } else {
+            // 20-Mar-2016, tatu: It is important to do specialization go through
+            //   TypeFactory to ensure proper resolution; with 2.7 and before, direct
+            //   call to JavaType was used, but that can not work reliably with 2.7
+            // 20-Mar-2016, tatu: Can finally add a check for type compatibility BUT
+            //   if so, need to add explicit checks for marker types. Not ideal, but
+            //   seems like a reasonable compromise.
+            if ((_defaultImpl == Void.class)
+                     || (_defaultImpl == NoClass.class)) {
+                defaultImpl = config.getTypeFactory().constructType(_defaultImpl);
+            } else {
+                defaultImpl = config.getTypeFactory()
+                    .constructSpecializedType(baseType, _defaultImpl);
+            }
+        }
+
         // First, method for converting type info to type id:
         switch (_includeAs) {
         case WRAPPER_ARRAY:
             return new AsArrayTypeDeserializer(baseType, idRes,
-                    _typeProperty, _typeIdVisible, _defaultImpl);
+                    _typeProperty, _typeIdVisible, defaultImpl);
         case PROPERTY:
         case EXISTING_PROPERTY: // as per [#528] same class as PROPERTY
             return new AsPropertyTypeDeserializer(baseType, idRes,
-                    _typeProperty, _typeIdVisible, _defaultImpl, _includeAs);
+                    _typeProperty, _typeIdVisible, defaultImpl, _includeAs);
         case WRAPPER_OBJECT:
             return new AsWrapperTypeDeserializer(baseType, idRes,
-                    _typeProperty, _typeIdVisible, _defaultImpl);
+                    _typeProperty, _typeIdVisible, defaultImpl);
         case EXTERNAL_PROPERTY:
             return new AsExternalTypeDeserializer(baseType, idRes,
-                    _typeProperty, _typeIdVisible, _defaultImpl);
+                    _typeProperty, _typeIdVisible, defaultImpl);
         }
         throw new IllegalStateException("Do not know how to construct standard type serializer for inclusion type: "+_includeAs);
     }
diff --git a/src/main/java/com/fasterxml/jackson/databind/jsontype/impl/SubTypeValidator.java b/src/main/java/com/fasterxml/jackson/databind/jsontype/impl/SubTypeValidator.java
index 08b5417..04db3ad 100644
--- a/src/main/java/com/fasterxml/jackson/databind/jsontype/impl/SubTypeValidator.java
+++ b/src/main/java/com/fasterxml/jackson/databind/jsontype/impl/SubTypeValidator.java
@@ -54,6 +54,9 @@
         // [databind#1855]: more 3rd party
         s.add("org.apache.tomcat.dbcp.dbcp2.BasicDataSource");
         s.add("com.sun.org.apache.bcel.internal.util.ClassLoader");
+        // [databind#1899]: more 3rd party
+        s.add("org.hibernate.jmx.StatisticsService");
+        s.add("org.apache.ibatis.datasource.jndi.JndiDataSourceFactory");
         // [databind#2032]: more 3rd party; data exfiltration via xml parsed ext entities
         s.add("org.apache.ibatis.parsing.XPathParser");
 
@@ -77,11 +80,11 @@
         s.add("org.jboss.util.propertyeditor.DocumentEditor");
         s.add("org.apache.openjpa.ee.RegistryManagedRuntime");
         s.add("org.apache.openjpa.ee.JNDIManagedRuntime");
-        s.add("org.apache.axis2.transport.jms.JMSOutTransportInfo");   
-        
-        // [databind#2326] (2.7.9.6): one more 3rd party gadget
-        s.add("com.mysql.cj.jdbc.admin.MiniAdmin");
-        
+        s.add("org.apache.axis2.transport.jms.JMSOutTransportInfo");
+
+        // [databind#2326] (2.8.11.4: one more 3rd party gadget
+        s.add("com.mysql.cj.jdbc.admin.MiniAdmin");        
+
         DEFAULT_NO_DESER_CLASS_NAMES = Collections.unmodifiableSet(s);
     }
 
@@ -96,7 +99,8 @@
 
     public static SubTypeValidator instance() { return instance; }
 
-    public void validateSubType(DeserializationContext ctxt, JavaType type) throws JsonMappingException
+    public void validateSubType(DeserializationContext ctxt, JavaType type)
+            throws JsonMappingException
     {
         // There are certain nasty classes that could cause problems, mostly
         // via default typing -- catch them here.
diff --git a/src/main/java/com/fasterxml/jackson/databind/jsontype/impl/TypeDeserializerBase.java b/src/main/java/com/fasterxml/jackson/databind/jsontype/impl/TypeDeserializerBase.java
index 9622759..7284b47 100644
--- a/src/main/java/com/fasterxml/jackson/databind/jsontype/impl/TypeDeserializerBase.java
+++ b/src/main/java/com/fasterxml/jackson/databind/jsontype/impl/TypeDeserializerBase.java
@@ -66,8 +66,11 @@
     /**********************************************************
      */
 
+    /**
+     * @since 2.8
+     */
     protected TypeDeserializerBase(JavaType baseType, TypeIdResolver idRes,
-            String typePropertyName, boolean typeIdVisible, Class<?> defaultImpl)
+            String typePropertyName, boolean typeIdVisible, JavaType defaultImpl)
     {
         _baseType = baseType;
         _idResolver = idRes;
@@ -76,18 +79,7 @@
         _typeIdVisible = typeIdVisible;
         // defaults are fine, although shouldn't need much concurrency
         _deserializers = new ConcurrentHashMap<String, JsonDeserializer<Object>>(16, 0.75f, 2);
-        if (defaultImpl == null) {
-            _defaultImpl = null;
-        } else {
-            /* 16-Oct-2011, tatu: should call this via TypeFactory; this is
-             *    not entirely safe... however, since Collections/Maps are
-             *    seldom (if ever) base types, may be ok.
-             */
-            // 01-Nov-2015, tatu: Actually this is still exactly wrong. Should fix.
-            // 15-Jan-2016, tatu: ... as witnessed by [databind#1083], patched, but
-            //     fundamentally this call can't be made to work for all cases
-            _defaultImpl = baseType.forcedNarrowBy(defaultImpl);
-        }
+        _defaultImpl = defaultImpl;
         _property = null;
     }
 
@@ -160,7 +152,14 @@
                 // As per [JACKSON-614], use the default impl if no type id available:
                 deser = _findDefaultImplDeserializer(ctxt);
                 if (deser == null) {
-                    deser = _handleUnknownTypeId(ctxt, typeId, _idResolver, _baseType);
+                    // 10-May-2016, tatu: We may get some help...
+                    JavaType actual = _handleUnknownTypeId(ctxt, typeId, _idResolver, _baseType);
+                    if (actual == null) { // what should this be taken to mean?
+                        // TODO: try to figure out something better
+                        return null;
+                    }
+                    // ... would this actually work?
+                    deser = ctxt.findContextualValueDeserializer(actual, _property);
                 }
             } else {
                 /* 16-Dec-2010, tatu: Since nominal type we get here has no (generic) type parameters,
@@ -178,7 +177,13 @@
                      *   important for some reason?
                      *   Disabling the check will break 2 Enum-related tests.
                      */
-                    type = ctxt.getTypeFactory().constructSpecializedType(_baseType, type.getRawClass());
+                    // 19-Jun-2016, tatu: As per [databind#1270] we may actually get full
+                    //   generic type with custom type resolvers. If so, should try to retain them.
+                    //  Whether this is sufficient to avoid problems remains to be seen, but for
+                    //  now it should improve things.
+                    if (!type.hasGenericTypes()) {
+                        type = ctxt.getTypeFactory().constructSpecializedType(_baseType, type.getRawClass());
+                    }
                 }
                 deser = ctxt.findContextualValueDeserializer(type, _property);
             }
@@ -241,7 +246,8 @@
              */
             deser = _findDefaultImplDeserializer(ctxt);
             if (deser == null) {
-                throw ctxt.mappingException("No (native) type id found when one was expected for polymorphic type handling");
+                ctxt.reportMappingException("No (native) type id found when one was expected for polymorphic type handling");
+                return null;
             }
         } else {
             String typeIdStr = (typeId instanceof String) ? (String) typeId : String.valueOf(typeId);
@@ -261,23 +267,18 @@
      *   should return that deserializer; otherwise throw an exception to indicate
      *   the problem.
      *
-     * @since 2.5
+     * @since 2.8
      */
-    protected JsonDeserializer<Object> _handleUnknownTypeId(DeserializationContext ctxt, String typeId,
+    protected JavaType _handleUnknownTypeId(DeserializationContext ctxt, String typeId,
             TypeIdResolver idResolver, JavaType baseType)
         throws IOException
     {
-        String extraDesc;
-        if (idResolver instanceof TypeIdResolverBase) {
-            extraDesc = ((TypeIdResolverBase) idResolver).getDescForKnownTypeIds();
-            if (extraDesc == null) {
-                extraDesc = "known type ids are not statically known";
-            } else {
-                extraDesc = "known type ids = " + extraDesc;
-            }
+        String extraDesc = idResolver.getDescForKnownTypeIds();
+        if (extraDesc == null) {
+            extraDesc = "known type ids are not statically known";
         } else {
-            extraDesc = null;
+            extraDesc = "known type ids = " + extraDesc;
         }
-        throw ctxt.unknownTypeException(_baseType, typeId, extraDesc);
+        return ctxt.handleUnknownTypeId(_baseType, typeId, idResolver, extraDesc);
     }
 }
diff --git a/src/main/java/com/fasterxml/jackson/databind/jsontype/impl/TypeIdResolverBase.java b/src/main/java/com/fasterxml/jackson/databind/jsontype/impl/TypeIdResolverBase.java
index 8532543..deeec6f 100644
--- a/src/main/java/com/fasterxml/jackson/databind/jsontype/impl/TypeIdResolverBase.java
+++ b/src/main/java/com/fasterxml/jackson/databind/jsontype/impl/TypeIdResolverBase.java
@@ -1,5 +1,7 @@
 package com.fasterxml.jackson.databind.jsontype.impl;
 
+import java.io.IOException;
+
 import com.fasterxml.jackson.databind.DatabindContext;
 import com.fasterxml.jackson.databind.JavaType;
 import com.fasterxml.jackson.databind.jsontype.TypeIdResolver;
@@ -51,27 +53,8 @@
         return idFromValueAndType(null, _baseType.getRawClass());
     }
 
-    /**
-     * @deprecated Since 2.3, override {@link #typeFromId(DatabindContext, String)} instead
-     *    to get access to contextual information
-     */
-    @Deprecated
     @Override
-    public JavaType typeFromId(String id) {
-        return typeFromId(null, id);
-    }
-
-    /**
-     * New method, replacement for {@link #typeFromId(String)}, which is given
-     * context for accessing information, including configuration and
-     * {@link TypeFactory}.
-     * 
-     * @return Type for given id
-     * 
-     * @since 2.3
-     */
-    @Override
-    public JavaType typeFromId(DatabindContext context, String id) {
+    public JavaType typeFromId(DatabindContext context, String id)  throws IOException {
         // 22-Dec-2015, tatu: Must be overridden by sub-classes, so let's throw
         //    an exception if not
         throw new IllegalStateException("Sub-class "+getClass().getName()+" MUST implement "
diff --git a/src/main/java/com/fasterxml/jackson/databind/jsontype/impl/TypeNameIdResolver.java b/src/main/java/com/fasterxml/jackson/databind/jsontype/impl/TypeNameIdResolver.java
index 9025daf..d607fbf 100644
--- a/src/main/java/com/fasterxml/jackson/databind/jsontype/impl/TypeNameIdResolver.java
+++ b/src/main/java/com/fasterxml/jackson/databind/jsontype/impl/TypeNameIdResolver.java
@@ -12,7 +12,7 @@
 public class TypeNameIdResolver extends TypeIdResolverBase
 {
     protected final MapperConfig<?> _config;
-    
+
     /**
      * Mappings from class name to type id, used for serialization
      */
@@ -22,7 +22,7 @@
      * Mappings from type id to JavaType, used for deserialization
      */
     protected final Map<String, JavaType> _idToType;
-    
+
     protected TypeNameIdResolver(MapperConfig<?> config, JavaType baseType,
             Map<String, String> typeToId, Map<String, JavaType> idToType)
     {
@@ -79,8 +79,7 @@
     public JsonTypeInfo.Id getMechanism() { return JsonTypeInfo.Id.NAME; }
 
     @Override
-    public String idFromValue(Object value)
-    {
+    public String idFromValue(Object value) {
         return idFromClass(value.getClass());
     }
 
@@ -123,12 +122,6 @@
         return idFromValue(value);
     }
 
-    @Deprecated
-    @Override
-    public JavaType typeFromId(String id) {
-        return _typeFromId(id);
-    }    
-
     @Override
     public JavaType typeFromId(DatabindContext context, String id) {
         return _typeFromId(id);
@@ -150,13 +143,9 @@
 
     @Override
     public String toString() {
-        StringBuilder sb = new StringBuilder();
-        sb.append('[').append(getClass().getName());
-        sb.append("; id-to-type=").append(_idToType);
-        sb.append(']');
-        return sb.toString();
+        return String.format("[%s; id-to-type=%s]", getClass().getName(), _idToType);
     }
-    
+
     /*
     /*********************************************************
     /* Helper methods
diff --git a/src/main/java/com/fasterxml/jackson/databind/module/SimpleAbstractTypeResolver.java b/src/main/java/com/fasterxml/jackson/databind/module/SimpleAbstractTypeResolver.java
index dbd1bf4..3b0c1fd 100644
--- a/src/main/java/com/fasterxml/jackson/databind/module/SimpleAbstractTypeResolver.java
+++ b/src/main/java/com/fasterxml/jackson/databind/module/SimpleAbstractTypeResolver.java
@@ -81,6 +81,7 @@
     }
 
     @Override
+    @Deprecated
     public JavaType resolveAbstractType(DeserializationConfig config, JavaType type){
         // never materialize anything, so:
         return null;
diff --git a/src/main/java/com/fasterxml/jackson/databind/node/ArrayNode.java b/src/main/java/com/fasterxml/jackson/databind/node/ArrayNode.java
index be2e037..345834a 100644
--- a/src/main/java/com/fasterxml/jackson/databind/node/ArrayNode.java
+++ b/src/main/java/com/fasterxml/jackson/databind/node/ArrayNode.java
@@ -31,6 +31,14 @@
     }
 
     /**
+     * @since 2.8
+     */
+    public ArrayNode(JsonNodeFactory nf, int capacity) {
+        super(nf);
+        _children = new ArrayList<JsonNode>(capacity);
+    }
+
+    /**
      * @since 2.7
      */
     public ArrayNode(JsonNodeFactory nf, List<JsonNode> children) {
@@ -66,7 +74,7 @@
     public boolean isEmpty(SerializerProvider serializers) {
         return _children.isEmpty();
     }
-    
+
     /*
     /**********************************************************
     /* Implementation of core JsonNode API
@@ -167,13 +175,13 @@
         }
         typeSer.writeTypeSuffixForArray(this, jg);
     }
-    
+
     /*
     /**********************************************************
     /* Public API, finding value nodes
     /**********************************************************
      */
-    
+
     @Override
     public JsonNode findValue(String fieldName)
     {
@@ -185,7 +193,7 @@
         }
         return null;
     }
-    
+
     @Override
     public List<JsonNode> findValues(String fieldName, List<JsonNode> foundSoFar)
     {
@@ -203,7 +211,7 @@
         }
         return foundSoFar;
     }
-    
+
     @Override
     public ObjectNode findParent(String fieldName)
     {
@@ -224,7 +232,7 @@
         }
         return foundSoFar;
     }
-    
+
     /*
     /**********************************************************
     /* Extended ObjectNode API, accessors
@@ -255,7 +263,7 @@
 
     /**
      * Method for adding specified node at the end of this array.
-     * 
+     *
      * @return This node, to allow chaining
      */
     public ArrayNode add(JsonNode value)
@@ -270,9 +278,9 @@
     /**
      * Method for adding all child nodes of given Array, appending to
      * child nodes this array contains
-     * 
+     *
      * @param other Array to add contents from
-     * 
+     *
      * @return This node (to allow chaining)
      */
     public ArrayNode addAll(ArrayNode other)
@@ -283,9 +291,9 @@
 
     /**
      * Method for adding given nodes as child nodes of this array node.
-     * 
+     *
      * @param nodes Nodes to add
-     * 
+     *
      * @return This node (to allow chaining)
      */
     public ArrayNode addAll(Collection<? extends JsonNode> nodes)
@@ -293,14 +301,14 @@
         _children.addAll(nodes);
         return this;
     }
-    
+
     /**
      * Method for inserting specified child node as an element
      * of this Array. If index is 0 or less, it will be inserted as
      * the first element; if >= size(), appended at the end, and otherwise
      * inserted before existing element in specified index.
      * No exceptions are thrown for any index.
-     * 
+     *
      * @return This node (to allow chaining)
      */
     public ArrayNode insert(int index, JsonNode value)
@@ -316,7 +324,7 @@
      * Method for removing an entry from this ArrayNode.
      * Will return value of the entry at specified index, if entry existed;
      * null if not.
-     * 
+     *
      * @return Node removed, if any; null if none
      */
     public JsonNode remove(int index)
@@ -330,7 +338,7 @@
     /**
      * Method for removing all elements of this array, leaving the
      * array empty.
-     * 
+     *
      * @return This node (to allow chaining)
      */
     @Override
@@ -339,7 +347,7 @@
         _children.clear();
         return this;
     }
-    
+
     /*
     /**********************************************************
     /* Extended ObjectNode API, mutators, generic; addXxx()/insertXxx()
@@ -375,7 +383,7 @@
     /**
      * Method that will construct a POJONode and add it at the end
      * of this array node.
-     * 
+     *
      * @return This array node, to allow chaining
      */
     public ArrayNode addPOJO(Object value)
@@ -390,7 +398,7 @@
 
     /**
      * @return This array node, to allow chaining
-     * 
+     *
      * @since 2.6
      */
     public ArrayNode addRawValue(RawValue raw) {
@@ -401,10 +409,10 @@
         }
         return this;
     }
-    
+
     /**
      * Method that will add a null value at the end of this array node.
-     * 
+     *
      * @return This array node, to allow chaining
      */
     public ArrayNode addNull()
@@ -415,7 +423,7 @@
 
     /**
      * Method for adding specified number at the end of this array.
-     * 
+     *
      * @return This array node, to allow chaining
      */
     public ArrayNode add(int v) {
@@ -426,7 +434,7 @@
     /**
      * Alternative method that we need to avoid bumping into NPE issues
      * with auto-unboxing.
-     * 
+     *
      * @return This array node, to allow chaining
      */
     public ArrayNode add(Integer value) {
@@ -435,10 +443,10 @@
         }
         return _add(numberNode(value.intValue()));
     }
-    
+
     /**
      * Method for adding specified number at the end of this array.
-     * 
+     *
      * @return This array node, to allow chaining
      */
     public ArrayNode add(long v) { return _add(numberNode(v)); }
@@ -446,7 +454,7 @@
     /**
      * Alternative method that we need to avoid bumping into NPE issues
      * with auto-unboxing.
-     * 
+     *
      * @return This array node, to allow chaining
      */
     public ArrayNode add(Long value) {
@@ -455,10 +463,10 @@
         }
         return _add(numberNode(value.longValue()));
     }
-    
+
     /**
      * Method for adding specified number at the end of this array.
-     * 
+     *
      * @return This array node, to allow chaining
      */
     public ArrayNode add(float v) {
@@ -468,7 +476,7 @@
     /**
      * Alternative method that we need to avoid bumping into NPE issues
      * with auto-unboxing.
-     * 
+     *
      * @return This array node, to allow chaining
      */
     public ArrayNode add(Float value) {
@@ -477,10 +485,10 @@
         }
         return _add(numberNode(value.floatValue()));
     }
-    
+
     /**
      * Method for adding specified number at the end of this array.
-     * 
+     *
      * @return This array node, to allow chaining
      */
     public ArrayNode add(double v) {
@@ -490,7 +498,7 @@
     /**
      * Alternative method that we need to avoid bumping into NPE issues
      * with auto-unboxing.
-     * 
+     *
      * @return This array node, to allow chaining
      */
     public ArrayNode add(Double value) {
@@ -499,10 +507,10 @@
         }
         return _add(numberNode(value.doubleValue()));
     }
-    
+
     /**
      * Method for adding specified number at the end of this array.
-     * 
+     *
      * @return This array node, to allow chaining
      */
     public ArrayNode add(BigDecimal v) {
@@ -514,7 +522,7 @@
 
     /**
      * Method for adding specified String value at the end of this array.
-     * 
+     *
      * @return This array node, to allow chaining
      */
     public ArrayNode add(String v) {
@@ -526,7 +534,7 @@
 
     /**
      * Method for adding specified boolean value at the end of this array.
-     * 
+     *
      * @return This array node, to allow chaining
      */
     public ArrayNode add(boolean v) {
@@ -536,7 +544,7 @@
     /**
      * Alternative method that we need to avoid bumping into NPE issues
      * with auto-unboxing.
-     * 
+     *
      * @return This array node, to allow chaining
      */
     public ArrayNode add(Boolean value) {
@@ -545,11 +553,11 @@
         }
         return _add(booleanNode(value.booleanValue()));
     }
-    
+
     /**
      * Method for adding specified binary value at the end of this array
      * (note: when serializing as JSON, will be output Base64 encoded)
-     * 
+     *
      * @return This array node, to allow chaining
      */
     public ArrayNode add(byte[] v) {
@@ -576,7 +584,7 @@
      * Method for creating an {@link ObjectNode}, appending it at the end
      * of this array, and returning the <b>newly created node</b>
      * (note: NOT 'this' array)
-     * 
+     *
      * @return Newly constructed ObjectNode
      */
     public ObjectNode insertObject(int index)
@@ -589,7 +597,7 @@
     /**
      * Method that will construct a POJONode and
      * insert it at specified position in this array.
-     * 
+     *
      * @return This array node, to allow chaining
      */
     public ArrayNode insertPOJO(int index, Object value)
@@ -603,7 +611,7 @@
     /**
      * Method that will insert a null value
      * at specified position in this array.
-     * 
+     *
      * @return This array node, to allow chaining
      */
     public ArrayNode insertNull(int index)
@@ -615,7 +623,7 @@
     /**
      * Method that will insert specified numeric value
      * at specified position in this array.
-     * 
+     *
      * @return This array node, to allow chaining
      */
     public ArrayNode insert(int index, int v) {
@@ -626,7 +634,7 @@
     /**
      * Alternative method that we need to avoid bumping into NPE issues
      * with auto-unboxing.
-     * 
+     *
      * @return This array node, to allow chaining
      */
     public ArrayNode insert(int index, Integer value) {
@@ -637,11 +645,11 @@
         }
         return this;
     }
-    
+
     /**
      * Method that will insert specified numeric value
      * at specified position in this array.
-     * 
+     *
      * @return This array node, to allow chaining
      */
     public ArrayNode insert(int index, long v) {
@@ -651,7 +659,7 @@
     /**
      * Alternative method that we need to avoid bumping into NPE issues
      * with auto-unboxing.
-     * 
+     *
      * @return This array node, to allow chaining
      */
     public ArrayNode insert(int index, Long value) {
@@ -660,11 +668,11 @@
         }
         return _insert(index, numberNode(value.longValue()));
     }
-    
+
     /**
      * Method that will insert specified numeric value
      * at specified position in this array.
-     * 
+     *
      * @return This array node, to allow chaining
      */
     public ArrayNode insert(int index, float v) {
@@ -674,7 +682,7 @@
     /**
      * Alternative method that we need to avoid bumping into NPE issues
      * with auto-unboxing.
-     * 
+     *
      * @return This array node, to allow chaining
      */
     public ArrayNode insert(int index, Float value) {
@@ -683,11 +691,11 @@
         }
         return _insert(index, numberNode(value.floatValue()));
     }
-    
+
     /**
      * Method that will insert specified numeric value
      * at specified position in this array.
-     * 
+     *
      * @return This array node, to allow chaining
      */
     public ArrayNode insert(int index, double v) {
@@ -697,7 +705,7 @@
     /**
      * Alternative method that we need to avoid bumping into NPE issues
      * with auto-unboxing.
-     * 
+     *
      * @return This array node, to allow chaining
      */
     public ArrayNode insert(int index, Double value) {
@@ -710,7 +718,7 @@
     /**
      * Method that will insert specified numeric value
      * at specified position in this array.
-     * 
+     *
      * @return This array node, to allow chaining
      */
     public ArrayNode insert(int index, BigDecimal v) {
@@ -723,7 +731,7 @@
     /**
      * Method that will insert specified String
      * at specified position in this array.
-     * 
+     *
      * @return This array node, to allow chaining
      */
     public ArrayNode insert(int index, String v) {
@@ -736,7 +744,7 @@
     /**
      * Method that will insert specified String
      * at specified position in this array.
-     * 
+     *
      * @return This array node, to allow chaining
      */
     public ArrayNode insert(int index, boolean v) {
@@ -746,7 +754,7 @@
     /**
      * Alternative method that we need to avoid bumping into NPE issues
      * with auto-unboxing.
-     * 
+     *
      * @return This array node, to allow chaining
      */
     public ArrayNode insert(int index, Boolean value) {
@@ -755,12 +763,12 @@
         }
         return _insert(index, booleanNode(value.booleanValue()));
     }
-    
+
     /**
      * Method that will insert specified binary value
      * at specified position in this array
      * (note: when written as JSON, will be Base64 encoded)
-     * 
+     *
      * @return This array node, to allow chaining
      */
     public ArrayNode insert(int index, byte[] v) {
diff --git a/src/main/java/com/fasterxml/jackson/databind/node/ContainerNode.java b/src/main/java/com/fasterxml/jackson/databind/node/ContainerNode.java
index 536755d..f2eb608 100644
--- a/src/main/java/com/fasterxml/jackson/databind/node/ContainerNode.java
+++ b/src/main/java/com/fasterxml/jackson/databind/node/ContainerNode.java
@@ -31,7 +31,7 @@
 
     @Override
     public abstract JsonToken asToken();
-    
+
     @Override
     public String asText() { return ""; }
 
@@ -65,6 +65,14 @@
     public final ArrayNode arrayNode() { return _nodeFactory.arrayNode(); }
 
     /**
+     * Factory method that constructs and returns an {@link ArrayNode} with an initial capacity
+     * Construction is done using registered {@link JsonNodeFactory}
+     * @param capacity the initial capacity of the ArrayNode
+     */
+    @Override
+    public final ArrayNode arrayNode(int capacity) { return _nodeFactory.arrayNode(capacity); }
+
+    /**
      * Factory method that constructs and returns an empty {@link ObjectNode}
      * Construction is done using registered {@link JsonNodeFactory}.
      */
@@ -113,7 +121,7 @@
     public final ValueNode numberNode(Float v) { return _nodeFactory.numberNode(v); }
     @Override
     public final ValueNode numberNode(Double v) { return _nodeFactory.numberNode(v); }
-    
+
     @Override
     public final TextNode textNode(String text) { return _nodeFactory.textNode(text); }
 
diff --git a/src/main/java/com/fasterxml/jackson/databind/node/FloatNode.java b/src/main/java/com/fasterxml/jackson/databind/node/FloatNode.java
index c79ac89..b4dc9fb 100644
--- a/src/main/java/com/fasterxml/jackson/databind/node/FloatNode.java
+++ b/src/main/java/com/fasterxml/jackson/databind/node/FloatNode.java
@@ -73,7 +73,7 @@
     public long longValue() { return (long) _value; }
 
     @Override
-    public float floatValue() { return (float) _value; }
+    public float floatValue() { return _value; }
     
     @Override
     public double doubleValue() { return _value; }
diff --git a/src/main/java/com/fasterxml/jackson/databind/node/JsonNodeCreator.java b/src/main/java/com/fasterxml/jackson/databind/node/JsonNodeCreator.java
index 5880370..55c880f 100644
--- a/src/main/java/com/fasterxml/jackson/databind/node/JsonNodeCreator.java
+++ b/src/main/java/com/fasterxml/jackson/databind/node/JsonNodeCreator.java
@@ -9,13 +9,13 @@
  * Interface that defines common "creator" functionality implemented
  * both by {@link JsonNodeFactory} and {@link ContainerNode} (that is,
  * JSON Object and Array nodes).
- * 
+ *
  * @since 2.3
  */
 public interface JsonNodeCreator
 {
     // Enumerated/singleton types
-    
+
     public ValueNode booleanNode(boolean v);
     public ValueNode nullNode();
 
@@ -41,7 +41,7 @@
     public ValueNode textNode(String text);
 
     // Other value (non-structured) nodes
-    
+
     public ValueNode binaryNode(byte[] data);
     public ValueNode binaryNode(byte[] data, int offset, int length);
     public ValueNode pojoNode(Object pojo);
@@ -54,7 +54,7 @@
      * Note that the concept may not work with all backends, and since
      * no translation of any kinds is done it will not work when converting
      * between data formats.
-     * 
+     *
      * @since 2.6
      */
     public ValueNode rawValueNode(RawValue value);
@@ -63,5 +63,13 @@
     // (bit unkosher, due to forward references... but has to do for now)
 
     public ArrayNode arrayNode();
+
+    /**
+     * Factory method for constructing a JSON Array node with an initial capacity
+     *
+     * @since 2.8
+     */
+    public ArrayNode arrayNode(int capacity);
+
     public ObjectNode objectNode();
 }
diff --git a/src/main/java/com/fasterxml/jackson/databind/node/JsonNodeFactory.java b/src/main/java/com/fasterxml/jackson/databind/node/JsonNodeFactory.java
index 0d0d574..70ec2f7 100644
--- a/src/main/java/com/fasterxml/jackson/databind/node/JsonNodeFactory.java
+++ b/src/main/java/com/fasterxml/jackson/databind/node/JsonNodeFactory.java
@@ -8,13 +8,13 @@
 /**
  * Base class that specifies methods for getting access to
  * Node instances (newly constructed, or shared, depending
- * on type), as well as basic implementation of the methods. 
+ * on type), as well as basic implementation of the methods.
  * Designed to be sub-classed if extended functionality (additions
  * to behavior of node types, mostly) is needed.
  */
 public class JsonNodeFactory
-    implements java.io.Serializable // since 2.1
-        ,JsonNodeCreator // since 2.3
+    implements java.io.Serializable, // since 2.1
+        JsonNodeCreator // since 2.3
 {
     // with 2.2
     private static final long serialVersionUID = 1L;
@@ -85,7 +85,7 @@
     {
         return bigDecimalExact ? decimalsAsIs : decimalsNormalized;
     }
-    
+
     /*
     /**********************************************************
     /* Factory methods for literal values
@@ -131,7 +131,7 @@
     public ValueNode numberNode(Byte value) {
         return (value == null) ? nullNode() : IntNode.valueOf(value.intValue());
     }
-    
+
     /**
      * Factory method for getting an instance of JSON numeric value
      * that expresses given 16-bit integer value
@@ -149,7 +149,7 @@
     public ValueNode numberNode(Short value) {
         return (value == null) ? nullNode() : ShortNode.valueOf(value);
     }
-    
+
     /**
      * Factory method for getting an instance of JSON numeric value
      * that expresses given 32-bit integer value
@@ -176,7 +176,7 @@
     public NumericNode numberNode(long v) {
         return LongNode.valueOf(v);
     }
-    
+
     /**
      * Alternate factory method that will handle wrapper value, which may be null.
      * Due to possibility of null, returning type is not guaranteed to be
@@ -189,7 +189,7 @@
         }
         return LongNode.valueOf(value.longValue());
     }
-    
+
     /**
      * Factory method for getting an instance of JSON numeric value
      * that expresses given unlimited range integer value
@@ -214,7 +214,7 @@
     public ValueNode numberNode(Float value) {
         return (value == null) ? nullNode() : FloatNode.valueOf(value.floatValue());
     }
-    
+
     /**
      * Factory method for getting an instance of JSON numeric value
      * that expresses given 64-bit floating point value
@@ -232,7 +232,7 @@
     public ValueNode numberNode(Double value) {
         return (value == null) ? nullNode() : DoubleNode.valueOf(value.doubleValue());
     }
-    
+
     /**
      * Factory method for getting an instance of JSON numeric value
      * that expresses given unlimited precision floating point value
@@ -310,6 +310,14 @@
     public ArrayNode arrayNode() { return new ArrayNode(this); }
 
     /**
+     * Factory method for constructing a JSON Array node with an initial capacity
+     *
+     * @since 2.8
+     */
+    @Override
+    public ArrayNode arrayNode(int capacity) { return new ArrayNode(this, capacity); }
+
+    /**
      * Factory method for constructing an empty JSON Object ("struct") node
      */
     @Override
@@ -334,7 +342,7 @@
     /* Helper methods
     /**********************************************************
      */
-    
+
     protected boolean _inIntRange(long l)
     {
         int i = (int) l;
diff --git a/src/main/java/com/fasterxml/jackson/databind/node/ObjectNode.java b/src/main/java/com/fasterxml/jackson/databind/node/ObjectNode.java
index ae4d7c9..387943e 100644
--- a/src/main/java/com/fasterxml/jackson/databind/node/ObjectNode.java
+++ b/src/main/java/com/fasterxml/jackson/databind/node/ObjectNode.java
@@ -279,33 +279,56 @@
      * all of its descendants using specified JSON generator.
      */
     @Override
-    public void serialize(JsonGenerator jg, SerializerProvider provider)
-        throws IOException, JsonProcessingException
+    public void serialize(JsonGenerator g, SerializerProvider provider)
+        throws IOException
     {
-        jg.writeStartObject();
+        @SuppressWarnings("deprecation")
+        boolean trimEmptyArray = (provider != null) &&
+                !provider.isEnabled(SerializationFeature.WRITE_EMPTY_JSON_ARRAYS);
+        g.writeStartObject(this);
         for (Map.Entry<String, JsonNode> en : _children.entrySet()) {
-            jg.writeFieldName(en.getKey());
-                /* 17-Feb-2009, tatu: Can we trust that all nodes will always
-                 *   extend BaseJsonNode? Or if not, at least implement
-                 *   JsonSerializable? Let's start with former, change if
-                 *   we must.
-                 */
-            ((BaseJsonNode) en.getValue()).serialize(jg, provider);
+            /* 17-Feb-2009, tatu: Can we trust that all nodes will always
+             *   extend BaseJsonNode? Or if not, at least implement
+             *   JsonSerializable? Let's start with former, change if
+             *   we must.
+             */
+            BaseJsonNode value = (BaseJsonNode) en.getValue();
+
+            // as per [databind#867], see if WRITE_EMPTY_JSON_ARRAYS feature is disabled,
+            // if the feature is disabled, then should not write an empty array
+            // to the output, so continue to the next element in the iteration
+            if (trimEmptyArray && value.isArray() && value.isEmpty(provider)) {
+            	continue;
+            }
+            g.writeFieldName(en.getKey());
+            value.serialize(g, provider);
         }
-        jg.writeEndObject();
+        g.writeEndObject();
     }
 
     @Override
-    public void serializeWithType(JsonGenerator jg, SerializerProvider provider,
+    public void serializeWithType(JsonGenerator g, SerializerProvider provider,
             TypeSerializer typeSer)
-        throws IOException, JsonProcessingException
+        throws IOException
     {
-        typeSer.writeTypePrefixForObject(this, jg);
+        @SuppressWarnings("deprecation")
+        boolean trimEmptyArray = (provider != null) &&
+                !provider.isEnabled(SerializationFeature.WRITE_EMPTY_JSON_ARRAYS);
+        typeSer.writeTypePrefixForObject(this, g);
         for (Map.Entry<String, JsonNode> en : _children.entrySet()) {
-            jg.writeFieldName(en.getKey());
-            ((BaseJsonNode) en.getValue()).serialize(jg, provider);
+            BaseJsonNode value = (BaseJsonNode) en.getValue();
+
+            // check if WRITE_EMPTY_JSON_ARRAYS feature is disabled,
+            // if the feature is disabled, then should not write an empty array
+            // to the output, so continue to the next element in the iteration
+            if (trimEmptyArray && value.isArray() && value.isEmpty(provider)) {
+                continue;
+            }
+            
+            g.writeFieldName(en.getKey());
+            value.serialize(g, provider);
         }
-        typeSer.writeTypeSuffixForObject(this, jg);
+        typeSer.writeTypeSuffixForObject(this, g);
     }
 
     /*
diff --git a/src/main/java/com/fasterxml/jackson/databind/node/TextNode.java b/src/main/java/com/fasterxml/jackson/databind/node/TextNode.java
index e65e589..a692776 100644
--- a/src/main/java/com/fasterxml/jackson/databind/node/TextNode.java
+++ b/src/main/java/com/fasterxml/jackson/databind/node/TextNode.java
@@ -57,9 +57,9 @@
      * base64 encoded; if so, they are decoded and resulting binary
      * data is returned.
      */
+    @SuppressWarnings("resource")
     public byte[] getBinaryValue(Base64Variant b64variant) throws IOException
     {
-        @SuppressWarnings("resource")
         ByteArrayBuilder builder = new ByteArrayBuilder(100);
         final String str = _value;
         int ptr = 0;
@@ -210,12 +210,12 @@
      */
     
     @Override
-    public final void serialize(JsonGenerator jg, SerializerProvider provider) throws IOException
+    public final void serialize(JsonGenerator g, SerializerProvider provider) throws IOException
     {
         if (_value == null) {
-            jg.writeNull();
+            g.writeNull();
         } else {
-            jg.writeString(_value);
+            g.writeString(_value);
         }
     }
 
@@ -264,7 +264,7 @@
     /* Helper methods
     /**********************************************************
      */
-    
+
     protected void _reportInvalidBase64(Base64Variant b64variant, char ch, int bindex)
         throws JsonParseException
     {
diff --git a/src/main/java/com/fasterxml/jackson/databind/ser/AnyGetterWriter.java b/src/main/java/com/fasterxml/jackson/databind/ser/AnyGetterWriter.java
index f74e1db..bedf67e 100644
--- a/src/main/java/com/fasterxml/jackson/databind/ser/AnyGetterWriter.java
+++ b/src/main/java/com/fasterxml/jackson/databind/ser/AnyGetterWriter.java
@@ -24,7 +24,7 @@
     protected JsonSerializer<Object> _serializer;
 
     protected MapSerializer _mapSerializer;
-    
+
     @SuppressWarnings("unchecked")
     public AnyGetterWriter(BeanProperty property,
             AnnotatedMember accessor, JsonSerializer<?> serializer)
@@ -37,6 +37,14 @@
         }
     }
 
+    /**
+     * @since 0.8.3
+     */
+    public void fixAccess(SerializationConfig config) {
+        _accessor.fixAccess(
+                config.isEnabled(MapperFeature.OVERRIDE_PUBLIC_ACCESS_MODIFIERS));
+    }
+
     public void getAndSerialize(Object bean, JsonGenerator gen, SerializerProvider provider)
         throws Exception
     {
@@ -45,8 +53,8 @@
             return;
         }
         if (!(value instanceof Map<?,?>)) {
-            throw JsonMappingException.from(gen, "Value returned by 'any-getter' ("
-                    +_accessor.getName()+"()) not java.util.Map but "+value.getClass().getName());
+            provider.reportMappingProblem("Value returned by 'any-getter' %s() not java.util.Map but %s",
+                    _accessor.getName(), value.getClass().getName());
         }
         // 23-Feb-2015, tatu: Nasty, but has to do (for now)
         if (_mapSerializer != null) {
@@ -68,8 +76,8 @@
             return;
         }
         if (!(value instanceof Map<?,?>)) {
-            throw JsonMappingException.from(gen, "Value returned by 'any-getter' ("
-                    +_accessor.getName()+"()) not java.util.Map but "+value.getClass().getName());
+            provider.reportMappingProblem("Value returned by 'any-getter' (%s()) not java.util.Map but %s",
+                    _accessor.getName(), value.getClass().getName());
         }
         // 19-Oct-2014, tatu: Should we try to support @JsonInclude options here?
         if (_mapSerializer != null) {
diff --git a/src/main/java/com/fasterxml/jackson/databind/ser/BasicSerializerFactory.java b/src/main/java/com/fasterxml/jackson/databind/ser/BasicSerializerFactory.java
index 523ae3d..29c4a49 100644
--- a/src/main/java/com/fasterxml/jackson/databind/ser/BasicSerializerFactory.java
+++ b/src/main/java/com/fasterxml/jackson/databind/ser/BasicSerializerFactory.java
@@ -9,6 +9,7 @@
 import java.util.*;
 
 import com.fasterxml.jackson.annotation.JsonFormat;
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
 import com.fasterxml.jackson.annotation.JsonInclude;
 import com.fasterxml.jackson.databind.*;
 import com.fasterxml.jackson.databind.annotation.JsonSerialize;
@@ -234,7 +235,7 @@
                         if (config.canOverrideAccessModifiers()) {
                             ClassUtil.checkAndFixAccess(m, config.isEnabled(MapperFeature.OVERRIDE_PUBLIC_ACCESS_MODIFIERS));
                         }
-                        ser = new JsonValueSerializer(m, delegate);
+                        ser = new JsonValueSerializer(am, delegate);
                     } else {
                         ser = StdKeySerializers.getFallbackKeySerializer(config, keyType.getRawClass());
                     }
@@ -353,7 +354,7 @@
                 ClassUtil.checkAndFixAccess(m, prov.isEnabled(MapperFeature.OVERRIDE_PUBLIC_ACCESS_MODIFIERS));
             }
             JsonSerializer<Object> ser = findSerializerFromAnnotation(prov, valueMethod);
-            return new JsonValueSerializer(m, ser);
+            return new JsonValueSerializer(valueMethod, ser);
         }
         // No well-known annotations...
         return null;
@@ -388,16 +389,10 @@
         if (Map.Entry.class.isAssignableFrom(raw)) {
             // 18-Oct-2015, tatu: With 2.7, need to dig type info:
             JavaType mapEntryType = type.findSuperType(Map.Entry.class);
-            
+
             // 28-Apr-2015, tatu: TypeFactory does it all for us already so
-            JavaType kt = mapEntryType.containedType(0);
-            if (kt == null) {
-                kt = TypeFactory.unknownType();
-            }
-            JavaType vt = mapEntryType.containedType(1);
-            if (vt == null) {
-                vt = TypeFactory.unknownType();
-            }
+            JavaType kt = mapEntryType.containedTypeOrUnknown(0);
+            JavaType vt = mapEntryType.containedTypeOrUnknown(1);
             return buildMapEntrySerializer(prov.getConfig(), type, beanDesc, staticTyping, kt, vt);
         }
         if (ByteBuffer.class.isAssignableFrom(raw)) {
@@ -768,8 +763,15 @@
             ser = findSerializerByAnnotations(prov, type, beanDesc); // (2) Annotations
             if (ser == null) {
                 Object filterId = findFilterId(config, beanDesc);
-                AnnotationIntrospector ai = config.getAnnotationIntrospector();
-                MapSerializer mapSer = MapSerializer.construct(ai.findPropertiesToIgnore(beanDesc.getClassInfo(), true),
+                // 01-May-2016, tatu: Which base type to use here gets tricky, since
+                //   most often it ought to be `Map` or `EnumMap`, but due to abstract
+                //   mapping it will more likely be concrete type like `HashMap`.
+                //   So, for time being, just pass `Map.class`
+                JsonIgnoreProperties.Value ignorals = config.getDefaultPropertyIgnorals(Map.class,
+                        beanDesc.getClassInfo());
+                Set<String> ignored = (ignorals == null) ? null
+                        : ignorals.findIgnoredForSerialization();
+                MapSerializer mapSer = MapSerializer.construct(ignored,
                         type, staticTyping, elementTypeSerializer,
                         keySerializer, elementValueSerializer, filterId);
                 Object suppressableValue = findSuppressableContentValue(config,
@@ -800,8 +802,12 @@
             JavaType contentType, BeanDescription beanDesc)
         throws JsonMappingException
     {
+        /* 16-Apr-2016, tatu: Should this consider possible property-config overrides?
+         *    Quite possibly yes, but would need to carefully check that content type being
+         *    used is appropriate.
+         */
         JsonInclude.Value inclV = beanDesc.findPropertyInclusion(config.getDefaultPropertyInclusion());
-        
+
         if (inclV == null) {
             return null;
         }
@@ -897,16 +903,6 @@
         return new IteratorSerializer(valueType, staticTyping, createTypeSerializer(config, valueType));
     }
 
-    @Deprecated // since 2.5
-    protected JsonSerializer<?> buildIteratorSerializer(SerializationConfig config,
-            JavaType type, BeanDescription beanDesc, boolean staticTyping) throws JsonMappingException
-    {
-        JavaType[] params = config.getTypeFactory().findTypeParameters(type, Iterator.class);
-        JavaType vt = (params == null || params.length != 1) ?
-                TypeFactory.unknownType() : params[0];
-        return buildIteratorSerializer(config, type, beanDesc, staticTyping, vt); 
-    }
-
     /**
      * @since 2.5
      */
@@ -918,18 +914,6 @@
         return new IterableSerializer(valueType, staticTyping, createTypeSerializer(config, valueType));
     }
 
-    @Deprecated // since 2.5
-    protected JsonSerializer<?> buildIterableSerializer(SerializationConfig config,
-            JavaType type, BeanDescription beanDesc,
-            boolean staticTyping)
-        throws JsonMappingException
-    {
-        JavaType[] params = config.getTypeFactory().findTypeParameters(type, Iterable.class);
-        JavaType vt = (params == null || params.length != 1) ?
-                TypeFactory.unknownType() : params[0];
-        return buildIterableSerializer(config, type, beanDesc, staticTyping, vt); 
-    }
-    
     /**
      * @since 2.5
      */
@@ -961,7 +945,7 @@
         @SuppressWarnings("unchecked")
         Class<Enum<?>> enumClass = (Class<Enum<?>>) type.getRawClass();
         JsonSerializer<?> ser = EnumSerializer.construct(enumClass, config, beanDesc, format);
-        // [Issue#120]: Allow post-processing
+        // [databind#120]: Allow post-processing
         if (_factoryConfig.hasSerializerModifiers()) {
             for (BeanSerializerModifier mod : _factoryConfig.serializerModifiers()) {
                 ser = mod.modifyEnumSerializer(config, type, beanDesc, ser);
diff --git a/src/main/java/com/fasterxml/jackson/databind/ser/BeanPropertyWriter.java b/src/main/java/com/fasterxml/jackson/databind/ser/BeanPropertyWriter.java
index b5972fb..49c87af 100644
--- a/src/main/java/com/fasterxml/jackson/databind/ser/BeanPropertyWriter.java
+++ b/src/main/java/com/fasterxml/jackson/databind/ser/BeanPropertyWriter.java
@@ -25,18 +25,18 @@
 
 /**
  * Base bean property handler class, which implements common parts of
- * reflection-based functionality for accessing a property value
- * and serializing it.
- *<p> 
+ * reflection-based functionality for accessing a property value and serializing
+ * it.
+ * <p>
  * Note that current design tries to keep instances immutable (semi-functional
- * style); mostly because these instances are exposed to application
- * code and this is to reduce likelihood of data corruption and
- * synchronization issues.
+ * style); mostly because these instances are exposed to application code and
+ * this is to reduce likelihood of data corruption and synchronization issues.
  */
-@JacksonStdImpl // since 2.6. NOTE: sub-classes typically are not
-public class BeanPropertyWriter
-    extends PropertyWriter // which extends `ConcreteBeanPropertyBase`
-    implements java.io.Serializable // since 2.6
+@JacksonStdImpl
+// since 2.6. NOTE: sub-classes typically are not
+public class BeanPropertyWriter extends PropertyWriter // which extends
+                                                       // `ConcreteBeanPropertyBase`
+        implements java.io.Serializable // since 2.6
 {
     // As of 2.7
     private static final long serialVersionUID = 1L;
@@ -47,19 +47,19 @@
     public final static Object MARKER_FOR_EMPTY = JsonInclude.Include.NON_EMPTY;
 
     /*
-    /**********************************************************
+    /***********************************************************
     /* Basic property metadata: name, type, other
-    /**********************************************************
+    /***********************************************************
      */
 
     /**
-     * Logical name of the property; will be used as the field name
-     * under which value for the property is written.
-     *<p>
-     * NOTE: do NOT change name of this field; it is accessed by
-     * Afterburner module (until 2.4; not directly from 2.5)
-     * ALSO NOTE: ... and while it really ought to be `SerializableString`,
-     * changing that is also binary-incompatible change. So nope.
+     * Logical name of the property; will be used as the field name under which
+     * value for the property is written.
+     * <p>
+     * NOTE: do NOT change name of this field; it is accessed by Afterburner
+     * module (until 2.4; not directly from 2.5) ALSO NOTE: ... and while it
+     * really ought to be `SerializableString`, changing that is also
+     * binary-incompatible change. So nope.
      */
     protected final SerializedString _name;
 
@@ -71,110 +71,106 @@
     protected final PropertyName _wrapperName;
 
     /**
-     * Type property is declared to have, either in class definition 
-     * or associated annotations.
+     * Type property is declared to have, either in class definition or
+     * associated annotations.
      */
     protected final JavaType _declaredType;
 
     /**
-     * Type to use for locating serializer; normally same as return
-     * type of the accessor method, but may be overridden by annotations.
+     * Type to use for locating serializer; normally same as return type of the
+     * accessor method, but may be overridden by annotations.
      */
     protected final JavaType _cfgSerializationType;
 
     /**
-     * Base type of the property, if the declared type is "non-trivial";
-     * meaning it is either a structured type (collection, map, array),
-     * or parameterized. Used to retain type information about contained
-     * type, which is mostly necessary if type meta-data is to be
-     * included.
+     * Base type of the property, if the declared type is "non-trivial"; meaning
+     * it is either a structured type (collection, map, array), or
+     * parameterized. Used to retain type information about contained type,
+     * which is mostly necessary if type meta-data is to be included.
      */
     protected JavaType _nonTrivialBaseType;
 
     /**
-     * Annotations from context (most often, class that declares property,
-     * or in case of sub-class serializer, from that sub-class)
-     *<p>
-     * NOTE: transient just to support JDK serializability; Annotations
-     * do not serialize. At all.
+     * Annotations from context (most often, class that declares property, or in
+     * case of sub-class serializer, from that sub-class)
+     * <p>
+     * NOTE: transient just to support JDK serializability; Annotations do not
+     * serialize. At all.
      */
     protected final transient Annotations _contextAnnotations;
 
     /*
-    /**********************************************************
+    /***********************************************************
     /* Settings for accessing property value to serialize
-    /**********************************************************
+    /***********************************************************
      */
 
     /**
-     * Member (field, method) that represents property and allows access
-     * to associated annotations.
+     * Member (field, method) that represents property and allows access to
+     * associated annotations.
      */
     protected final AnnotatedMember _member;
-    
+
     /**
-     * Accessor method used to get property value, for
-     * method-accessible properties.
-     * Null if and only if {@link #_field} is null.
-     *<p>
+     * Accessor method used to get property value, for method-accessible
+     * properties. Null if and only if {@link #_field} is null.
+     * <p>
      * `transient` (and non-final) only to support JDK serializability.
      */
     protected transient Method _accessorMethod;
-    
+
     /**
-     * Field that contains the property value for field-accessible
-     * properties.
+     * Field that contains the property value for field-accessible properties.
      * Null if and only if {@link #_accessorMethod} is null.
-     *<p>
+     * <p>
      * `transient` (and non-final) only to support JDK serializability.
      */
     protected transient Field _field;
 
     /*
-    /**********************************************************
+    /***********************************************************
     /* Serializers needed
-    /**********************************************************
+    /***********************************************************
      */
 
     /**
-     * Serializer to use for writing out the value: null if it can not
-     * be known statically; non-null if it can.
+     * Serializer to use for writing out the value: null if it can not be known
+     * statically; non-null if it can.
      */
     protected JsonSerializer<Object> _serializer;
 
     /**
-     * Serializer used for writing out null values, if any: if null,
-     * null values are to be suppressed.
+     * Serializer used for writing out null values, if any: if null, null values
+     * are to be suppressed.
      */
     protected JsonSerializer<Object> _nullSerializer;
 
     /**
-     * If property being serialized needs type information to be
-     * included this is the type serializer to use.
-     * Declared type (possibly augmented with annotations) of property
-     * is used for determining exact mechanism to use (compared to
-     * actual runtime type used for serializing actual state).
+     * If property being serialized needs type information to be included this
+     * is the type serializer to use. Declared type (possibly augmented with
+     * annotations) of property is used for determining exact mechanism to use
+     * (compared to actual runtime type used for serializing actual state).
      */
     protected TypeSerializer _typeSerializer;
 
     /**
      * In case serializer is not known statically (i.e. <code>_serializer</code>
-     * is null), we will use a lookup structure for storing dynamically
-     * resolved mapping from type(s) to serializer(s).
+     * is null), we will use a lookup structure for storing dynamically resolved
+     * mapping from type(s) to serializer(s).
      */
     protected transient PropertySerializerMap _dynamicSerializers;
 
     /*
-    /**********************************************************
+    /***********************************************************
     /* Filtering
-    /**********************************************************
+    /***********************************************************
      */
 
     /**
-     * Whether null values are to be suppressed (nothing written out if
-     * value is null) or not. Note that this is a configuration value
-     * during construction, and actual handling relies on setting
-     * (or not) of {@link #_nullSerializer}.
+     * Whether null values are to be suppressed (nothing written out if value is
+     * null) or not. Note that this is a configuration value during
+     * construction, and actual handling relies on setting (or not) of
+     * {@link #_nullSerializer}.
      */
     protected final boolean _suppressNulls;
 
@@ -185,33 +181,32 @@
     protected final Object _suppressableValue;
 
     /**
-     * Alternate set of property writers used when view-based filtering
-     * is available for the Bean.
+     * Alternate set of property writers used when view-based filtering is
+     * available for the Bean.
      */
     protected final Class<?>[] _includeInViews;
 
     /*
     /**********************************************************
-    /* Opaque internal data that bean serializer factory and
+    /* Opaqueinternal data that bean serializer factory and
     /* bean serializers can add.
     /**********************************************************
      */
 
-    protected transient HashMap<Object,Object> _internalSettings;
+    protected transient HashMap<Object, Object> _internalSettings;
 
     /*
-    /**********************************************************
+    /***********************************************************
     /* Construction, configuration
-    /**********************************************************
+    /***********************************************************
      */
 
     @SuppressWarnings("unchecked")
     public BeanPropertyWriter(BeanPropertyDefinition propDef,
             AnnotatedMember member, Annotations contextAnnotations,
-            JavaType declaredType,
-            JsonSerializer<?> ser, TypeSerializer typeSer, JavaType serType,
-            boolean suppressNulls, Object suppressableValue)
-    {
+            JavaType declaredType, JsonSerializer<?> ser,
+            TypeSerializer typeSer, JavaType serType, boolean suppressNulls,
+            Object suppressableValue) {
         super(propDef);
         _member = member;
         _contextAnnotations = contextAnnotations;
@@ -222,7 +217,8 @@
 
         _declaredType = declaredType;
         _serializer = (JsonSerializer<Object>) ser;
-        _dynamicSerializers = (ser == null) ? PropertySerializerMap.emptyForProperties() : null;
+        _dynamicSerializers = (ser == null) ? PropertySerializerMap
+                .emptyForProperties() : null;
         _typeSerializer = typeSer;
         _cfgSerializationType = serType;
 
@@ -233,7 +229,8 @@
             _accessorMethod = (Method) member.getMember();
             _field = null;
         } else {
-            // 01-Dec-2014, tatu: Used to be illegal, but now explicitly allowed for virtual props
+            // 01-Dec-2014, tatu: Used to be illegal, but now explicitly allowed
+            // for virtual props
             _accessorMethod = null;
             _field = null;
         }
@@ -245,9 +242,9 @@
     }
 
     /**
-     * Constructor that may be of use to virtual properties, when there is need for
-     * the zero-arg ("default") constructor, and actual initialization is done
-     * after constructor call.
+     * Constructor that may be of use to virtual properties, when there is need
+     * for the zero-arg ("default") constructor, and actual initialization is
+     * done after constructor call.
      * 
      * @since 2.5
      */
@@ -284,13 +281,13 @@
     /**
      * @since 2.5
      */
-    protected BeanPropertyWriter(BeanPropertyWriter base, PropertyName name)
-    {
+    protected BeanPropertyWriter(BeanPropertyWriter base, PropertyName name) {
         super(base);
-        /* 02-Dec-2014, tatu: This is a big mess, alas, what with dependency
-         *   to MapperConfig to encode, and Afterburner having heartburn
-         *   for SerializableString (vs SerializedString).
-         *   Hope it can be resolved/reworked in 2.6 timeframe, if not for 2.5
+        /*
+         * 02-Dec-2014, tatu: This is a big mess, alas, what with dependency to
+         * MapperConfig to encode, and Afterburner having heartburn for
+         * SerializableString (vs SerializedString). Hope it can be
+         * resolved/reworked in 2.6 timeframe, if not for 2.5
          */
         _name = new SerializedString(name.getSimpleName());
         _wrapperName = base._wrapperName;
@@ -306,7 +303,8 @@
         _nullSerializer = base._nullSerializer;
         // one more thing: copy internal settings, if any
         if (base._internalSettings != null) {
-            _internalSettings = new HashMap<Object,Object>(base._internalSettings);
+            _internalSettings = new HashMap<Object, Object>(
+                    base._internalSettings);
         }
         _cfgSerializationType = base._cfgSerializationType;
         _dynamicSerializers = base._dynamicSerializers;
@@ -330,7 +328,8 @@
         _serializer = base._serializer;
         _nullSerializer = base._nullSerializer;
         if (base._internalSettings != null) {
-            _internalSettings = new HashMap<Object,Object>(base._internalSettings);
+            _internalSettings = new HashMap<Object, Object>(
+                    base._internalSettings);
         }
         _cfgSerializationType = base._cfgSerializationType;
         _dynamicSerializers = base._dynamicSerializers;
@@ -352,15 +351,15 @@
     /**
      * Overridable factory method used by sub-classes
      *
-     * @since 2.6.0
+     * @since 2.6
      */
     protected BeanPropertyWriter _new(PropertyName newName) {
         return new BeanPropertyWriter(this, newName);
     }
 
     /**
-     * Method called to set, reset or clear the configured type serializer
-     * for property.
+     * Method called to set, reset or clear the configured type serializer for
+     * property.
      *
      * @since 2.6
      */
@@ -370,8 +369,6 @@
 
     /**
      * Method called to assign value serializer for property
-     * 
-     * @since 2.0
      */
     public void assignSerializer(JsonSerializer<Object> ser) {
         // may need to disable check in future?
@@ -383,12 +380,10 @@
 
     /**
      * Method called to assign null value serializer for property
-     * 
-     * @since 2.0
      */
     public void assignNullSerializer(JsonSerializer<Object> nullSer) {
         // may need to disable check in future?
-        if (_nullSerializer != null && _nullSerializer != nullSer) {
+        if ((_nullSerializer != null) && (_nullSerializer != nullSer)) {
             throw new IllegalStateException("Can not override null serializer");
         }
         _nullSerializer = nullSer;
@@ -404,20 +399,32 @@
 
     /**
      * Method called to define type to consider as "non-trivial" basetype,
-     * needed for dynamic serialization resolution for complex (usually container)
-     * types
+     * needed for dynamic serialization resolution for complex (usually
+     * container) types
      */
     public void setNonTrivialBaseType(JavaType t) {
         _nonTrivialBaseType = t;
     }
 
+    /**
+     * Method called to ensure that the mutator has proper access rights to
+     * be called, as per configuration. Overridden by implementations that
+     * have mutators that require access, fields and setters.
+     *
+     * @since 2.8.3
+     */
+    public void fixAccess(SerializationConfig config) {
+        _member.fixAccess(config.isEnabled(MapperFeature.OVERRIDE_PUBLIC_ACCESS_MODIFIERS));
+    }
+
     /*
-    /**********************************************************
+    /***********************************************************
     /* JDK Serializability
-    /**********************************************************
+    /***********************************************************
      */
 
-    /* Ideally would not require mutable state, and instead would re-create with
+    /*
+     * Ideally would not require mutable state, and instead would re-create with
      * final settings. However, as things are, with sub-types and all, simplest
      * to just change Field/Method value directly.
      */
@@ -436,21 +443,32 @@
     }
 
     /*
-    /**********************************************************
+    /************************************************************
     /* BeanProperty impl
-    /**********************************************************
+    /***********************************************************
      */
 
     // Note: also part of 'PropertyWriter'
-    @Override public String getName() { return _name.getValue(); }
+    @Override
+    public String getName() {
+        return _name.getValue();
+    }
 
     // Note: also part of 'PropertyWriter'
-    @Override public PropertyName getFullName() { // !!! TODO: impl properly
+    @Override
+    public PropertyName getFullName() { // !!! TODO: impl properly
         return new PropertyName(_name.getValue());
     }
 
-    @Override public JavaType getType() { return _declaredType; }
-    @Override public PropertyName getWrapperName() { return _wrapperName; }
+    @Override
+    public JavaType getType() {
+        return _declaredType;
+    }
+
+    @Override
+    public PropertyName getWrapperName() {
+        return _wrapperName;
+    }
 
     // Note: also part of 'PropertyWriter'
     @Override
@@ -461,32 +479,37 @@
     // Note: also part of 'PropertyWriter'
     @Override
     public <A extends Annotation> A getContextAnnotation(Class<A> acls) {
-        return (_contextAnnotations == null) ? null : _contextAnnotations.get(acls);
+        return (_contextAnnotations == null) ? null : _contextAnnotations
+                .get(acls);
     }
 
-    @Override public AnnotatedMember getMember() { return _member; }
+    @Override
+    public AnnotatedMember getMember() {
+        return _member;
+    }
 
     // @since 2.3 -- needed so it can be overridden by unwrapping writer
-    protected void _depositSchemaProperty(ObjectNode propertiesNode, JsonNode schemaNode) {
+    protected void _depositSchemaProperty(ObjectNode propertiesNode,
+            JsonNode schemaNode) {
         propertiesNode.set(getName(), schemaNode);
     }
 
     /*
-    /**********************************************************
+    /***********************************************************
     /* Managing and accessing of opaque internal settings
     /* (used by extensions)
-    /**********************************************************
+    /***********************************************************
      */
-    
+
     /**
      * Method for accessing value of specified internal setting.
      * 
      * @return Value of the setting, if any; null if none.
      */
-    public Object getInternalSetting(Object key)  {
+    public Object getInternalSetting(Object key) {
         return (_internalSettings == null) ? null : _internalSettings.get(key);
     }
-    
+
     /**
      * Method for setting specific internal setting to given value
      * 
@@ -494,7 +517,7 @@
      */
     public Object setInternalSetting(Object key, Object value) {
         if (_internalSettings == null) {
-            _internalSettings = new HashMap<Object,Object>();
+            _internalSettings = new HashMap<Object, Object>();
         }
         return _internalSettings.put(key, value);
     }
@@ -515,35 +538,49 @@
         }
         return removed;
     }
-    
+
     /*
-    /**********************************************************
+    /***********************************************************
     /* Accessors
-    /**********************************************************
+    /***********************************************************
      */
 
-    public SerializableString getSerializedName() { return _name; }
-    
-    public boolean hasSerializer() { return _serializer != null; }
-    public boolean hasNullSerializer() { return _nullSerializer != null; }
+    public SerializableString getSerializedName() {
+        return _name;
+    }
+
+    public boolean hasSerializer() {
+        return _serializer != null;
+    }
+
+    public boolean hasNullSerializer() {
+        return _nullSerializer != null;
+    }
 
     /**
      * @since 2.6
      */
-    public TypeSerializer getTypeSerializer() { return _typeSerializer; }
+    public TypeSerializer getTypeSerializer() {
+        return _typeSerializer;
+    }
 
     /**
      * Accessor that will return true if this bean property has to support
      * "unwrapping"; ability to replace POJO structural wrapping with optional
-     * name prefix and/or suffix (or in some cases, just removal of wrapper name).
-     *<p>
+     * name prefix and/or suffix (or in some cases, just removal of wrapper
+     * name).
+     * <p>
      * Default implementation simply returns false.
      * 
      * @since 2.3
      */
-    public boolean isUnwrapping() { return false; }
-    
-    public boolean willSuppressNulls() { return _suppressNulls; }
+    public boolean isUnwrapping() {
+        return false;
+    }
+
+    public boolean willSuppressNulls() {
+        return _suppressNulls;
+    }
 
     /**
      * Method called to check to see if this property has a name that would
@@ -556,33 +593,25 @@
             return _wrapperName.equals(name);
         }
         // Bit convoluted since our support for namespaces is spotty but:
-        return name.hasSimpleName(_name.getValue())
-                && !name.hasNamespace();
+        return name.hasSimpleName(_name.getValue()) && !name.hasNamespace();
     }
-    
-    // Needed by BeanSerializer#getSchema
-    public JsonSerializer<Object> getSerializer() { return _serializer; }
 
-    public JavaType getSerializationType() { return _cfgSerializationType; }
+    // Needed by BeanSerializer#getSchema
+    public JsonSerializer<Object> getSerializer() {
+        return _serializer;
+    }
+
+    public JavaType getSerializationType() {
+        return _cfgSerializationType;
+    }
 
     public Class<?> getRawSerializationType() {
-        return (_cfgSerializationType == null) ? null : _cfgSerializationType.getRawClass();
+        return (_cfgSerializationType == null) ? null : _cfgSerializationType
+                .getRawClass();
     }
 
-    /*
-    public JavaType getFullPropertyType() {
-        if (_accessorMethod != null) {
-            return _accessorMethod.getType()
-        }
-        if (_field != null) {
-            return _field.getType();
-        }
-        return null;
-    }
-    */
-    
     /**
-     * @deprecated Since 2.7, to be removed from 2.8, use {@link #getType()} instead.
+     * @deprecated Since 2.7, to be removed from 2.9, use {@link #getType()} instead.
      */
     @Deprecated
     public Class<?> getPropertyType() {
@@ -600,7 +629,7 @@
      *
      * @return The property type, or null if not found.
      *
-     * @deprecated Since 2.7, to be removed from 2.8, use {@link #getType()} instead.
+     * @deprecated Since 2.7, to be removed from 2.9, use {@link #getType()} instead.
      */
     @Deprecated
     public Type getGenericPropertyType() {
@@ -613,24 +642,27 @@
         return null;
     }
 
-    public Class<?>[] getViews() { return _includeInViews; }
+    public Class<?>[] getViews() {
+        return _includeInViews;
+    }
 
     /*
-    /**********************************************************
+    /***********************************************************
     /* PropertyWriter methods (serialization)
-    /**********************************************************
+    /***********************************************************
      */
 
     /**
-     * Method called to access property that this bean stands for, from
-     * within given bean, and to serialize it as a JSON Object field
-     * using appropriate serializer.
+     * Method called to access property that this bean stands for, from within
+     * given bean, and to serialize it as a JSON Object field using appropriate
+     * serializer.
      */
     @Override
-    public void serializeAsField(Object bean, JsonGenerator gen, SerializerProvider prov) throws Exception
-    {
+    public void serializeAsField(Object bean, JsonGenerator gen,
+            SerializerProvider prov) throws Exception {
         // inlined 'get()'
-        final Object value = (_accessorMethod == null) ? _field.get(bean) : _accessorMethod.invoke(bean);
+        final Object value = (_accessorMethod == null) ? _field.get(bean)
+                : _accessorMethod.invoke(bean);
 
         // Null handling is bit different, check that first
         if (value == null) {
@@ -676,33 +708,33 @@
     }
 
     /**
-     * Method called to indicate that serialization of a field was omitted
-     * due to filtering, in cases where backend data format does not allow
-     * basic omission.
+     * Method called to indicate that serialization of a field was omitted due
+     * to filtering, in cases where backend data format does not allow basic
+     * omission.
      * 
      * @since 2.3
      */
     @Override
-    public void serializeAsOmittedField(Object bean, JsonGenerator gen, SerializerProvider prov) throws Exception
-    {
+    public void serializeAsOmittedField(Object bean, JsonGenerator gen,
+            SerializerProvider prov) throws Exception {
         if (!gen.canOmitFields()) {
             gen.writeOmittedField(_name.getValue());
         }
     }
-    
+
     /**
-     * Alternative to {@link #serializeAsField} that is used when a POJO
-     * is serialized as JSON Array; the difference is that no field names
-     * are written.
+     * Alternative to {@link #serializeAsField} that is used when a POJO is
+     * serialized as JSON Array; the difference is that no field names are
+     * written.
      * 
      * @since 2.3
      */
     @Override
-    public void serializeAsElement(Object bean, JsonGenerator gen, SerializerProvider prov)
-        throws Exception
-    {
+    public void serializeAsElement(Object bean, JsonGenerator gen,
+            SerializerProvider prov) throws Exception {
         // inlined 'get()'
-        final Object value = (_accessorMethod == null) ? _field.get(bean) : _accessorMethod.invoke(bean);
+        final Object value = (_accessorMethod == null) ? _field.get(bean)
+                : _accessorMethod.invoke(bean);
         if (value == null) { // nulls need specialized handling
             if (_nullSerializer != null) {
                 _nullSerializer.serialize(null, gen, prov);
@@ -724,11 +756,14 @@
         // and then see if we must suppress certain values (default, empty)
         if (_suppressableValue != null) {
             if (MARKER_FOR_EMPTY == _suppressableValue) {
-                if (ser.isEmpty(prov, value)) { // can NOT suppress entries in tabular output
+                if (ser.isEmpty(prov, value)) { // can NOT suppress entries in
+                                                // tabular output
                     serializeAsPlaceholder(bean, gen, prov);
                     return;
                 }
-            } else if (_suppressableValue.equals(value)) { // can NOT suppress entries in tabular output
+            } else if (_suppressableValue.equals(value)) { // can NOT suppress
+                                                           // entries in tabular
+                                                           // output
                 serializeAsPlaceholder(bean, gen, prov);
                 return;
             }
@@ -747,39 +782,36 @@
     }
 
     /**
-     * Method called to serialize a placeholder used in tabular output when
-     * real value is not to be included (is filtered out), but when we need
-     * an entry so that field indexes will not be off. Typically this should
-     * output null or empty String, depending on datatype.
+     * Method called to serialize a placeholder used in tabular output when real
+     * value is not to be included (is filtered out), but when we need an entry
+     * so that field indexes will not be off. Typically this should output null
+     * or empty String, depending on datatype.
      * 
      * @since 2.1
      */
     @Override
-    public void serializeAsPlaceholder(Object bean, JsonGenerator gen, SerializerProvider prov)
-        throws Exception
-    {
+    public void serializeAsPlaceholder(Object bean, JsonGenerator gen,
+            SerializerProvider prov) throws Exception {
         if (_nullSerializer != null) {
             _nullSerializer.serialize(null, gen, prov);
         } else {
             gen.writeNull();
         }
     }
-    
+
     /*
-    /**********************************************************
+    /***********************************************************
     /* PropertyWriter methods (schema generation)
-    /**********************************************************
+    /***********************************************************
      */
 
     // Also part of BeanProperty implementation
     @Override
     public void depositSchemaProperty(JsonObjectFormatVisitor v,
-            SerializerProvider provider)
-        throws JsonMappingException
-    {
+            SerializerProvider provider) throws JsonMappingException {
         if (v != null) {
             if (isRequired()) {
-                v.property(this); 
+                v.property(this);
             } else {
                 v.optionalProperty(this);
             }
@@ -789,20 +821,23 @@
     // // // Legacy support for JsonFormatVisitable
 
     /**
-     * Attempt to add the output of the given {@link BeanPropertyWriter} in the given {@link ObjectNode}.
-     * Otherwise, add the default schema {@link JsonNode} in place of the writer's output
+     * Attempt to add the output of the given {@link BeanPropertyWriter} in the
+     * given {@link ObjectNode}. Otherwise, add the default schema
+     * {@link JsonNode} in place of the writer's output
      * 
-     * @param propertiesNode Node which the given property would exist within
-     * @param provider Provider that can be used for accessing dynamic aspects of serialization
-     *  processing
+     * @param propertiesNode
+     *            Node which the given property would exist within
+     * @param provider
+     *            Provider that can be used for accessing dynamic aspects of
+     *            serialization processing
      */
     @Override
     @Deprecated
-    public void depositSchemaProperty(ObjectNode propertiesNode, SerializerProvider provider)
-        throws JsonMappingException
-    {
+    public void depositSchemaProperty(ObjectNode propertiesNode,
+            SerializerProvider provider) throws JsonMappingException {
         JavaType propType = getSerializationType();
-        // 03-Dec-2010, tatu: SchemaAware REALLY should use JavaType, but alas it doesn't...
+        // 03-Dec-2010, tatu: SchemaAware REALLY should use JavaType, but alas
+        // it doesn't...
         Type hint = (propType == null) ? getType() : propType.getRawClass();
         JsonNode schemaNode;
         // Maybe it already has annotated/statically configured serializer?
@@ -812,9 +847,11 @@
         }
         boolean isOptional = !isRequired();
         if (ser instanceof SchemaAware) {
-            schemaNode =  ((SchemaAware) ser).getSchema(provider, hint, isOptional) ;
-        } else {  
-            schemaNode = com.fasterxml.jackson.databind.jsonschema.JsonSchema.getDefaultSchemaNode(); 
+            schemaNode = ((SchemaAware) ser).getSchema(provider, hint,
+                    isOptional);
+        } else {
+            schemaNode = com.fasterxml.jackson.databind.jsonschema.JsonSchema
+                    .getDefaultSchemaNode();
         }
         _depositSchemaProperty(propertiesNode, schemaNode);
     }
@@ -825,12 +862,13 @@
     /**********************************************************
      */
 
-    protected JsonSerializer<Object> _findAndAddDynamic(PropertySerializerMap map,
-            Class<?> type, SerializerProvider provider) throws JsonMappingException
-    {
+    protected JsonSerializer<Object> _findAndAddDynamic(
+            PropertySerializerMap map, Class<?> type,
+            SerializerProvider provider) throws JsonMappingException {
         PropertySerializerMap.SerializerAndMapResult result;
         if (_nonTrivialBaseType != null) {
-            JavaType t = provider.constructSpecializedType(_nonTrivialBaseType, type);
+            JavaType t = provider.constructSpecializedType(_nonTrivialBaseType,
+                    type);
             result = map.findAndAddPrimarySerializer(t, provider, this);
         } else {
             result = map.findAndAddPrimarySerializer(type, provider, this);
@@ -843,40 +881,44 @@
     }
 
     /**
-     * Method that can be used to access value of the property this
-     * Object describes, from given bean instance.
-     *<p>
+     * Method that can be used to access value of the property this Object
+     * describes, from given bean instance.
+     * <p>
      * Note: method is final as it should not need to be overridden -- rather,
-     * calling method(s) ({@link #serializeAsField}) should be overridden
-     * to change the behavior
+     * calling method(s) ({@link #serializeAsField}) should be overridden to
+     * change the behavior
      */
     public final Object get(Object bean) throws Exception {
-        return (_accessorMethod == null) ? _field.get(bean) : _accessorMethod.invoke(bean);
+        return (_accessorMethod == null) ? _field.get(bean) : _accessorMethod
+                .invoke(bean);
     }
 
     /**
      * Method called to handle a direct self-reference through this property.
-     * Method can choose to indicate an error by throwing {@link JsonMappingException};
-     * fully handle serialization (and return true); or indicate that it should be
-     * serialized normally (return false).
-     *<p>
+     * Method can choose to indicate an error by throwing
+     * {@link JsonMappingException}; fully handle serialization (and return
+     * true); or indicate that it should be serialized normally (return false).
+     * <p>
      * Default implementation will throw {@link JsonMappingException} if
-     * {@link SerializationFeature#FAIL_ON_SELF_REFERENCES} is enabled;
-     * or return <code>false</code> if it is disabled.
+     * {@link SerializationFeature#FAIL_ON_SELF_REFERENCES} is enabled; or
+     * return <code>false</code> if it is disabled.
      *
-     * @return True if method fully handled self-referential value; false if not (caller
-     *    is to handle it) or {@link JsonMappingException} if there is no way handle it
+     * @return True if method fully handled self-referential value; false if not
+     *         (caller is to handle it) or {@link JsonMappingException} if there
+     *         is no way handle it
      */
-    protected boolean _handleSelfReference(Object bean, JsonGenerator gen, SerializerProvider prov, JsonSerializer<?> ser)
+    protected boolean _handleSelfReference(Object bean, JsonGenerator gen,
+            SerializerProvider prov, JsonSerializer<?> ser)
             throws JsonMappingException {
         if (prov.isEnabled(SerializationFeature.FAIL_ON_SELF_REFERENCES)
                 && !ser.usesObjectId()) {
             // 05-Feb-2013, tatu: Usually a problem, but NOT if we are handling
-            //    object id; this may be the case for BeanSerializers at least.
-            // 13-Feb-2014, tatu: another possible ok case: custom serializer (something
-            //   OTHER than {@link BeanSerializerBase}
+            // object id; this may be the case for BeanSerializers at least.
+            // 13-Feb-2014, tatu: another possible ok case: custom serializer
+            // (something
+            // OTHER than {@link BeanSerializerBase}
             if (ser instanceof BeanSerializerBase) {
-                throw JsonMappingException.from(gen, "Direct self-reference leading to cycle");
+                prov.reportMappingProblem("Direct self-reference leading to cycle");
             }
         }
         return false;
@@ -887,16 +929,20 @@
         StringBuilder sb = new StringBuilder(40);
         sb.append("property '").append(getName()).append("' (");
         if (_accessorMethod != null) {
-            sb.append("via method ").append(_accessorMethod.getDeclaringClass().getName()).append("#").append(_accessorMethod.getName());
+            sb.append("via method ")
+                    .append(_accessorMethod.getDeclaringClass().getName())
+                    .append("#").append(_accessorMethod.getName());
         } else if (_field != null) {
-            sb.append("field \"").append(_field.getDeclaringClass().getName()).append("#").append(_field.getName());
+            sb.append("field \"").append(_field.getDeclaringClass().getName())
+                    .append("#").append(_field.getName());
         } else {
             sb.append("virtual");
         }
         if (_serializer == null) {
             sb.append(", no static serializer");
         } else {
-            sb.append(", static serializer of type "+_serializer.getClass().getName());
+            sb.append(", static serializer of type "
+                    + _serializer.getClass().getName());
         }
         sb.append(')');
         return sb.toString();
diff --git a/src/main/java/com/fasterxml/jackson/databind/ser/BeanSerializer.java b/src/main/java/com/fasterxml/jackson/databind/ser/BeanSerializer.java
index c309bba..7dc0d17 100644
--- a/src/main/java/com/fasterxml/jackson/databind/ser/BeanSerializer.java
+++ b/src/main/java/com/fasterxml/jackson/databind/ser/BeanSerializer.java
@@ -1,9 +1,9 @@
 package com.fasterxml.jackson.databind.ser;
 
 import java.io.IOException;
+import java.util.Set;
 
 import com.fasterxml.jackson.core.JsonGenerator;
-
 import com.fasterxml.jackson.databind.*;
 import com.fasterxml.jackson.databind.ser.impl.BeanAsArraySerializer;
 import com.fasterxml.jackson.databind.ser.impl.ObjectIdWriter;
@@ -64,7 +64,7 @@
         super(src, objectIdWriter, filterId);
     }
     
-    protected BeanSerializer(BeanSerializerBase src, String[] toIgnore) {
+    protected BeanSerializer(BeanSerializerBase src, Set<String> toIgnore) {
         super(src, toIgnore);
     }
 
@@ -99,7 +99,7 @@
     }
 
     @Override
-    protected BeanSerializerBase withIgnorals(String[] toIgnore) {
+    protected BeanSerializerBase withIgnorals(Set<String> toIgnore) {
         return new BeanSerializer(this, toIgnore);
     }
 
@@ -148,9 +148,7 @@
             _serializeWithObjectId(bean, gen, provider, true);
             return;
         }
-        gen.writeStartObject();
-        // [databind#631]: Assign current value, to be accessible by custom serializers
-        gen.setCurrentValue(bean);
+        gen.writeStartObject(bean);
         if (_propertyFilterId != null) {
             serializeFieldsFiltered(bean, gen, provider);
         } else {
diff --git a/src/main/java/com/fasterxml/jackson/databind/ser/BeanSerializerBuilder.java b/src/main/java/com/fasterxml/jackson/databind/ser/BeanSerializerBuilder.java
index d4aa8e0..95613e1 100644
--- a/src/main/java/com/fasterxml/jackson/databind/ser/BeanSerializerBuilder.java
+++ b/src/main/java/com/fasterxml/jackson/databind/ser/BeanSerializerBuilder.java
@@ -179,11 +179,24 @@
             properties = NO_PROPERTIES;
         } else {
             properties = _properties.toArray(new BeanPropertyWriter[_properties.size()]);
+            if (_config.isEnabled(MapperFeature.CAN_OVERRIDE_ACCESS_MODIFIERS)) {
+                for (int i = 0, end = properties.length; i < end; ++i) {
+                    properties[i].fixAccess(_config);
+                }
+            }
+        }
+        if (_anyGetter != null) {
+            _anyGetter.fixAccess(_config);
+        }
+        if (_typeId != null) {
+            if (_config.isEnabled(MapperFeature.CAN_OVERRIDE_ACCESS_MODIFIERS)) {
+                _typeId.fixAccess(_config.isEnabled(MapperFeature.OVERRIDE_PUBLIC_ACCESS_MODIFIERS));
+            }
         }
         return new BeanSerializer(_beanDesc.getType(), this,
                 properties, _filteredProperties);
     }
-    
+
     /**
      * Factory method for constructing an "empty" serializer; one that
      * outputs no properties (but handles JSON objects properly, including
diff --git a/src/main/java/com/fasterxml/jackson/databind/ser/BeanSerializerFactory.java b/src/main/java/com/fasterxml/jackson/databind/ser/BeanSerializerFactory.java
index 4e3760c..921d67e 100644
--- a/src/main/java/com/fasterxml/jackson/databind/ser/BeanSerializerFactory.java
+++ b/src/main/java/com/fasterxml/jackson/databind/ser/BeanSerializerFactory.java
@@ -3,10 +3,13 @@
 import java.util.*;
 import java.util.concurrent.atomic.AtomicReference;
 
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
 import com.fasterxml.jackson.annotation.ObjectIdGenerator;
 import com.fasterxml.jackson.annotation.ObjectIdGenerators;
 import com.fasterxml.jackson.annotation.JsonTypeInfo.As;
+
 import com.fasterxml.jackson.databind.*;
+import com.fasterxml.jackson.databind.cfg.ConfigOverride;
 import com.fasterxml.jackson.databind.cfg.SerializerFactoryConfig;
 import com.fasterxml.jackson.databind.introspect.*;
 import com.fasterxml.jackson.databind.jsontype.NamedType;
@@ -19,7 +22,6 @@
 import com.fasterxml.jackson.databind.ser.std.MapSerializer;
 import com.fasterxml.jackson.databind.ser.std.StdDelegatingSerializer;
 import com.fasterxml.jackson.databind.type.ReferenceType;
-import com.fasterxml.jackson.databind.util.ArrayBuilders;
 import com.fasterxml.jackson.databind.util.ClassUtil;
 import com.fasterxml.jackson.databind.util.Converter;
 
@@ -141,8 +143,17 @@
         boolean staticTyping;
         // Next: we may have annotations that further indicate actual type to use (a super type)
         final AnnotationIntrospector intr = config.getAnnotationIntrospector();
-        JavaType type = (intr == null) ? origType
-                : intr.refineSerializationType(config, beanDesc.getClassInfo(), origType);
+        JavaType type;
+
+        if (intr == null) {
+            type = origType;
+        } else {
+            try {
+                type = intr.refineSerializationType(config, beanDesc.getClassInfo(), origType);
+            } catch (JsonMappingException e) {
+                return prov.reportBadTypeDefinition(beanDesc, e.getMessage());
+            }
+        }
         if (type == origType) { // no changes, won't force static typing
             staticTyping = false;
         } else { // changes; assume static typing; plus, need to re-introspect if class differs
@@ -405,7 +416,7 @@
         // Any properties to suppress?
         props = filterBeanProperties(config, beanDesc, props);
 
-        // [JACKSON-440] Need to allow reordering of properties to serialize
+        // Need to allow reordering of properties to serialize
         if (_factoryConfig.hasSerializerModifiers()) {
             for (BeanSerializerModifier mod : _factoryConfig.serializerModifiers()) {
                 props = mod.orderProperties(config, beanDesc, props);
@@ -423,21 +434,18 @@
 
         AnnotatedMember anyGetter = beanDesc.findAnyGetter();
         if (anyGetter != null) {
-            if (config.canOverrideAccessModifiers()) {
-                anyGetter.fixAccess(config.isEnabled(MapperFeature.OVERRIDE_PUBLIC_ACCESS_MODIFIERS));
-            }
             JavaType type = anyGetter.getType();
             // copied from BasicSerializerFactory.buildMapSerializer():
             boolean staticTyping = config.isEnabled(MapperFeature.USE_STATIC_TYPING);
             JavaType valueType = type.getContentType();
             TypeSerializer typeSer = createTypeSerializer(config, valueType);
             // last 2 nulls; don't know key, value serializers (yet)
-            // 23-Feb-2015, tatu: As per [#705], need to support custom serializers
+            // 23-Feb-2015, tatu: As per [databind#705], need to support custom serializers
             JsonSerializer<?> anySer = findSerializerFromAnnotation(prov, anyGetter);
             if (anySer == null) {
                 // TODO: support '@JsonIgnoreProperties' with any setter?
-                anySer = MapSerializer.construct(/* ignored props*/ null, type, staticTyping,
-                        typeSer, null, null, /*filterId*/ null);
+                anySer = MapSerializer.construct(/* ignored props*/ (Set<String>) null,
+                        type, staticTyping, typeSer, null, null, /*filterId*/ null);
             }
             // TODO: can we find full PropertyName?
             PropertyName name = PropertyName.construct(anyGetter.getName());
@@ -454,9 +462,8 @@
                 builder = mod.updateBuilder(config, beanDesc, builder);
             }
         }
-        
+
         JsonSerializer<Object> ser = (JsonSerializer<Object>) builder.build();
-        
         if (ser == null) {
             // If we get this far, there were no properties found, so no regular BeanSerializer
             // would be constructed. But, couple of exceptions.
@@ -568,7 +575,7 @@
         List<BeanPropertyDefinition> properties = beanDesc.findProperties();
         final SerializationConfig config = prov.getConfig();
 
-        // [JACKSON-429]: ignore specified types
+        // ignore specified types
         removeIgnorableTypes(config, beanDesc, properties);
         
         // and possibly remove ones without matching mutator...
@@ -585,17 +592,11 @@
         PropertyBuilder pb = constructPropertyBuilder(config, beanDesc);
         
         ArrayList<BeanPropertyWriter> result = new ArrayList<BeanPropertyWriter>(properties.size());
-        final boolean fixAccess = config.canOverrideAccessModifiers();
-        final boolean forceAccess = fixAccess && config.isEnabled(MapperFeature.OVERRIDE_PUBLIC_ACCESS_MODIFIERS);
-
         for (BeanPropertyDefinition property : properties) {
             final AnnotatedMember accessor = property.getAccessor();
             // Type id? Requires special handling:
             if (property.isTypeId()) {
-                if (accessor != null) { // only add if we can access... but otherwise?
-                    if (fixAccess) {
-                        accessor.fixAccess(forceAccess);
-                    }
+                if (accessor != null) {
                     builder.setTypeId(accessor);
                 }
                 continue;
@@ -627,15 +628,20 @@
     protected List<BeanPropertyWriter> filterBeanProperties(SerializationConfig config,
             BeanDescription beanDesc, List<BeanPropertyWriter> props)
     {
-        AnnotationIntrospector intr = config.getAnnotationIntrospector();
-        AnnotatedClass ac = beanDesc.getClassInfo();
-        String[] ignored = intr.findPropertiesToIgnore(ac, true);
-        if (ignored != null && ignored.length > 0) {
-            HashSet<String> ignoredSet = ArrayBuilders.arrayToSet(ignored);
-            Iterator<BeanPropertyWriter> it = props.iterator();
-            while (it.hasNext()) {
-                if (ignoredSet.contains(it.next().getName())) {
-                    it.remove();
+        // 01-May-2016, tatu: Which base type to use here gets tricky, since
+        //   it may often make most sense to use general type for overrides,
+        //   but what we have here may be more specific impl type. But for now
+        //   just use it as is.
+        JsonIgnoreProperties.Value ignorals = config.getDefaultPropertyIgnorals(beanDesc.getBeanClass(),
+                beanDesc.getClassInfo());
+        if (ignorals != null) {
+            Set<String> ignored = ignorals.findIgnoredForSerialization();
+            if (!ignored.isEmpty()) {
+                Iterator<BeanPropertyWriter> it = props.iterator();
+                while (it.hasNext()) {
+                    if (ignored.contains(it.next().getName())) {
+                        it.remove();
+                    }
                 }
             }
         }
@@ -653,7 +659,7 @@
      */
     protected void processViews(SerializationConfig config, BeanSerializerBuilder builder)
     {
-        // [JACKSON-232]: whether non-annotated fields are included by default or not is configurable
+        // whether non-annotated fields are included by default or not is configurable
         List<BeanPropertyWriter> props = builder.getProperties();
         boolean includeByDefault = config.isEnabled(MapperFeature.DEFAULT_VIEW_INCLUSION);
         final int propCount = props.size();
@@ -700,12 +706,19 @@
             Class<?> type = accessor.getRawType();
             Boolean result = ignores.get(type);
             if (result == null) {
-                BeanDescription desc = config.introspectClassAnnotations(type);
-                AnnotatedClass ac = desc.getClassInfo();
-                result = intr.isIgnorableType(ac);
-                // default to false, non-ignorable
+                // 21-Apr-2016, tatu: For 2.8, can specify config overrides
+                ConfigOverride override = config.findConfigOverride(type);
+                if (override != null) {
+                    result = override.getIsIgnoredType();
+                }
                 if (result == null) {
-                    result = Boolean.FALSE;
+                    BeanDescription desc = config.introspectClassAnnotations(type);
+                    AnnotatedClass ac = desc.getClassInfo();
+                    result = intr.isIgnorableType(ac);
+                    // default to false, non-ignorable
+                    if (result == null) {
+                        result = Boolean.FALSE;
+                    }
                 }
                 ignores.put(type, result);
             }
@@ -725,7 +738,7 @@
         Iterator<BeanPropertyDefinition> it = properties.iterator();
         while (it.hasNext()) {
             BeanPropertyDefinition property = it.next();
-            // one caveat: as per [JACKSON-806], only remove implicit properties;
+            // one caveat: only remove implicit properties;
             // explicitly annotated ones should remain
             if (!property.couldDeserialize() && !property.isExplicitlyIncluded()) {
                 it.remove();
@@ -778,9 +791,6 @@
         throws JsonMappingException
     {
         final PropertyName name = propDef.getFullName();
-        if (prov.canOverrideAccessModifiers()) {
-            accessor.fixAccess(prov.isEnabled(MapperFeature.OVERRIDE_PUBLIC_ACCESS_MODIFIERS));
-        }
         JavaType type = accessor.getType();
         BeanProperty.Std property = new BeanProperty.Std(name, type, propDef.getWrapperName(),
                 pb.getClassAnnotations(), accessor, propDef.getMetadata());
@@ -803,8 +813,7 @@
         }
         // and if not JAXB collection/array with annotations, maybe regular type info?
         TypeSerializer typeSer = findPropertyTypeSerializer(type, prov.getConfig(), accessor);
-        BeanPropertyWriter pbw = pb.buildWriter(prov, propDef, type, annotatedSerializer,
+        return pb.buildWriter(prov, propDef, type, annotatedSerializer,
                         typeSer, contentTypeSer, accessor, staticTyping);
-        return pbw;
     }
 }
diff --git a/src/main/java/com/fasterxml/jackson/databind/ser/DefaultSerializerProvider.java b/src/main/java/com/fasterxml/jackson/databind/ser/DefaultSerializerProvider.java
index b4984f3..ed8e965 100644
--- a/src/main/java/com/fasterxml/jackson/databind/ser/DefaultSerializerProvider.java
+++ b/src/main/java/com/fasterxml/jackson/databind/ser/DefaultSerializerProvider.java
@@ -36,7 +36,7 @@
 
     /*
     /**********************************************************
-    /* State, for non-blueprint instances: Object Id handling
+    /* State, for non-blueprint instances
     /**********************************************************
      */
 
@@ -47,7 +47,15 @@
     protected transient Map<Object, WritableObjectId> _seenObjectIds;
     
     protected transient ArrayList<ObjectIdGenerator<?>> _objectIdGenerators;
-    
+
+    /**
+     * Generator used for serialization. Needed mostly for error reporting
+     * purposes.
+     *
+     * @since 2.8
+     */
+    protected transient JsonGenerator _generator;
+
     /*
     /**********************************************************
     /* Life-cycle
@@ -66,6 +74,14 @@
     }
 
     /**
+     * Method that sub-classes need to implement: used to create a non-blueprint instances
+     * from the blueprint.
+     * This is needed to retain state during serialization.
+     */
+    public abstract DefaultSerializerProvider createInstance(SerializationConfig config,
+            SerializerFactory jsf);
+
+    /**
      * Method needed to ensure that {@link ObjectMapper#copy} will work
      * properly; specifically, that caches are cleared, but settings
      * will otherwise remain identical; and that no sharing of state
@@ -76,402 +92,48 @@
     public DefaultSerializerProvider copy() {
         throw new IllegalStateException("DefaultSerializerProvider sub-class not overriding copy()");
     }
-    
+
     /*
     /**********************************************************
-    /* Extended API: methods that ObjectMapper will call
+    /* Abstract method impls, factory methods
     /**********************************************************
      */
-
-    /**
-     * Overridable method, used to create a non-blueprint instances from the blueprint.
-     * This is needed to retain state during serialization.
-     */
-    public abstract DefaultSerializerProvider createInstance(SerializationConfig config,
-            SerializerFactory jsf);
-
-    /**
-     * The method to be called by {@link ObjectMapper} and {@link ObjectWriter}
-     * for serializing given value, using serializers that
-     * this provider has access to (via caching and/or creating new serializers
-     * as need be).
-     */
-    public void serializeValue(JsonGenerator gen, Object value) throws IOException
-    {
-        if (value == null) {
-            _serializeNull(gen);
-            return;
-        }
-        Class<?> cls = value.getClass();
-        // true, since we do want to cache root-level typed serializers (ditto for null property)
-        final JsonSerializer<Object> ser = findTypedValueSerializer(cls, true, null);
-
-        // Ok: should we wrap result in an additional property ("root name")?
-        final boolean wrap;
-        PropertyName rootName = _config.getFullRootName();
-
-        if (rootName == null) { // not explicitly specified
-            // [JACKSON-163]
-            wrap = _config.isEnabled(SerializationFeature.WRAP_ROOT_VALUE);
-            if (wrap) {
-                gen.writeStartObject();
-                PropertyName pname = _config.findRootName(value.getClass());
-                gen.writeFieldName(pname.simpleAsEncoded(_config));
-            }
-        } else if (rootName.isEmpty()) {
-            wrap = false;
-        } else { // [JACKSON-764]
-            // empty String means explicitly disabled; non-empty that it is enabled
-            wrap = true;
-            gen.writeStartObject();
-            gen.writeFieldName(rootName.getSimpleName());
-        }
-        try {
-            ser.serialize(value, gen, this);
-            if (wrap) {
-                gen.writeEndObject();
-            }
-        } catch (IOException ioe) { // As per [JACKSON-99], pass IOException and subtypes as-is
-            throw ioe;
-        } catch (Exception e) { // but wrap RuntimeExceptions, to get path information
-            String msg = e.getMessage();
-            if (msg == null) {
-                msg = "[no message for "+e.getClass().getName()+"]";
-            }
-            throw new JsonMappingException(gen, msg, e);
-        }
-    }
-
-    /**
-     * The method to be called by {@link ObjectMapper} and {@link ObjectWriter}
-     * for serializing given value (assumed to be of specified root type,
-     * instead of runtime type of value),
-     * using serializers that
-     * this provider has access to (via caching and/or creating new serializers
-     * as need be),
-     * 
-     * @param rootType Type to use for locating serializer to use, instead of actual
-     *    runtime type. Must be actual type, or one of its super types
-     */
-    public void serializeValue(JsonGenerator gen, Object value, JavaType rootType) throws IOException
-    {
-        if (value == null) {
-            _serializeNull(gen);
-            return;
-        }
-        // Let's ensure types are compatible at this point
-        if (!rootType.getRawClass().isAssignableFrom(value.getClass())) {
-            _reportIncompatibleRootType(value, rootType);
-        }
-        // root value, not reached via property:
-        JsonSerializer<Object> ser = findTypedValueSerializer(rootType, true, null);
-
-        // Ok: should we wrap result in an additional property ("root name")?
-        final boolean wrap;
-        PropertyName rootName = _config.getFullRootName();
-        if (rootName == null) { // not explicitly specified
-            // [JACKSON-163]
-            wrap = _config.isEnabled(SerializationFeature.WRAP_ROOT_VALUE);
-            if (wrap) {
-                gen.writeStartObject();
-                PropertyName pname = _config.findRootName(value.getClass());
-                gen.writeFieldName(pname.simpleAsEncoded(_config));
-            }
-        } else if (rootName.isEmpty()) {
-            wrap = false;
-        } else { // [JACKSON-764]
-            // empty String means explicitly disabled; non-empty that it is enabled
-            wrap = true;
-            gen.writeStartObject();
-            gen.writeFieldName(rootName.getSimpleName());
-        }
-        try {
-            ser.serialize(value, gen, this);
-            if (wrap) {
-                gen.writeEndObject();
-            }
-        } catch (IOException ioe) { // no wrapping for IO (and derived)
-            throw ioe;
-        } catch (Exception e) { // but others do need to be, to get path etc
-            String msg = e.getMessage();
-            if (msg == null) {
-                msg = "[no message for "+e.getClass().getName()+"]";
-            }
-            throw JsonMappingException.from(gen, msg, e);
-        }
-    }
-
-    /**
-     * The method to be called by {@link ObjectWriter}
-     * for serializing given value (assumed to be of specified root type,
-     * instead of runtime type of value), when it may know specific
-     * {@link JsonSerializer} to use.
-     * 
-     * @param rootType Type to use for locating serializer to use, instead of actual
-     *    runtime type, if no serializer is passed
-     * @param ser Root Serializer to use, if not null
-     * 
-     * @since 2.1
-     */
-    public void serializeValue(JsonGenerator gen, Object value, JavaType rootType,
-            JsonSerializer<Object> ser) throws IOException
-    {
-        if (value == null) {
-            _serializeNull(gen);
-            return;
-        }
-        // Let's ensure types are compatible at this point
-        if ((rootType != null) && !rootType.getRawClass().isAssignableFrom(value.getClass())) {
-            _reportIncompatibleRootType(value, rootType);
-        }
-        // root value, not reached via property:
-        if (ser == null) {
-            ser = findTypedValueSerializer(rootType, true, null);
-        }
-        // Ok: should we wrap result in an additional property ("root name")?
-        final boolean wrap;
-        PropertyName rootName = _config.getFullRootName();
-        if (rootName == null) { // not explicitly specified
-            // [JACKSON-163]
-            wrap = _config.isEnabled(SerializationFeature.WRAP_ROOT_VALUE);
-            if (wrap) {
-                gen.writeStartObject();
-                PropertyName pname = (rootType == null)
-                        ? _config.findRootName(value.getClass())
-                        : _config.findRootName(rootType);
-                gen.writeFieldName(pname.simpleAsEncoded(_config));
-            }
-        } else if (rootName.isEmpty()) {
-            wrap = false;
-        } else { // [JACKSON-764]
-            // empty String means explicitly disabled; non-empty that it is enabled
-            wrap = true;
-            gen.writeStartObject();
-            gen.writeFieldName(rootName.getSimpleName());
-        }
-        try {
-            ser.serialize(value, gen, this);
-            if (wrap) {
-                gen.writeEndObject();
-            }
-        } catch (IOException ioe) { // no wrapping for IO (and derived)
-            throw ioe;
-        } catch (Exception e) { // but others do need to be, to get path etc
-            String msg = e.getMessage();
-            if (msg == null) {
-                msg = "[no message for "+e.getClass().getName()+"]";
-            }
-            throw JsonMappingException.from(gen, msg, e);
-        }
-    }
-
-    /**
-     * Alternate serialization call used for polymorphic types, when {@link TypeSerializer}
-     * is already known, but the actual serializer may or may not be.
-     *
-     * @since 2.6
-     */
-    public void serializePolymorphic(JsonGenerator gen, Object value, JavaType rootType,
-            JsonSerializer<Object> valueSer, TypeSerializer typeSer)
-        throws IOException
-    {
-        if (value == null) {
-            _serializeNull(gen);
-            return;
-        }
-        // Let's ensure types are compatible at this point
-        if ((rootType != null) && !rootType.getRawClass().isAssignableFrom(value.getClass())) {
-            _reportIncompatibleRootType(value, rootType);
-        }
-        /* 12-Jun-2015, tatu: nominal root type is necessary for Maps at least;
-         *   possibly collections, but can cause problems for other polymorphic
-         *   types. We really need to distinguish between serialization type,
-         *   base type; but right we don't. Hence this check
-         */
-        if (valueSer == null) {
-            if ((rootType != null) && rootType.isContainerType()) {
-                valueSer = findValueSerializer(rootType, null);
-            } else {
-                valueSer = findValueSerializer(value.getClass(), null);
-            }
-        }
-
-        final boolean wrap;
-        PropertyName rootName = _config.getFullRootName();
-        if (rootName == null) {
-            wrap = _config.isEnabled(SerializationFeature.WRAP_ROOT_VALUE);
-            if (wrap) {
-                gen.writeStartObject();
-                PropertyName pname = _config.findRootName(value.getClass());
-                gen.writeFieldName(pname.simpleAsEncoded(_config));
-            }
-        } else if (rootName.isEmpty()) {
-            wrap = false;
-        } else {
-            wrap = true;
-            gen.writeStartObject();
-            gen.writeFieldName(rootName.getSimpleName());
-        }
-        try {
-            valueSer.serializeWithType(value, gen, this, typeSer);
-            if (wrap) {
-                gen.writeEndObject();
-            }
-        } catch (IOException ioe) { // no wrapping for IO (and derived)
-            throw ioe;
-        } catch (Exception e) { // but others do need to be, to get path etc
-            String msg = e.getMessage();
-            if (msg == null) {
-                msg = "[no message for "+e.getClass().getName()+"]";
-            }
-            throw JsonMappingException.from(gen, msg, e);
-        }
-    }
-
-    /**
-     * @deprecated since 2.6; remove from 2.7 or later
-     */
-    @Deprecated
-    public void serializePolymorphic(JsonGenerator gen, Object value, TypeSerializer typeSer)
-            throws IOException
-    {
-        JavaType t = (value == null) ? null : _config.constructType(value.getClass());
-        serializePolymorphic(gen, value, t, null, typeSer);
-    }
-
-    /**
-     * Helper method called when root value to serialize is null
-     * 
-     * @since 2.3
-     */
-    protected void _serializeNull(JsonGenerator gen) throws IOException
-    {
-        JsonSerializer<Object> ser = getDefaultNullValueSerializer();
-        try {
-            ser.serialize(null, gen, this);
-        } catch (IOException ioe) { // no wrapping for IO (and derived)
-            throw ioe;
-        } catch (Exception e) { // but others do need to be, to get path etc
-            String msg = e.getMessage();
-            if (msg == null) {
-                msg = "[no message for "+e.getClass().getName()+"]";
-            }
-            throw JsonMappingException.from(gen, msg, e);
-        }
-    }
-
-    /**
-     * The method to be called by {@link ObjectMapper}
-     * to generate <a href="http://json-schema.org/">JSON schema</a> for
-     * given type.
-     *
-     * @param type The type for which to generate schema
-     * 
-     * @deprecated Should not be used any more
-     */
-    @Deprecated // since 2.6
-    public com.fasterxml.jackson.databind.jsonschema.JsonSchema generateJsonSchema(Class<?> type)
-        throws JsonMappingException
-    {
-        if (type == null) {
-            throw new IllegalArgumentException("A class must be provided");
-        }
-        /* no need for embedded type information for JSON schema generation (all
-         * type information it needs is accessible via "untyped" serializer)
-         */
-        JsonSerializer<Object> ser = findValueSerializer(type, null);
-        JsonNode schemaNode = (ser instanceof SchemaAware) ?
-                ((SchemaAware) ser).getSchema(this, null) : com.fasterxml.jackson.databind.jsonschema.JsonSchema.getDefaultSchemaNode();
-        if (!(schemaNode instanceof ObjectNode)) {
-            throw new IllegalArgumentException("Class " + type.getName()
-                    +" would not be serialized as a JSON object and therefore has no schema");
-        }
-        return new com.fasterxml.jackson.databind.jsonschema.JsonSchema((ObjectNode) schemaNode);
-    }
     
-    /**
-     * The method to be called by {@link ObjectMapper} and {@link ObjectWriter}
-     * to to expose the format of the given to to the given visitor
-     *
-     * @param javaType The type for which to generate format
-     * @param visitor the visitor to accept the format
-     */
-    public void acceptJsonFormatVisitor(JavaType javaType, JsonFormatVisitorWrapper visitor)
-        throws JsonMappingException
+    @Override
+    public JsonSerializer<Object> serializerInstance(Annotated annotated, Object serDef) throws JsonMappingException
     {
-        if (javaType == null) {
-            throw new IllegalArgumentException("A class must be provided");
+        if (serDef == null) {
+            return null;
         }
-        /* no need for embedded type information for JSON schema generation (all
-         * type information it needs is accessible via "untyped" serializer)
-         */
-        visitor.setProvider(this);
-        findValueSerializer(javaType, null).acceptJsonFormatVisitor(visitor, javaType);
-    }
-
-    /**
-     * Method that can be called to see if this serializer provider
-     * can find a serializer for an instance of given class.
-     *<p>
-     * Note that no Exceptions are thrown, including unchecked ones:
-     * implementations are to swallow exceptions if necessary.
-     */
-    public boolean hasSerializerFor(Class<?> cls, AtomicReference<Throwable> cause)
-    {
-        // 07-Nov-2015, tatu: One special case, Object.class; will work only if
-        //   empty beans are allowed or custom serializer registered. Easiest to
-        //   check here.
-        if (cls == Object.class) {
-            if (!_config.isEnabled(SerializationFeature.FAIL_ON_EMPTY_BEANS)) {
-                return true;
-            }
-        }
+        JsonSerializer<?> ser;
         
-        try {
-            JsonSerializer<?> ser = _findExplicitUntypedSerializer(cls);
-            return (ser != null);
-        } catch (JsonMappingException e) {
-            if (cause != null) {
-                cause.set(e);
+        if (serDef instanceof JsonSerializer) {
+            ser = (JsonSerializer<?>) serDef;
+        } else {
+            /* Alas, there's no way to force return type of "either class
+             * X or Y" -- need to throw an exception after the fact
+             */
+            if (!(serDef instanceof Class)) {
+                throw new IllegalStateException("AnnotationIntrospector returned serializer definition of type "
+                        +serDef.getClass().getName()+"; expected type JsonSerializer or Class<JsonSerializer> instead");
             }
-        } catch (RuntimeException e) {
-            if (cause == null) { // earlier behavior
-                throw e;
+            Class<?> serClass = (Class<?>)serDef;
+            // there are some known "no class" markers to consider too:
+            if (serClass == JsonSerializer.None.class || ClassUtil.isBogusClass(serClass)) {
+                return null;
             }
-            cause.set(e);
+            if (!JsonSerializer.class.isAssignableFrom(serClass)) {
+                throw new IllegalStateException("AnnotationIntrospector returned Class "
+                        +serClass.getName()+"; expected Class<JsonSerializer>");
+            }
+            HandlerInstantiator hi = _config.getHandlerInstantiator();
+            ser = (hi == null) ? null : hi.serializerInstance(_config, annotated, serClass);
+            if (ser == null) {
+                ser = (JsonSerializer<?>) ClassUtil.createInstance(serClass,
+                        _config.canOverrideAccessModifiers());
+            }
         }
-        return false;
-    }
-
-    /*
-    /********************************************************
-    /* Access to caching details
-    /********************************************************
-     */
-
-    /**
-     * Method that can be used to determine how many serializers this
-     * provider is caching currently
-     * (if it does caching: default implementation does)
-     * Exact count depends on what kind of serializers get cached;
-     * default implementation caches all serializers, including ones that
-     * are eagerly constructed (for optimal access speed)
-     *<p> 
-     * The main use case for this method is to allow conditional flushing of
-     * serializer cache, if certain number of entries is reached.
-     */
-    public int cachedSerializersCount() {
-        return _serializerCache.size();
-    }
-
-    /**
-     * Method that will drop all serializers currently cached by this provider.
-     * This can be used to remove memory usage (in case some serializers are
-     * only used once or so), or to force re-construction of serializers after
-     * configuration changes for mapper than owns the provider.
-     */
-    public void flushCachedSerializers() {
-        _serializerCache.flush();
+        return (JsonSerializer<Object>) _handleResolvable(ser);
     }
 
     /*
@@ -531,50 +193,423 @@
         }
         return new IdentityHashMap<Object,WritableObjectId>();
     }
-    
+
     /*
     /**********************************************************
-    /* Factory method impls
+    /* Extended API: simple accesors
+    /**********************************************************
+     */
+
+    /**
+     * Method that can be called to see if this serializer provider
+     * can find a serializer for an instance of given class.
+     *<p>
+     * Note that no Exceptions are thrown, including unchecked ones:
+     * implementations are to swallow exceptions if necessary.
+     */
+    public boolean hasSerializerFor(Class<?> cls, AtomicReference<Throwable> cause)
+    {
+        // 07-Nov-2015, tatu: One special case, Object.class; will work only if
+        //   empty beans are allowed or custom serializer registered. Easiest to
+        //   check here.
+        if (cls == Object.class) {
+            if (!_config.isEnabled(SerializationFeature.FAIL_ON_EMPTY_BEANS)) {
+                return true;
+            }
+        }
+        
+        try {
+            JsonSerializer<?> ser = _findExplicitUntypedSerializer(cls);
+            return (ser != null);
+        } catch (JsonMappingException e) {
+            if (cause != null) {
+                cause.set(e);
+            }
+        } catch (RuntimeException e) {
+            if (cause == null) { // earlier behavior
+                throw e;
+            }
+            cause.set(e);
+        }
+        return false;
+    }
+
+    /**
+     * Accessor for the {@link JsonGenerator} currently in use for serializing
+     * content. Null for blueprint instances; non-null for actual active
+     * provider instances.
+     *
+     * @since 2.8
+     */
+    @Override
+    public JsonGenerator getGenerator() {
+        return _generator;
+    }
+
+    /*
+    /**********************************************************
+    /* Extended API called by ObjectMapper: value serialization
     /**********************************************************
      */
     
-    @Override
-    public JsonSerializer<Object> serializerInstance(Annotated annotated, Object serDef) throws JsonMappingException
+    /**
+     * The method to be called by {@link ObjectMapper} and {@link ObjectWriter}
+     * for serializing given value, using serializers that
+     * this provider has access to (via caching and/or creating new serializers
+     * as need be).
+     */
+    public void serializeValue(JsonGenerator gen, Object value) throws IOException
     {
-        if (serDef == null) {
-            return null;
+        _generator = gen;
+        if (value == null) {
+            _serializeNull(gen);
+            return;
         }
-        JsonSerializer<?> ser;
-        
-        if (serDef instanceof JsonSerializer) {
-            ser = (JsonSerializer<?>) serDef;
-        } else {
-            /* Alas, there's no way to force return type of "either class
-             * X or Y" -- need to throw an exception after the fact
-             */
-            if (!(serDef instanceof Class)) {
-                throw new IllegalStateException("AnnotationIntrospector returned serializer definition of type "
-                        +serDef.getClass().getName()+"; expected type JsonSerializer or Class<JsonSerializer> instead");
+        Class<?> cls = value.getClass();
+        // true, since we do want to cache root-level typed serializers (ditto for null property)
+        final JsonSerializer<Object> ser = findTypedValueSerializer(cls, true, null);
+
+        // Ok: should we wrap result in an additional property ("root name")?
+        final boolean wrap;
+        PropertyName rootName = _config.getFullRootName();
+
+        if (rootName == null) { // not explicitly specified
+            wrap = _config.isEnabled(SerializationFeature.WRAP_ROOT_VALUE);
+            if (wrap) {
+                gen.writeStartObject();
+                PropertyName pname = _config.findRootName(value.getClass());
+                gen.writeFieldName(pname.simpleAsEncoded(_config));
             }
-            Class<?> serClass = (Class<?>)serDef;
-            // there are some known "no class" markers to consider too:
-            if (serClass == JsonSerializer.None.class || ClassUtil.isBogusClass(serClass)) {
-                return null;
-            }
-            if (!JsonSerializer.class.isAssignableFrom(serClass)) {
-                throw new IllegalStateException("AnnotationIntrospector returned Class "
-                        +serClass.getName()+"; expected Class<JsonSerializer>");
-            }
-            HandlerInstantiator hi = _config.getHandlerInstantiator();
-            ser = (hi == null) ? null : hi.serializerInstance(_config, annotated, serClass);
-            if (ser == null) {
-                ser = (JsonSerializer<?>) ClassUtil.createInstance(serClass,
-                        _config.canOverrideAccessModifiers());
-            }
+        } else if (rootName.isEmpty()) {
+            wrap = false;
+        } else { // [JACKSON-764]
+            // empty String means explicitly disabled; non-empty that it is enabled
+            wrap = true;
+            gen.writeStartObject();
+            gen.writeFieldName(rootName.getSimpleName());
         }
-        return (JsonSerializer<Object>) _handleResolvable(ser);
+        try {
+            ser.serialize(value, gen, this);
+            if (wrap) {
+                gen.writeEndObject();
+            }
+        } catch (IOException ioe) { // As per [JACKSON-99], pass IOException and subtypes as-is
+            throw ioe;
+        } catch (Exception e) { // but wrap RuntimeExceptions, to get path information
+            String msg = e.getMessage();
+            if (msg == null) {
+                msg = "[no message for "+e.getClass().getName()+"]";
+            }
+            throw new JsonMappingException(gen, msg, e);
+        }
     }
 
+    /**
+     * The method to be called by {@link ObjectMapper} and {@link ObjectWriter}
+     * for serializing given value (assumed to be of specified root type,
+     * instead of runtime type of value),
+     * using serializers that
+     * this provider has access to (via caching and/or creating new serializers
+     * as need be),
+     * 
+     * @param rootType Type to use for locating serializer to use, instead of actual
+     *    runtime type. Must be actual type, or one of its super types
+     */
+    public void serializeValue(JsonGenerator gen, Object value, JavaType rootType) throws IOException
+    {
+        _generator = gen;
+        if (value == null) {
+            _serializeNull(gen);
+            return;
+        }
+        // Let's ensure types are compatible at this point
+        if (!rootType.getRawClass().isAssignableFrom(value.getClass())) {
+            _reportIncompatibleRootType(value, rootType);
+        }
+        // root value, not reached via property:
+        JsonSerializer<Object> ser = findTypedValueSerializer(rootType, true, null);
+
+        // Ok: should we wrap result in an additional property ("root name")?
+        final boolean wrap;
+        PropertyName rootName = _config.getFullRootName();
+        if (rootName == null) { // not explicitly specified
+            wrap = _config.isEnabled(SerializationFeature.WRAP_ROOT_VALUE);
+            if (wrap) {
+                gen.writeStartObject();
+                PropertyName pname = _config.findRootName(value.getClass());
+                gen.writeFieldName(pname.simpleAsEncoded(_config));
+            }
+        } else if (rootName.isEmpty()) {
+            wrap = false;
+        } else {
+            // empty String means explicitly disabled; non-empty that it is enabled
+            wrap = true;
+            gen.writeStartObject();
+            gen.writeFieldName(rootName.getSimpleName());
+        }
+        try {
+            ser.serialize(value, gen, this);
+            if (wrap) {
+                gen.writeEndObject();
+            }
+        } catch (IOException ioe) { // no wrapping for IO (and derived)
+            throw ioe;
+        } catch (Exception e) { // but others do need to be, to get path etc
+            String msg = e.getMessage();
+            if (msg == null) {
+                msg = "[no message for "+e.getClass().getName()+"]";
+            }
+            reportMappingProblem(e, msg);
+        }
+    }
+
+    /**
+     * The method to be called by {@link ObjectWriter}
+     * for serializing given value (assumed to be of specified root type,
+     * instead of runtime type of value), when it may know specific
+     * {@link JsonSerializer} to use.
+     * 
+     * @param rootType Type to use for locating serializer to use, instead of actual
+     *    runtime type, if no serializer is passed
+     * @param ser Root Serializer to use, if not null
+     * 
+     * @since 2.1
+     */
+    public void serializeValue(JsonGenerator gen, Object value, JavaType rootType,
+            JsonSerializer<Object> ser) throws IOException
+    {
+        _generator = gen;
+        if (value == null) {
+            _serializeNull(gen);
+            return;
+        }
+        // Let's ensure types are compatible at this point
+        if ((rootType != null) && !rootType.getRawClass().isAssignableFrom(value.getClass())) {
+            _reportIncompatibleRootType(value, rootType);
+        }
+        // root value, not reached via property:
+        if (ser == null) {
+            ser = findTypedValueSerializer(rootType, true, null);
+        }
+        // Ok: should we wrap result in an additional property ("root name")?
+        final boolean wrap;
+        PropertyName rootName = _config.getFullRootName();
+        if (rootName == null) { // not explicitly specified
+            // [JACKSON-163]
+            wrap = _config.isEnabled(SerializationFeature.WRAP_ROOT_VALUE);
+            if (wrap) {
+                gen.writeStartObject();
+                PropertyName pname = (rootType == null)
+                        ? _config.findRootName(value.getClass())
+                        : _config.findRootName(rootType);
+                gen.writeFieldName(pname.simpleAsEncoded(_config));
+            }
+        } else if (rootName.isEmpty()) {
+            wrap = false;
+        } else { // [JACKSON-764]
+            // empty String means explicitly disabled; non-empty that it is enabled
+            wrap = true;
+            gen.writeStartObject();
+            gen.writeFieldName(rootName.getSimpleName());
+        }
+        try {
+            ser.serialize(value, gen, this);
+            if (wrap) {
+                gen.writeEndObject();
+            }
+        } catch (IOException ioe) { // no wrapping for IO (and derived)
+            throw ioe;
+        } catch (Exception e) { // but others do need to be, to get path etc
+            String msg = e.getMessage();
+            if (msg == null) {
+                msg = "[no message for "+e.getClass().getName()+"]";
+            }
+            reportMappingProblem(e, msg);
+        }
+    }
+
+    /**
+     * Alternate serialization call used for polymorphic types, when {@link TypeSerializer}
+     * is already known, but the actual serializer may or may not be.
+     *
+     * @since 2.6
+     */
+    public void serializePolymorphic(JsonGenerator gen, Object value, JavaType rootType,
+            JsonSerializer<Object> valueSer, TypeSerializer typeSer)
+        throws IOException
+    {
+        _generator = gen;
+        if (value == null) {
+            _serializeNull(gen);
+            return;
+        }
+        // Let's ensure types are compatible at this point
+        if ((rootType != null) && !rootType.getRawClass().isAssignableFrom(value.getClass())) {
+            _reportIncompatibleRootType(value, rootType);
+        }
+        /* 12-Jun-2015, tatu: nominal root type is necessary for Maps at least;
+         *   possibly collections, but can cause problems for other polymorphic
+         *   types. We really need to distinguish between serialization type,
+         *   base type; but right we don't. Hence this check
+         */
+        if (valueSer == null) {
+            if ((rootType != null) && rootType.isContainerType()) {
+                valueSer = findValueSerializer(rootType, null);
+            } else {
+                valueSer = findValueSerializer(value.getClass(), null);
+            }
+        }
+
+        final boolean wrap;
+        PropertyName rootName = _config.getFullRootName();
+        if (rootName == null) {
+            wrap = _config.isEnabled(SerializationFeature.WRAP_ROOT_VALUE);
+            if (wrap) {
+                gen.writeStartObject();
+                PropertyName pname = _config.findRootName(value.getClass());
+                gen.writeFieldName(pname.simpleAsEncoded(_config));
+            }
+        } else if (rootName.isEmpty()) {
+            wrap = false;
+        } else {
+            wrap = true;
+            gen.writeStartObject();
+            gen.writeFieldName(rootName.getSimpleName());
+        }
+        try {
+            valueSer.serializeWithType(value, gen, this, typeSer);
+            if (wrap) {
+                gen.writeEndObject();
+            }
+        } catch (IOException ioe) { // no wrapping for IO (and derived)
+            throw ioe;
+        } catch (Exception e) { // but others do need to be, to get path etc
+            String msg = e.getMessage();
+            if (msg == null) {
+                msg = "[no message for "+e.getClass().getName()+"]";
+            }
+            reportMappingProblem(e, msg);
+        }
+    }
+
+    /**
+     * @deprecated since 2.6; remove from 2.7 or later
+     */
+    @Deprecated
+    public void serializePolymorphic(JsonGenerator gen, Object value, TypeSerializer typeSer)
+            throws IOException
+    {
+        JavaType t = (value == null) ? null : _config.constructType(value.getClass());
+        serializePolymorphic(gen, value, t, null, typeSer);
+    }
+
+    /**
+     * Helper method called when root value to serialize is null
+     * 
+     * @since 2.3
+     */
+    protected void _serializeNull(JsonGenerator gen) throws IOException
+    {
+        JsonSerializer<Object> ser = getDefaultNullValueSerializer();
+        try {
+            ser.serialize(null, gen, this);
+        } catch (IOException ioe) { // no wrapping for IO (and derived)
+            throw ioe;
+        } catch (Exception e) { // but others do need to be, to get path etc
+            String msg = e.getMessage();
+            if (msg == null) {
+                msg = "[no message for "+e.getClass().getName()+"]";
+            }
+            reportMappingProblem(e, msg);
+        }
+    }
+    /*
+    /********************************************************
+    /* Access to caching details
+    /********************************************************
+     */
+
+    /**
+     * Method that can be used to determine how many serializers this
+     * provider is caching currently
+     * (if it does caching: default implementation does)
+     * Exact count depends on what kind of serializers get cached;
+     * default implementation caches all serializers, including ones that
+     * are eagerly constructed (for optimal access speed)
+     *<p> 
+     * The main use case for this method is to allow conditional flushing of
+     * serializer cache, if certain number of entries is reached.
+     */
+    public int cachedSerializersCount() {
+        return _serializerCache.size();
+    }
+
+    /**
+     * Method that will drop all serializers currently cached by this provider.
+     * This can be used to remove memory usage (in case some serializers are
+     * only used once or so), or to force re-construction of serializers after
+     * configuration changes for mapper than owns the provider.
+     */
+    public void flushCachedSerializers() {
+        _serializerCache.flush();
+    }
+
+    /*
+    /**********************************************************
+    /* Extended API called by ObjectMapper: other
+    /**********************************************************
+     */
+
+    /**
+     * The method to be called by {@link ObjectMapper} and {@link ObjectWriter}
+     * to to expose the format of the given to to the given visitor
+     *
+     * @param javaType The type for which to generate format
+     * @param visitor the visitor to accept the format
+     */
+    public void acceptJsonFormatVisitor(JavaType javaType, JsonFormatVisitorWrapper visitor)
+        throws JsonMappingException
+    {
+        if (javaType == null) {
+            throw new IllegalArgumentException("A class must be provided");
+        }
+        /* no need for embedded type information for JSON schema generation (all
+         * type information it needs is accessible via "untyped" serializer)
+         */
+        visitor.setProvider(this);
+        findValueSerializer(javaType, null).acceptJsonFormatVisitor(visitor, javaType);
+    }
+
+    /**
+     * The method to be called by {@link ObjectMapper}
+     * to generate <a href="http://json-schema.org/">JSON schema</a> for
+     * given type.
+     *
+     * @param type The type for which to generate schema
+     * 
+     * @deprecated Should not be used any more
+     */
+    @Deprecated // since 2.6
+    public com.fasterxml.jackson.databind.jsonschema.JsonSchema generateJsonSchema(Class<?> type)
+        throws JsonMappingException
+    {
+        if (type == null) {
+            throw new IllegalArgumentException("A class must be provided");
+        }
+        /* no need for embedded type information for JSON schema generation (all
+         * type information it needs is accessible via "untyped" serializer)
+         */
+        JsonSerializer<Object> ser = findValueSerializer(type, null);
+        JsonNode schemaNode = (ser instanceof SchemaAware) ?
+                ((SchemaAware) ser).getSchema(this, null) : com.fasterxml.jackson.databind.jsonschema.JsonSchema.getDefaultSchemaNode();
+        if (!(schemaNode instanceof ObjectNode)) {
+            throw new IllegalArgumentException("Class " + type.getName()
+                    +" would not be serialized as a JSON object and therefore has no schema");
+        }
+        return new com.fasterxml.jackson.databind.jsonschema.JsonSchema((ObjectNode) schemaNode);
+    }
+    
+    
     /*
     /**********************************************************
     /* Helper classes
@@ -591,7 +626,8 @@
         public Impl() { super(); }
         public Impl(Impl src) { super(src); }
 
-        protected Impl(SerializerProvider src, SerializationConfig config,SerializerFactory f) {
+        protected Impl(SerializerProvider src, SerializationConfig config,
+                SerializerFactory f) {
             super(src, config, f);
         }
 
diff --git a/src/main/java/com/fasterxml/jackson/databind/ser/PropertyBuilder.java b/src/main/java/com/fasterxml/jackson/databind/ser/PropertyBuilder.java
index f89612e..6363421 100644
--- a/src/main/java/com/fasterxml/jackson/databind/ser/PropertyBuilder.java
+++ b/src/main/java/com/fasterxml/jackson/databind/ser/PropertyBuilder.java
@@ -16,17 +16,10 @@
 {
     // @since 2.7
     private final static Object NO_DEFAULT_MARKER = Boolean.FALSE;
-    
+
     final protected SerializationConfig _config;
     final protected BeanDescription _beanDesc;
 
-    /**
-     * Default inclusion mode for properties of the POJO for which
-     * properties are collected; possibly overridden on
-     * per-property basis.
-     */
-    final protected JsonInclude.Value _defaultInclusion;
-
     final protected AnnotationIntrospector _annotationIntrospector;
 
     /**
@@ -40,11 +33,41 @@
      */
     protected Object _defaultBean;
 
+    /**
+     * Default inclusion mode for properties of the POJO for which
+     * properties are collected; possibly overridden on
+     * per-property basis. Combines global inclusion defaults and
+     * per-type (annotation and type-override) inclusion overrides.
+     */
+    final protected JsonInclude.Value _defaultInclusion;
+
+    /**
+     * Marker flag used to indicate that "real" default values are to be used
+     * for properties, as per per-type value inclusion of type <code>NON_DEFAULT</code>
+     *
+     * @since 2.8
+     */
+    final protected boolean _useRealPropertyDefaults;
+    
     public PropertyBuilder(SerializationConfig config, BeanDescription beanDesc)
     {
         _config = config;
         _beanDesc = beanDesc;
-        _defaultInclusion = beanDesc.findPropertyInclusion(config.getDefaultPropertyInclusion());
+        // 08-Sep-2016, tatu: This gets tricky, with 3 levels of definitions:
+        //  (a) global default inclusion
+        //  (b) per-type default inclusion (from annotation or config overrides;
+        //     latter having precedence
+        //  Cc) per-property override
+        //
+        //  and not only requiring merging, but also considering special handling
+        //  for NON_DEFAULT in case of (b) (vs (a) or (c))
+        JsonInclude.Value inclPerType = JsonInclude.Value.merge(
+                beanDesc.findPropertyInclusion(JsonInclude.Value.empty()),
+                config.getDefaultPropertyInclusion(beanDesc.getBeanClass(),
+                        JsonInclude.Value.empty()));
+        _defaultInclusion = JsonInclude.Value.merge(config.getDefaultPropertyInclusion(),
+                inclPerType);
+        _useRealPropertyDefaults = inclPerType.getValueInclusion() == JsonInclude.Include.NON_DEFAULT;
         _annotationIntrospector = _config.getAnnotationIntrospector();
     }
 
@@ -63,6 +86,7 @@
      *    to use for contained values (only used for properties that are
      *    of container type)
      */
+    @SuppressWarnings("deprecation")
     protected BeanPropertyWriter buildWriter(SerializerProvider prov,
             BeanPropertyDefinition propDef, JavaType declaredType, JsonSerializer<?> ser,
             TypeSerializer typeSer, TypeSerializer contentTypeSer,
@@ -70,7 +94,12 @@
         throws JsonMappingException
     {
         // do we have annotation that forces type to use (to declared type or its super type)?
-        JavaType serializationType = findSerializationType(am, defaultUseStaticTyping, declaredType);
+        JavaType serializationType;
+        try {
+            serializationType = findSerializationType(am, defaultUseStaticTyping, declaredType);
+        } catch (JsonMappingException e) {
+            return prov.reportBadPropertyDefinition(_beanDesc, propDef, e.getMessage());
+        }
 
         // Container types can have separate type serializers for content (value / element) type
         if (contentTypeSer != null) {
@@ -85,44 +114,60 @@
             JavaType ct = serializationType.getContentType();
             // Not exactly sure why, but this used to occur; better check explicitly:
             if (ct == null) {
-                throw new IllegalStateException("Problem trying to create BeanPropertyWriter for property '"
-                        +propDef.getName()+"' (of type "+_beanDesc.getType()+"); serialization type "+serializationType+" has no content");
+                prov.reportBadPropertyDefinition(_beanDesc, propDef,
+                        "serialization type "+serializationType+" has no content");
             }
             serializationType = serializationType.withContentTypeHandler(contentTypeSer);
             ct = serializationType.getContentType();
         }
-        
+
         Object valueToSuppress = null;
         boolean suppressNulls = false;
 
-        JsonInclude.Value inclV = _defaultInclusion.withOverrides(propDef.findInclusion());
+        // 12-Jul-2016, tatu: [databind#1256] Need to make sure we consider type refinement
+        JavaType actualType = (serializationType == null) ? declaredType : serializationType;
+        
+        // 17-Aug-2016, tatu: Default inclusion covers global default (for all types), as well
+        //   as type-default for enclosing POJO. What we need, then, is per-type default (if any)
+        //   for declared property type... and finally property annotation overrides
+        JsonInclude.Value inclV = _config.getDefaultPropertyInclusion(actualType.getRawClass(),
+                _defaultInclusion);
+
+        // property annotation override
+        
+        inclV = inclV.withOverrides(propDef.findInclusion());
         JsonInclude.Include inclusion = inclV.getValueInclusion();
+
         if (inclusion == JsonInclude.Include.USE_DEFAULTS) { // should not occur but...
             inclusion = JsonInclude.Include.ALWAYS;
         }
-
-        /*
-        JsonInclude.Include inclusion = propDef.findInclusion().getValueInclusion();
-        if (inclusion == JsonInclude.Include.USE_DEFAULTS) { // since 2.6
-            inclusion = _defaultInclusion;
-            if (inclusion == null) {
-                inclusion = JsonInclude.Include.ALWAYS;
-            }
-        }
-        */
-
+        
         switch (inclusion) {
         case NON_DEFAULT:
             // 11-Nov-2015, tatu: This is tricky because semantics differ between cases,
-            //    so that if enclosing class has this, we may need to values of property,
+            //    so that if enclosing class has this, we may need to access values of property,
             //    whereas for global defaults OR per-property overrides, we have more
             //    static definition. Sigh.
-            // First: case of class specifying it; try to find POJO property defaults
-            JavaType t = (serializationType == null) ? declaredType : serializationType;
-            if (_defaultInclusion.getValueInclusion() == JsonInclude.Include.NON_DEFAULT) {
-                valueToSuppress = getPropertyDefaultValue(propDef.getName(), am, t);
+            // First: case of class/type specifying it; try to find POJO property defaults
+            Object defaultBean;
+
+            // 16-Oct-2016, tatu: Note: if we can not for some reason create "default instance",
+            //    revert logic to the case of general/per-property handling, so both
+            //    type-default AND null are to be excluded.
+            //    (as per [databind#1417]
+            if (_useRealPropertyDefaults && (defaultBean = getDefaultBean()) != null) {
+                // 07-Sep-2016, tatu: may also need to front-load access forcing now
+                if (prov.isEnabled(MapperFeature.CAN_OVERRIDE_ACCESS_MODIFIERS)) {
+                    am.fixAccess(_config.isEnabled(MapperFeature.OVERRIDE_PUBLIC_ACCESS_MODIFIERS));
+                }
+                try {
+                    valueToSuppress = am.getValue(defaultBean);
+                } catch (Exception e) {
+                    _throwWrapped(e, propDef.getName(), defaultBean);
+                }
             } else {
-                valueToSuppress = getDefaultValue(t);
+                valueToSuppress = getDefaultValue(actualType);
+                suppressNulls = true;
             }
             if (valueToSuppress == null) {
                 suppressNulls = true;
@@ -131,13 +176,12 @@
                     valueToSuppress = ArrayBuilders.getArrayComparator(valueToSuppress);
                 }
             }
-
             break;
         case NON_ABSENT: // new with 2.6, to support Guava/JDK8 Optionals
             // always suppress nulls
             suppressNulls = true;
             // and for referential types, also "empty", which in their case means "absent"
-            if (declaredType.isReferenceType()) {
+            if (actualType.isReferenceType()) {
                 valueToSuppress = BeanPropertyWriter.MARKER_FOR_EMPTY;
             }
             break;
@@ -153,7 +197,7 @@
         case ALWAYS: // default
         default:
             // we may still want to suppress empty collections, as per [JACKSON-254]:
-            if (declaredType.isContainerType()
+            if (actualType.isContainerType()
                     && !_config.isEnabled(SerializationFeature.WRITE_EMPTY_JSON_ARRAYS)) {
                 valueToSuppress = BeanPropertyWriter.MARKER_FOR_EMPTY;
             }
@@ -192,6 +236,7 @@
         throws JsonMappingException
     {
         JavaType secondary = _annotationIntrospector.refineSerializationType(_config, a, declaredType);
+
         // 11-Oct-2015, tatu: As of 2.7, not 100% sure following checks are needed. But keeping
         //    for now, just in case
         if (secondary != declaredType) {
@@ -263,15 +308,19 @@
     /**
      * Accessor used to find out "default value" for given property, to use for
      * comparing values to serialize, to determine whether to exclude value from serialization with
-     * inclusion type of {@link com.fasterxml.jackson.annotation.JsonInclude.Include#NON_EMPTY}.
+     * inclusion type of {@link com.fasterxml.jackson.annotation.JsonInclude.Include#NON_DEFAULT}.
      * This method is called when we specifically want to know default value within context
      * of a POJO, when annotation is within containing class, and not for property or
      * defined as global baseline.
      *<p>
-     * Note that returning of pseudo-type 
+     * Note that returning of pseudo-type
+     * {@link com.fasterxml.jackson.annotation.JsonInclude.Include#NON_EMPTY} requires special handling.
      *
      * @since 2.7
+     * @deprecated Since 2.8.5 since this will not allow determining difference between "no default instance"
+     *    case and default being `null`.
      */
+    @Deprecated // since 2.8.5
     protected Object getPropertyDefaultValue(String name, AnnotatedMember member,
             JavaType type)
     {
diff --git a/src/main/java/com/fasterxml/jackson/databind/ser/impl/BeanAsArraySerializer.java b/src/main/java/com/fasterxml/jackson/databind/ser/impl/BeanAsArraySerializer.java
index d646ab5..3f764ca 100644
--- a/src/main/java/com/fasterxml/jackson/databind/ser/impl/BeanAsArraySerializer.java
+++ b/src/main/java/com/fasterxml/jackson/databind/ser/impl/BeanAsArraySerializer.java
@@ -1,6 +1,7 @@
 package com.fasterxml.jackson.databind.ser.impl;
 
 import java.io.IOException;
+import java.util.Set;
 
 import com.fasterxml.jackson.core.JsonGenerator;
 import com.fasterxml.jackson.databind.*;
@@ -62,7 +63,7 @@
         _defaultSerializer = src;
     }
 
-    protected BeanAsArraySerializer(BeanSerializerBase src, String[] toIgnore) {
+    protected BeanAsArraySerializer(BeanSerializerBase src, Set<String> toIgnore) {
         super(src, toIgnore);
         _defaultSerializer = src;
     }
@@ -102,9 +103,9 @@
     public BeanSerializerBase withFilterId(Object filterId) {
         return new BeanAsArraySerializer(this, _objectIdWriter, filterId);
     }
-    
+
     @Override
-    protected BeanAsArraySerializer withIgnorals(String[] toIgnore) {
+    protected BeanAsArraySerializer withIgnorals(Set<String> toIgnore) {
         return new BeanAsArraySerializer(this, toIgnore);
     }
 
diff --git a/src/main/java/com/fasterxml/jackson/databind/ser/impl/FailingSerializer.java b/src/main/java/com/fasterxml/jackson/databind/ser/impl/FailingSerializer.java
index 79b291f..6021fa8 100644
--- a/src/main/java/com/fasterxml/jackson/databind/ser/impl/FailingSerializer.java
+++ b/src/main/java/com/fasterxml/jackson/databind/ser/impl/FailingSerializer.java
@@ -13,7 +13,7 @@
 
 /**
  * Special bogus "serializer" that will throw
- * {@link JsonGenerationException} if its {@link #serialize}
+ * {@link JsonMappingException} if its {@link #serialize}
  * gets invoked. Most commonly registered as handler for unknown types,
  * as well as for catching unintended usage (like trying to use null
  * as Map/Object key).
@@ -32,7 +32,7 @@
     @Override
     public void serialize(Object value, JsonGenerator g, SerializerProvider provider) throws IOException
     {
-        throw new JsonGenerationException(_msg, g);
+        provider.reportMappingProblem(_msg);
     }
 
     @Override
diff --git a/src/main/java/com/fasterxml/jackson/databind/ser/impl/MapEntrySerializer.java b/src/main/java/com/fasterxml/jackson/databind/ser/impl/MapEntrySerializer.java
index 4b36328..7deb535 100644
--- a/src/main/java/com/fasterxml/jackson/databind/ser/impl/MapEntrySerializer.java
+++ b/src/main/java/com/fasterxml/jackson/databind/ser/impl/MapEntrySerializer.java
@@ -187,9 +187,7 @@
     public void serialize(Map.Entry<?, ?> value, JsonGenerator gen, SerializerProvider provider)
         throws IOException
     {
-        gen.writeStartObject();
-        // [databind#631]: Assign current value, to be accessible by custom serializers
-        gen.setCurrentValue(value);
+        gen.writeStartObject(value);
         if (_valueSerializer != null) {
             serializeUsing(value, gen, provider, _valueSerializer);
         } else {
diff --git a/src/main/java/com/fasterxml/jackson/databind/ser/impl/StringArraySerializer.java b/src/main/java/com/fasterxml/jackson/databind/ser/impl/StringArraySerializer.java
index c1e574f..bbd9e23 100644
--- a/src/main/java/com/fasterxml/jackson/databind/ser/impl/StringArraySerializer.java
+++ b/src/main/java/com/fasterxml/jackson/databind/ser/impl/StringArraySerializer.java
@@ -28,6 +28,7 @@
     /* Note: not clean in general, but we are betting against
      * anyone re-defining properties of String.class here...
      */
+    @SuppressWarnings("deprecation")
     private final static JavaType VALUE_TYPE = TypeFactory.defaultInstance().uncheckedSimpleType(String.class);
 
     public final static StringArraySerializer instance = new StringArraySerializer();
diff --git a/src/main/java/com/fasterxml/jackson/databind/ser/impl/UnknownSerializer.java b/src/main/java/com/fasterxml/jackson/databind/ser/impl/UnknownSerializer.java
index f6498f1..6c1530b 100644
--- a/src/main/java/com/fasterxml/jackson/databind/ser/impl/UnknownSerializer.java
+++ b/src/main/java/com/fasterxml/jackson/databind/ser/impl/UnknownSerializer.java
@@ -29,7 +29,7 @@
     {
         // 27-Nov-2009, tatu: As per [JACKSON-201] may or may not fail...
         if (provider.isEnabled(SerializationFeature.FAIL_ON_EMPTY_BEANS)) {
-            failForEmpty(gen, value);
+            failForEmpty(provider, value);
         }
         // But if it's fine, we'll just output empty JSON Object:
         gen.writeStartObject();
@@ -41,7 +41,7 @@
             TypeSerializer typeSer) throws IOException
     {
         if (provider.isEnabled(SerializationFeature.FAIL_ON_EMPTY_BEANS)) {
-            failForEmpty(gen, value);
+            failForEmpty(provider, value);
         }
         typeSer.writeTypePrefixForObject(value, gen);
         typeSer.writeTypeSuffixForObject(value, gen);
@@ -64,8 +64,9 @@
         visitor.expectAnyFormat(typeHint);
     }
 
-    protected void failForEmpty(JsonGenerator gen, Object value) throws JsonMappingException {
-        throw JsonMappingException.from(gen,
-                "No serializer found for class "+value.getClass().getName()+" and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS) )");
+    protected void failForEmpty(SerializerProvider prov, Object value)
+            throws JsonMappingException {
+        prov.reportMappingProblem("No serializer found for class %s and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS)",
+                value.getClass().getName());
     }
 }
diff --git a/src/main/java/com/fasterxml/jackson/databind/ser/impl/UnwrappingBeanSerializer.java b/src/main/java/com/fasterxml/jackson/databind/ser/impl/UnwrappingBeanSerializer.java
index aa502a2..834e03a 100644
--- a/src/main/java/com/fasterxml/jackson/databind/ser/impl/UnwrappingBeanSerializer.java
+++ b/src/main/java/com/fasterxml/jackson/databind/ser/impl/UnwrappingBeanSerializer.java
@@ -1,7 +1,6 @@
 package com.fasterxml.jackson.databind.ser.impl;
 
 import com.fasterxml.jackson.core.JsonGenerator;
-
 import com.fasterxml.jackson.databind.*;
 import com.fasterxml.jackson.databind.jsontype.TypeSerializer;
 import com.fasterxml.jackson.databind.ser.BeanPropertyWriter;
@@ -9,6 +8,7 @@
 import com.fasterxml.jackson.databind.util.NameTransformer;
 
 import java.io.IOException;
+import java.util.Set;
 
 public class UnwrappingBeanSerializer
     extends BeanSerializerBase
@@ -49,7 +49,7 @@
         _nameTransformer = src._nameTransformer;
     }
 
-    protected UnwrappingBeanSerializer(UnwrappingBeanSerializer src, String[] toIgnore) {
+    protected UnwrappingBeanSerializer(UnwrappingBeanSerializer src, Set<String> toIgnore) {
         super(src, toIgnore);
         _nameTransformer = src._nameTransformer;
     }
@@ -82,7 +82,7 @@
     }
 
     @Override
-    protected BeanSerializerBase withIgnorals(String[] toIgnore) {
+    protected BeanSerializerBase withIgnorals(Set<String> toIgnore) {
         return new UnwrappingBeanSerializer(this, toIgnore);
     }
 
@@ -126,10 +126,8 @@
     		TypeSerializer typeSer) throws IOException
     {
         if (provider.isEnabled(SerializationFeature.FAIL_ON_UNWRAPPED_TYPE_IDENTIFIERS)) {
-            throw JsonMappingException.from(gen,
-                    "Unwrapped property requires use of type information: can not serialize without disabling `SerializationFeature.FAIL_ON_UNWRAPPED_TYPE_IDENTIFIERS`");
+            provider.reportMappingProblem("Unwrapped property requires use of type information: can not serialize without disabling `SerializationFeature.FAIL_ON_UNWRAPPED_TYPE_IDENTIFIERS`");
         }
-
         gen.setCurrentValue(bean); // [databind#631]
         if (_objectIdWriter != null) {
             _serializeWithObjectId(bean, gen, provider, typeSer);
diff --git a/src/main/java/com/fasterxml/jackson/databind/ser/std/ArraySerializerBase.java b/src/main/java/com/fasterxml/jackson/databind/ser/std/ArraySerializerBase.java
index e1a3f1a..c89409c 100644
--- a/src/main/java/com/fasterxml/jackson/databind/ser/std/ArraySerializerBase.java
+++ b/src/main/java/com/fasterxml/jackson/databind/ser/std/ArraySerializerBase.java
@@ -87,14 +87,14 @@
             Boolean unwrapSingle);
 
     @Override
-    public JsonSerializer<?> createContextual(SerializerProvider provider,
+    public JsonSerializer<?> createContextual(SerializerProvider serializers,
             BeanProperty property) throws JsonMappingException
     {
         Boolean unwrapSingle = null;
 
         // First: if we have a property, may have property-annotation overrides
         if (property != null) {
-            JsonFormat.Value format = property.findPropertyFormat(provider.getConfig(), _handledType);
+            JsonFormat.Value format = findFormatOverrides(serializers, property, handledType());
             if (format != null) {
                 unwrapSingle = format.getFeature(JsonFormat.Feature.WRITE_SINGLE_ELEM_ARRAYS_UNWRAPPED);
                 if (unwrapSingle != _unwrapSingle) {
@@ -119,9 +119,9 @@
                 return;
             }
         }
+        gen.setCurrentValue(value);
         gen.writeStartArray();
         // [databind#631]: Assign current value, to be accessible by custom serializers
-        gen.setCurrentValue(value);
         serializeContents(value, gen, provider);
         gen.writeEndArray();
     }
@@ -131,7 +131,6 @@
             TypeSerializer typeSer)
         throws IOException
     {
-        // note: let's NOT consider [JACKSON-805] here; gets too complicated, and probably just won't work
         typeSer.writeTypePrefixForArray(value, gen);
         // [databind#631]: Assign current value, to be accessible by custom serializers
         gen.setCurrentValue(value);
diff --git a/src/main/java/com/fasterxml/jackson/databind/ser/std/AsArraySerializerBase.java b/src/main/java/com/fasterxml/jackson/databind/ser/std/AsArraySerializerBase.java
index 7d84b33..a1bd6b9 100644
--- a/src/main/java/com/fasterxml/jackson/databind/ser/std/AsArraySerializerBase.java
+++ b/src/main/java/com/fasterxml/jackson/databind/ser/std/AsArraySerializerBase.java
@@ -161,7 +161,7 @@
      * known statically.
      */
     @Override
-    public JsonSerializer<?> createContextual(SerializerProvider provider,
+    public JsonSerializer<?> createContextual(SerializerProvider serializers,
             BeanProperty property)
         throws JsonMappingException
     {
@@ -169,43 +169,39 @@
         if (typeSer != null) {
             typeSer = typeSer.forProperty(property);
         }
-        /* 29-Sep-2012, tatu: Actually, we need to do much more contextual
-         *    checking here since we finally know for sure the property,
-         *    and it may have overrides
-         */
         JsonSerializer<?> ser = null;
         Boolean unwrapSingle = null;
         // First: if we have a property, may have property-annotation overrides
         
         if (property != null) {
-            final AnnotationIntrospector intr = provider.getAnnotationIntrospector();
+            final AnnotationIntrospector intr = serializers.getAnnotationIntrospector();
             AnnotatedMember m = property.getMember();
             if (m != null) {
                 Object serDef = intr.findContentSerializer(m);
                 if (serDef != null) {
-                    ser = provider.serializerInstance(m, serDef);
+                    ser = serializers.serializerInstance(m, serDef);
                 }
             }
-            JsonFormat.Value format = property.findPropertyFormat(provider.getConfig(), _handledType);
-            if (format != null) {
-                unwrapSingle = format.getFeature(JsonFormat.Feature.WRITE_SINGLE_ELEM_ARRAYS_UNWRAPPED);
-            }
+        }
+        JsonFormat.Value format = findFormatOverrides(serializers, property, handledType());
+        if (format != null) {
+            unwrapSingle = format.getFeature(JsonFormat.Feature.WRITE_SINGLE_ELEM_ARRAYS_UNWRAPPED);
         }
         if (ser == null) {
             ser = _elementSerializer;
         }
         // 18-Feb-2013, tatu: May have a content converter:
-        ser = findConvertingContentSerializer(provider, property, ser);
+        ser = findConvertingContentSerializer(serializers, property, ser);
         if (ser == null) {
             // 30-Sep-2012, tatu: One more thing -- if explicit content type is annotated,
             //   we can consider it a static case as well.
             if (_elementType != null) {
                 if (_staticTyping && !_elementType.isJavaLangObject()) {
-                    ser = provider.findValueSerializer(_elementType, property);
+                    ser = serializers.findValueSerializer(_elementType, property);
                 }
             }
         } else {
-            ser = provider.handleSecondaryContextualization(ser, property);
+            ser = serializers.handleSecondaryContextualization(ser, property);
         }
         if ((ser != _elementSerializer)
                 || (property != _property)
diff --git a/src/main/java/com/fasterxml/jackson/databind/ser/std/AtomicReferenceSerializer.java b/src/main/java/com/fasterxml/jackson/databind/ser/std/AtomicReferenceSerializer.java
index 4d1fb89..7726bb0 100644
--- a/src/main/java/com/fasterxml/jackson/databind/ser/std/AtomicReferenceSerializer.java
+++ b/src/main/java/com/fasterxml/jackson/databind/ser/std/AtomicReferenceSerializer.java
@@ -1,120 +1,40 @@
 package com.fasterxml.jackson.databind.ser.std;
 
-import java.io.IOException;
 import java.util.concurrent.atomic.AtomicReference;
 
 import com.fasterxml.jackson.annotation.JsonInclude;
-import com.fasterxml.jackson.core.JsonGenerator;
+
 import com.fasterxml.jackson.databind.*;
-import com.fasterxml.jackson.databind.annotation.JsonSerialize;
-import com.fasterxml.jackson.databind.introspect.Annotated;
-import com.fasterxml.jackson.databind.jsonFormatVisitors.JsonFormatVisitorWrapper;
 import com.fasterxml.jackson.databind.jsontype.TypeSerializer;
-import com.fasterxml.jackson.databind.ser.ContextualSerializer;
-import com.fasterxml.jackson.databind.ser.impl.PropertySerializerMap;
 import com.fasterxml.jackson.databind.type.ReferenceType;
 import com.fasterxml.jackson.databind.util.NameTransformer;
 
-// Since 2.6 in its own class
 public class AtomicReferenceSerializer
-    extends StdSerializer<AtomicReference<?>>
-    implements ContextualSerializer
+    extends ReferenceTypeSerializer<AtomicReference<?>>
 {
     private static final long serialVersionUID = 1L;
 
-    /**
-     * Declared type parameter for Optional.
-     */
-    protected final JavaType _referredType;
-
-    protected final BeanProperty _property;
-
-    /**
-     * Type serializer used for values, if any.
-     *
-     * @since 2.7
-     */
-    protected final TypeSerializer _valueTypeSerializer;
-
-    /**
-     * @since 2.7
-     */
-    protected final JsonSerializer<Object> _valueSerializer;
-
-    /**
-     * To support unwrapped values of dynamic types, will need this:
-     *
-     * @since 2.7
-     */
-    protected final NameTransformer _unwrapper;
-
-    /**
-     * Further guidance on serialization-inclusion (or not), regarding
-     * contained value (if any).
-     *
-     * @since 2.7
-     */
-    protected final JsonInclude.Include _contentInclusion;
-    
-    /**
-     * If element type can not be statically determined, mapping from
-     * runtime type to serializer is handled using this object
-     *
-     * @since 2.7
-     */
-    protected transient PropertySerializerMap _dynamicSerializers;
-
     /*
     /**********************************************************
     /* Constructors, factory methods
     /**********************************************************
      */
 
-    public AtomicReferenceSerializer(ReferenceType fullType, boolean staticTyping, TypeSerializer vts,
-            JsonSerializer<Object> ser)
+    public AtomicReferenceSerializer(ReferenceType fullType, boolean staticTyping,
+            TypeSerializer vts, JsonSerializer<Object> ser)
     {
-        super(fullType);
-        _referredType = fullType.getReferencedType();
-        _property = null;
-        _valueTypeSerializer = vts;
-        _valueSerializer = ser;
-        _unwrapper = null;
-        _contentInclusion = null;
-        _dynamicSerializers = PropertySerializerMap.emptyForProperties();
+        super(fullType, staticTyping, vts, ser);
     }
 
-    @SuppressWarnings("unchecked")
     protected AtomicReferenceSerializer(AtomicReferenceSerializer base, BeanProperty property,
             TypeSerializer vts, JsonSerializer<?> valueSer,
             NameTransformer unwrapper,
             JsonInclude.Include contentIncl)
     {
-        super(base);
-        _referredType = base._referredType;
-        _dynamicSerializers = base._dynamicSerializers;
-        _property = property;
-        _valueTypeSerializer = vts;
-        _valueSerializer = (JsonSerializer<Object>) valueSer;
-        _unwrapper = unwrapper;
-        if ((contentIncl == JsonInclude.Include.USE_DEFAULTS)
-                || (contentIncl == JsonInclude.Include.ALWAYS)) {
-            _contentInclusion = null;
-        } else {
-            _contentInclusion = contentIncl;
-        }
+        super(base, property, vts, valueSer, unwrapper, contentIncl);
     }
 
     @Override
-    public JsonSerializer<AtomicReference<?>> unwrappingSerializer(NameTransformer transformer) {
-        JsonSerializer<Object> ser = _valueSerializer;
-        if (ser != null) {
-            ser = ser.unwrappingSerializer(transformer);
-        }
-        NameTransformer unwrapper = (_unwrapper == null) ? transformer
-                : NameTransformer.chainedTransformer(transformer, _unwrapper);
-        return withResolved(_property, _valueTypeSerializer, ser, unwrapper, _contentInclusion);
-    }
-    
     protected AtomicReferenceSerializer withResolved(BeanProperty prop,
             TypeSerializer vts, JsonSerializer<?> valueSer,
             NameTransformer unwrapper,
@@ -130,227 +50,22 @@
 
     /*
     /**********************************************************
-    /* Contextualization (support for property annotations)
+    /* Abstract method impls
     /**********************************************************
      */
 
     @Override
-    public JsonSerializer<?> createContextual(SerializerProvider provider,
-            BeanProperty property) throws JsonMappingException
-    {
-        TypeSerializer typeSer = _valueTypeSerializer;
-        if (typeSer != null) {
-            typeSer = typeSer.forProperty(property);
-        }
-        // First: do we have an annotation override from property?
-        JsonSerializer<?> ser = findAnnotatedContentSerializer(provider, property);;
-        if (ser == null) {
-            // If not, use whatever was configured by type
-            ser = _valueSerializer;
-            if (ser == null) {
-                // A few conditions needed to be able to fetch serializer here:
-                if (_useStatic(provider, property, _referredType)) {
-                    ser = _findSerializer(provider, _referredType, property);
-                }
-            } else {
-                ser = provider.handlePrimaryContextualization(ser, property);
-            }
-        }
-        // Also: may want to have more refined exclusion based on referenced value
-        JsonInclude.Include contentIncl = _contentInclusion;
-        if (property != null) {
-            JsonInclude.Value incl = property.findPropertyInclusion(provider.getConfig(),
-                    AtomicReference.class);
-            JsonInclude.Include newIncl = incl.getContentInclusion();
-            if ((newIncl != contentIncl) && (newIncl != JsonInclude.Include.USE_DEFAULTS)) {
-                contentIncl = newIncl;
-            }
-        }
-        return withResolved(property, typeSer, ser, _unwrapper, contentIncl);
-    }
-
-    protected boolean _useStatic(SerializerProvider provider, BeanProperty property,
-            JavaType referredType)
-    {
-        // First: no serializer for `Object.class`, must be dynamic
-        if (referredType.isJavaLangObject()) {
-            return false;
-        }
-        // but if type is final, might as well fetch
-        if (referredType.isFinal()) { // or should we allow annotation override? (only if requested...)
-            return true;
-        }
-        // also: if indicated by typing, should be considered static
-        if (referredType.useStaticType()) {
-            return true;
-        }
-        // if neither, maybe explicit annotation?
-        AnnotationIntrospector intr = provider.getAnnotationIntrospector();
-        if ((intr != null) && (property != null)) {
-            Annotated ann = property.getMember();
-            if (ann != null) {
-                JsonSerialize.Typing t = intr.findSerializationTyping(property.getMember());
-                if (t == JsonSerialize.Typing.STATIC) {
-                    return true;
-                }
-                if (t == JsonSerialize.Typing.DYNAMIC) {
-                    return false;
-                }
-            }
-        }
-        // and finally, may be forced by global static typing (unlikely...)
-        return provider.isEnabled(MapperFeature.USE_STATIC_TYPING);
-    }
-
-    /*
-    /**********************************************************
-    /* Accessors
-    /**********************************************************
-     */
-
-    @Override
-    public boolean isEmpty(SerializerProvider provider, AtomicReference<?> value)
-    {
-        if (value == null) {
-            return true;
-        }
-        Object contents = value.get();
-        if (contents == null) {
-            return true;
-        }
-        if (_contentInclusion == null) {
-            return false;
-        }
-        JsonSerializer<Object> ser = _valueSerializer;
-        if (ser == null) {
-            try {
-                ser = _findCachedSerializer(provider, contents.getClass());
-            } catch (JsonMappingException e) { // nasty but necessary
-                throw new RuntimeJsonMappingException(e);
-            }
-        }
-        return ser.isEmpty(provider, contents);
-
+    protected boolean _isValueEmpty(AtomicReference<?> value) {
+        return value.get() == null;
     }
 
     @Override
-    public boolean isUnwrappingSerializer() {
-        return (_unwrapper != null);
-    }
-
-    /*
-    /**********************************************************
-    /* Serialization methods
-    /**********************************************************
-     */
-
-    @Override
-    public void serialize(AtomicReference<?> ref, JsonGenerator g, SerializerProvider provider)
-        throws IOException
-    {
-        Object value = ref.get();
-        if (value == null) {
-            if (_unwrapper == null) {
-                provider.defaultSerializeNull(g);
-            }
-            return;
-        }
-        JsonSerializer<Object> ser = _valueSerializer;
-        if (ser == null) {
-            ser = _findCachedSerializer(provider, value.getClass());
-        }
-        if (_valueTypeSerializer != null) {
-            ser.serializeWithType(value, g, provider, _valueTypeSerializer);
-        } else {
-            ser.serialize(value, g, provider);
-        }
+    protected Object _getReferenced(AtomicReference<?> value) {
+        return value.get();
     }
 
     @Override
-    public void serializeWithType(AtomicReference<?> ref,
-            JsonGenerator g, SerializerProvider provider,
-            TypeSerializer typeSer) throws IOException
-    {
-        Object value = ref.get();
-        if (value == null) {
-            if (_unwrapper == null) {
-                provider.defaultSerializeNull(g);
-            }
-            return;
-        }
-
-        // 19-Apr-2016, tatu: In order to basically "skip" the whole wrapper level
-        //    (which is what non-polymorphic serialization does too), we will need
-        //    to simply delegate call, I think, and NOT try to use it here.
-        
-        // Otherwise apply type-prefix/suffix, then std serialize:
-        /*
-        typeSer.writeTypePrefixForScalar(ref, g);
-        serialize(ref, g, provider);
-        typeSer.writeTypeSuffixForScalar(ref, g);
-        */
-
-        JsonSerializer<Object> ser = _valueSerializer;
-        if (ser == null) {
-            ser = _findCachedSerializer(provider, value.getClass());
-        }
-        ser.serializeWithType(value, g, provider, typeSer);
+    protected Object _getReferencedIfPresent(AtomicReference<?> value) {
+        return value.get();
     }
-
-    /*
-    /**********************************************************
-    /* Introspection support
-    /**********************************************************
-     */
-
-    @Override
-    public void acceptJsonFormatVisitor(JsonFormatVisitorWrapper visitor, JavaType typeHint)
-        throws JsonMappingException
-    {
-        JsonSerializer<?> ser = _valueSerializer;
-        if (ser == null) {
-            ser = _findSerializer(visitor.getProvider(), _referredType, _property);
-            if (_unwrapper != null) {
-                ser = ser.unwrappingSerializer(_unwrapper);
-            }
-        }
-        ser.acceptJsonFormatVisitor(visitor, _referredType);
-    }
-
-    /*
-    /**********************************************************
-    /* Helper methods
-    /**********************************************************
-     */
-    
-    /**
-     * Helper method that encapsulates logic of retrieving and caching required
-     * serializer.
-     */
-    private final JsonSerializer<Object> _findCachedSerializer(SerializerProvider provider,
-            Class<?> type) throws JsonMappingException
-    {
-        JsonSerializer<Object> ser = _dynamicSerializers.serializerFor(type);
-        if (ser == null) {
-            ser = _findSerializer(provider, type, _property);
-            if (_unwrapper != null) {
-                ser = ser.unwrappingSerializer(_unwrapper);
-            }
-            _dynamicSerializers = _dynamicSerializers.newWith(type, ser);
-        }
-        return ser;
-    }
-
-    private final JsonSerializer<Object> _findSerializer(SerializerProvider provider,
-            Class<?> type, BeanProperty prop) throws JsonMappingException
-    {
-        return provider.findTypedValueSerializer(type, true, prop);
-    }
-
-    private final JsonSerializer<Object> _findSerializer(SerializerProvider provider,
-        JavaType type, BeanProperty prop) throws JsonMappingException
-    {
-        return provider.findTypedValueSerializer(type, true, prop);
-    }
-
 }
diff --git a/src/main/java/com/fasterxml/jackson/databind/ser/std/BeanSerializerBase.java b/src/main/java/com/fasterxml/jackson/databind/ser/std/BeanSerializerBase.java
index 3b838cc..ab0850e 100644
--- a/src/main/java/com/fasterxml/jackson/databind/ser/std/BeanSerializerBase.java
+++ b/src/main/java/com/fasterxml/jackson/databind/ser/std/BeanSerializerBase.java
@@ -4,12 +4,9 @@
 import java.lang.reflect.Type;
 import java.util.*;
 
-import com.fasterxml.jackson.annotation.JsonFormat;
-import com.fasterxml.jackson.annotation.ObjectIdGenerator;
-import com.fasterxml.jackson.annotation.ObjectIdGenerators;
+import com.fasterxml.jackson.annotation.*;
 import com.fasterxml.jackson.core.*;
 import com.fasterxml.jackson.databind.*;
-import com.fasterxml.jackson.databind.introspect.Annotated;
 import com.fasterxml.jackson.databind.introspect.AnnotatedMember;
 import com.fasterxml.jackson.databind.introspect.ObjectIdInfo;
 import com.fasterxml.jackson.databind.jsonFormatVisitors.JsonFormatVisitable;
@@ -161,12 +158,16 @@
         _serializationShape = src._serializationShape;
     }
 
+    @Deprecated // since 2.8, remove soon
     protected BeanSerializerBase(BeanSerializerBase src, String[] toIgnore)
     {
+        this(src, ArrayBuilders.arrayToSet(toIgnore));
+    }
+    
+    protected BeanSerializerBase(BeanSerializerBase src, Set<String> toIgnore)
+    {
         super(src._handledType);
 
-        // Bit clumsy, but has to do:
-        HashSet<String> ignoredSet = ArrayBuilders.arrayToSet(toIgnore);
         final BeanPropertyWriter[] propsIn = src._props;
         final BeanPropertyWriter[] fpropsIn = src._filteredProps;
         final int len = propsIn.length;
@@ -177,7 +178,7 @@
         for (int i = 0; i < len; ++i) {
             BeanPropertyWriter bpw = propsIn[i];
             // should be ignored?
-            if (ignoredSet.contains(bpw.getName())) {
+            if ((toIgnore != null) && toIgnore.contains(bpw.getName())) {
                 continue;
             }
             propsOut.add(bpw);
@@ -207,9 +208,20 @@
      * Mutant factory used for creating a new instance with additional
      * set of properties to ignore (from properties this instance otherwise has)
      * 
-     * @since 2.0
+     * @since 2.8
      */
-    protected abstract BeanSerializerBase withIgnorals(String[] toIgnore);
+    protected abstract BeanSerializerBase withIgnorals(Set<String> toIgnore);
+    
+    /**
+     * Mutant factory used for creating a new instance with additional
+     * set of properties to ignore (from properties this instance otherwise has)
+     * 
+     * @deprecated since 2.8
+     */
+    @Deprecated
+    protected BeanSerializerBase withIgnorals(String[] toIgnore) {
+        return withIgnorals(ArrayBuilders.arrayToSet(toIgnore));
+    }
 
     /**
      * Mutant factory for creating a variant that output POJO as a
@@ -393,38 +405,38 @@
         
         // Let's start with one big transmutation: Enums that are annotated
         // to serialize as Objects may want to revert
+        JsonFormat.Value format = findFormatOverrides(provider, property, handledType());
         JsonFormat.Shape shape = null;
-        if (accessor != null) {
-            JsonFormat.Value format = intr.findFormat((Annotated) accessor);
-
-            if (format != null) {
-                shape = format.getShape();
-                // or, alternatively, asked to revert "back to" other representations...
-                if (shape != _serializationShape) {
-                    if (_handledType.isEnum()) {
-                        switch (shape) {
-                        case STRING:
-                        case NUMBER:
-                        case NUMBER_INT:
-                            // 12-Oct-2014, tatu: May need to introspect full annotations... but
-                            //   for now, just do class ones
-                            BeanDescription desc = config.introspectClassAnnotations(_handledType);
-                            JsonSerializer<?> ser = EnumSerializer.construct(_handledType,
-                                    provider.getConfig(), desc, format);
-                            return provider.handlePrimaryContextualization(ser, property);
-                        }
+        if ((format != null) && format.hasShape()) {
+            shape = format.getShape();
+            // or, alternatively, asked to revert "back to" other representations...
+            if ((shape != JsonFormat.Shape.ANY) && (shape != _serializationShape)) {
+                if (_handledType.isEnum()) {
+                    switch (shape) {
+                    case STRING:
+                    case NUMBER:
+                    case NUMBER_INT:
+                        // 12-Oct-2014, tatu: May need to introspect full annotations... but
+                        //   for now, just do class ones
+                        BeanDescription desc = config.introspectClassAnnotations(_handledType);
+                        JsonSerializer<?> ser = EnumSerializer.construct(_handledType,
+                                provider.getConfig(), desc, format);
+                        return provider.handlePrimaryContextualization(ser, property);
                     }
                 }
             }
         }
 
         ObjectIdWriter oiw = _objectIdWriter;
-        String[] ignorals = null;
+        Set<String> ignoredProps = null;
         Object newFilterId = null;
-        
+
         // Then we may have an override for Object Id
         if (accessor != null) {
-            ignorals = intr.findPropertiesToIgnore(accessor, true);
+            JsonIgnoreProperties.Value ignorals = intr.findPropertyIgnorals(accessor);
+            if (ignorals != null) {
+                ignoredProps = ignorals.findIgnoredForSerialization();
+            }
             ObjectIdInfo objectIdInfo = intr.findObjectIdInfo(accessor);
             if (objectIdInfo == null) {
                 // no ObjectId override, but maybe ObjectIdRef?
@@ -501,8 +513,8 @@
             }
         }
         // And possibly add more properties to ignore
-        if (ignorals != null && ignorals.length != 0) {
-            contextual = contextual.withIgnorals(ignorals);
+        if ((ignoredProps != null) && !ignoredProps.isEmpty()) {
+            contextual = contextual.withIgnorals(ignoredProps);
         }
         if (newFilterId != null) {
             contextual = contextual.withFilterId(newFilterId);
@@ -590,7 +602,7 @@
             return;
         }
         if (startEndObject) {
-            gen.writeStartObject();
+            gen.writeStartObject(bean);
         }
         objectId.writeAsField(gen, provider, w);
         if (_propertyFilterId != null) {
diff --git a/src/main/java/com/fasterxml/jackson/databind/ser/std/DateTimeSerializerBase.java b/src/main/java/com/fasterxml/jackson/databind/ser/std/DateTimeSerializerBase.java
index 68dbf40..4b9312b 100644
--- a/src/main/java/com/fasterxml/jackson/databind/ser/std/DateTimeSerializerBase.java
+++ b/src/main/java/com/fasterxml/jackson/databind/ser/std/DateTimeSerializerBase.java
@@ -13,7 +13,6 @@
 import com.fasterxml.jackson.core.JsonParser;
 
 import com.fasterxml.jackson.databind.*;
-import com.fasterxml.jackson.databind.introspect.Annotated;
 import com.fasterxml.jackson.databind.jsonFormatVisitors.*;
 import com.fasterxml.jackson.databind.ser.ContextualSerializer;
 import com.fasterxml.jackson.databind.util.StdDateFormat;
@@ -28,7 +27,7 @@
      * Java timestamp, regardless of other settings.
      */
     protected final Boolean _useTimestamp;
-    
+
     /**
      * Specific format to use, if not default format: non null value
      * also indicates that serialization is to be done as JSON String,
@@ -50,35 +49,76 @@
     public JsonSerializer<?> createContextual(SerializerProvider serializers,
             BeanProperty property) throws JsonMappingException
     {
-        if (property != null) {
-            JsonFormat.Value format = serializers.getAnnotationIntrospector().findFormat((Annotated)property.getMember());
-            if (format != null) {
-
-            	// Simple case first: serialize as numeric timestamp?
-                JsonFormat.Shape shape = format.getShape();
-                if (shape.isNumeric()) {
-                    return withFormat(Boolean.TRUE, null);
-                }
-
-                if ((shape == JsonFormat.Shape.STRING) || format.hasPattern()
-                                || format.hasLocale() || format.hasTimeZone()) {
-                    TimeZone tz = format.getTimeZone();
-                    final String pattern = format.hasPattern()
-                                    ? format.getPattern()
-                                    : StdDateFormat.DATE_FORMAT_STR_ISO8601;
-                    final Locale loc = format.hasLocale()
-                                    ? format.getLocale()
-                                    : serializers.getLocale();
-                    SimpleDateFormat df = new SimpleDateFormat(pattern, loc);
-                    if (tz == null) {
-                        tz = serializers.getTimeZone();
-                    }
-                    df.setTimeZone(tz);
-                    return withFormat(Boolean.FALSE, df);
-                }
-            }
+        if (property == null) {
+            return this;
         }
-        return this;
+        JsonFormat.Value format = findFormatOverrides(serializers, property, handledType());
+        if (format == null) {
+            return this;
+        }
+        // Simple case first: serialize as numeric timestamp?
+        JsonFormat.Shape shape = format.getShape();
+        if (shape.isNumeric()) {
+            return withFormat(Boolean.TRUE, null);
+        }
+
+        // 08-Jun-2017, tatu: With [databind#1648], this gets bit tricky..
+        // First: custom pattern will override things
+        if (format.hasPattern()) {
+            final Locale loc = format.hasLocale()
+                            ? format.getLocale()
+                            : serializers.getLocale();
+            SimpleDateFormat df = new SimpleDateFormat(format.getPattern(), loc);
+            TimeZone tz = format.hasTimeZone() ? format.getTimeZone()
+                    : serializers.getTimeZone();
+            df.setTimeZone(tz);
+            return withFormat(Boolean.FALSE, df);
+        }
+
+        // Otherwise, need one of these changes:
+        final boolean hasLocale = format.hasLocale();
+        final boolean hasTZ = format.hasTimeZone();
+        final boolean asString = (shape == JsonFormat.Shape.STRING);
+
+        if (!hasLocale && !hasTZ && !asString) {
+            return this;
+        }
+
+        DateFormat df0 = serializers.getConfig().getDateFormat();
+        // Jackson's own `StdDateFormat` is quite easy to deal with...
+        if (df0 instanceof StdDateFormat) {
+            StdDateFormat std = (StdDateFormat) df0;
+            if (format.hasLocale()) {
+                std = std.withLocale(format.getLocale());
+            }
+            if (format.hasTimeZone()) {
+                std = std.withTimeZone(format.getTimeZone());
+            }
+            return withFormat(Boolean.FALSE, std);
+        }
+
+        // 08-Jun-2017, tatu: Unfortunately there's no generally usable
+        //    mechanism for changing `DateFormat` instances (or even clone()ing)
+        //    So: require it be `SimpleDateFormat`; can't config other types
+        if (!(df0 instanceof SimpleDateFormat)) {
+//            serializers.reportBadDefinition(handledType(), String.format(
+            serializers.reportMappingProblem(
+"Configured `DateFormat` (%s) not a `SimpleDateFormat`; can not configure `Locale` or `TimeZone`",
+df0.getClass().getName());
+        }
+        SimpleDateFormat df = (SimpleDateFormat) df0;
+        if (hasLocale) {
+            // Ugh. No way to change `Locale`, create copy; must re-crete completely:
+            df = new SimpleDateFormat(df.toPattern(), format.getLocale());
+        } else {
+            df = (SimpleDateFormat) df.clone();
+        }
+        TimeZone newTz = format.getTimeZone();
+        boolean changeTZ = (newTz != null) && !newTz.equals(df.getTimeZone());
+        if (changeTZ) {
+            df.setTimeZone(newTz);
+        }
+        return withFormat(Boolean.FALSE, df);
     }
 
     /*
diff --git a/src/main/java/com/fasterxml/jackson/databind/ser/std/EnumSerializer.java b/src/main/java/com/fasterxml/jackson/databind/ser/std/EnumSerializer.java
index 95e16a5..dae384a 100644
--- a/src/main/java/com/fasterxml/jackson/databind/ser/std/EnumSerializer.java
+++ b/src/main/java/com/fasterxml/jackson/databind/ser/std/EnumSerializer.java
@@ -11,7 +11,6 @@
 
 import com.fasterxml.jackson.databind.*;
 import com.fasterxml.jackson.databind.annotation.JacksonStdImpl;
-import com.fasterxml.jackson.databind.introspect.Annotated;
 import com.fasterxml.jackson.databind.jsonFormatVisitors.JsonFormatVisitorWrapper;
 import com.fasterxml.jackson.databind.jsonFormatVisitors.JsonStringFormatVisitor;
 import com.fasterxml.jackson.databind.node.ArrayNode;
@@ -24,8 +23,6 @@
  *<p>
  * Based on {@link StdScalarSerializer} since the JSON value is
  * scalar (String).
- * 
- * @author tatu
  */
 @JacksonStdImpl
 public class EnumSerializer
@@ -70,7 +67,7 @@
         _values = v;
         _serializeAsIndex = serializeAsIndex;
     }
-    
+
     /**
      * Factory method used by {@link com.fasterxml.jackson.databind.ser.BasicSerializerFactory}
      * for constructing serializer instance of Enum types.
@@ -86,7 +83,7 @@
          *   handle toString() case dynamically (for example)
          */
         EnumValues v = EnumValues.constructFromName(config, (Class<Enum<?>>) enumClass);
-        Boolean serializeAsIndex = _isShapeWrittenUsingIndex(enumClass, format, true);
+        Boolean serializeAsIndex = _isShapeWrittenUsingIndex(enumClass, format, true, null);
         return new EnumSerializer(v, serializeAsIndex);
     }
 
@@ -96,12 +93,15 @@
      * choice here, however.
      */
     @Override
-    public JsonSerializer<?> createContextual(SerializerProvider prov, BeanProperty property) throws JsonMappingException
+    public JsonSerializer<?> createContextual(SerializerProvider serializers,
+            BeanProperty property) throws JsonMappingException
     {
         if (property != null) {
-            JsonFormat.Value format = prov.getAnnotationIntrospector().findFormat((Annotated) property.getMember());
+            JsonFormat.Value format = findFormatOverrides(serializers,
+                    property, handledType());
             if (format != null) {
-                Boolean serializeAsIndex = _isShapeWrittenUsingIndex(property.getType().getRawClass(), format, false);
+                Boolean serializeAsIndex = _isShapeWrittenUsingIndex(property.getType().getRawClass(),
+                        format, false, _serializeAsIndex);
                 if (serializeAsIndex != _serializeAsIndex) {
                     return new EnumSerializer(_values, serializeAsIndex);
                 }
@@ -140,11 +140,16 @@
         }
         gen.writeString(_values.serializedValueFor(en));
     }
-    
+
+    /*
+    /**********************************************************
+    /* Schema support
+    /**********************************************************
+     */
+
     @Override
     public JsonNode getSchema(SerializerProvider provider, Type typeHint)
     {
-        // [JACKSON-684]: serialize as index?
         if (_serializeAsIndex(provider)) {
             return createSchemaNode("integer", true);
         }
@@ -205,28 +210,32 @@
     }
 
     /**
-     * Helper method called to check whether 
+     * Helper method called to check whether serialization should be done using
+     * index (number) or not.
      */
     protected static Boolean _isShapeWrittenUsingIndex(Class<?> enumClass,
-            JsonFormat.Value format, boolean fromClass)
+            JsonFormat.Value format, boolean fromClass,
+            Boolean defaultValue)
     {
         JsonFormat.Shape shape = (format == null) ? null : format.getShape();
         if (shape == null) {
-            return null;
+            return defaultValue;
         }
-        if (shape == Shape.ANY || shape == Shape.SCALAR) { // i.e. "default", check dynamically
-            return null;
+        // i.e. "default", check dynamically
+        if (shape == Shape.ANY || shape == Shape.SCALAR) {
+            return defaultValue;
         }
-        if (shape == Shape.STRING) {
+        // 19-May-2016, tatu: also consider "natural" shape
+        if (shape == Shape.STRING || shape == Shape.NATURAL) {
             return Boolean.FALSE;
         }
         // 01-Oct-2014, tatu: For convenience, consider "as-array" to also mean 'yes, use index')
         if (shape.isNumeric() || (shape == Shape.ARRAY)) {
             return Boolean.TRUE;
         }
-        throw new IllegalArgumentException("Unsupported serialization shape ("+shape+") for Enum "+enumClass.getName()
-                    +", not supported as "
-                    + (fromClass? "class" : "property")
-                    +" annotation");
+        // 07-Mar-2017, tatu: Also means `OBJECT` not available as property annotation...
+        throw new IllegalArgumentException(String.format(
+                "Unsupported serialization shape (%s) for Enum %s, not supported as %s annotation",
+                    shape, enumClass.getName(), (fromClass? "class" : "property")));
     }
 }
diff --git a/src/main/java/com/fasterxml/jackson/databind/ser/std/JsonValueSerializer.java b/src/main/java/com/fasterxml/jackson/databind/ser/std/JsonValueSerializer.java
index a3998c7..7582c3a 100644
--- a/src/main/java/com/fasterxml/jackson/databind/ser/std/JsonValueSerializer.java
+++ b/src/main/java/com/fasterxml/jackson/databind/ser/std/JsonValueSerializer.java
@@ -2,12 +2,11 @@
 
 import java.io.IOException;
 import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-import java.lang.reflect.Modifier;
 import java.lang.reflect.Type;
 import java.util.LinkedHashSet;
 import java.util.Set;
 
+import com.fasterxml.jackson.annotation.JsonTypeInfo.As;
 import com.fasterxml.jackson.core.*;
 import com.fasterxml.jackson.databind.*;
 import com.fasterxml.jackson.databind.annotation.JacksonStdImpl;
@@ -16,6 +15,7 @@
 import com.fasterxml.jackson.databind.jsonFormatVisitors.JsonFormatVisitorWrapper;
 import com.fasterxml.jackson.databind.jsonFormatVisitors.JsonStringFormatVisitor;
 import com.fasterxml.jackson.databind.jsonschema.SchemaAware;
+import com.fasterxml.jackson.databind.jsontype.TypeIdResolver;
 import com.fasterxml.jackson.databind.jsontype.TypeSerializer;
 import com.fasterxml.jackson.databind.ser.BeanSerializer;
 import com.fasterxml.jackson.databind.ser.ContextualSerializer;
@@ -37,13 +37,16 @@
 public class JsonValueSerializer
     extends StdSerializer<Object>
     implements ContextualSerializer, JsonFormatVisitable, SchemaAware
-{
-    protected final Method _accessorMethod;
+    {
+    /**
+     * @since 2.8 (was "plain" method before)
+     */
+    protected final AnnotatedMethod _accessorMethod;
 
     protected final JsonSerializer<Object> _valueSerializer;
 
     protected final BeanProperty _property;
-    
+
     /**
      * This is a flag that is set in rare (?) cases where this serializer
      * is used for "natural" types (boolean, int, String, double); and where
@@ -58,21 +61,19 @@
     /**********************************************************
      */
 
-    // Added in 2.7.4 for forward-compatibility reasons; will be used by default in 2.8.0
-    public JsonValueSerializer(AnnotatedMethod valueMethod, JsonSerializer<?> ser) {
-        this(valueMethod.getAnnotated(), ser);
-    }
-    
     /**
      * @param ser Explicit serializer to use, if caller knows it (which
      *    occurs if and only if the "value method" was annotated with
      *    {@link com.fasterxml.jackson.databind.annotation.JsonSerialize#using}), otherwise
      *    null
+     *    
+     * @since 2.8 Earlier method took "raw" Method, but that does not work with access
+     *    to information we need
      */
     @SuppressWarnings("unchecked")
-    public JsonValueSerializer(Method valueMethod, JsonSerializer<?> ser)
+    public JsonValueSerializer(AnnotatedMethod valueMethod, JsonSerializer<?> ser)
     {
-        super(valueMethod.getReturnType(), false);
+        super(valueMethod.getType());
         _accessorMethod = valueMethod;
         _valueSerializer = (JsonSerializer<Object>) ser;
         _property = null;
@@ -126,9 +127,8 @@
              * if not, we don't really know the actual type until we get the instance.
              */
             // 10-Mar-2010, tatu: Except if static typing is to be used
-            if (provider.isEnabled(MapperFeature.USE_STATIC_TYPING)
-                    || Modifier.isFinal(_accessorMethod.getReturnType().getModifiers())) {
-                JavaType t = provider.constructType(_accessorMethod.getGenericReturnType());
+            JavaType t = _accessorMethod.getType();
+            if (provider.isEnabled(MapperFeature.USE_STATIC_TYPING) || t.isFinal()) {
                 // false -> no need to cache
                 /* 10-Mar-2010, tatu: Ideally we would actually separate out type
                  *   serializer from value serializer; but, alas, there's no access
@@ -158,12 +158,12 @@
      */
     
     @Override
-    public void serialize(Object bean, JsonGenerator jgen, SerializerProvider prov) throws IOException
+    public void serialize(Object bean, JsonGenerator gen, SerializerProvider prov) throws IOException
     {
         try {
-            Object value = _accessorMethod.invoke(bean);
+            Object value = _accessorMethod.getValue(bean);
             if (value == null) {
-                prov.defaultSerializeNull(jgen);
+                prov.defaultSerializeNull(gen);
                 return;
             }
             JsonSerializer<Object> ser = _valueSerializer;
@@ -176,7 +176,7 @@
                 // let's cache it, may be needed soon again
                 ser = prov.findTypedValueSerializer(c, true, _property);
             }
-            ser.serialize(value, jgen, prov);
+            ser.serialize(value, gen, prov);
         } catch (IOException ioe) {
             throw ioe;
         } catch (Exception e) {
@@ -195,20 +195,20 @@
     }
 
     @Override
-    public void serializeWithType(Object bean, JsonGenerator jgen, SerializerProvider provider,
+    public void serializeWithType(Object bean, JsonGenerator gen, SerializerProvider provider,
             TypeSerializer typeSer0) throws IOException
     {
         // Regardless of other parts, first need to find value to serialize:
         Object value = null;
         try {
-            value = _accessorMethod.invoke(bean);
+            value = _accessorMethod.getValue(bean);
             // and if we got null, can also just write it directly
             if (value == null) {
-                provider.defaultSerializeNull(jgen);
+                provider.defaultSerializeNull(gen);
                 return;
             }
             JsonSerializer<Object> ser = _valueSerializer;
-            if (ser == null) { // already got a serializer? fabulous, that be easy...
+            if (ser == null) { // no serializer yet? Need to fetch
 //                ser = provider.findTypedValueSerializer(value.getClass(), true, _property);
                 ser = provider.findValueSerializer(value.getClass(), _property);
             } else {
@@ -216,18 +216,17 @@
                  *    this (note: type is for the wrapper type, not enclosed value!)
                  */
                 if (_forceTypeInformation) {
-                    typeSer0.writeTypePrefixForScalar(bean, jgen);
-                    ser.serialize(value, jgen, provider);
-                    typeSer0.writeTypeSuffixForScalar(bean, jgen);
+                    typeSer0.writeTypePrefixForScalar(bean, gen);
+                    ser.serialize(value, gen, provider);
+                    typeSer0.writeTypeSuffixForScalar(bean, gen);
                     return;
                 }
             }
-            /* 13-Feb-2013, tatu: Turns out that work-around should NOT be required
-             *   at all; it would not lead to correct behavior (as per #167).
-             */
-            // and then redirect type id lookups
-//            TypeSerializer typeSer = new TypeSerializerWrapper(typeSer0, bean);
-            ser.serializeWithType(value, jgen, provider, typeSer0);
+            // 28-Sep-2016, tatu: As per [databind#1385], we do need to do some juggling
+            //    to use different Object for type id (logical type) and actual serialization
+            //    (delegat type).
+            TypeSerializerRerouter rr = new TypeSerializerRerouter(typeSer0, bean);
+            ser.serializeWithType(value, gen, provider, rr);
         } catch (IOException ioe) {
             throw ioe;
         } catch (Exception e) {
@@ -261,32 +260,25 @@
         throws JsonMappingException
     {
         /* 27-Apr-2015, tatu: First things first; for JSON Schema introspection,
-         *    Enums are special, and unfortunately we will need to add special
+         *    Enum types that use `@JsonValue` are special (but NOT necessarily
+         *    anything else that RETURNS an enum!)
+         *    So we will need to add special
          *    handling here (see https://github.com/FasterXML/jackson-module-jsonSchema/issues/57
          *    for details).
+         *    
+         *    Note that meaning of JsonValue, then, is very different for Enums. Sigh.
          */
-        Class<?> decl = (typeHint == null) ? null : typeHint.getRawClass();
-        if (decl == null) {
-            decl = _accessorMethod.getDeclaringClass();
-        }
-        if ((decl != null) && (decl.isEnum())) {
-            if (_acceptJsonFormatVisitorForEnum(visitor, typeHint, decl)) {
+        final JavaType type = _accessorMethod.getType();
+        Class<?> declaring = _accessorMethod.getDeclaringClass();
+        if ((declaring != null) && declaring.isEnum()) {
+            if (_acceptJsonFormatVisitorForEnum(visitor, typeHint, declaring)) {
                 return;
             }
         }
-        
         JsonSerializer<Object> ser = _valueSerializer;
         if (ser == null) {
-            if (typeHint == null) {
-                if (_property != null) {
-                    typeHint = _property.getType();
-                }
-                if (typeHint == null) {
-                    typeHint = visitor.getProvider().constructType(_handledType);
-                }
-            }
-            ser = visitor.getProvider().findTypedValueSerializer(typeHint, false, _property);
-            if (ser == null) {
+            ser = visitor.getProvider().findTypedValueSerializer(type, false, _property);
+            if (ser == null) { // can this ever occur?
                 visitor.expectAnyFormat(typeHint);
                 return;
             }
@@ -296,7 +288,7 @@
 
     /**
      * Overridable helper method used for special case handling of schema information for
-     * Enums
+     * Enums.
      * 
      * @return True if method handled callbacks; false if not; in latter case caller will
      *   send default callbacks
@@ -313,7 +305,10 @@
             Set<String> enums = new LinkedHashSet<String>();
             for (Object en : enumType.getEnumConstants()) {
                 try {
-                    enums.add(String.valueOf(_accessorMethod.invoke(en)));
+                    // 21-Apr-2016, tatu: This is convoluted to the max, but essentially we
+                    //   call `@JsonValue`-annotated accessor method on all Enum members,
+                    //   so it all "works out". To some degree.
+                    enums.add(String.valueOf(_accessorMethod.callOn(en)));
                 } catch (Exception e) {
                     Throwable t = e;
                     while (t instanceof InvocationTargetException && t.getCause() != null) {
@@ -328,9 +323,8 @@
             stringVisitor.enumTypes(enums);
         }
         return true;
-        
     }
-    
+
     protected boolean isNaturalTypeWithStdHandling(Class<?> rawType, JsonSerializer<?> ser)
     {
         // First: do we have a natural type being handled?
@@ -346,7 +340,7 @@
         }
         return isDefaultSerializer(ser);
     }
-    
+
     /*
     /**********************************************************
     /* Other methods
@@ -357,4 +351,123 @@
     public String toString() {
         return "(@JsonValue serializer for method " + _accessorMethod.getDeclaringClass() + "#" + _accessorMethod.getName() + ")";
     }
+
+    /*
+    /**********************************************************
+    /* Helper class
+    /**********************************************************
+     */
+
+    /**
+     * Silly little wrapper class we need to re-route type serialization so that we can
+     * override Object to use for type id (logical type) even when asking serialization
+     * of something else (delegate type)
+     */
+    static class TypeSerializerRerouter
+        extends TypeSerializer
+    {
+        protected final TypeSerializer _typeSerializer;
+        protected final Object _forObject;
+
+        public TypeSerializerRerouter(TypeSerializer ts, Object ob) {
+            _typeSerializer = ts;
+            _forObject = ob;
+        }
+
+        @Override
+        public TypeSerializer forProperty(BeanProperty prop) { // should never get called
+            throw new UnsupportedOperationException();
+        }
+
+        @Override
+        public As getTypeInclusion() {
+            return _typeSerializer.getTypeInclusion();
+        }
+
+        @Override
+        public String getPropertyName() {
+            return _typeSerializer.getPropertyName();
+        }
+
+        @Override
+        public TypeIdResolver getTypeIdResolver() {
+            return _typeSerializer.getTypeIdResolver();
+        }
+
+        @Override
+        public void writeTypePrefixForScalar(Object value, JsonGenerator gen) throws IOException {
+            _typeSerializer.writeTypePrefixForScalar(_forObject, gen);
+        }
+
+        @Override
+        public void writeTypePrefixForObject(Object value, JsonGenerator gen) throws IOException {
+            _typeSerializer.writeTypePrefixForObject(_forObject, gen);
+        }
+
+        @Override
+        public void writeTypePrefixForArray(Object value, JsonGenerator gen) throws IOException {
+            _typeSerializer.writeTypePrefixForArray(_forObject, gen);
+        }
+
+        @Override
+        public void writeTypeSuffixForScalar(Object value, JsonGenerator gen) throws IOException {
+            _typeSerializer.writeTypeSuffixForScalar(_forObject, gen);
+        }
+
+        @Override
+        public void writeTypeSuffixForObject(Object value, JsonGenerator gen) throws IOException {
+            _typeSerializer.writeTypeSuffixForObject(_forObject, gen);
+        }
+
+        @Override
+        public void writeTypeSuffixForArray(Object value, JsonGenerator gen) throws IOException {
+            _typeSerializer.writeTypeSuffixForArray(_forObject, gen);
+        }
+
+        @Override
+        public void writeTypePrefixForScalar(Object value, JsonGenerator gen, Class<?> type) throws IOException {
+            _typeSerializer.writeTypePrefixForScalar(_forObject, gen, type);
+        }
+
+        @Override
+        public void writeTypePrefixForObject(Object value, JsonGenerator gen, Class<?> type) throws IOException {
+            _typeSerializer.writeTypePrefixForObject(_forObject, gen, type);
+        }
+
+        @Override
+        public void writeTypePrefixForArray(Object value, JsonGenerator gen, Class<?> type) throws IOException {
+            _typeSerializer.writeTypePrefixForArray(_forObject, gen, type);
+        }
+        
+        @Override
+        public void writeCustomTypePrefixForScalar(Object value, JsonGenerator gen, String typeId)
+                throws IOException {
+            _typeSerializer.writeCustomTypePrefixForScalar(_forObject, gen, typeId);
+        }
+
+        @Override
+        public void writeCustomTypePrefixForObject(Object value, JsonGenerator gen, String typeId) throws IOException {
+            _typeSerializer.writeCustomTypePrefixForObject(_forObject, gen, typeId);
+        }
+
+        @Override
+        public void writeCustomTypePrefixForArray(Object value, JsonGenerator gen, String typeId) throws IOException {
+            _typeSerializer.writeCustomTypePrefixForArray(_forObject, gen, typeId);
+        }
+
+        @Override
+        public void writeCustomTypeSuffixForScalar(Object value, JsonGenerator gen, String typeId) throws IOException {
+            _typeSerializer.writeCustomTypeSuffixForScalar(_forObject, gen, typeId);
+        }
+
+        @Override
+        public void writeCustomTypeSuffixForObject(Object value, JsonGenerator gen, String typeId) throws IOException {
+            _typeSerializer.writeCustomTypeSuffixForObject(_forObject, gen, typeId);
+        }
+
+        @Override
+        public void writeCustomTypeSuffixForArray(Object value, JsonGenerator gen, String typeId) throws IOException {
+            _typeSerializer.writeCustomTypeSuffixForArray(_forObject, gen, typeId);
+        }
+    }
 }
diff --git a/src/main/java/com/fasterxml/jackson/databind/ser/std/MapSerializer.java b/src/main/java/com/fasterxml/jackson/databind/ser/std/MapSerializer.java
index 85ad2fe..a3af8cc 100644
--- a/src/main/java/com/fasterxml/jackson/databind/ser/std/MapSerializer.java
+++ b/src/main/java/com/fasterxml/jackson/databind/ser/std/MapSerializer.java
@@ -4,17 +4,16 @@
 import java.lang.reflect.Type;
 import java.util.*;
 
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
 import com.fasterxml.jackson.annotation.JsonInclude;
-
 import com.fasterxml.jackson.core.*;
-
 import com.fasterxml.jackson.databind.*;
 import com.fasterxml.jackson.databind.annotation.JacksonStdImpl;
 import com.fasterxml.jackson.databind.introspect.AnnotatedMember;
 import com.fasterxml.jackson.databind.jsonFormatVisitors.JsonFormatVisitorWrapper;
 import com.fasterxml.jackson.databind.jsonFormatVisitors.JsonMapFormatVisitor;
 import com.fasterxml.jackson.databind.jsontype.TypeSerializer;
-import com.fasterxml.jackson.databind.node.ObjectNode;
 import com.fasterxml.jackson.databind.ser.ContainerSerializer;
 import com.fasterxml.jackson.databind.ser.ContextualSerializer;
 import com.fasterxml.jackson.databind.ser.PropertyFilter;
@@ -45,7 +44,7 @@
     /**
      * Set of entries to omit during serialization, if any
      */
-    protected final HashSet<String> _ignoredEntries;
+    protected final Set<String> _ignoredEntries;
 
     /**
      * Whether static types should be used for serialization of values
@@ -120,13 +119,14 @@
      * @since 2.5
      */
     @SuppressWarnings("unchecked")
-    protected MapSerializer(HashSet<String> ignoredEntries,
+    protected MapSerializer(Set<String> ignoredEntries,
             JavaType keyType, JavaType valueType, boolean valueTypeIsStatic,
             TypeSerializer vts,
             JsonSerializer<?> keySerializer, JsonSerializer<?> valueSerializer)
     {
         super(Map.class, false);
-        _ignoredEntries = ignoredEntries;
+        _ignoredEntries = ((ignoredEntries == null) || ignoredEntries.isEmpty())
+                ? null : ignoredEntries;
         _keyType = keyType;
         _valueType = valueType;
         _valueTypeIsStatic = valueTypeIsStatic;
@@ -152,10 +152,11 @@
     @SuppressWarnings("unchecked")
     protected MapSerializer(MapSerializer src, BeanProperty property,
             JsonSerializer<?> keySerializer, JsonSerializer<?> valueSerializer,
-            HashSet<String> ignored)
+            Set<String> ignoredEntries)
     {
         super(Map.class, false);
-        _ignoredEntries = ignored;
+        _ignoredEntries = ((ignoredEntries == null) || ignoredEntries.isEmpty())
+                ? null : ignoredEntries;
         _keyType = src._keyType;
         _valueType = src._valueType;
         _valueTypeIsStatic = src._valueTypeIsStatic;
@@ -231,7 +232,7 @@
      */
     public MapSerializer withResolved(BeanProperty property,
             JsonSerializer<?> keySerializer, JsonSerializer<?> valueSerializer,
-            HashSet<String> ignored, boolean sortKeys)
+            Set<String> ignored, boolean sortKeys)
     {
         _ensureOverride();
         MapSerializer ser = new MapSerializer(this, property, keySerializer, valueSerializer, ignored);
@@ -266,15 +267,29 @@
     
     /**
      * @since 2.3
+     *
+     * @deprecated Since 2.8 use the other overload
      */
+    @Deprecated // since 2.8
     public static MapSerializer construct(String[] ignoredList, JavaType mapType,
             boolean staticValueType, TypeSerializer vts,
             JsonSerializer<Object> keySerializer, JsonSerializer<Object> valueSerializer,
             Object filterId)
     {
-        HashSet<String> ignoredEntries = (ignoredList == null || ignoredList.length == 0)
+        Set<String> ignoredEntries = (ignoredList == null || ignoredList.length == 0)
                 ? null : ArrayBuilders.arrayToSet(ignoredList);
+        return construct(ignoredEntries, mapType, staticValueType, vts,
+                keySerializer, valueSerializer, filterId);
+    }
 
+    /**
+     * @since 2.8
+     */
+    public static MapSerializer construct(Set<String> ignoredEntries, JavaType mapType,
+            boolean staticValueType, TypeSerializer vts,
+            JsonSerializer<Object> keySerializer, JsonSerializer<Object> valueSerializer,
+            Object filterId)
+    {
         JavaType keyType, valueType;
         
         if (mapType == null) {
@@ -311,10 +326,6 @@
             BeanProperty property)
         throws JsonMappingException
     {
-        /* 29-Sep-2012, tatu: Actually, we need to do much more contextual
-         *    checking here since we finally know for sure the property,
-         *    and it may have overrides
-         */
         JsonSerializer<?> ser = null;
         JsonSerializer<?> keySer = null;
         final AnnotationIntrospector intr = provider.getAnnotationIntrospector();
@@ -333,12 +344,10 @@
             }
         }
 
-        if (property != null) {
-            JsonInclude.Value inclV = property.findPropertyInclusion(provider.getConfig(), Map.class);
-            JsonInclude.Include incl = inclV.getContentInclusion();
-            if ((incl != null) && (incl != JsonInclude.Include.USE_DEFAULTS)) {
-                suppressableValue = incl;
-            }
+        JsonInclude.Value inclV = findIncludeOverrides(provider, property, Map.class);
+        JsonInclude.Include incl = inclV.getContentInclusion();
+        if ((incl != null) && (incl != JsonInclude.Include.USE_DEFAULTS)) {
+            suppressableValue = incl;
         }
         if (ser == null) {
             ser = _valueSerializer;
@@ -363,19 +372,29 @@
         } else {
             keySer = provider.handleSecondaryContextualization(keySer, property);
         }
-        HashSet<String> ignored = _ignoredEntries;
+        Set<String> ignored = _ignoredEntries;
         boolean sortKeys = false;
-        if (intr != null && propertyAcc != null) {
-            String[] moreToIgnore = intr.findPropertiesToIgnore(propertyAcc, true);
-            if (moreToIgnore != null) {
-                ignored = (ignored == null) ? new HashSet<String>() : new HashSet<String>(ignored);
-                for (String str : moreToIgnore) {
-                    ignored.add(str);
+        if ((intr != null) && (propertyAcc != null)) {
+            JsonIgnoreProperties.Value ignorals = intr.findPropertyIgnorals(propertyAcc);
+            if (ignorals != null){
+                Set<String> newIgnored = ignorals.findIgnoredForSerialization();
+                if ((newIgnored != null) && !newIgnored.isEmpty()) {
+                    ignored = (ignored == null) ? new HashSet<String>() : new HashSet<String>(ignored);
+                    for (String str : newIgnored) {
+                        ignored.add(str);
+                    }
                 }
             }
             Boolean b = intr.findSerializationSortAlphabetically(propertyAcc);
             sortKeys = (b != null) && b.booleanValue();
         }
+        JsonFormat.Value format = findFormatOverrides(provider, property, Map.class);
+        if (format != null) {
+            Boolean B = format.getFeature(JsonFormat.Feature.WRITE_SORTED_MAP_ENTRIES);
+            if (B != null) {
+                sortKeys = B.booleanValue();
+            }
+        }
         MapSerializer mser = withResolved(property, keySer, ser, ignored, sortKeys);
         if (suppressableValue != _suppressableValue) {
             mser = mser.withContentInclusion(suppressableValue);
@@ -418,7 +437,7 @@
         }
         // 05-Nove-2015, tatu: Simple cases are cheap, but for recursive
         //   emptiness checking we actually need to see if values are empty as well.
-        Object supp = this._suppressableValue;
+        Object supp = _suppressableValue;
 
         if ((supp == null) || (supp == JsonInclude.Include.ALWAYS)) {
             return false;
@@ -493,9 +512,7 @@
     public void serialize(Map<?,?> value, JsonGenerator gen, SerializerProvider provider)
         throws IOException
     {
-        gen.writeStartObject();
-        // [databind#631]: Assign current value, to be accessible by custom serializers
-        gen.setCurrentValue(value);
+        gen.writeStartObject(value);
         if (!value.isEmpty()) {
             Object suppressableValue = _suppressableValue;
             if (suppressableValue == JsonInclude.Include.ALWAYS) {
@@ -506,7 +523,7 @@
                 }
             }
             if (_sortKeys || provider.isEnabled(SerializationFeature.ORDER_MAP_ENTRIES_BY_KEYS)) {
-                value = _orderEntries(value);
+                value = _orderEntries(value, gen, provider, suppressableValue);
             }
             PropertyFilter pf;
             if ((_filterId != null) && (pf = findPropertyFilter(provider, _filterId, value)) != null) {
@@ -540,7 +557,7 @@
                 }
             }
             if (_sortKeys || provider.isEnabled(SerializationFeature.ORDER_MAP_ENTRIES_BY_KEYS)) {
-                value = _orderEntries(value);
+                value = _orderEntries(value, gen, provider, suppressableValue);
             }
             PropertyFilter pf;
             if ((_filterId != null) && (pf = findPropertyFilter(provider, _filterId, value)) != null) {
@@ -576,7 +593,7 @@
             return;
         }
         final JsonSerializer<Object> keySerializer = _keySerializer;
-        final HashSet<String> ignored = _ignoredEntries;
+        final Set<String> ignored = _ignoredEntries;
 
         PropertySerializerMap serializers = _dynamicValueSerializers;
 
@@ -589,7 +606,7 @@
                 provider.findNullKeySerializer(_keyType, _property).serialize(null, gen, provider);
             } else {
                 // One twist: is entry ignorable? If so, skip
-                if (ignored != null && ignored.contains(keyElem)) continue;
+                if ((ignored != null) && ignored.contains(keyElem)) continue;
                 keySerializer.serialize(keyElem, gen, provider);
             }
 
@@ -634,7 +651,7 @@
             serializeTypedFields(value, gen, provider, suppressableValue);
             return;
         }
-        final HashSet<String> ignored = _ignoredEntries;
+        final Set<String> ignored = _ignoredEntries;
         PropertySerializerMap serializers = _dynamicValueSerializers;
 
         for (Map.Entry<?,?> entry : value.entrySet()) {
@@ -698,7 +715,7 @@
         throws IOException
     {
         final JsonSerializer<Object> keySerializer = _keySerializer;
-        final HashSet<String> ignored = _ignoredEntries;
+        final Set<String> ignored = _ignoredEntries;
         final TypeSerializer typeSer = _valueTypeSerializer;
 
         for (Map.Entry<?,?> entry : value.entrySet()) {
@@ -739,7 +756,7 @@
             Object suppressableValue) // since 2.5
         throws IOException
     {
-        final HashSet<String> ignored = _ignoredEntries;
+        final Set<String> ignored = _ignoredEntries;
 
         PropertySerializerMap serializers = _dynamicValueSerializers;
         final MapProperty prop = new MapProperty(_valueTypeSerializer, _property);
@@ -811,7 +828,7 @@
             Object suppressableValue) // since 2.5
         throws IOException
     {
-        final HashSet<String> ignored = _ignoredEntries;
+        final Set<String> ignored = _ignoredEntries;
         PropertySerializerMap serializers = _dynamicValueSerializers;
 
         for (Map.Entry<?,?> entry : value.entrySet()) {
@@ -878,10 +895,9 @@
     @Override
     public JsonNode getSchema(SerializerProvider provider, Type typeHint)
     {
-        ObjectNode o = createSchemaNode("object", true);
         //(ryan) even though it's possible to statically determine the "value" type of the map,
         // there's no way to statically determine the keys, so the "Entries" can't be determined.
-        return o;
+        return createSchemaNode("object", true);
     }
 
     @Override
@@ -927,23 +943,85 @@
         return result.serializer;
     }
 
-    protected Map<?,?> _orderEntries(Map<?,?> input)
+    protected Map<?,?> _orderEntries(Map<?,?> input, JsonGenerator gen,
+            SerializerProvider provider, Object suppressableValue) throws IOException
     {
         // minor optimization: may already be sorted?
         if (input instanceof SortedMap<?,?>) {
             return input;
         }
-        // [databind#1411]: TreeMap does not like null key...
-        if (input.containsKey(null)) {
+        // [databind#1411]: TreeMap does not like null key... (although note that
+        //   check above should prevent this code from being called in that case)
+        // [databind#153]: but, apparently, some custom Maps do manage hit this
+        //   problem.
+        if (_hasNullKey(input)) {
             TreeMap<Object,Object> result = new TreeMap<Object,Object>();
             for (Map.Entry<?,?> entry : input.entrySet()) {
                 Object key = entry.getKey();
-                if (key != null) {
-                    result.put(key, entry.getValue());
-                }
+                if (key == null) {
+                    _writeNullKeyedEntry(gen, provider, suppressableValue, entry.getValue());
+                    continue;
+                } 
+                result.put(key, entry.getValue());
             }
             return result;
         }
         return new TreeMap<Object,Object>(input);
     }
+
+    /**
+     * @since 2.8.7
+     */
+    protected boolean _hasNullKey(Map<?,?> input) {
+        // 19-Feb-2017, tatu: As per [databind#1513] there are many cases where `null`
+        //   keys are not allowed, and even attempt to check for presence can cause
+        //   problems. Without resorting to external sorting (and internal API change),
+        //   or custom sortable Map implementation (more code) we can try black- or
+        //   white-listing (that is; either skip known problem cases; or only apply for
+        //   known good cases).
+        //   While my first instinct was to do black-listing (remove Hashtable and ConcurrentHashMap),
+        //   all in all it is probably better to just white list `HashMap` (and its sub-classes).
+        
+        return (input instanceof HashMap) && input.containsKey(null);
+    }
+    
+    protected void _writeNullKeyedEntry(JsonGenerator gen, SerializerProvider provider,
+            Object suppressableValue, Object value) throws IOException
+    {
+        JsonSerializer<Object> keySerializer = provider.findNullKeySerializer(_keyType, _property);
+        JsonSerializer<Object> valueSer;
+        if (value == null) {
+            if (suppressableValue != null) { // all suppressions include null-suppression
+                return;
+            }
+            valueSer = provider.getDefaultNullValueSerializer();
+        } else {
+            valueSer = _valueSerializer;
+            if (valueSer == null) {
+                Class<?> cc = value.getClass();
+                valueSer = _dynamicValueSerializers.serializerFor(cc);
+                if (valueSer == null) {
+                    if (_valueType.hasGenericTypes()) {
+                        valueSer = _findAndAddDynamic(_dynamicValueSerializers,
+                                provider.constructSpecializedType(_valueType, cc), provider);
+                    } else {
+                        valueSer = _findAndAddDynamic(_dynamicValueSerializers, cc, provider);
+                    }
+                }
+            }
+            // also may need to skip non-empty values:
+            if ((suppressableValue == JsonInclude.Include.NON_EMPTY)
+                    && valueSer.isEmpty(provider, value)) {
+                return;
+            }
+        }
+        // and then serialize, if all went well
+        try {
+            keySerializer.serialize(null, gen, provider);
+            valueSer.serialize(value, gen, provider);
+        } catch (Exception e) {
+            String keyDesc = "";
+            wrapAndThrow(provider, e, value, keyDesc);
+        }
+    }
 }
diff --git a/src/main/java/com/fasterxml/jackson/databind/ser/std/NumberSerializers.java b/src/main/java/com/fasterxml/jackson/databind/ser/std/NumberSerializers.java
index 3585892..e27722c 100644
--- a/src/main/java/com/fasterxml/jackson/databind/ser/std/NumberSerializers.java
+++ b/src/main/java/com/fasterxml/jackson/databind/ser/std/NumberSerializers.java
@@ -10,7 +10,6 @@
 
 import com.fasterxml.jackson.databind.*;
 import com.fasterxml.jackson.databind.annotation.JacksonStdImpl;
-import com.fasterxml.jackson.databind.introspect.AnnotatedMember;
 import com.fasterxml.jackson.databind.jsonFormatVisitors.JsonFormatVisitorWrapper;
 import com.fasterxml.jackson.databind.jsontype.TypeSerializer;
 import com.fasterxml.jackson.databind.ser.ContextualSerializer;
@@ -21,25 +20,24 @@
  */
 @SuppressWarnings("serial")
 public class NumberSerializers {
-    protected NumberSerializers() {
-    }
+    protected NumberSerializers() { }
 
     public static void addAll(Map<String, JsonSerializer<?>> allDeserializers) {
-        final JsonSerializer<?> intS = new IntegerSerializer();
-        allDeserializers.put(Integer.class.getName(), intS);
-        allDeserializers.put(Integer.TYPE.getName(), intS);
-        allDeserializers.put(Long.class.getName(), LongSerializer.instance);
-        allDeserializers.put(Long.TYPE.getName(), LongSerializer.instance);
+        allDeserializers.put(Integer.class.getName(), new IntegerSerializer(Integer.class));
+        allDeserializers.put(Integer.TYPE.getName(), new IntegerSerializer(Integer.TYPE));
+        allDeserializers.put(Long.class.getName(), new LongSerializer(Long.class));
+        allDeserializers.put(Long.TYPE.getName(), new LongSerializer(Long.TYPE));
+
         allDeserializers.put(Byte.class.getName(), IntLikeSerializer.instance);
         allDeserializers.put(Byte.TYPE.getName(), IntLikeSerializer.instance);
         allDeserializers.put(Short.class.getName(), ShortSerializer.instance);
         allDeserializers.put(Short.TYPE.getName(), ShortSerializer.instance);
 
         // Numbers, limited length floating point
+        allDeserializers.put(Double.class.getName(), new DoubleSerializer(Double.class));
+        allDeserializers.put(Double.TYPE.getName(), new DoubleSerializer(Double.TYPE));
         allDeserializers.put(Float.class.getName(), FloatSerializer.instance);
         allDeserializers.put(Float.TYPE.getName(), FloatSerializer.instance);
-        allDeserializers.put(Double.class.getName(), DoubleSerializer.instance);
-        allDeserializers.put(Double.TYPE.getName(), DoubleSerializer.instance);
     }
 
     /*
@@ -82,19 +80,14 @@
 
         @Override
         public JsonSerializer<?> createContextual(SerializerProvider prov,
-                BeanProperty property) throws JsonMappingException {
-            if (property != null) {
-                AnnotatedMember m = property.getMember();
-                if (m != null) {
-                    JsonFormat.Value format = prov.getAnnotationIntrospector()
-                            .findFormat(m);
-                    if (format != null) {
-                        switch (format.getShape()) {
-                        case STRING:
-                            return ToStringSerializer.instance;
-                        default:
-                        }
-                    }
+                BeanProperty property) throws JsonMappingException
+        {
+            JsonFormat.Value format = findFormatOverrides(prov, property, handledType());
+            if (format != null) {
+                switch (format.getShape()) {
+                case STRING:
+                    return ToStringSerializer.instance;
+                default:
                 }
             }
             return this;
@@ -102,9 +95,9 @@
     }
 
     /*
-     * /********************************************************** /* Concrete
-     * serializers, numerics
-     * /**********************************************************
+     *************************************************************
+     * Concrete serializers, numerics
+     *************************************************************
      */
 
     @JacksonStdImpl
@@ -134,8 +127,8 @@
      */
     @JacksonStdImpl
     public final static class IntegerSerializer extends Base<Object> {
-        public IntegerSerializer() {
-            super(Integer.class, JsonParser.NumberType.INT, "integer");
+        public IntegerSerializer(Class<?> type) {
+            super(type, JsonParser.NumberType.INT, "integer");
         }
 
         @Override
@@ -176,10 +169,8 @@
 
     @JacksonStdImpl
     public final static class LongSerializer extends Base<Object> {
-        final static LongSerializer instance = new LongSerializer();
-
-        public LongSerializer() {
-            super(Long.class, JsonParser.NumberType.LONG, "number");
+        public LongSerializer(Class<?> cls) {
+            super(cls, JsonParser.NumberType.LONG, "number");
         }
 
         @Override
@@ -213,10 +204,8 @@
      */
     @JacksonStdImpl
     public final static class DoubleSerializer extends Base<Object> {
-        final static DoubleSerializer instance = new DoubleSerializer();
-
-        public DoubleSerializer() {
-            super(Double.class, JsonParser.NumberType.DOUBLE, "number");
+        public DoubleSerializer(Class<?> cls) {
+            super(cls, JsonParser.NumberType.DOUBLE, "number");
         }
 
         @Override
diff --git a/src/main/java/com/fasterxml/jackson/databind/ser/std/ObjectArraySerializer.java b/src/main/java/com/fasterxml/jackson/databind/ser/std/ObjectArraySerializer.java
index 250cbbc..d71bc40 100644
--- a/src/main/java/com/fasterxml/jackson/databind/ser/std/ObjectArraySerializer.java
+++ b/src/main/java/com/fasterxml/jackson/databind/ser/std/ObjectArraySerializer.java
@@ -123,7 +123,7 @@
      */
 
     @Override
-    public JsonSerializer<?> createContextual(SerializerProvider provider,
+    public JsonSerializer<?> createContextual(SerializerProvider serializers,
             BeanProperty property)
         throws JsonMappingException
     {
@@ -137,33 +137,33 @@
         // First: if we have a property, may have property-annotation overrides
         if (property != null) {
             AnnotatedMember m = property.getMember();
-            final AnnotationIntrospector intr = provider.getAnnotationIntrospector();
+            final AnnotationIntrospector intr = serializers.getAnnotationIntrospector();
             if (m != null) {
                 Object serDef = intr.findContentSerializer(m);
                 if (serDef != null) {
-                    ser = provider.serializerInstance(m, serDef);
+                    ser = serializers.serializerInstance(m, serDef);
                 }
             }
-            JsonFormat.Value format = property.findPropertyFormat(provider.getConfig(), _handledType);
-            if (format != null) {
-                unwrapSingle = format.getFeature(JsonFormat.Feature.WRITE_SINGLE_ELEM_ARRAYS_UNWRAPPED);
-            }
+        }
+        JsonFormat.Value format = findFormatOverrides(serializers, property, handledType());
+        if (format != null) {
+            unwrapSingle = format.getFeature(JsonFormat.Feature.WRITE_SINGLE_ELEM_ARRAYS_UNWRAPPED);
         }
         if (ser == null) {
             ser = _elementSerializer;
         }
-        // #124: May have a content converter
-        ser = findConvertingContentSerializer(provider, property, ser);
+        // [databind#124]: May have a content converter
+        ser = findConvertingContentSerializer(serializers, property, ser);
         if (ser == null) {
             // 30-Sep-2012, tatu: One more thing -- if explicit content type is annotated,
             //   we can consider it a static case as well.
             if (_elementType != null) {
                 if (_staticTyping && !_elementType.isJavaLangObject()) {
-                    ser = provider.findValueSerializer(_elementType, property);
+                    ser = serializers.findValueSerializer(_elementType, property);
                 }
             }
         } else {
-            ser = provider.handleSecondaryContextualization(ser, property);
+            ser = serializers.handleSecondaryContextualization(ser, property);
         }
         return withResolved(property, vts, ser, unwrapSingle);
     }
diff --git a/src/main/java/com/fasterxml/jackson/databind/ser/std/ReferenceTypeSerializer.java b/src/main/java/com/fasterxml/jackson/databind/ser/std/ReferenceTypeSerializer.java
new file mode 100644
index 0000000..095d209
--- /dev/null
+++ b/src/main/java/com/fasterxml/jackson/databind/ser/std/ReferenceTypeSerializer.java
@@ -0,0 +1,354 @@
+package com.fasterxml.jackson.databind.ser.std;
+
+import java.io.IOException;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.core.JsonGenerator;
+import com.fasterxml.jackson.databind.*;
+import com.fasterxml.jackson.databind.annotation.JsonSerialize;
+import com.fasterxml.jackson.databind.introspect.Annotated;
+import com.fasterxml.jackson.databind.jsonFormatVisitors.JsonFormatVisitorWrapper;
+import com.fasterxml.jackson.databind.jsontype.TypeSerializer;
+import com.fasterxml.jackson.databind.ser.ContextualSerializer;
+import com.fasterxml.jackson.databind.ser.impl.PropertySerializerMap;
+import com.fasterxml.jackson.databind.type.ReferenceType;
+import com.fasterxml.jackson.databind.util.NameTransformer;
+
+/**
+ * Base implementation for values of {@link ReferenceType}.
+ * Implements most of functionality, only leaving couple of abstract
+ * methods for sub-classes to implement
+ *
+ * @since 2.8
+ */
+public abstract class ReferenceTypeSerializer<T>
+    extends StdSerializer<T>
+    implements ContextualSerializer
+{
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * Value type
+     */
+    protected final JavaType _referredType;
+
+    protected final BeanProperty _property;
+
+    /**
+     * Type serializer used for values, if any.
+     */
+    protected final TypeSerializer _valueTypeSerializer;
+
+    /**
+     * Serializer for content values, if statically known.
+     */
+    protected final JsonSerializer<Object> _valueSerializer;
+
+    /**
+     * In case of unwrapping, need name transformer.
+     */
+    protected final NameTransformer _unwrapper;
+
+    /**
+     * Further guidance on serialization-inclusion (or not), regarding
+     * contained value (if any).
+     */
+    protected final JsonInclude.Include _contentInclusion;
+    
+    /**
+     * If element type can not be statically determined, mapping from
+     * runtime type to serializer is handled using this object
+     */
+    protected transient PropertySerializerMap _dynamicSerializers;
+
+    /*
+    /**********************************************************
+    /* Constructors, factory methods
+    /**********************************************************
+     */
+
+    public ReferenceTypeSerializer(ReferenceType fullType, boolean staticTyping,
+            TypeSerializer vts, JsonSerializer<Object> ser)
+    {
+        super(fullType);
+        _referredType = fullType.getReferencedType();
+        _property = null;
+        _valueTypeSerializer = vts;
+        _valueSerializer = ser;
+        _unwrapper = null;
+        _contentInclusion = null;
+        _dynamicSerializers = PropertySerializerMap.emptyForProperties();
+    }
+
+    @SuppressWarnings("unchecked")
+    protected ReferenceTypeSerializer(ReferenceTypeSerializer<?> base, BeanProperty property,
+            TypeSerializer vts, JsonSerializer<?> valueSer,
+            NameTransformer unwrapper,
+            JsonInclude.Include contentIncl)
+    {
+        super(base);
+        _referredType = base._referredType;
+        _dynamicSerializers = base._dynamicSerializers;
+        _property = property;
+        _valueTypeSerializer = vts;
+        _valueSerializer = (JsonSerializer<Object>) valueSer;
+        _unwrapper = unwrapper;
+        if ((contentIncl == JsonInclude.Include.USE_DEFAULTS)
+                || (contentIncl == JsonInclude.Include.ALWAYS)) {
+            _contentInclusion = null;
+        } else {
+            _contentInclusion = contentIncl;
+        }
+    }
+
+    @Override
+    public JsonSerializer<T> unwrappingSerializer(NameTransformer transformer) {
+        JsonSerializer<Object> ser = _valueSerializer;
+        if (ser != null) {
+            ser = ser.unwrappingSerializer(transformer);
+        }
+        NameTransformer unwrapper = (_unwrapper == null) ? transformer
+                : NameTransformer.chainedTransformer(transformer, _unwrapper);
+        return withResolved(_property, _valueTypeSerializer, ser, unwrapper, _contentInclusion);
+    }
+
+    /*
+    /**********************************************************
+    /* Abstract methods to implement
+    /**********************************************************
+     */
+    
+    protected abstract ReferenceTypeSerializer<T> withResolved(BeanProperty prop,
+            TypeSerializer vts, JsonSerializer<?> valueSer,
+            NameTransformer unwrapper,
+            JsonInclude.Include contentIncl);
+
+    protected abstract boolean _isValueEmpty(T value);
+
+    protected abstract Object _getReferenced(T value);
+
+    protected abstract Object _getReferencedIfPresent(T value);
+
+    /*
+    /**********************************************************
+    /* Contextualization (support for property annotations)
+    /**********************************************************
+     */
+
+    @Override
+    public JsonSerializer<?> createContextual(SerializerProvider provider,
+            BeanProperty property) throws JsonMappingException
+    {
+        TypeSerializer typeSer = _valueTypeSerializer;
+        if (typeSer != null) {
+            typeSer = typeSer.forProperty(property);
+        }
+        // First: do we have an annotation override from property?
+        JsonSerializer<?> ser = findAnnotatedContentSerializer(provider, property);;
+        if (ser == null) {
+            // If not, use whatever was configured by type
+            ser = _valueSerializer;
+            if (ser == null) {
+                // A few conditions needed to be able to fetch serializer here:
+                if (_useStatic(provider, property, _referredType)) {
+                    ser = _findSerializer(provider, _referredType, property);
+                }
+            } else {
+                ser = provider.handlePrimaryContextualization(ser, property);
+            }
+        }
+        // Also: may want to have more refined exclusion based on referenced value
+        JsonInclude.Include contentIncl = _contentInclusion;
+        JsonInclude.Value incl = findIncludeOverrides(provider, property, handledType());
+        JsonInclude.Include newIncl = incl.getContentInclusion();
+        if ((newIncl != contentIncl) && (newIncl != JsonInclude.Include.USE_DEFAULTS)) {
+            contentIncl = newIncl;
+        }
+        return withResolved(property, typeSer, ser, _unwrapper, contentIncl);
+    }
+
+    protected boolean _useStatic(SerializerProvider provider, BeanProperty property,
+            JavaType referredType)
+    {
+        // First: no serializer for `Object.class`, must be dynamic
+        if (referredType.isJavaLangObject()) {
+            return false;
+        }
+        // but if type is final, might as well fetch
+        if (referredType.isFinal()) { // or should we allow annotation override? (only if requested...)
+            return true;
+        }
+        // also: if indicated by typing, should be considered static
+        if (referredType.useStaticType()) {
+            return true;
+        }
+        // if neither, maybe explicit annotation?
+        AnnotationIntrospector intr = provider.getAnnotationIntrospector();
+        if ((intr != null) && (property != null)) {
+            Annotated ann = property.getMember();
+            if (ann != null) {
+                JsonSerialize.Typing t = intr.findSerializationTyping(property.getMember());
+                if (t == JsonSerialize.Typing.STATIC) {
+                    return true;
+                }
+                if (t == JsonSerialize.Typing.DYNAMIC) {
+                    return false;
+                }
+            }
+        }
+        // and finally, may be forced by global static typing (unlikely...)
+        return provider.isEnabled(MapperFeature.USE_STATIC_TYPING);
+    }
+
+    /*
+    /**********************************************************
+    /* Accessors
+    /**********************************************************
+     */
+
+    @Override
+    public boolean isEmpty(SerializerProvider provider, T value)
+    {
+        if ((value == null) || _isValueEmpty(value)) {
+            return true;
+        }
+        if (_contentInclusion == null) {
+            return false;
+        }
+        Object contents = _getReferenced(value);
+        JsonSerializer<Object> ser = _valueSerializer;
+        if (ser == null) {
+            try {
+                ser = _findCachedSerializer(provider, contents.getClass());
+            } catch (JsonMappingException e) { // nasty but necessary
+                throw new RuntimeJsonMappingException(e);
+            }
+        }
+        return ser.isEmpty(provider, contents);
+    }
+
+    @Override
+    public boolean isUnwrappingSerializer() {
+        return (_unwrapper != null);
+    }
+
+    /*
+    /**********************************************************
+    /* Serialization methods
+    /**********************************************************
+     */
+
+    @Override
+    public void serialize(T ref, JsonGenerator g, SerializerProvider provider)
+        throws IOException
+    {
+        Object value = _getReferencedIfPresent(ref);
+        if (value == null) {
+            if (_unwrapper == null) {
+                provider.defaultSerializeNull(g);
+            }
+            return;
+        }
+        JsonSerializer<Object> ser = _valueSerializer;
+        if (ser == null) {
+            ser = _findCachedSerializer(provider, value.getClass());
+        }
+        if (_valueTypeSerializer != null) {
+            ser.serializeWithType(value, g, provider, _valueTypeSerializer);
+        } else {
+            ser.serialize(value, g, provider);
+        }
+    }
+
+    @Override
+    public void serializeWithType(T ref,
+            JsonGenerator g, SerializerProvider provider,
+            TypeSerializer typeSer) throws IOException
+    {
+        Object value = _getReferencedIfPresent(ref);
+        if (value == null) {
+            if (_unwrapper == null) {
+                provider.defaultSerializeNull(g);
+            }
+            return;
+        }
+
+        // 19-Apr-2016, tatu: In order to basically "skip" the whole wrapper level
+        //    (which is what non-polymorphic serialization does too), we will need
+        //    to simply delegate call, I think, and NOT try to use it here.
+        
+        // Otherwise apply type-prefix/suffix, then std serialize:
+        /*
+        typeSer.writeTypePrefixForScalar(ref, g);
+        serialize(ref, g, provider);
+        typeSer.writeTypeSuffixForScalar(ref, g);
+        */
+        JsonSerializer<Object> ser = _valueSerializer;
+        if (ser == null) {
+            ser = _findCachedSerializer(provider, value.getClass());
+        }
+        ser.serializeWithType(value, g, provider, typeSer);
+    }
+
+    /*
+    /**********************************************************
+    /* Introspection support
+    /**********************************************************
+     */
+
+    @Override
+    public void acceptJsonFormatVisitor(JsonFormatVisitorWrapper visitor, JavaType typeHint)
+        throws JsonMappingException
+    {
+        JsonSerializer<?> ser = _valueSerializer;
+        if (ser == null) {
+            ser = _findSerializer(visitor.getProvider(), _referredType, _property);
+            if (_unwrapper != null) {
+                ser = ser.unwrappingSerializer(_unwrapper);
+            }
+        }
+        ser.acceptJsonFormatVisitor(visitor, _referredType);
+    }
+
+    /*
+    /**********************************************************
+    /* Helper methods
+    /**********************************************************
+     */
+    
+    /**
+     * Helper method that encapsulates logic of retrieving and caching required
+     * serializer.
+     */
+    private final JsonSerializer<Object> _findCachedSerializer(SerializerProvider provider,
+            Class<?> type) throws JsonMappingException
+    {
+        JsonSerializer<Object> ser = _dynamicSerializers.serializerFor(type);
+        if (ser == null) {
+            ser = _findSerializer(provider, type, _property);
+            if (_unwrapper != null) {
+                ser = ser.unwrappingSerializer(_unwrapper);
+            }
+            _dynamicSerializers = _dynamicSerializers.newWith(type, ser);
+        }
+        return ser;
+    }
+
+    private final JsonSerializer<Object> _findSerializer(SerializerProvider provider,
+            Class<?> type, BeanProperty prop) throws JsonMappingException
+    {
+        // 13-Mar-2017, tatu: Used to call `findTypeValueSerializer()`, but contextualization
+        //   not working for that case for some reason
+ //        return provider.findTypedValueSerializer(type, true, prop);
+        return provider.findValueSerializer(type, prop);
+    }
+
+    private final JsonSerializer<Object> _findSerializer(SerializerProvider provider,
+        JavaType type, BeanProperty prop) throws JsonMappingException
+    {
+        // 13-Mar-2017, tatu: Used to call `findTypeValueSerializer()`, but contextualization
+        //   not working for that case for some reason
+//        return provider.findTypedValueSerializer(type, true, prop);
+        return provider.findValueSerializer(type, prop);
+    }
+}
diff --git a/src/main/java/com/fasterxml/jackson/databind/ser/std/SerializableSerializer.java b/src/main/java/com/fasterxml/jackson/databind/ser/std/SerializableSerializer.java
index 34190b3..793a49c 100644
--- a/src/main/java/com/fasterxml/jackson/databind/ser/std/SerializableSerializer.java
+++ b/src/main/java/com/fasterxml/jackson/databind/ser/std/SerializableSerializer.java
@@ -85,16 +85,14 @@
             try {
                 objectNode.set("properties", _getObjectMapper().readTree(objectProperties));
             } catch (IOException e) {
-                throw JsonMappingException.from(provider,
-                        "Failed to parse @JsonSerializableSchema.schemaObjectPropertiesDefinition value");
+                provider.reportMappingProblem("Failed to parse @JsonSerializableSchema.schemaObjectPropertiesDefinition value");
             }
         }
         if (itemDefinition != null) {
             try {
                 objectNode.set("items", _getObjectMapper().readTree(itemDefinition));
             } catch (IOException e) {
-                throw JsonMappingException.from(provider,
-                        "Failed to parse @JsonSerializableSchema.schemaItemDefinition value");
+                provider.reportMappingProblem("Failed to parse @JsonSerializableSchema.schemaItemDefinition value");
             }
         }
         // always optional, no need to specify:
diff --git a/src/main/java/com/fasterxml/jackson/databind/ser/std/StaticListSerializerBase.java b/src/main/java/com/fasterxml/jackson/databind/ser/std/StaticListSerializerBase.java
index 0e40c89..759c46d 100644
--- a/src/main/java/com/fasterxml/jackson/databind/ser/std/StaticListSerializerBase.java
+++ b/src/main/java/com/fasterxml/jackson/databind/ser/std/StaticListSerializerBase.java
@@ -60,35 +60,36 @@
      */
 
     @Override
-    public JsonSerializer<?> createContextual(SerializerProvider provider, BeanProperty property)
-            throws JsonMappingException
+    public JsonSerializer<?> createContextual(SerializerProvider serializers,
+            BeanProperty property)
+        throws JsonMappingException
     {
         JsonSerializer<?> ser = null;
         Boolean unwrapSingle = null;
         
         if (property != null) {
-            final AnnotationIntrospector intr = provider.getAnnotationIntrospector();
+            final AnnotationIntrospector intr = serializers.getAnnotationIntrospector();
             AnnotatedMember m = property.getMember();
             if (m != null) {
                 Object serDef = intr.findContentSerializer(m);
                 if (serDef != null) {
-                    ser = provider.serializerInstance(m, serDef);
+                    ser = serializers.serializerInstance(m, serDef);
                 }
             }
-            JsonFormat.Value format = property.findPropertyFormat(provider.getConfig(), _handledType);
-            if (format != null) {
-                unwrapSingle = format.getFeature(JsonFormat.Feature.WRITE_SINGLE_ELEM_ARRAYS_UNWRAPPED);
-            }
+        }
+        JsonFormat.Value format = findFormatOverrides(serializers, property, handledType());
+        if (format != null) {
+            unwrapSingle = format.getFeature(JsonFormat.Feature.WRITE_SINGLE_ELEM_ARRAYS_UNWRAPPED);
         }
         if (ser == null) {
             ser = _serializer;
         }
         // [databind#124]: May have a content converter
-        ser = findConvertingContentSerializer(provider, property, ser);
+        ser = findConvertingContentSerializer(serializers, property, ser);
         if (ser == null) {
-            ser = provider.findValueSerializer(String.class, property);
+            ser = serializers.findValueSerializer(String.class, property);
         } else {
-            ser = provider.handleSecondaryContextualization(ser, property);
+            ser = serializers.handleSecondaryContextualization(ser, property);
         }
         // Optimization: default serializer just writes String, so we can avoid a call:
         if (isDefaultSerializer(ser)) {
diff --git a/src/main/java/com/fasterxml/jackson/databind/ser/std/StdArraySerializers.java b/src/main/java/com/fasterxml/jackson/databind/ser/std/StdArraySerializers.java
index 417cc9e..16c7e96 100644
--- a/src/main/java/com/fasterxml/jackson/databind/ser/std/StdArraySerializers.java
+++ b/src/main/java/com/fasterxml/jackson/databind/ser/std/StdArraySerializers.java
@@ -86,6 +86,7 @@
         extends ArraySerializerBase<boolean[]>
     {
         // as above, assuming no one re-defines primitive/wrapper types
+        @SuppressWarnings("deprecation")
         private final static JavaType VALUE_TYPE = TypeFactory.defaultInstance().uncheckedSimpleType(Boolean.class);
 
         public BooleanArraySerializer() { super(boolean[].class); }
@@ -131,28 +132,28 @@
         }
 
         @Override
-        public final void serialize(boolean[] value, JsonGenerator jgen, SerializerProvider provider) throws IOException
+        public final void serialize(boolean[] value, JsonGenerator g, SerializerProvider provider) throws IOException
         {
             final int len = value.length;
             if (len == 1) {
                 if (((_unwrapSingle == null) &&
                         provider.isEnabled(SerializationFeature.WRITE_SINGLE_ELEM_ARRAYS_UNWRAPPED))
                         || (_unwrapSingle == Boolean.TRUE)) {
-                    serializeContents(value, jgen, provider);
+                    serializeContents(value, g, provider);
                     return;
                 }
             }
-            jgen.writeStartArray(len);
-            serializeContents(value, jgen, provider);
-            jgen.writeEndArray();
+            g.writeStartArray(len);
+            serializeContents(value, g, provider);
+            g.writeEndArray();
         }
         
         @Override
-        public void serializeContents(boolean[] value, JsonGenerator jgen, SerializerProvider provider)
+        public void serializeContents(boolean[] value, JsonGenerator g, SerializerProvider provider)
             throws IOException, JsonGenerationException
         {
             for (int i = 0, len = value.length; i < len; ++i) {
-                jgen.writeBoolean(value[i]);
+                g.writeBoolean(value[i]);
             }
         }
 
@@ -176,6 +177,7 @@
     public static class ShortArraySerializer extends TypedPrimitiveArraySerializer<short[]>
     {
         // as above, assuming no one re-defines primitive/wrapper types
+        @SuppressWarnings("deprecation")
         private final static JavaType VALUE_TYPE = TypeFactory.defaultInstance().uncheckedSimpleType(Short.TYPE);
 
         public ShortArraySerializer() { super(short[].class); }
@@ -216,37 +218,37 @@
         }
 
         @Override
-        public final void serialize(short[] value, JsonGenerator jgen, SerializerProvider provider) throws IOException
+        public final void serialize(short[] value, JsonGenerator g, SerializerProvider provider) throws IOException
         {
         	final int len = value.length;
             if (len == 1) {
                 if (((_unwrapSingle == null) &&
                         provider.isEnabled(SerializationFeature.WRITE_SINGLE_ELEM_ARRAYS_UNWRAPPED))
                         || (_unwrapSingle == Boolean.TRUE)) {
-                    serializeContents(value, jgen, provider);
+                    serializeContents(value, g, provider);
                     return;
                 }
             }
-            jgen.writeStartArray(len);
-            serializeContents(value, jgen, provider);
-            jgen.writeEndArray();
+            g.writeStartArray(len);
+            serializeContents(value, g, provider);
+            g.writeEndArray();
         }
         
         @SuppressWarnings("cast")
         @Override
-        public void serializeContents(short[] value, JsonGenerator jgen, SerializerProvider provider)
+        public void serializeContents(short[] value, JsonGenerator g, SerializerProvider provider)
             throws IOException, JsonGenerationException
         {
             if (_valueTypeSerializer != null) {
                 for (int i = 0, len = value.length; i < len; ++i) {
-                    _valueTypeSerializer.writeTypePrefixForScalar(null, jgen, Short.TYPE);
-                    jgen.writeNumber(value[i]);
-                    _valueTypeSerializer.writeTypeSuffixForScalar(null, jgen);
+                    _valueTypeSerializer.writeTypePrefixForScalar(null, g, Short.TYPE);
+                    g.writeNumber(value[i]);
+                    _valueTypeSerializer.writeTypeSuffixForScalar(null, g);
                 }
                 return;
             }
             for (int i = 0, len = value.length; i < len; ++i) {
-                jgen.writeNumber((int)value[i]);
+                g.writeNumber((int)value[i]);
             }
         }
 
@@ -284,41 +286,41 @@
         }
         
         @Override
-        public void serialize(char[] value, JsonGenerator jgen, SerializerProvider provider)
+        public void serialize(char[] value, JsonGenerator g, SerializerProvider provider)
             throws IOException, JsonGenerationException
         {
             // [JACKSON-289] allows serializing as 'sparse' char array too:
             if (provider.isEnabled(SerializationFeature.WRITE_CHAR_ARRAYS_AS_JSON_ARRAYS)) {
-                jgen.writeStartArray(value.length);
-                _writeArrayContents(jgen, value);
-                jgen.writeEndArray();
+                g.writeStartArray(value.length);
+                _writeArrayContents(g, value);
+                g.writeEndArray();
             } else {
-                jgen.writeString(value, 0, value.length);
+                g.writeString(value, 0, value.length);
             }
         }
 
         @Override
-        public void serializeWithType(char[] value, JsonGenerator jgen, SerializerProvider provider,
+        public void serializeWithType(char[] value, JsonGenerator g, SerializerProvider provider,
                 TypeSerializer typeSer)
             throws IOException, JsonGenerationException
         {
             // [JACKSON-289] allows serializing as 'sparse' char array too:
             if (provider.isEnabled(SerializationFeature.WRITE_CHAR_ARRAYS_AS_JSON_ARRAYS)) {
-                typeSer.writeTypePrefixForArray(value, jgen);
-                _writeArrayContents(jgen, value);
-                typeSer.writeTypeSuffixForArray(value, jgen);
+                typeSer.writeTypePrefixForArray(value, g);
+                _writeArrayContents(g, value);
+                typeSer.writeTypeSuffixForArray(value, g);
             } else { // default is to write as simple String
-                typeSer.writeTypePrefixForScalar(value, jgen);
-                jgen.writeString(value, 0, value.length);
-                typeSer.writeTypeSuffixForScalar(value, jgen);
+                typeSer.writeTypePrefixForScalar(value, g);
+                g.writeString(value, 0, value.length);
+                typeSer.writeTypeSuffixForScalar(value, g);
             }
         }
 
-        private final void _writeArrayContents(JsonGenerator jgen, char[] value)
+        private final void _writeArrayContents(JsonGenerator g, char[] value)
             throws IOException, JsonGenerationException
         {
             for (int i = 0, len = value.length; i < len; ++i) {
-                jgen.writeString(value, i, 1);
+                g.writeString(value, i, 1);
             }
         }
 
@@ -343,6 +345,7 @@
     public static class IntArraySerializer extends ArraySerializerBase<int[]>
     {
         // as above, assuming no one re-defines primitive/wrapper types
+        @SuppressWarnings("deprecation")
         private final static JavaType VALUE_TYPE = TypeFactory.defaultInstance().uncheckedSimpleType(Integer.TYPE);
 
         public IntArraySerializer() { super(int[].class); }
@@ -391,28 +394,28 @@
         }
 
         @Override
-        public final void serialize(int[] value, JsonGenerator jgen, SerializerProvider provider) throws IOException
+        public final void serialize(int[] value, JsonGenerator g, SerializerProvider provider) throws IOException
         {
             final int len = value.length;
             if (len == 1) {
                 if (((_unwrapSingle == null) &&
                         provider.isEnabled(SerializationFeature.WRITE_SINGLE_ELEM_ARRAYS_UNWRAPPED))
                         || (_unwrapSingle == Boolean.TRUE)) {
-                    serializeContents(value, jgen, provider);
+                    serializeContents(value, g, provider);
                     return;
                 }
             }
-            jgen.writeStartArray(len);
-            serializeContents(value, jgen, provider);
-            jgen.writeEndArray();
+            // 11-May-2016, tatu: As per [core#277] we have efficient `writeArray(...)` available
+            g.setCurrentValue(value);
+            g.writeArray(value, 0, value.length);
         }
 
         @Override
-        public void serializeContents(int[] value, JsonGenerator jgen, SerializerProvider provider)
+        public void serializeContents(int[] value, JsonGenerator g, SerializerProvider provider)
             throws IOException
         {
             for (int i = 0, len = value.length; i < len; ++i) {
-                jgen.writeNumber(value[i]);
+                g.writeNumber(value[i]);
             }
         }
 
@@ -432,6 +435,7 @@
     public static class LongArraySerializer extends TypedPrimitiveArraySerializer<long[]>
     {
         // as above, assuming no one re-defines primitive/wrapper types
+        @SuppressWarnings("deprecation")
         private final static JavaType VALUE_TYPE = TypeFactory.defaultInstance().uncheckedSimpleType(Long.TYPE);
 
         public LongArraySerializer() { super(long[].class); }
@@ -472,37 +476,37 @@
         }
 
         @Override
-        public final void serialize(long[] value, JsonGenerator jgen, SerializerProvider provider) throws IOException
+        public final void serialize(long[] value, JsonGenerator g, SerializerProvider provider) throws IOException
         {
             final int len = value.length;
             if (len == 1) {
                 if (((_unwrapSingle == null) &&
                         provider.isEnabled(SerializationFeature.WRITE_SINGLE_ELEM_ARRAYS_UNWRAPPED))
                         || (_unwrapSingle == Boolean.TRUE)) {
-                    serializeContents(value, jgen, provider);
+                    serializeContents(value, g, provider);
                     return;
                 }
             }
-            jgen.writeStartArray(len);
-            serializeContents(value, jgen, provider);
-            jgen.writeEndArray();
+            // 11-May-2016, tatu: As per [core#277] we have efficient `writeArray(...)` available
+            g.setCurrentValue(value);
+            g.writeArray(value, 0, value.length);
         }
         
         @Override
-        public void serializeContents(long[] value, JsonGenerator jgen, SerializerProvider provider)
+        public void serializeContents(long[] value, JsonGenerator g, SerializerProvider provider)
             throws IOException
         {
             if (_valueTypeSerializer != null) {
                 for (int i = 0, len = value.length; i < len; ++i) {
-                    _valueTypeSerializer.writeTypePrefixForScalar(null, jgen, Long.TYPE);
-                    jgen.writeNumber(value[i]);
-                    _valueTypeSerializer.writeTypeSuffixForScalar(null, jgen);
+                    _valueTypeSerializer.writeTypePrefixForScalar(null, g, Long.TYPE);
+                    g.writeNumber(value[i]);
+                    _valueTypeSerializer.writeTypeSuffixForScalar(null, g);
                 }
                 return;
             }
             
             for (int i = 0, len = value.length; i < len; ++i) {
-                jgen.writeNumber(value[i]);
+                g.writeNumber(value[i]);
             }
         }
 
@@ -525,6 +529,7 @@
     public static class FloatArraySerializer extends TypedPrimitiveArraySerializer<float[]>
     {
         // as above, assuming no one re-defines primitive/wrapper types
+        @SuppressWarnings("deprecation")
         private final static JavaType VALUE_TYPE = TypeFactory.defaultInstance().uncheckedSimpleType(Float.TYPE);
         
         public FloatArraySerializer() {
@@ -567,36 +572,36 @@
         }
 
         @Override
-        public final void serialize(float[] value, JsonGenerator gen, SerializerProvider provider) throws IOException
+        public final void serialize(float[] value, JsonGenerator g, SerializerProvider provider) throws IOException
         {
             final int len = value.length;
             if (len == 1) {
                 if (((_unwrapSingle == null) &&
                         provider.isEnabled(SerializationFeature.WRITE_SINGLE_ELEM_ARRAYS_UNWRAPPED))
                         || (_unwrapSingle == Boolean.TRUE)) {
-                    serializeContents(value, gen, provider);
+                    serializeContents(value, g, provider);
                     return;
                 }
             }
-            gen.writeStartArray(len);
-            serializeContents(value, gen, provider);
-            gen.writeEndArray();
+            g.writeStartArray(len);
+            serializeContents(value, g, provider);
+            g.writeEndArray();
         }
         
         @Override
-        public void serializeContents(float[] value, JsonGenerator gen, SerializerProvider provider)
+        public void serializeContents(float[] value, JsonGenerator g, SerializerProvider provider)
             throws IOException, JsonGenerationException
         {
             if (_valueTypeSerializer != null) {
                 for (int i = 0, len = value.length; i < len; ++i) {
-                    _valueTypeSerializer.writeTypePrefixForScalar(null, gen, Float.TYPE);
-                    gen.writeNumber(value[i]);
-                    _valueTypeSerializer.writeTypeSuffixForScalar(null, gen);
+                    _valueTypeSerializer.writeTypePrefixForScalar(null, g, Float.TYPE);
+                    g.writeNumber(value[i]);
+                    _valueTypeSerializer.writeTypeSuffixForScalar(null, g);
                 }
                 return;
             }
             for (int i = 0, len = value.length; i < len; ++i) {
-                gen.writeNumber(value[i]);
+                g.writeNumber(value[i]);
             }
         }
 
@@ -616,6 +621,7 @@
     public static class DoubleArraySerializer extends ArraySerializerBase<double[]>
     {
         // as above, assuming no one re-defines primitive/wrapper types
+        @SuppressWarnings("deprecation")
         private final static JavaType VALUE_TYPE = TypeFactory.defaultInstance().uncheckedSimpleType(Double.TYPE);
 
         public DoubleArraySerializer() { super(double[].class); }
@@ -664,27 +670,27 @@
         }
 
         @Override
-        public final void serialize(double[] value, JsonGenerator gen, SerializerProvider provider) throws IOException
+        public final void serialize(double[] value, JsonGenerator g, SerializerProvider provider) throws IOException
         {
             final int len = value.length;
             if (len == 1) {
                 if (((_unwrapSingle == null) &&
                         provider.isEnabled(SerializationFeature.WRITE_SINGLE_ELEM_ARRAYS_UNWRAPPED))
                         || (_unwrapSingle == Boolean.TRUE)) {
-                    serializeContents(value, gen, provider);
+                    serializeContents(value, g, provider);
                     return;
                 }
             }
-            gen.writeStartArray(len);
-            serializeContents(value, gen, provider);
-            gen.writeEndArray();
+            // 11-May-2016, tatu: As per [core#277] we have efficient `writeArray(...)` available
+            g.setCurrentValue(value);
+            g.writeArray(value, 0, value.length);
         }
 
         @Override
-        public void serializeContents(double[] value, JsonGenerator gen, SerializerProvider provider) throws IOException
+        public void serializeContents(double[] value, JsonGenerator g, SerializerProvider provider) throws IOException
         {
             for (int i = 0, len = value.length; i < len; ++i) {
-                gen.writeNumber(value[i]);
+                g.writeNumber(value[i]);
             }
         }
 
diff --git a/src/main/java/com/fasterxml/jackson/databind/ser/std/StdKeySerializer.java b/src/main/java/com/fasterxml/jackson/databind/ser/std/StdKeySerializer.java
index 3fbb8d0..fceba52 100644
--- a/src/main/java/com/fasterxml/jackson/databind/ser/std/StdKeySerializer.java
+++ b/src/main/java/com/fasterxml/jackson/databind/ser/std/StdKeySerializer.java
@@ -12,8 +12,11 @@
  * Specialized serializer that can be used as the generic key
  * serializer, when serializing {@link java.util.Map}s to JSON
  * Objects.
+ *
+ * @deprecated Since 2.8, use {@link StdKeySerializers.Default} instead.
  */
 @SuppressWarnings("serial")
+@Deprecated // since 2.8,
 public class StdKeySerializer extends StdSerializer<Object>
 {
     public StdKeySerializer() { super(Object.class); }
@@ -28,12 +31,15 @@
         } else if (cls.isEnum()) {
             // 24-Sep-2015, tatu: Minor improvement over older (2.6.2 and before) code: at least
             //     use name/toString() variation for as per configuration
-            Enum<?> en = (Enum<?>) value;
-
             if (provider.isEnabled(SerializationFeature.WRITE_ENUMS_USING_TO_STRING)) {
-                str = en.toString();
+                str = value.toString();
             } else {
-                str = en.name();
+                Enum<?> en = (Enum<?>) value;
+                if (provider.isEnabled(SerializationFeature.WRITE_ENUMS_USING_TO_STRING)) {
+                    str = String.valueOf(en.ordinal());
+                } else {
+                    str = en.name();
+                }
             }
         } else if (value instanceof Date) {
             provider.defaultSerializeDateKey((Date) value, g);
diff --git a/src/main/java/com/fasterxml/jackson/databind/ser/std/StdKeySerializers.java b/src/main/java/com/fasterxml/jackson/databind/ser/std/StdKeySerializers.java
index 7afcc55..369e659 100644
--- a/src/main/java/com/fasterxml/jackson/databind/ser/std/StdKeySerializers.java
+++ b/src/main/java/com/fasterxml/jackson/databind/ser/std/StdKeySerializers.java
@@ -6,12 +6,14 @@
 
 import com.fasterxml.jackson.core.*;
 import com.fasterxml.jackson.databind.*;
+import com.fasterxml.jackson.databind.jsonFormatVisitors.JsonFormatVisitorWrapper;
 import com.fasterxml.jackson.databind.ser.impl.PropertySerializerMap;
 import com.fasterxml.jackson.databind.util.EnumValues;
 
 @SuppressWarnings("serial")
 public class StdKeySerializers
 {
+    @SuppressWarnings("deprecation")
     protected final static JsonSerializer<Object> DEFAULT_KEY_SERIALIZER = new StdKeySerializer();
 
     protected final static JsonSerializer<Object> DEFAULT_STRING_SERIALIZER = new StringKeySerializer();
@@ -41,7 +43,9 @@
             return DEFAULT_STRING_SERIALIZER;
         }
         if (rawKeyType.isPrimitive() || Number.class.isAssignableFrom(rawKeyType)) {
-            return DEFAULT_KEY_SERIALIZER;
+            // 28-Jun-2016, tatu: Used to just return DEFAULT_KEY_SERIALIZER, but makes
+            //   more sense to use simpler one directly
+            return new Default(Default.TYPE_TO_STRING, rawKeyType);
         }
         if (rawKeyType == Class.class) {
             return new Default(Default.TYPE_CLASS, rawKeyType);
@@ -56,7 +60,10 @@
         if (rawKeyType == java.util.UUID.class) {
             return new Default(Default.TYPE_TO_STRING, rawKeyType);
         }
-        return useDefault ? DEFAULT_KEY_SERIALIZER : null;
+        if (useDefault) {
+            return DEFAULT_KEY_SERIALIZER;
+        }
+        return null;
     }
 
     /**
@@ -137,9 +144,19 @@
                 break;
             case TYPE_ENUM:
                 {
-                    String str = provider.isEnabled(SerializationFeature.WRITE_ENUMS_USING_TO_STRING)
-                            ? value.toString() : ((Enum<?>) value).name();
-                    g.writeFieldName(str);
+                    String key;
+
+                    if (provider.isEnabled(SerializationFeature.WRITE_ENUMS_USING_TO_STRING)) {
+                        key = value.toString();
+                    } else {
+                        Enum<?> e = (Enum<?>) value;
+                        if (provider.isEnabled(SerializationFeature.WRITE_ENUMS_USING_INDEX)) {
+                            key = String.valueOf(e.ordinal());
+                        } else {
+                            key = e.name();
+                        }
+                    }
+                    g.writeFieldName(key);
                 }
                 break;
             case TYPE_TO_STRING:
@@ -182,9 +199,21 @@
             ser.serialize(value, g, provider);
         }
 
+        @Override
+        public void acceptJsonFormatVisitor(JsonFormatVisitorWrapper visitor, JavaType typeHint) throws JsonMappingException {
+            visitStringFormat(visitor, typeHint);
+        }
+
         protected JsonSerializer<Object> _findAndAddDynamic(PropertySerializerMap map,
                 Class<?> type, SerializerProvider provider) throws JsonMappingException
         {
+            // 27-Jun-2017, tatu: [databind#1679] Need to avoid StackOverflowError...
+            if (type == Object.class) {
+                // basically just need to call `toString()`, easiest way:
+                JsonSerializer<Object> ser = new Default(Default.TYPE_TO_STRING, type);
+                _dynamicSerializers = map.newWith(type, ser);
+                return ser;
+            }
             PropertySerializerMap.SerializerAndMapResult result =
                     // null -> for now we won't keep ref or pass BeanProperty; could change
                     map.findAndAddKeySerializer(type, provider, null);
@@ -238,6 +267,10 @@
                 return;
             }
             Enum<?> en = (Enum<?>) value;
+            if (serializers.isEnabled(SerializationFeature.WRITE_ENUMS_USING_INDEX)) {
+                g.writeFieldName(String.valueOf(en.ordinal()));
+                return;
+            }
             g.writeFieldName(_values.serializedValueFor(en));
         }
     }
diff --git a/src/main/java/com/fasterxml/jackson/databind/ser/std/StdSerializer.java b/src/main/java/com/fasterxml/jackson/databind/ser/std/StdSerializer.java
index 010f53d..a1108e8 100644
--- a/src/main/java/com/fasterxml/jackson/databind/ser/std/StdSerializer.java
+++ b/src/main/java/com/fasterxml/jackson/databind/ser/std/StdSerializer.java
@@ -5,6 +5,7 @@
 import java.lang.reflect.Type;
 
 import com.fasterxml.jackson.annotation.JsonFormat;
+import com.fasterxml.jackson.annotation.JsonInclude;
 import com.fasterxml.jackson.core.*;
 import com.fasterxml.jackson.core.JsonParser.NumberType;
 import com.fasterxml.jackson.databind.*;
@@ -440,9 +441,8 @@
             throw JsonMappingException.from(provider,
                     "Can not resolve PropertyFilter with id '"+filterId+"'; no FilterProvider configured");
         }
-        PropertyFilter filter = filters.findPropertyFilter(filterId, valueToFilter);
         // But whether unknown ids are ok just depends on filter provider; if we get null that's fine
-        return filter;
+        return filters.findPropertyFilter(filterId, valueToFilter);
     }
 
     /**
@@ -484,6 +484,19 @@
     }
 
     /**
+     * @since 2.8
+     */
+    protected JsonInclude.Value findIncludeOverrides(SerializerProvider provider,
+            BeanProperty prop, Class<?> typeForDefaults)
+    {
+        if (prop != null) {
+            return prop.findPropertyInclusion(provider.getConfig(), typeForDefaults);
+        }
+        // even without property or AnnotationIntrospector, may have type-specific defaults
+        return provider.getDefaultPropertyInclusion(typeForDefaults);
+    }
+    
+    /**
      * Convenience method for finding out possibly configured content value serializer.
      *
      * @since 2.7.4
diff --git a/src/main/java/com/fasterxml/jackson/databind/ser/std/ToStringSerializer.java b/src/main/java/com/fasterxml/jackson/databind/ser/std/ToStringSerializer.java
index f9d3a69..5d3aa91 100644
--- a/src/main/java/com/fasterxml/jackson/databind/ser/std/ToStringSerializer.java
+++ b/src/main/java/com/fasterxml/jackson/databind/ser/std/ToStringSerializer.java
@@ -47,12 +47,6 @@
     }
 
     @Override
-    @Deprecated
-    public boolean isEmpty(Object value) {
-        return isEmpty(null, value);
-    }
-
-    @Override
     public boolean isEmpty(SerializerProvider prov, Object value) {
         if (value == null) {
             return true;
diff --git a/src/main/java/com/fasterxml/jackson/databind/type/ArrayType.java b/src/main/java/com/fasterxml/jackson/databind/type/ArrayType.java
index d4543a2..24ac759 100644
--- a/src/main/java/com/fasterxml/jackson/databind/type/ArrayType.java
+++ b/src/main/java/com/fasterxml/jackson/databind/type/ArrayType.java
@@ -182,6 +182,11 @@
     }
 
     @Override
+    public boolean hasHandlers() {
+        return super.hasHandlers() || _componentType.hasHandlers();
+    }
+    
+    @Override
     public StringBuilder getGenericSignature(StringBuilder sb) {
         sb.append('[');
         return _componentType.getGenericSignature(sb);
diff --git a/src/main/java/com/fasterxml/jackson/databind/type/CollectionLikeType.java b/src/main/java/com/fasterxml/jackson/databind/type/CollectionLikeType.java
index 45d6ca4..f355160 100644
--- a/src/main/java/com/fasterxml/jackson/databind/type/CollectionLikeType.java
+++ b/src/main/java/com/fasterxml/jackson/databind/type/CollectionLikeType.java
@@ -134,6 +134,19 @@
     }
 
     @Override
+    public JavaType withHandlersFrom(JavaType src) {
+        JavaType type = super.withHandlersFrom(src);
+        JavaType srcCt = src.getContentType();
+        if (srcCt != null) {
+            JavaType ct = _elementType.withHandlersFrom(srcCt);
+            if (ct != _elementType) {
+                type = type.withContentType(ct);
+            }
+        }
+        return type;
+    }
+    
+    @Override
     public CollectionLikeType withStaticTyping() {
         if (_asStatic) {
             return this;
@@ -177,6 +190,11 @@
     }    
 
     @Override
+    public boolean hasHandlers() {
+        return super.hasHandlers() || _elementType.hasHandlers();
+    }
+
+    @Override
     public StringBuilder getErasedSignature(StringBuilder sb) {
         return _classSignature(_class, sb, true);
     }
diff --git a/src/main/java/com/fasterxml/jackson/databind/type/CollectionType.java b/src/main/java/com/fasterxml/jackson/databind/type/CollectionType.java
index e0a7856..7b38ab4 100644
--- a/src/main/java/com/fasterxml/jackson/databind/type/CollectionType.java
+++ b/src/main/java/com/fasterxml/jackson/databind/type/CollectionType.java
@@ -42,7 +42,7 @@
     }
 
     /**
-     * @deprecated Since 2.7, remove from 2.8
+     * @deprecated Since 2.7, remove from 2.9
      */
     @Deprecated // since 2.7
     public static CollectionType construct(Class<?> rawType, JavaType elemT) {
diff --git a/src/main/java/com/fasterxml/jackson/databind/type/MapLikeType.java b/src/main/java/com/fasterxml/jackson/databind/type/MapLikeType.java
index b8d5ea4..f1d1ee0 100644
--- a/src/main/java/com/fasterxml/jackson/databind/type/MapLikeType.java
+++ b/src/main/java/com/fasterxml/jackson/databind/type/MapLikeType.java
@@ -27,8 +27,9 @@
     protected final JavaType _valueType;
 
     /*
-     * /********************************************************** /* Life-cycle
-     * /**********************************************************
+    /**********************************************************
+    * Life-cycle
+    /**********************************************************
      */
 
     protected MapLikeType(Class<?> mapType, TypeBindings bindings,
@@ -145,6 +146,29 @@
     }
 
     @Override
+    public JavaType withHandlersFrom(JavaType src) {
+        JavaType type = super.withHandlersFrom(src);
+        JavaType srcKeyType = src.getKeyType();
+        // "withKeyType()" not part of JavaType, hence must verify:
+        if (type instanceof MapLikeType) {
+            if (srcKeyType != null) {
+                JavaType ct = _keyType.withHandlersFrom(srcKeyType);
+                if (ct != _keyType) {
+                    type = ((MapLikeType) type).withKeyType(ct);
+                }
+            }
+        }
+        JavaType srcCt = src.getContentType();
+        if (srcCt != null) {
+            JavaType ct = _valueType.withHandlersFrom(srcCt);
+            if (ct != _valueType) {
+                type = type.withContentType(ct);
+            }
+        }
+        return type;
+    }
+
+    @Override
     public MapLikeType withStaticTyping() {
         if (_asStatic) {
             return this;
@@ -176,8 +200,9 @@
     }
 
     /*
-     * /********************************************************** /* Public API
-     * /**********************************************************
+    /**********************************************************
+    /* Public API
+    /**********************************************************
      */
 
     @Override
@@ -211,6 +236,12 @@
     }
 
     @Override
+    public boolean hasHandlers() {
+        return super.hasHandlers() || _valueType.hasHandlers()
+                || _keyType.hasHandlers();
+    }
+
+    @Override
     public StringBuilder getErasedSignature(StringBuilder sb) {
         return _classSignature(_class, sb, true);
     }
@@ -226,8 +257,9 @@
     }
 
     /*
-     * /********************************************************** /* Extended
-     * API /**********************************************************
+    /**********************************************************
+    /* Extended API
+    /**********************************************************
      */
 
     public MapLikeType withKeyTypeHandler(Object h) {
@@ -252,24 +284,22 @@
     }
 
     /*
-     * /********************************************************** /* Standard
-     * methods /**********************************************************
+    /**********************************************************
+    /* Standard methods
+    /**********************************************************
      */
 
     @Override
     public String toString() {
-        return "[map-like type; class " + _class.getName() + ", " + _keyType
-                + " -> " + _valueType + "]";
+        return String.format("[map-like type; class %s, %s -> %s]",
+                _class.getName(), _keyType, _valueType);
     }
 
     @Override
     public boolean equals(Object o) {
-        if (o == this)
-            return true;
-        if (o == null)
-            return false;
-        if (o.getClass() != getClass())
-            return false;
+        if (o == this) return true;
+        if (o == null) return false;
+        if (o.getClass() != getClass()) return false;
 
         MapLikeType other = (MapLikeType) o;
         return (_class == other._class) && _keyType.equals(other._keyType)
diff --git a/src/main/java/com/fasterxml/jackson/databind/type/PlaceholderForType.java b/src/main/java/com/fasterxml/jackson/databind/type/PlaceholderForType.java
new file mode 100644
index 0000000..54ed402
--- /dev/null
+++ b/src/main/java/com/fasterxml/jackson/databind/type/PlaceholderForType.java
@@ -0,0 +1,109 @@
+package com.fasterxml.jackson.databind.type;
+
+import com.fasterxml.jackson.databind.JavaType;
+
+/**
+ * Helper type used when introspecting bindings for already resolved types,
+ * needed for specialization.
+ *
+ * @since 2.8.11
+ */
+public class PlaceholderForType extends TypeBase
+{
+    private static final long serialVersionUID = 1L;
+
+    protected final int _ordinal;
+
+    /**
+     * Type assigned during wildcard resolution (which follows type
+     * structure resolution)
+     */
+    protected JavaType _actualType;
+    
+    public PlaceholderForType(int ordinal)
+    {
+        super(Object.class, TypeBindings.emptyBindings(),
+                TypeFactory.unknownType(), null, 1, // super-class, super-interfaces, hashCode
+                null, null, false); // value/type handler, as-static
+        _ordinal = ordinal;
+    }
+
+    public JavaType actualType() { return _actualType; }
+    public void actualType(JavaType t) { _actualType = t; }
+
+    // Override to get better diagnostics
+    @Override
+    protected String buildCanonicalName() {
+        return toString();
+    }
+
+    @Override
+    public StringBuilder getGenericSignature(StringBuilder sb) {
+        return getErasedSignature(sb);
+    }
+
+    @Override
+    public StringBuilder getErasedSignature(StringBuilder sb) {
+        sb.append('$').append(_ordinal+1);
+        return sb;
+    }
+
+    @Override
+    public JavaType withTypeHandler(Object h) {
+        return _unsupported();
+    }
+
+    @Override
+    public JavaType withContentTypeHandler(Object h) {
+        return _unsupported();
+    }
+
+    @Override
+    public JavaType withValueHandler(Object h) {
+        return _unsupported();
+    }
+
+    @Override
+    public JavaType withContentValueHandler(Object h) {
+        return _unsupported();
+    }
+
+    @Override
+    public JavaType withContentType(JavaType contentType) {
+        return _unsupported();
+    }
+
+    @Override
+    public JavaType withStaticTyping() {
+        return _unsupported();
+    }
+
+    @Override
+    public JavaType refine(Class<?> rawType, TypeBindings bindings, JavaType superClass, JavaType[] superInterfaces) {
+        return _unsupported();
+    }
+
+    @Override
+    protected JavaType _narrow(Class<?> subclass) {
+        return _unsupported();
+    }
+
+    @Override
+    public boolean isContainerType() {
+        return false;
+    }
+
+    @Override
+    public String toString() {
+        return getErasedSignature(new StringBuilder()).toString();
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        return (o == this);
+    }
+
+    private <T> T _unsupported() {
+        throw new UnsupportedOperationException("Operation should not be attempted on "+getClass().getName());
+    }
+}
diff --git a/src/main/java/com/fasterxml/jackson/databind/type/ReferenceType.java b/src/main/java/com/fasterxml/jackson/databind/type/ReferenceType.java
index 76deae2..e8c6962 100644
--- a/src/main/java/com/fasterxml/jackson/databind/type/ReferenceType.java
+++ b/src/main/java/com/fasterxml/jackson/databind/type/ReferenceType.java
@@ -16,38 +16,59 @@
 
     protected final JavaType _referencedType;
 
+    /**
+     * Essential type used for type ids, for example if type id is needed for
+     * referencing type with polymorphic handling. Typically initialized when
+     * a {@link SimpleType} is upgraded into reference type, but NOT changed
+     * if being sub-classed.
+     *
+     * @since 2.8
+     */
+    protected final JavaType _anchorType;
+
     protected ReferenceType(Class<?> cls, TypeBindings bindings,
             JavaType superClass, JavaType[] superInts, JavaType refType,
+            JavaType anchorType,
             Object valueHandler, Object typeHandler, boolean asStatic)
     {
         super(cls, bindings, superClass, superInts, refType.hashCode(),
                 valueHandler, typeHandler, asStatic);
         _referencedType = refType;
+        _anchorType = (anchorType == null) ? this : anchorType;
     }
 
     /**
+     * Constructor used when upgrading into this type (via {@link #upgradeFrom},
+     * the usual way for {@link ReferenceType}s to come into existence.
+     * Sets up what is considered the "base" reference type
+     *
      * @since 2.7
      */
     protected ReferenceType(TypeBase base, JavaType refType)
     {
         super(base);
         _referencedType = refType;
+        // we'll establish this as the anchor type
+        _anchorType = this;
     }
 
     /**
      * Factory method that can be used to "upgrade" a basic type into collection-like
      * one; usually done via {@link TypeModifier}
+     * 
+     * @param baseType Resolved non-reference type (usually {@link SimpleType}) that is being upgraded
+     * @param refdType Referenced type; usually the first and only type parameter, but not necessarily
      *
      * @since 2.7
      */
-    public static ReferenceType upgradeFrom(JavaType baseType, JavaType refType) {
-        if (refType == null) {
+    public static ReferenceType upgradeFrom(JavaType baseType, JavaType refdType) {
+        if (refdType == null) {
             throw new IllegalArgumentException("Missing referencedType");
         }
         // 19-Oct-2015, tatu: Not sure if and how other types could be used as base;
         //    will cross that bridge if and when need be
         if (baseType instanceof TypeBase) {
-            return new ReferenceType((TypeBase) baseType, refType);
+            return new ReferenceType((TypeBase) baseType, refdType);
         }
         throw new IllegalArgumentException("Can not upgrade from an instance of "+baseType.getClass());
     }
@@ -59,14 +80,14 @@
             JavaType superClass, JavaType[] superInts, JavaType refType)
     {
         return new ReferenceType(cls, bindings, superClass, superInts,
-                refType, null, null, false);
+                refType, null, null, null, false);
     }
 
     @Deprecated // since 2.7
     public static ReferenceType construct(Class<?> cls, JavaType refType) {
         return new ReferenceType(cls, TypeBindings.emptyBindings(),
                 // !!! TODO: missing supertypes
-                null, null, refType, null, null, false);
+                null, null, null, refType, null, null, false);
     }
 
     @Override
@@ -75,7 +96,7 @@
             return this;
         }
         return new ReferenceType(_class, _bindings, _superClass, _superInterfaces,
-                contentType, _valueHandler, _typeHandler, _asStatic);
+                contentType, _anchorType, _valueHandler, _typeHandler, _asStatic);
     }
 
     @Override
@@ -84,8 +105,8 @@
         if (h == _typeHandler) {
             return this;
         }
-        return new ReferenceType(_class, _bindings,
-                _superClass, _superInterfaces, _referencedType, _valueHandler, h, _asStatic);
+        return new ReferenceType(_class, _bindings, _superClass, _superInterfaces,
+                _referencedType, _anchorType, _valueHandler, h, _asStatic);
     }
 
     @Override
@@ -94,8 +115,8 @@
         if (h == _referencedType.<Object>getTypeHandler()) {
             return this;
         }
-        return new ReferenceType(_class, _bindings,
-                _superClass, _superInterfaces, _referencedType.withTypeHandler(h),
+        return new ReferenceType(_class, _bindings, _superClass, _superInterfaces,
+                _referencedType.withTypeHandler(h), _anchorType,
                 _valueHandler, _typeHandler, _asStatic);
     }
 
@@ -105,7 +126,8 @@
             return this;
         }
         return new ReferenceType(_class, _bindings,
-                _superClass, _superInterfaces, _referencedType, h, _typeHandler,_asStatic);
+                _superClass, _superInterfaces, _referencedType, _anchorType,
+                h, _typeHandler,_asStatic);
     }
 
     @Override
@@ -115,7 +137,7 @@
         }
         JavaType refdType = _referencedType.withValueHandler(h);
         return new ReferenceType(_class, _bindings,
-                _superClass, _superInterfaces, refdType,
+                _superClass, _superInterfaces, refdType, _anchorType,
                 _valueHandler, _typeHandler, _asStatic);
     }
 
@@ -124,8 +146,8 @@
         if (_asStatic) {
             return this;
         }
-        return new ReferenceType(_class, _bindings,
-                _superClass, _superInterfaces, _referencedType.withStaticTyping(),
+        return new ReferenceType(_class, _bindings, _superClass, _superInterfaces,
+                _referencedType.withStaticTyping(), _anchorType,
                  _valueHandler, _typeHandler, true);
     }
 
@@ -133,7 +155,7 @@
     public JavaType refine(Class<?> rawType, TypeBindings bindings,
             JavaType superClass, JavaType[] superInterfaces) {
         return new ReferenceType(rawType, _bindings,
-                superClass, superInterfaces, _referencedType,
+                superClass, superInterfaces, _referencedType, _anchorType,
                 _valueHandler, _typeHandler, _asStatic);
     }
 
@@ -144,6 +166,7 @@
         sb.append(_class.getName());
         sb.append('<');
         sb.append(_referencedType.toCanonical());
+        sb.append('>');
         return sb.toString();
     }
 
@@ -159,7 +182,7 @@
     {
         // Should we check that there is a sub-class relationship?
         return new ReferenceType(subclass, _bindings,
-                _superClass, _superInterfaces, _referencedType,
+                _superClass, _superInterfaces, _referencedType, _anchorType,
                 _valueHandler, _typeHandler, _asStatic);
     }
 
@@ -173,13 +196,18 @@
     public JavaType getContentType() {
         return _referencedType;
     }
-    
+
     @Override
     public JavaType getReferencedType() {
         return _referencedType;
     }
 
     @Override
+    public boolean hasContentType() {
+        return true;
+    }
+
+    @Override
     public boolean isReferenceType() {
         return true;
     }
@@ -198,7 +226,25 @@
         sb.append(">;");
         return sb;
     }
-    
+
+    /*
+    /**********************************************************
+    /* Extended API
+    /**********************************************************
+     */
+
+    public JavaType getAnchorType() {
+        return _anchorType;
+    }
+
+    /**
+     * Convenience accessor that allows checking whether this is the anchor type
+     * itself; if not, it must be one of supertypes that is also a {@link ReferenceType}
+     */
+    public boolean isAnchorType() {
+        return (_anchorType == this);
+    }
+
     /*
     /**********************************************************
     /* Standard methods
diff --git a/src/main/java/com/fasterxml/jackson/databind/type/ResolvedRecursiveType.java b/src/main/java/com/fasterxml/jackson/databind/type/ResolvedRecursiveType.java
index 13c3e59..53e061c 100644
--- a/src/main/java/com/fasterxml/jackson/databind/type/ResolvedRecursiveType.java
+++ b/src/main/java/com/fasterxml/jackson/databind/type/ResolvedRecursiveType.java
@@ -25,6 +25,14 @@
         }
         _referencedType = ref;
     }
+   
+    @Override
+    public JavaType getSuperClass() {
+    	if (_referencedType != null) {
+    		return _referencedType.getSuperClass();
+    	}
+    	return super.getSuperClass();
+    }
 
     public JavaType getSelfReferencedType() { return _referencedType; }
 
@@ -103,8 +111,22 @@
     public boolean equals(Object o) {
         if (o == this) return true;
         if (o == null) return false;
-        if (o.getClass() != getClass()) return false;
+        if (o.getClass() == getClass()) {
+            // 16-Jun-2017, tatu: as per [databind#1658], can not do recursive call since
+            //    there is likely to be a cycle...
 
-        return ((ResolvedRecursiveType) o).getSelfReferencedType().equals(getSelfReferencedType());
+            // but... true or false?
+            return false;
+            
+            /*
+            // Do NOT ever match unresolved references
+            if (_referencedType == null) {
+                return false;
+            }
+            return (o.getClass() == getClass()
+                    && _referencedType.equals(((ResolvedRecursiveType) o).getSelfReferencedType()));
+                    */
+        }
+        return false;
     }
 }
diff --git a/src/main/java/com/fasterxml/jackson/databind/type/SimpleType.java b/src/main/java/com/fasterxml/jackson/databind/type/SimpleType.java
index 0273c70..1fb2433 100644
--- a/src/main/java/com/fasterxml/jackson/databind/type/SimpleType.java
+++ b/src/main/java/com/fasterxml/jackson/databind/type/SimpleType.java
@@ -128,7 +128,7 @@
         // Should we check that there is a sub-class relationship?
         // 15-Jan-2016, tatu: Almost yes, but there are some complications with
         //    placeholder values (`Void`, `NoClass`), so can not quite do yet.
-        // TODO: fix in 2.8
+        // TODO: fix in 2.9
         if (!_class.isAssignableFrom(subclass)) {
             /*
             throw new IllegalArgumentException("Class "+subclass.getName()+" not sub-type of "
@@ -211,7 +211,7 @@
         // SimpleType means something not-specialized, so:
         return null;
     }
-    
+
     @Override
     protected String buildCanonicalName()
     {
@@ -241,6 +241,9 @@
 
     @Override
     public boolean isContainerType() { return false; }
+    
+    @Override
+    public boolean hasContentType() { return false; }
 
     @Override
     public StringBuilder getErasedSignature(StringBuilder sb) {
diff --git a/src/main/java/com/fasterxml/jackson/databind/type/TypeBase.java b/src/main/java/com/fasterxml/jackson/databind/type/TypeBase.java
index 73e1d94..056c727 100644
--- a/src/main/java/com/fasterxml/jackson/databind/type/TypeBase.java
+++ b/src/main/java/com/fasterxml/jackson/databind/type/TypeBase.java
@@ -81,14 +81,6 @@
     public abstract StringBuilder getErasedSignature(StringBuilder sb);
 
     @Override
-    @SuppressWarnings("unchecked")
-    public <T> T getValueHandler() { return (T) _valueHandler; }
-
-    @Override
-    @SuppressWarnings("unchecked")
-    public <T> T getTypeHandler() { return (T) _typeHandler; }
-
-    @Override
     public TypeBindings getBindings() {
         return _bindings;
     }
diff --git a/src/main/java/com/fasterxml/jackson/databind/type/TypeFactory.java b/src/main/java/com/fasterxml/jackson/databind/type/TypeFactory.java
index 0022ddd..46910eb 100644
--- a/src/main/java/com/fasterxml/jackson/databind/type/TypeFactory.java
+++ b/src/main/java/com/fasterxml/jackson/databind/type/TypeFactory.java
@@ -114,7 +114,7 @@
      * actual generic types), we will use small cache to avoid repetitive
      * resolution of core types
      */
-    protected final LRUMap<Object,JavaType> _typeCache = new LRUMap<Object,JavaType>(16, 100);
+    protected final LRUMap<Object,JavaType> _typeCache;
 
     /*
     /**********************************************************
@@ -142,16 +142,29 @@
      */
 
     private TypeFactory() {
+        this(null);
+    }
+
+    /**
+     * @since 2.8
+     */
+    protected TypeFactory(LRUMap<Object,JavaType> typeCache) {
+        if (typeCache == null) {
+            typeCache = new LRUMap<Object,JavaType>(16, 200);
+        }
+        _typeCache = typeCache;
         _parser = new TypeParser(this);
         _modifiers = null;
         _classLoader = null;
     }
 
-    protected TypeFactory(TypeParser p, TypeModifier[] mods) {
-        this(p, mods, null);
-    }
-    
-    protected TypeFactory(TypeParser p, TypeModifier[] mods, ClassLoader classLoader) {
+    protected TypeFactory(LRUMap<Object,JavaType> typeCache, TypeParser p,
+            TypeModifier[] mods, ClassLoader classLoader)
+    {
+        if (typeCache == null) {
+            typeCache = new LRUMap<Object,JavaType>(16, 200);
+        }
+        _typeCache = typeCache;
         // As per [databind#894] must ensure we have back-linkage from TypeFactory:
         _parser = p.withFactory(this);
         _modifiers = mods;
@@ -160,17 +173,34 @@
 
     public TypeFactory withModifier(TypeModifier mod) 
     {
+        LRUMap<Object,JavaType> typeCache = _typeCache;
+        TypeModifier[] mods;
         if (mod == null) { // mostly for unit tests
-            return new TypeFactory(_parser, _modifiers, _classLoader);
+            mods = null;
+            // 30-Jun-2016, tatu: for some reason expected semantics are to clear cache
+            //    in this case; can't recall why, but keeping the same
+            typeCache = null;
+        } else if (_modifiers == null) {
+            mods = new TypeModifier[] { mod };
+        } else {
+            mods = ArrayBuilders.insertInListNoDup(_modifiers, mod);
         }
-        if (_modifiers == null) {
-            return new TypeFactory(_parser, new TypeModifier[] { mod }, _classLoader);
-        }
-        return new TypeFactory(_parser, ArrayBuilders.insertInListNoDup(_modifiers, mod), _classLoader);
+        return new TypeFactory(typeCache, _parser, mods, _classLoader);
     }
-    
+
     public TypeFactory withClassLoader(ClassLoader classLoader) {
-        return new TypeFactory(_parser, _modifiers, classLoader);
+        return new TypeFactory(_typeCache, _parser, _modifiers, classLoader);
+    }
+
+    /**
+     * Mutant factory method that will construct new {@link TypeFactory} with
+     * identical settings except for different cache; most likely one with
+     * bigger maximum size.
+     *
+     * @since 2.8
+     */
+    public TypeFactory withCache(LRUMap<Object,JavaType> cache)  {
+        return new TypeFactory(cache, _parser, _modifiers, _classLoader);
     }
 
     /**
@@ -251,7 +281,7 @@
         Throwable prob = null;
         ClassLoader loader = this.getClassLoader();
         if (loader == null) {
-          loader = 	Thread.currentThread().getContextClassLoader();
+            loader = 	Thread.currentThread().getContextClassLoader();
         }
         if (loader != null) {
             try {
@@ -322,7 +352,7 @@
         // also: if we start from untyped, not much to save
         do { // bogus loop to be able to break
             if (rawBase == Object.class) {
-                newType = _fromClass(null, subclass, TypeBindings.emptyBindings());
+                newType = _fromClass(null, subclass, EMPTY_BINDINGS);
                 break;
             }
             if (!rawBase.isAssignableFrom(subclass)) {
@@ -333,7 +363,7 @@
 
             // (1) Original target type has no generics -- just resolve subtype
             if (baseType.getBindings().isEmpty()) {
-                newType = _fromClass(null, subclass, TypeBindings.emptyBindings());     
+                newType = _fromClass(null, subclass, EMPTY_BINDINGS);     
                 break;
             }
             // (2) A small set of "well-known" List/Map subtypes where can take a short-cut
@@ -369,102 +399,94 @@
                 newType = _fromClass(null, subclass, TypeBindings.emptyBindings());     
                 break;
             }
-            
-            // If not, we'll need to do more thorough forward+backwards resolution. Sigh.
-            // !!! TODO (as of 28-Jan-2016, at least)
-            
-            // 20-Oct-2015, tatu: Container, Map-types somewhat special. There is
-            //    a way to fully resolve and merge hierarchies; but that gets expensive
-            //    so let's, for now, try to create close-enough approximation that
-            //    is not 100% same, structurally, but has equivalent information for
-            //    our specific neeeds.
-            // 29-Mar-2016, tatu: See [databind#1173]  (and test `TypeResolverTest`)
-            //  for a case where this code does get invoked: not ideal
-            // 29-Jun-2016, tatu: As to bindings, this works for [databind#1215], but
-            //  not certain it would reliably work... but let's hope for best for now
+            // (4) If all else fails, do the full traversal using placeholders
             TypeBindings tb = _bindingsForSubtype(baseType, typeParamCount, subclass);
-            if (baseType.isInterface()) {
-                newType = baseType.refine(subclass, tb, null, new JavaType[] { baseType });
-            } else {
-                newType = baseType.refine(subclass, tb, baseType, NO_TYPES);
-            }
-            // Only SimpleType returns null, but if so just resolve regularly
-            if (newType == null) {
-                newType = _fromClass(null, subclass, tb);
-            }
+            newType = _fromClass(null, subclass, tb);
+
         } while (false);
 
-        // except possibly handlers
-//      newType = newType.withHandlersFrom(baseType);
+        // 25-Sep-2016, tatu: As per [databind#1384] also need to ensure handlers get
+        //   copied as well
+        newType = newType.withHandlersFrom(baseType);
         return newType;
-
-        // 20-Oct-2015, tatu: Old simplistic approach
-        
-        /*
-        // Currently mostly SimpleType instances can become something else
-        if (baseType instanceof SimpleType) {
-            // and only if subclass is an array, Collection or Map
-            if (subclass.isArray()
-                || Map.class.isAssignableFrom(subclass)
-                || Collection.class.isAssignableFrom(subclass)) {
-                // need to assert type compatibility...
-                if (!baseType.getRawClass().isAssignableFrom(subclass)) {
-                    throw new IllegalArgumentException("Class "+subclass.getClass().getName()+" not subtype of "+baseType);
-                }
-                // this _should_ work, right?
-                JavaType subtype = _fromClass(null, subclass, TypeBindings.emptyBindings());
-                // one more thing: handlers to copy?
-                Object h = baseType.getValueHandler();
-                if (h != null) {
-                    subtype = subtype.withValueHandler(h);
-                }
-                h = baseType.getTypeHandler();
-                if (h != null) {
-                    subtype = subtype.withTypeHandler(h);
-                }
-                return subtype;
-            }
-        }
-        // But there is the need for special case for arrays too, it seems
-        if (baseType instanceof ArrayType) {
-            if (subclass.isArray()) {
-                // actually see if it might be a no-op first:
-                ArrayType at = (ArrayType) baseType;
-                Class<?> rawComp = subclass.getComponentType();
-                if (at.getContentType().getRawClass() == rawComp) {
-                    return baseType;
-                }
-                JavaType componentType = _fromAny(null, rawComp, null);
-                return ((ArrayType) baseType).withComponentType(componentType);
-            }
-        }
-
-        // otherwise regular narrowing should work just fine
-        return baseType.narrowBy(subclass);
-        */
     }
 
     private TypeBindings _bindingsForSubtype(JavaType baseType, int typeParamCount, Class<?> subclass)
     {
-        // But otherwise gets bit tricky, as we need to partially resolve the type hierarchy
-        // (hopefully passing null Class for root is ok)
-        int baseCount = baseType.containedTypeCount();
-        if (baseCount == typeParamCount) {
-            if (typeParamCount == 1) {
-                return TypeBindings.create(subclass, baseType.containedType(0));
-            }
-            if (typeParamCount == 2) {
-                return TypeBindings.create(subclass, baseType.containedType(0),
-                        baseType.containedType(1));
-            }
-            List<JavaType> types = new ArrayList<JavaType>(baseCount);
-            for (int i = 0; i < baseCount; ++i) {
-                types.add(baseType.containedType(i));
-            }
-            return TypeBindings.create(subclass, types);
+        PlaceholderForType[] placeholders = new PlaceholderForType[typeParamCount];
+        for (int i = 0; i < typeParamCount; ++i) {
+            placeholders[i] = new PlaceholderForType(i);
         }
-        // Otherwise, two choices: match N first, or empty. Do latter, for now
-        return TypeBindings.emptyBindings();
+        TypeBindings b = TypeBindings.create(subclass, placeholders);
+        // First: pseudo-resolve to get placeholders in place:
+        JavaType tmpSub = _fromClass(null, subclass, b);
+        // Then find super-type
+        JavaType baseWithPlaceholders = tmpSub.findSuperType(baseType.getRawClass());
+        if (baseWithPlaceholders == null) { // should be found but...
+            throw new IllegalArgumentException(String.format(
+                    "Internal error: unable to locate supertype (%s) from resolved subtype %s", baseType.getRawClass().getName(),
+                    subclass.getName()));
+        }
+        // and traverse type hierarchies to both verify and to resolve placeholders
+        String error = _resolveTypePlaceholders(baseType, baseWithPlaceholders);
+        if (error != null) {
+            throw new IllegalArgumentException("Failed to specialize base type "+baseType.toCanonical()+" as "
+                    +subclass.getName()+", problem: "+error);
+        }
+
+        final JavaType[] typeParams = new JavaType[typeParamCount];
+        for (int i = 0; i < typeParamCount; ++i) {
+            JavaType t = placeholders[i].actualType();
+            // 18-Oct-2017, tatu: Looks like sometimes we have incomplete bindings (even if not
+            //     common, it is possible if subtype is type-erased class with added type
+            //     variable -- see test(s) with "bogus" type(s)).
+            if (t == null) {
+                t = unknownType();
+            }
+            typeParams[i] = t;
+        }
+        return TypeBindings.create(subclass, typeParams);
+    }
+
+    private String _resolveTypePlaceholders(JavaType sourceType, JavaType actualType)
+        throws IllegalArgumentException
+    {
+        List<JavaType> expectedTypes = sourceType.getBindings().getTypeParameters();
+        List<JavaType> actualTypes = actualType.getBindings().getTypeParameters();
+        for (int i = 0, len = expectedTypes.size(); i < len; ++i) {
+            JavaType exp = expectedTypes.get(i);
+            JavaType act = actualTypes.get(i);
+            if (!_verifyAndResolvePlaceholders(exp, act)) {
+                return String.format("Type parameter #%d/%d differs; can not specialize %s with %s",
+                        (i+1), len, exp.toCanonical(), act.toCanonical());
+            }
+        }
+        return null;
+    }
+
+    private boolean _verifyAndResolvePlaceholders(JavaType exp, JavaType act)
+    {
+        // See if we have an actual type placeholder to resolve; if yes, replace
+        if (act instanceof PlaceholderForType) {
+            ((PlaceholderForType) act).actualType(exp);
+            return true;
+        }
+        // if not, try to verify compatibility. But note that we can not
+        // use simple equality as we need to resolve recursively
+        if (exp.getRawClass() != act.getRawClass()) {
+            return false;
+        }
+        // But we can check type parameters "blindly"
+        List<JavaType> expectedTypes = exp.getBindings().getTypeParameters();
+        List<JavaType> actualTypes = act.getBindings().getTypeParameters();
+        for (int i = 0, len = expectedTypes.size(); i < len; ++i) {
+            JavaType exp2 = expectedTypes.get(i);
+            JavaType act2 = actualTypes.get(i);
+            if (!_verifyAndResolvePlaceholders(exp2, act2)) {
+                return false;
+            }
+        }
+        return true;
     }
 
     /**
@@ -686,7 +708,8 @@
      * NOTE: type modifiers are NOT called on Collection type itself; but are called
      * for contained types.
      */
-    public CollectionType constructCollectionType(Class<? extends Collection> collectionClass, Class<?> elementClass) {
+    public CollectionType constructCollectionType(Class<? extends Collection> collectionClass,
+            Class<?> elementClass) {
         return constructCollectionType(collectionClass,
                 _fromClass(null, elementClass, EMPTY_BINDINGS));
     }
@@ -697,7 +720,8 @@
      * NOTE: type modifiers are NOT called on Collection type itself; but are called
      * for contained types.
      */
-    public CollectionType constructCollectionType(Class<? extends Collection> collectionClass, JavaType elementType) {
+    public CollectionType constructCollectionType(Class<? extends Collection> collectionClass,
+            JavaType elementType) {
         // 19-Oct-2015, tatu: Allow case of no-type-variables, since it seems likely to be
         //    a valid use case here
         return (CollectionType) _fromClass(null, collectionClass,
@@ -736,7 +760,8 @@
      * NOTE: type modifiers are NOT called on constructed type itself; but are called
      * for contained types.
      */
-    public MapType constructMapType(Class<? extends Map> mapClass, Class<?> keyClass, Class<?> valueClass) {
+    public MapType constructMapType(Class<? extends Map> mapClass,
+            Class<?> keyClass, Class<?> valueClass) {
         JavaType kt, vt;
         if (mapClass == Properties.class) {
             kt = vt = CORE_TYPE_STRING;
@@ -755,9 +780,7 @@
      */
     public MapType constructMapType(Class<? extends Map> mapClass, JavaType keyType, JavaType valueType) {
         return (MapType) _fromClass(null, mapClass,
-                TypeBindings.create(mapClass, new JavaType[] {
-                        keyType, valueType
-                }));
+                TypeBindings.create(mapClass, keyType, valueType));
     }
 
     /**
@@ -823,12 +846,17 @@
     }
 
     /**
-     * Method that will force construction of a simple type, without trying to
-     * check for more specialized types.
+     * Method that use by core Databind functionality, and that should NOT be called
+     * by application code outside databind package.
      *<p> 
-     * NOTE: no type modifiers are called on type either, so calling this method
-     * should only be used if caller really knows what it's doing...
+     * Unchecked here not only means that no checks are made as to whether given class
+     * might be non-simple type (like {@link CollectionType}) but also that most of supertype
+     * information is not gathered. This means that unless called on primitive types or
+     * {@link java.lang.String}, results are probably not what you want to use.
+     *
+     * @deprecated Since 2.8, to indicate users should never call this method.
      */
+    @Deprecated // since 2.8
     public JavaType uncheckedSimpleType(Class<?> cls) {
         // 18-Oct-2015, tatu: Not sure how much problem missing super-type info is here
         return _constructSimple(cls, EMPTY_BINDINGS, null, null);
@@ -865,7 +893,7 @@
         int len = parameterClasses.length;
         JavaType[] pt = new JavaType[len];
         for (int i = 0; i < len; ++i) {
-            pt[i] = _fromClass(null, parameterClasses[i], null);
+            pt[i] = _fromClass(null, parameterClasses[i], EMPTY_BINDINGS);
         }
         return constructParametricType(parametrized, pt);
     }
@@ -997,7 +1025,7 @@
             JavaType superClass, JavaType[] superInterfaces)
     {
         JavaType kt, vt;
-        
+
         // 28-May-2015, tatu: Properties are special, as per [databind#810]; fake "correct" parameter sig
         if (rawClass == Properties.class) {
             kt = vt = CORE_TYPE_STRING;
@@ -1188,12 +1216,12 @@
         final Object key;
         if ((bindings == null) || bindings.isEmpty()) {
             key = rawType;
-            result = _typeCache.get(key); // ok, cache object is synced
-            if (result != null) {
-                return result;
-            }
         } else {
-            key = null;
+            key = bindings.asKey(rawType);
+        }
+        result = _typeCache.get(key); // ok, cache object is synced
+        if (result != null) {
+            return result;
         }
 
         // 15-Oct-2015, tatu: recursive reference?
@@ -1253,7 +1281,9 @@
             }
         }
         context.resolveSelfReferences(result);
-        if (key != null) {
+        // 16-Jul-2016, tatu: [databind#1302] is solved different way, but ideally we shouldn't
+        //     cache anything with partially resolved `ResolvedRecursiveType`... so maybe improve
+        if (!result.hasHandlers()) {
             _typeCache.putIfAbsent(key, result); // cache object syncs
         }
         return result;
@@ -1291,6 +1321,10 @@
     protected JavaType _fromWellKnownClass(ClassStack context, Class<?> rawType, TypeBindings bindings,
             JavaType superClass, JavaType[] superInterfaces)
     {
+        if (bindings == null) {
+            bindings = TypeBindings.emptyBindings();
+        }
+        
         // Quite simple when we resolving exact class/interface; start with that
         if (rawType == Map.class) {
             return _mapType(rawType, bindings, superClass, superInterfaces);
@@ -1352,13 +1386,12 @@
         // always of type Class: if not, need to add more code to resolve it to Class.        
         Type[] args = ptype.getActualTypeArguments();
         int paramCount = (args == null) ? 0 : args.length;
-        JavaType[] pt;
         TypeBindings newBindings;        
 
         if (paramCount == 0) {
             newBindings = EMPTY_BINDINGS;
         } else {
-            pt = new JavaType[paramCount];
+            JavaType[] pt = new JavaType[paramCount];
             for (int i = 0; i < paramCount; ++i) {
                 pt[i] = _fromAny(context, args[i], parentBindings);
             }
diff --git a/src/main/java/com/fasterxml/jackson/databind/type/TypeParser.java b/src/main/java/com/fasterxml/jackson/databind/type/TypeParser.java
index fe2d096..1817e0a 100644
--- a/src/main/java/com/fasterxml/jackson/databind/type/TypeParser.java
+++ b/src/main/java/com/fasterxml/jackson/databind/type/TypeParser.java
@@ -28,8 +28,7 @@
 
     public JavaType parse(String canonical) throws IllegalArgumentException
     {
-        canonical = canonical.trim();
-        MyTokenizer tokens = new MyTokenizer(canonical);
+        MyTokenizer tokens = new MyTokenizer(canonical.trim());
         JavaType type = parseType(tokens);
         // must be end, now
         if (tokens.hasMoreTokens()) {
@@ -57,7 +56,7 @@
             // can be comma that separates types, or closing '>'
             tokens.pushBack(token);
         }
-        return _factory._fromClass(null, base, null);
+        return _factory._fromClass(null, base, TypeBindings.emptyBindings());
     }
 
     protected List<JavaType> parseTypes(MyTokenizer tokens)
@@ -90,19 +89,18 @@
 
     protected IllegalArgumentException _problem(MyTokenizer tokens, String msg)
     {
-        return new IllegalArgumentException("Failed to parse type '"+tokens.getAllInput()
-                +"' (remaining: '"+tokens.getRemainingInput()+"'): "+msg);
+        return new IllegalArgumentException(String.format("Failed to parse type '%s' (remaining: '%s'): %s",
+                tokens.getAllInput(), tokens.getRemainingInput(), msg));
     }
 
-    final static class MyTokenizer
-        extends StringTokenizer
+    final static class MyTokenizer extends StringTokenizer
     {
         protected final String _input;
 
         protected int _index;
 
         protected String _pushbackToken;
-        
+
         public MyTokenizer(String str) {            
             super(str, "<,>", true);
             _input = str;
@@ -121,18 +119,19 @@
                 _pushbackToken = null;
             } else {
                 token = super.nextToken();
+                _index += token.length();
+                token = token.trim();
             }
-            _index += token.length();
             return token;
         }
 
         public void pushBack(String token) {
             _pushbackToken = token;
-            _index -= token.length();
+            // let's NOT change index for now, since token may have been trim()ed
         }
-        
+
         public String getAllInput() { return _input; }
-        public String getUsedInput() { return _input.substring(0, _index); }
+//        public String getUsedInput() { return _input.substring(0, _index); }
         public String getRemainingInput() { return _input.substring(_index); }
     }
 }
diff --git a/src/main/java/com/fasterxml/jackson/databind/util/ArrayBuilders.java b/src/main/java/com/fasterxml/jackson/databind/util/ArrayBuilders.java
index 8ce5766..834a96e 100644
--- a/src/main/java/com/fasterxml/jackson/databind/util/ArrayBuilders.java
+++ b/src/main/java/com/fasterxml/jackson/databind/util/ArrayBuilders.java
@@ -181,7 +181,7 @@
             }
         };
     }
-    
+
     public static <T> HashSet<T> arrayToSet(T[] elements)
     {
         HashSet<T> result = new HashSet<T>();
diff --git a/src/main/java/com/fasterxml/jackson/databind/util/ClassUtil.java b/src/main/java/com/fasterxml/jackson/databind/util/ClassUtil.java
index a73657c..5d14255 100644
--- a/src/main/java/com/fasterxml/jackson/databind/util/ClassUtil.java
+++ b/src/main/java/com/fasterxml/jackson/databind/util/ClassUtil.java
@@ -1,9 +1,12 @@
 package com.fasterxml.jackson.databind.util;
 
+import java.io.Closeable;
+import java.io.IOException;
 import java.lang.annotation.Annotation;
 import java.lang.reflect.*;
 import java.util.*;
 
+import com.fasterxml.jackson.core.JsonGenerator;
 import com.fasterxml.jackson.databind.JavaType;
 import com.fasterxml.jackson.databind.annotation.JacksonStdImpl;
 
@@ -415,7 +418,22 @@
         }
         throw (Error) t;
     }
-    
+
+    /**
+     * Method that works like {@link #throwRootCause} if (and only if)
+     * root cause is an {@link IOException}; otherwise returns root cause
+     *
+     * @since 2.8
+     */
+    public static Throwable throwRootCauseIfIOE(Throwable t) throws IOException
+    {
+        t = getRootCause(t);
+        if (t instanceof IOException) {
+            throw (IOException) t;
+        }
+        return t;
+    }
+
     /**
      * Method that will wrap 't' as an {@link IllegalArgumentException} if it
      * is a checked exception; otherwise (runtime exception or error) throw as is
@@ -461,6 +479,73 @@
         throwAsIAE(getRootCause(t), msg);
     }
 
+    /**
+     * Helper method that encapsulate logic in trying to close output generator
+     * in case of failure; useful mostly in forcing flush()ing as otherwise
+     * error conditions tend to be hard to diagnose. However, it is often the
+     * case that output state may be corrupt so we need to be prepared for
+     * secondary exception without masking original one.
+     *
+     * @since 2.8
+     */
+    public static void closeOnFailAndThrowAsIAE(JsonGenerator g, Exception fail)
+            throws IOException
+    {
+        /* 04-Mar-2014, tatu: Let's try to prevent auto-closing of
+         *    structures, which typically causes more damage.
+         */
+        g.disable(JsonGenerator.Feature.AUTO_CLOSE_JSON_CONTENT);
+        try {
+            g.close();
+        } catch (Exception e) {
+            fail.addSuppressed(e);
+        }
+        if (fail instanceof IOException) {
+            throw (IOException) fail;
+        }
+        if (fail instanceof RuntimeException) {
+            throw (RuntimeException) fail;
+        }
+        throw new RuntimeException(fail);
+    }
+
+    /**
+     * Helper method that encapsulate logic in trying to close given {@link Closeable}
+     * in case of failure; useful mostly in forcing flush()ing as otherwise
+     * error conditions tend to be hard to diagnose. However, it is often the
+     * case that output state may be corrupt so we need to be prepared for
+     * secondary exception without masking original one.
+     *
+     * @since 2.8
+     */
+    public static void closeOnFailAndThrowAsIAE(JsonGenerator g,
+            Closeable toClose, Exception fail)
+        throws IOException
+    {
+        if (g != null) {
+            g.disable(JsonGenerator.Feature.AUTO_CLOSE_JSON_CONTENT);
+            try {
+                g.close();
+            } catch (Exception e) {
+                fail.addSuppressed(e);
+            }
+        }
+        if (toClose != null) {
+            try {
+                toClose.close();
+            } catch (Exception e) {
+                fail.addSuppressed(e);
+            }
+        }
+        if (fail instanceof IOException) {
+            throw (IOException) fail;
+        }
+        if (fail instanceof RuntimeException) {
+            throw (RuntimeException) fail;
+        }
+        throw new RuntimeException(fail);
+    }
+
     /*
     /**********************************************************
     /* Instantiation
@@ -699,7 +784,7 @@
     {
         // First things first: if not empty, easy to determine
         if (!s.isEmpty()) {
-    		    return findEnumType(s.iterator().next());
+            return findEnumType(s.iterator().next());
         }
         // Otherwise need to locate using an internal field
         return EnumTypeLocator.instance.enumTypeFor(s);
@@ -753,6 +838,36 @@
         return (Class<? extends Enum<?>>) cls;
     }
 
+    /**
+     * A method that will look for the first Enum value annotated with the given Annotation.
+     * <p>
+     * If there's more than one value annotated, the first one found will be returned. Which one exactly is used is undetermined.
+     *
+     * @param enumClass The Enum class to scan for a value with the given annotation
+     * @param annotationClass The annotation to look for.
+     * @return the Enum value annotated with the given Annotation or {@code null} if none is found.
+     * @throws IllegalArgumentException if there's a reflection issue accessing the Enum
+     * @since 2.8
+     */
+    public static <T extends Annotation> Enum<?> findFirstAnnotatedEnumValue(Class<Enum<?>> enumClass, Class<T> annotationClass)
+    {
+        Field[] fields = getDeclaredFields(enumClass);
+        for (Field field : fields) {
+            if (field.isEnumConstant()) {
+                Annotation defaultValueAnnotation = field.getAnnotation(annotationClass);
+                if (defaultValueAnnotation != null) {
+                    final String name = field.getName();
+                    for (Enum<?> enumValue : enumClass.getEnumConstants()) {
+                        if (name.equals(enumValue.name())) {
+                            return enumValue;
+                        }
+                    }
+                }
+            }
+        }
+        return null;
+    }
+
     /*
     /**********************************************************
     /* Jackson-specific stuff
@@ -864,7 +979,6 @@
      * @since 2.7
      */
     public static Class<?> getDeclaringClass(Class<?> cls) {
-        // Caching does not seem worthwhile, as per profiling
         return isObjectOrPrimitive(cls) ? null : cls.getDeclaringClass();
     }
 
diff --git a/src/main/java/com/fasterxml/jackson/databind/util/EnumResolver.java b/src/main/java/com/fasterxml/jackson/databind/util/EnumResolver.java
index 59f5dc5..d6ef5e6 100644
--- a/src/main/java/com/fasterxml/jackson/databind/util/EnumResolver.java
+++ b/src/main/java/com/fasterxml/jackson/databind/util/EnumResolver.java
@@ -5,7 +5,7 @@
 
 import com.fasterxml.jackson.databind.AnnotationIntrospector;
 
-    /**
+/**
  * Helper class used to resolve String values (either JSON Object field
  * names or regular String values) into Java Enum instances.
  */
@@ -19,11 +19,14 @@
 
     protected final HashMap<String, Enum<?>> _enumsById;
 
-    protected EnumResolver(Class<Enum<?>> enumClass, Enum<?>[] enums, HashMap<String, Enum<?>> map)
+    protected final Enum<?> _defaultValue;
+
+    protected EnumResolver(Class<Enum<?>> enumClass, Enum<?>[] enums, HashMap<String, Enum<?>> map, Enum<?> defaultValue)
     {
         _enumClass = enumClass;
         _enums = enums;
         _enumsById = map;
+        _defaultValue = defaultValue;
     }
 
     /**
@@ -45,14 +48,28 @@
             }
             map.put(name, enumValues[i]);
         }
-        return new EnumResolver(enumCls, enumValues, map);
+
+        Enum<?> defaultEnum = ai.findDefaultEnumValue(enumCls);
+
+        return new EnumResolver(enumCls, enumValues, map, defaultEnum);
+    }
+
+    /**
+     * @deprecated Since 2.8, use {@link #constructUsingToString(Class, AnnotationIntrospector)} instead
+     */
+    @Deprecated
+    public static EnumResolver constructUsingToString(Class<Enum<?>> enumCls) {
+        return constructUsingToString(enumCls, null);
     }
 
     /**
      * Factory method for constructing resolver that maps from Enum.toString() into
      * Enum value
+     *
+     * @since 2.8
      */
-    public static EnumResolver constructUsingToString(Class<Enum<?>> enumCls)
+    public static EnumResolver constructUsingToString(Class<Enum<?>> enumCls,
+            AnnotationIntrospector ai)
     {
         Enum<?>[] enumValues = enumCls.getEnumConstants();
         HashMap<String, Enum<?>> map = new HashMap<String, Enum<?>>();
@@ -61,11 +78,23 @@
             Enum<?> e = enumValues[i];
             map.put(e.toString(), e);
         }
-        return new EnumResolver(enumCls, enumValues, map);
+        Enum<?> defaultEnum = (ai == null) ? null : ai.findDefaultEnumValue(enumCls);
+        return new EnumResolver(enumCls, enumValues, map, defaultEnum);
     }
 
-    public static EnumResolver constructUsingMethod(Class<Enum<?>> enumCls,
-            Method accessor)
+    /**
+     * @deprecated Since 2.8, use {@link #constructUsingMethod(Class, Method, AnnotationIntrospector)} instead
+     */
+    @Deprecated
+    public static EnumResolver constructUsingMethod(Class<Enum<?>> enumCls, Method accessor) {
+        return constructUsingMethod(enumCls, accessor, null);
+    }
+
+    /**
+     * @since 2.8
+     */
+    public static EnumResolver constructUsingMethod(Class<Enum<?>> enumCls, Method accessor,
+            AnnotationIntrospector ai)
     {
         Enum<?>[] enumValues = enumCls.getEnumConstants();
         HashMap<String, Enum<?>> map = new HashMap<String, Enum<?>>();
@@ -81,7 +110,8 @@
                 throw new IllegalArgumentException("Failed to access @JsonValue of Enum value "+en+": "+e.getMessage());
             }
         }
-        return new EnumResolver(enumCls, enumValues, map);
+        Enum<?> defaultEnum = (ai != null) ? ai.findDefaultEnumValue(enumCls) : null;
+        return new EnumResolver(enumCls, enumValues, map, defaultEnum);
     }    
 
     /**
@@ -99,33 +129,56 @@
     }
 
     /**
+     * @deprecated Since 2.8, use {@link #constructUnsafeUsingToString(Class, AnnotationIntrospector)} instead
+     */
+    @Deprecated
+    public static EnumResolver constructUnsafeUsingToString(Class<?> rawEnumCls)
+    {
+        return constructUnsafeUsingToString(rawEnumCls, null);
+    }
+
+    /**
      * Method that needs to be used instead of {@link #constructUsingToString}
      * if static type of enum is not known.
+     *
+     * @since 2.8
      */
     @SuppressWarnings({ "unchecked" })
-    public static EnumResolver constructUnsafeUsingToString(Class<?> rawEnumCls)
-    {            
+    public static EnumResolver constructUnsafeUsingToString(Class<?> rawEnumCls,
+            AnnotationIntrospector ai)
+    {
         // oh so wrong... not much that can be done tho
         Class<Enum<?>> enumCls = (Class<Enum<?>>) rawEnumCls;
-        return constructUsingToString(enumCls);
+        return constructUsingToString(enumCls, ai);
+    }
+
+    /**
+     * @deprecated Since 2.8, use {@link #constructUnsafeUsingMethod(Class, Method, AnnotationIntrospector)} instead.
+     */
+    @Deprecated
+    public static EnumResolver constructUnsafeUsingMethod(Class<?> rawEnumCls, Method accessor) {
+        return constructUnsafeUsingMethod(rawEnumCls, accessor, null);
     }
 
     /**
      * Method used when actual String serialization is indicated using @JsonValue
      * on a method.
+     *
+     * @since 2.8
      */
     @SuppressWarnings({ "unchecked" })
-    public static EnumResolver constructUnsafeUsingMethod(Class<?> rawEnumCls, Method accessor)
+    public static EnumResolver constructUnsafeUsingMethod(Class<?> rawEnumCls, Method accessor,
+            AnnotationIntrospector ai)
     {            
         // wrong as ever but:
         Class<Enum<?>> enumCls = (Class<Enum<?>>) rawEnumCls;
-        return constructUsingMethod(enumCls, accessor);
+        return constructUsingMethod(enumCls, accessor, ai);
     }
 
     public CompactStringObjectMap constructLookup() {
         return CompactStringObjectMap.construct(_enumsById);
     }
-    
+
     public Enum<?> findEnum(String key) { return _enumsById.get(key); }
 
     public Enum<?> getEnum(int index) {
@@ -135,6 +188,10 @@
         return _enums[index];
     }
 
+    public Enum<?> getDefaultValue(){
+        return _defaultValue;
+    }
+
     public Enum<?>[] getRawEnums() {
         return _enums;
     }
diff --git a/src/main/java/com/fasterxml/jackson/databind/util/ISO8601Utils.java b/src/main/java/com/fasterxml/jackson/databind/util/ISO8601Utils.java
index 196eec8..b6f30c5 100644
--- a/src/main/java/com/fasterxml/jackson/databind/util/ISO8601Utils.java
+++ b/src/main/java/com/fasterxml/jackson/databind/util/ISO8601Utils.java
@@ -376,44 +376,4 @@
         }
         return string.length();
     }
-
-    public static void main(String[] args)
-    {
-        final int REPS = 250000;
-        while (true) {
-            long start = System.currentTimeMillis();
-            int resp = test1(REPS, 3);
-            long msecs = System.currentTimeMillis() - start;
-            System.out.println("Pow ("+resp+") -> "+msecs+" ms");
-
-            start = System.currentTimeMillis();
-            resp = test2(REPS, 3);
-            msecs = System.currentTimeMillis() - start;
-            System.out.println("Iter ("+resp+") -> "+msecs+" ms");
-        }
-    }
-
-    static int test1(int reps, int pow)
-    {
-        int resp = 3;
-        while (--reps >= 0) {
-            resp = (int) Math.pow(10, pow);
-        }
-        return resp;
-    }
-
-    static int test2(int reps, int pow)
-    {
-        int resp = 3;
-        while (--reps >= 0) {
-            resp = 10;
-            int p = pow;
-
-            while (--p > 0) {
-                resp *= 10;
-            }
-        }
-        return resp;
-    }
 }
-
diff --git a/src/main/java/com/fasterxml/jackson/databind/util/JSONPObject.java b/src/main/java/com/fasterxml/jackson/databind/util/JSONPObject.java
index 3379d40..29b2d15 100644
--- a/src/main/java/com/fasterxml/jackson/databind/util/JSONPObject.java
+++ b/src/main/java/com/fasterxml/jackson/databind/util/JSONPObject.java
@@ -13,8 +13,6 @@
  * <a href="http://en.wikipedia.org/wiki/JSONP">JSONP</a> wrapping.
  * 
  * @see com.fasterxml.jackson.databind.util.JSONWrappedObject
- * 
- * @author tatu
  */
 public class JSONPObject
     implements JsonSerializable
@@ -55,29 +53,45 @@
      */
 
     @Override
-    public void serializeWithType(JsonGenerator jgen, SerializerProvider provider, TypeSerializer typeSer)
-            throws IOException, JsonProcessingException
+    public void serializeWithType(JsonGenerator gen, SerializerProvider provider, TypeSerializer typeSer)
+            throws IOException
     {
         // No type for JSONP wrapping: value serializer will handle typing for value:
-        serialize(jgen, provider);
+        serialize(gen, provider);
     }
 
     @Override
-    public void serialize(JsonGenerator jgen, SerializerProvider provider)
-            throws IOException, JsonProcessingException
+    public void serialize(JsonGenerator gen, SerializerProvider provider)
+            throws IOException
     {
         // First, wrapping:
-        jgen.writeRaw(_function);
-        jgen.writeRaw('(');
+        gen.writeRaw(_function);
+        gen.writeRaw('(');
+
         if (_value == null) {
-            provider.defaultSerializeNull(jgen);
-        } else if (_serializationType != null) {
-            provider.findTypedValueSerializer(_serializationType, true, null).serialize(_value, jgen, provider);
+            provider.defaultSerializeNull(gen);
         } else {
-            Class<?> cls = _value.getClass();
-            provider.findTypedValueSerializer(cls, true, null).serialize(_value, jgen, provider);
+            // NOTE: Escape line-separator characters that break JSONP only if no custom character escapes are set.
+            // If custom escapes are in place JSONP-breaking characters will not be escaped and it is recommended to
+            // add escaping for those (see JsonpCharacterEscapes class).
+            boolean override = (gen.getCharacterEscapes() == null);
+            if (override) {
+                gen.setCharacterEscapes(JsonpCharacterEscapes.instance());
+            }
+
+            try {
+                if (_serializationType != null) {
+                    provider.findTypedValueSerializer(_serializationType, true, null).serialize(_value, gen, provider);
+                } else {
+                    provider.findTypedValueSerializer(_value.getClass(), true, null).serialize(_value, gen, provider);
+                }
+            } finally {
+                if (override) {
+                    gen.setCharacterEscapes(null);
+                }
+            }
         }
-        jgen.writeRaw(')');
+        gen.writeRaw(')');
     }
 
     /*
diff --git a/src/main/java/com/fasterxml/jackson/databind/util/JSONWrappedObject.java b/src/main/java/com/fasterxml/jackson/databind/util/JSONWrappedObject.java
index f411a92..121b1e3 100644
--- a/src/main/java/com/fasterxml/jackson/databind/util/JSONWrappedObject.java
+++ b/src/main/java/com/fasterxml/jackson/databind/util/JSONWrappedObject.java
@@ -41,7 +41,7 @@
      * to include (if any).
      */
     protected final JavaType _serializationType;
-    
+
     public JSONWrappedObject(String prefix, String suffix, Object value) {
         this(prefix, suffix, value, (JavaType) null);
     }
diff --git a/src/main/java/com/fasterxml/jackson/databind/util/LinkedNode.java b/src/main/java/com/fasterxml/jackson/databind/util/LinkedNode.java
index 75d3caf..fa7cdae 100644
--- a/src/main/java/com/fasterxml/jackson/databind/util/LinkedNode.java
+++ b/src/main/java/com/fasterxml/jackson/databind/util/LinkedNode.java
@@ -4,8 +4,6 @@
  * Node of a forward-only linked list.
  * 
  * @author tatu
- *
- * @param <T> Type of contained object
  */
 public final class LinkedNode<T>
 {
diff --git a/src/main/java/com/fasterxml/jackson/databind/util/ObjectIdMap.java b/src/main/java/com/fasterxml/jackson/databind/util/ObjectIdMap.java
deleted file mode 100644
index 0d558b7..0000000
--- a/src/main/java/com/fasterxml/jackson/databind/util/ObjectIdMap.java
+++ /dev/null
@@ -1,38 +0,0 @@
-package com.fasterxml.jackson.databind.util;
-
-import java.util.IdentityHashMap;
-
-/**
- * Map used during serialization, to keep track of referable Objects
- * along with lazily evaluated ids.
- */
-@SuppressWarnings("serial")
-public class ObjectIdMap extends IdentityHashMap<Object,Object>
-{
-    public ObjectIdMap()
-    {
-        super(16);
-    }
-
-    /*
-    /**********************************************************
-    /* API
-    /**********************************************************
-     */
-
-    /**
-     * Method that is called to figure out whether we have already
-     * seen given POJO: if yes, we will return its id (first looking
-     * it up as necessary); if not, we will mark down that we have
-     * seen it but return null.
-     */
-    public Object findId(Object pojo)
-    {
-        return get(pojo);
-    }
-    
-    public void insertId(Object pojo, Object id)
-    {
-        put(pojo, id);
-    }
-}
diff --git a/src/main/java/com/fasterxml/jackson/databind/util/StdDateFormat.java b/src/main/java/com/fasterxml/jackson/databind/util/StdDateFormat.java
index 8bc7921..46346de 100644
--- a/src/main/java/com/fasterxml/jackson/databind/util/StdDateFormat.java
+++ b/src/main/java/com/fasterxml/jackson/databind/util/StdDateFormat.java
@@ -40,6 +40,13 @@
     protected final static String DATE_FORMAT_STR_ISO8601_Z = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'";
 
     /**
+     * Same as 'regular' 8601 except misses timezone altogether
+     *
+     * @since 2.8.10
+     */
+    protected final static String DATE_FORMAT_STR_ISO8601_NO_TZ = "yyyy-MM-dd'T'HH:mm:ss.SSS";
+
+    /**
      * ISO-8601 with just the Date part, no time
      */
     protected final static String DATE_FORMAT_STR_PLAIN = "yyyy-MM-dd";
@@ -56,6 +63,7 @@
     protected final static String[] ALL_FORMATS = new String[] {
         DATE_FORMAT_STR_ISO8601,
         DATE_FORMAT_STR_ISO8601_Z,
+        DATE_FORMAT_STR_ISO8601_NO_TZ,
         DATE_FORMAT_STR_RFC1123,
         DATE_FORMAT_STR_PLAIN
     };
@@ -70,11 +78,12 @@
     }
 
     private final static Locale DEFAULT_LOCALE = Locale.US;
-    
+
     protected final static DateFormat DATE_FORMAT_RFC1123;
 
     protected final static DateFormat DATE_FORMAT_ISO8601;
     protected final static DateFormat DATE_FORMAT_ISO8601_Z;
+    protected final static DateFormat DATE_FORMAT_ISO8601_NO_TZ; // since 2.8.10
 
     protected final static DateFormat DATE_FORMAT_PLAIN;
 
@@ -93,6 +102,8 @@
         DATE_FORMAT_ISO8601.setTimeZone(DEFAULT_TIMEZONE);
         DATE_FORMAT_ISO8601_Z = new SimpleDateFormat(DATE_FORMAT_STR_ISO8601_Z, DEFAULT_LOCALE);
         DATE_FORMAT_ISO8601_Z.setTimeZone(DEFAULT_TIMEZONE);
+        DATE_FORMAT_ISO8601_NO_TZ = new SimpleDateFormat(DATE_FORMAT_STR_ISO8601_NO_TZ, DEFAULT_LOCALE);
+        DATE_FORMAT_ISO8601_NO_TZ.setTimeZone(DEFAULT_TIMEZONE);
         DATE_FORMAT_PLAIN = new SimpleDateFormat(DATE_FORMAT_STR_PLAIN, DEFAULT_LOCALE);
         DATE_FORMAT_PLAIN.setTimeZone(DEFAULT_TIMEZONE);
     }
@@ -123,6 +134,7 @@
     protected transient DateFormat _formatRFC1123;
     protected transient DateFormat _formatISO8601;
     protected transient DateFormat _formatISO8601_z;
+    protected transient DateFormat _formatISO8601_noTz; // 2.8.10
     protected transient DateFormat _formatPlain;
 
     /*
@@ -447,8 +459,11 @@
             df = _formatISO8601_z;
             formatStr = DATE_FORMAT_STR_ISO8601_Z;
             if (df == null) {
+                // 10-Jun-2017, tatu: As per [databind#1651], when using this format,
+                //    must use UTC, not whatever is configured as default timezone
+                //    (because we know `Z` identifier is used)
                 df = _formatISO8601_z = _cloneFormat(DATE_FORMAT_ISO8601_Z, formatStr,
-                        _timezone, _locale, _lenient);
+                        DEFAULT_TIMEZONE, _locale, _lenient);
             }
             // may be missing milliseconds... if so, add
             if (dateStr.charAt(len-4) == ':') {
@@ -501,11 +516,11 @@
                             _timezone, _locale, _lenient);
                 }
             } else {
-                // If not, plain date. Easiest to just patch 'Z' in the end?
-                StringBuilder sb = new StringBuilder(dateStr);
-                // And possible also millisecond part if missing
+                // If not, plain date, no timezone
                 int timeLen = len - dateStr.lastIndexOf('T') - 1;
+                // And possible also millisecond part if missing
                 if (timeLen < 12) { // missing, or partial
+                    StringBuilder sb = new StringBuilder(dateStr);
                     switch (timeLen) {
                     case 11: sb.append('0');
                     case 10: sb.append('0');
@@ -514,13 +529,15 @@
                     default:
                         sb.append(".000");
                     }
+                    dateStr = sb.toString();
                 }
-                sb.append('Z');
-                dateStr = sb.toString();
-                df = _formatISO8601_z;
-                formatStr = DATE_FORMAT_STR_ISO8601_Z;
+                df = _formatISO8601_noTz;
+                formatStr = DATE_FORMAT_STR_ISO8601_NO_TZ;
                 if (df == null) {
-                    df = _formatISO8601_z = _cloneFormat(DATE_FORMAT_ISO8601_Z, formatStr,
+                    // 10-Jun-2017, tatu: As per [databind#1651], when using this format,
+                    //    must use UTC, not whatever is configured as default timezone
+                    //    (because we know `Z` identifier is used)
+                    df = _formatISO8601_noTz = _cloneFormat(DATE_FORMAT_ISO8601_NO_TZ, formatStr,
                             _timezone, _locale, _lenient);
                 }
             }
@@ -582,6 +599,8 @@
         _formatRFC1123 = null;
         _formatISO8601 = null;
         _formatISO8601_z = null;
+        _formatISO8601_noTz = null;
+
         _formatPlain = null;
     }
 }
diff --git a/src/main/java/com/fasterxml/jackson/databind/util/TokenBuffer.java b/src/main/java/com/fasterxml/jackson/databind/util/TokenBuffer.java
index 9a375e9..1f05c32 100644
--- a/src/main/java/com/fasterxml/jackson/databind/util/TokenBuffer.java
+++ b/src/main/java/com/fasterxml/jackson/databind/util/TokenBuffer.java
@@ -414,10 +414,15 @@
             case VALUE_EMBEDDED_OBJECT:
                 {
                     Object value = segment.get(ptr);
+                    // 01-Sep-2016, tatu: as per [databind#1361], should use `writeEmbeddedObject()`;
+                    //    however, may need to consider alternatives for some well-known types
+                    //    first
                     if (value instanceof RawValue) {
                         ((RawValue) value).serialize(gen);
-                    } else {
+                    } else if (value instanceof JsonSerializable) {
                         gen.writeObject(value);
+                    } else {
+                        gen.writeEmbeddedObject(value);
                     }
                 }
                 break;
@@ -448,7 +453,9 @@
             copyCurrentStructure(p);
         } while ((t = p.nextToken()) == JsonToken.FIELD_NAME);
         if (t != JsonToken.END_OBJECT) {
-            throw ctxt.mappingException("Expected END_OBJECT after copying contents of a JsonParser into TokenBuffer, got "+t);
+            ctxt.reportWrongTokenException(p, JsonToken.END_OBJECT,
+                    "Expected END_OBJECT after copying contents of a JsonParser into TokenBuffer, got "+t);
+            // never gets here
         }
         writeEndObject();
         return this;
@@ -645,6 +652,18 @@
         _writeContext = _writeContext.createChildObjectContext();
     }
 
+    @Override // since 2.8
+    public void writeStartObject(Object forValue) throws IOException
+    {
+        _writeContext.writeValue();
+        _append(JsonToken.START_OBJECT);
+        JsonWriteContext ctxt = _writeContext.createChildObjectContext();
+        _writeContext = ctxt;
+        if (forValue != null) {
+            ctxt.setCurrentValue(forValue);
+        }
+    }
+
     @Override
     public final void writeEndObject() throws IOException
     {
@@ -927,6 +946,11 @@
         _hasNativeId = true;
     }
 
+    @Override // since 2.8
+    public void writeEmbeddedObject(Object object) throws IOException {
+        _appendValue(JsonToken.VALUE_EMBEDDED_OBJECT, object);
+    }
+
     /*
     /**********************************************************
     /* JsonGenerator implementation; pass-through copy
@@ -1013,41 +1037,41 @@
     }
     
     @Override
-    public void copyCurrentStructure(JsonParser jp) throws IOException
+    public void copyCurrentStructure(JsonParser p) throws IOException
     {
-        JsonToken t = jp.getCurrentToken();
+        JsonToken t = p.getCurrentToken();
 
         // Let's handle field-name separately first
         if (t == JsonToken.FIELD_NAME) {
             if (_mayHaveNativeIds) {
-                _checkNativeIds(jp);
+                _checkNativeIds(p);
             }
-            writeFieldName(jp.getCurrentName());
-            t = jp.nextToken();
+            writeFieldName(p.getCurrentName());
+            t = p.nextToken();
             // fall-through to copy the associated value
         }
 
         if (_mayHaveNativeIds) {
-            _checkNativeIds(jp);
+            _checkNativeIds(p);
         }
         
         switch (t) {
         case START_ARRAY:
             writeStartArray();
-            while (jp.nextToken() != JsonToken.END_ARRAY) {
-                copyCurrentStructure(jp);
+            while (p.nextToken() != JsonToken.END_ARRAY) {
+                copyCurrentStructure(p);
             }
             writeEndArray();
             break;
         case START_OBJECT:
             writeStartObject();
-            while (jp.nextToken() != JsonToken.END_OBJECT) {
-                copyCurrentStructure(jp);
+            while (p.nextToken() != JsonToken.END_OBJECT) {
+                copyCurrentStructure(p);
             }
             writeEndObject();
             break;
         default: // others are simple:
-            copyCurrentEvent(jp);
+            copyCurrentEvent(p);
         }
     }
 
diff --git a/src/test/java/com/fasterxml/jackson/databind/BaseMapTest.java b/src/test/java/com/fasterxml/jackson/databind/BaseMapTest.java
index 8db5792..311ffad 100644
--- a/src/test/java/com/fasterxml/jackson/databind/BaseMapTest.java
+++ b/src/test/java/com/fasterxml/jackson/databind/BaseMapTest.java
@@ -7,6 +7,7 @@
 
 import com.fasterxml.jackson.annotation.JsonCreator;
 import com.fasterxml.jackson.annotation.JsonValue;
+import com.fasterxml.jackson.core.FormatSchema;
 import com.fasterxml.jackson.core.JsonGenerator;
 import com.fasterxml.jackson.core.JsonParser;
 import com.fasterxml.jackson.core.JsonProcessingException;
@@ -26,6 +27,13 @@
     /**********************************************************
      */
 
+    public static class BogusSchema implements FormatSchema {
+        @Override
+        public String getSchemaType() {
+            return "TestFormat";
+        }
+    }
+
     /**
      * Simple wrapper around boolean types, usually to test value
      * conversions or wrapping
@@ -52,6 +60,13 @@
         public LongWrapper() { }
         public LongWrapper(long value) { l = value; }
     }
+
+    protected static class DoubleWrapper {
+        public double d;
+
+        public DoubleWrapper() { }
+        public DoubleWrapper(double value) { d = value; }
+    }
     
     /**
      * Simple wrapper around String type, usually to test value
@@ -67,7 +82,7 @@
     }
 
     protected static class ObjectWrapper {
-        private final Object object;
+        final Object object;
         protected ObjectWrapper(final Object object) {
             this.object = object;
         }
@@ -121,12 +136,37 @@
 
     public enum ABC { A, B, C; }
 
+    // since 2.8
+    public static class Point {
+        public int x, y;
+
+        protected Point() { } // for deser
+        public Point(int x0, int y0) {
+            x = x0;
+            y = y0;
+        }
+    
+        @Override
+        public boolean equals(Object o) {
+            if (!(o instanceof Point)) {
+                return false;
+            }
+            Point other = (Point) o;
+            return (other.x == x) && (other.y == y);
+        }
+
+        @Override
+        public String toString() {
+            return String.format("[x=%d, y=%d]", x, y);
+        }
+    }
+
     /*
     /**********************************************************
     /* Shared serializers
     /**********************************************************
      */
-    
+
     @SuppressWarnings("serial")
     public static class UpperCasingSerializer extends StdScalarSerializer<String>
     {
@@ -165,22 +205,25 @@
     /**********************************************************
      */
 
-    private final static ObjectMapper SHARED_MAPPER = new ObjectMapper();
+    private static ObjectMapper SHARED_MAPPER;
 
     protected ObjectMapper objectMapper() {
+        if (SHARED_MAPPER == null) {
+            SHARED_MAPPER = new ObjectMapper();
+        }
         return SHARED_MAPPER;
     }
     
     protected ObjectWriter objectWriter() {
-        return SHARED_MAPPER.writer();
+        return objectMapper().writer();
     }
 
     protected ObjectReader objectReader() {
-        return SHARED_MAPPER.reader();
+        return objectMapper().reader();
     }
     
     protected ObjectReader objectReader(Class<?> cls) {
-        return SHARED_MAPPER.readerFor(cls);
+        return objectMapper().readerFor(cls);
     }
 
     // @since 2.7
@@ -237,13 +280,13 @@
     protected String serializeAsString(Object value)
         throws IOException
     {
-        return serializeAsString(SHARED_MAPPER, value);
+        return serializeAsString(objectMapper(), value);
     }
 
     protected String asJSONObjectValueString(Object... args)
         throws IOException
     {
-        return asJSONObjectValueString(SHARED_MAPPER, args);
+        return asJSONObjectValueString(objectMapper(), args);
     }
 
     protected String asJSONObjectValueString(ObjectMapper m, Object... args)
@@ -265,7 +308,7 @@
     protected <T> T readAndMapFromString(String input, Class<T> cls)
         throws IOException
     {
-        return readAndMapFromString(SHARED_MAPPER, input, cls);
+        return readAndMapFromString(objectMapper(), input, cls);
     }
 
     protected <T> T readAndMapFromString(ObjectMapper m, String input, Class<T> cls) throws IOException
diff --git a/src/test/java/com/fasterxml/jackson/databind/BaseTest.java b/src/test/java/com/fasterxml/jackson/databind/BaseTest.java
index 8226035..ef03fda 100644
--- a/src/test/java/com/fasterxml/jackson/databind/BaseTest.java
+++ b/src/test/java/com/fasterxml/jackson/databind/BaseTest.java
@@ -290,22 +290,21 @@
     }
 
     protected JsonParser createParserUsingReader(JsonFactory f, String input)
-        throws IOException, JsonParseException
+        throws IOException
     {
         return f.createParser(new StringReader(input));
     }
 
     protected JsonParser createParserUsingStream(String input, String encoding)
-        throws IOException, JsonParseException
+        throws IOException
     {
         return createParserUsingStream(new JsonFactory(), input, encoding);
     }
 
     protected JsonParser createParserUsingStream(JsonFactory f,
-                                                 String input, String encoding)
-        throws IOException, JsonParseException
+            String input, String encoding)
+        throws IOException
     {
-
         /* 23-Apr-2008, tatus: UTF-32 is not supported by JDK, have to
          *   use our own codec too (which is not optimal since there's
          *   a chance both encoder and decoder might have bugs, but ones
@@ -365,7 +364,9 @@
                 return;
             }
         }
-        fail("Expected an exception with one of substrings ("+Arrays.asList(matches)+"): got one with message \""+msg+"\"");
+        fail("Expected an exception with one of substrings ("
+                +Arrays.asList(matches)+"): got one (of type "+e.getClass().getName()
+                +") with message \""+msg+"\"");
     }
 
     /**
diff --git a/src/test/java/com/fasterxml/jackson/databind/ObjectMapperTest.java b/src/test/java/com/fasterxml/jackson/databind/ObjectMapperTest.java
index 6a10a47..02a5d76 100644
--- a/src/test/java/com/fasterxml/jackson/databind/ObjectMapperTest.java
+++ b/src/test/java/com/fasterxml/jackson/databind/ObjectMapperTest.java
@@ -62,7 +62,7 @@
         ObjectMapper m = new ObjectMapper();
         // should have default factory
         assertNotNull(m.getNodeFactory());
-        JsonNodeFactory nf = JsonNodeFactory.instance;
+        JsonNodeFactory nf = new JsonNodeFactory(true);
         m.setNodeFactory(nf);
         assertNull(m.getInjectableValues());
         assertSame(nf, m.getNodeFactory());
@@ -299,4 +299,43 @@
         assertFalse(copy.isEnabled(JsonParser.Feature.ALLOW_COMMENTS));
         assertTrue(mapper.isEnabled(JsonParser.Feature.ALLOW_COMMENTS));
     }
+
+    // since 2.8
+    public void testDataOutputViaMapper() throws Exception
+    {
+        ByteArrayOutputStream bytes = new ByteArrayOutputStream();
+        ObjectNode input = MAPPER.createObjectNode();
+        input.put("a", 1);
+        DataOutput data = new DataOutputStream(bytes);
+        final String exp = "{\"a\":1}";
+        MAPPER.writeValue(data, input);
+        assertEquals(exp, bytes.toString("UTF-8"));
+
+        // and also via ObjectWriter...
+        bytes.reset();
+        data = new DataOutputStream(bytes);
+        MAPPER.writer().writeValue(data, input);
+        assertEquals(exp, bytes.toString("UTF-8"));
+    }
+
+    // since 2.8
+    @SuppressWarnings("unchecked")
+    public void testDataInputViaMapper() throws Exception
+    {
+        byte[] src = "{\"a\":1}".getBytes("UTF-8");
+        DataInput input = new DataInputStream(new ByteArrayInputStream(src));
+        Map<String,Object> map = (Map<String,Object>) MAPPER.readValue(input, Map.class);
+        assertEquals(Integer.valueOf(1), map.get("a"));
+
+        input = new DataInputStream(new ByteArrayInputStream(src));
+        // and via ObjectReader
+        map = MAPPER.readerFor(Map.class)
+                .readValue(input);
+        assertEquals(Integer.valueOf(1), map.get("a"));
+
+        input = new DataInputStream(new ByteArrayInputStream(src));
+        JsonNode n = MAPPER.readerFor(Map.class)
+                .readTree(input);
+        assertNotNull(n);
+    }
 }
diff --git a/src/test/java/com/fasterxml/jackson/databind/TestFormatSchema.java b/src/test/java/com/fasterxml/jackson/databind/TestFormatSchema.java
index 0809df0..a5050b7 100644
--- a/src/test/java/com/fasterxml/jackson/databind/TestFormatSchema.java
+++ b/src/test/java/com/fasterxml/jackson/databind/TestFormatSchema.java
@@ -123,11 +123,6 @@
         public void setCodec(ObjectCodec c) { }
 
         @Override
-        protected boolean loadMore() throws IOException {
-            return false;
-        }
-
-        @Override
         protected void _closeInput() throws IOException {
         }
 
diff --git a/src/test/java/com/fasterxml/jackson/databind/TestObjectMapperBeanDeserializer.java b/src/test/java/com/fasterxml/jackson/databind/TestObjectMapperBeanDeserializer.java
index 6778274..5d96b07 100644
--- a/src/test/java/com/fasterxml/jackson/databind/TestObjectMapperBeanDeserializer.java
+++ b/src/test/java/com/fasterxml/jackson/databind/TestObjectMapperBeanDeserializer.java
@@ -217,7 +217,8 @@
             OtherBean otherResult = MAPPER.readValue("13", OtherBean.class);
             fail("Expected an exception, but got result value: "+otherResult.o);
         } catch (JsonMappingException e) {
-            verifyException(e, "from Integral number", "no single-int-arg constructor/factory method");
+            verifyException(e, "deserialize from Number value",
+                    "no int/Integer-argument constructor/factory method");
             assertValidLocation(e.getLocation());
         }
     }
@@ -233,7 +234,8 @@
             OtherBean otherResult = MAPPER.readValue(""+value, OtherBean.class);
             fail("Expected an exception, but got result value: "+otherResult.o);
         } catch (JsonMappingException e) {
-            verifyException(e, "from Long integral number", "no single-long-arg constructor/factory method");
+            verifyException(e, "deserialize from Number value",
+                    "no long/Long-argument constructor/factory method");
             assertValidLocation(e.getLocation());
         }
     }
@@ -247,7 +249,8 @@
             OtherBean otherResult = MAPPER.readValue("13.5", OtherBean.class);
             fail("Expected an exception, but got result value: "+otherResult.o);
         } catch (JsonMappingException e) {
-            verifyException(e, "from Floating-point number", "no one-double/Double-arg constructor/factory method");
+            verifyException(e, "deserialize from Number value",
+                    "no double/Double-argument constructor/factory method");
             assertValidLocation(e.getLocation());
         }
     }
diff --git a/src/test/java/com/fasterxml/jackson/databind/contextual/TestContextualWithAnnDeserializer.java b/src/test/java/com/fasterxml/jackson/databind/contextual/TestContextualWithAnnDeserializer.java
index d20d37d..e019014 100644
--- a/src/test/java/com/fasterxml/jackson/databind/contextual/TestContextualWithAnnDeserializer.java
+++ b/src/test/java/com/fasterxml/jackson/databind/contextual/TestContextualWithAnnDeserializer.java
@@ -46,9 +46,9 @@
         }
 
         @Override
-        public StringValue deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
+        public StringValue deserialize(JsonParser p, DeserializationContext ctxt) throws IOException
         {
-            return new StringValue(""+_fieldName+"="+jp.getText());
+            return new StringValue(""+_fieldName+"="+p.getText());
         }
 
         @Override
@@ -61,38 +61,10 @@
                 ann = property.getContextAnnotation(Name.class);
             }
             String propertyName = (ann == null) ?  "UNKNOWN" : ann.value();
-            return new MyContextualDeserializer(propertyName);
+            return new AnnotatedContextualDeserializer(propertyName);
         }
     }
 
-    static class MyContextualDeserializer
-        extends JsonDeserializer<StringValue>
-        implements ContextualDeserializer
-    {
-        protected final String _fieldName;
-        
-        public MyContextualDeserializer() { this(""); }
-        public MyContextualDeserializer(String fieldName) {
-            _fieldName = fieldName;
-        }
-    
-        @Override
-        public StringValue deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
-        {
-            return new StringValue(""+_fieldName+"="+jp.getText());
-        }
-
-        @Override
-        public JsonDeserializer<?> createContextual(DeserializationContext ctxt,
-                BeanProperty property)
-            throws JsonMappingException
-        {
-            String name = (property == null) ? "NULL" : property.getName();
-            return new MyContextualDeserializer(name);
-        }
-    }
-
-    
     // ensure that direct associations also work
     public void testAnnotatedContextual() throws Exception
     {
@@ -103,5 +75,4 @@
         assertNotNull(bean);
         assertEquals("xyz=a", bean.value.value);
     }
-
 }
diff --git a/src/test/java/com/fasterxml/jackson/databind/convert/ConvertingAbstractSerializer795Test.java b/src/test/java/com/fasterxml/jackson/databind/convert/ConvertingAbstractSerializer795Test.java
index 3fceada..f251599 100644
--- a/src/test/java/com/fasterxml/jackson/databind/convert/ConvertingAbstractSerializer795Test.java
+++ b/src/test/java/com/fasterxml/jackson/databind/convert/ConvertingAbstractSerializer795Test.java
@@ -34,9 +34,9 @@
         @JsonDeserialize(converter = AbstractCustomTypeDeserializationConverter.class)
         private final AbstractCustomType customField;
 
-        @JsonCreator AbstractCustomTypeUser(@JsonProperty("customField")
-        AbstractCustomType customField) {
-            this.customField = customField;
+        @JsonCreator
+        AbstractCustomTypeUser(@JsonProperty("customField") AbstractCustomType cf) {
+            this.customField = cf;
         }
     }
 
@@ -65,6 +65,12 @@
         }
     }
 
+    /*
+    /**********************************************************
+    /* Test methods
+    /**********************************************************
+     */
+
     private static final ObjectMapper JSON_MAPPER = new ObjectMapper();
 
     public void testAbstractTypeDeserialization() throws Exception {
diff --git a/src/test/java/com/fasterxml/jackson/databind/convert/TestArrayConversions.java b/src/test/java/com/fasterxml/jackson/databind/convert/TestArrayConversions.java
index ab7f50a..a4156eb 100644
--- a/src/test/java/com/fasterxml/jackson/databind/convert/TestArrayConversions.java
+++ b/src/test/java/com/fasterxml/jackson/databind/convert/TestArrayConversions.java
@@ -196,8 +196,8 @@
         for (int i = 0; i < size; ++i) {
             Number n1 = (Number) Array.get(inputArray, i);
             Number n2 = (Number) Array.get(outputArray, i);
-            double value1 = ((Number) n1).longValue();
-            double value2 = ((Number) n2).longValue();
+            double value1 = n1.longValue();
+            double value2 = n2.longValue();
             assertEquals("Entry #"+i+"/"+size+" not equal", value1, value2);
         }        
     }
@@ -207,10 +207,9 @@
         for (int i = 0; i < size; ++i) {
             Number n1 = (Number) Array.get(inputArray, i);
             Number n2 = (Number) Array.get(outputArray, i);
-            double value1 = ((Number) n1).doubleValue();
-            double value2 = ((Number) n2).doubleValue();
+            double value1 = n1.doubleValue();
+            double value2 = n2.doubleValue();
             assertEquals("Entry #"+i+"/"+size+" not equal", value1, value2);
-        }        
+        }
     }
-
 }
diff --git a/src/test/java/com/fasterxml/jackson/databind/convert/TestBeanConversions.java b/src/test/java/com/fasterxml/jackson/databind/convert/TestBeanConversions.java
index 3baee20..34c161e 100644
--- a/src/test/java/com/fasterxml/jackson/databind/convert/TestBeanConversions.java
+++ b/src/test/java/com/fasterxml/jackson/databind/convert/TestBeanConversions.java
@@ -15,13 +15,13 @@
 {
     final ObjectMapper MAPPER = new ObjectMapper();
 
-    static class Point {
+    static class PointZ {
         public int x, y;
 
         public int z = -13;
 
-        public Point() { }
-        public Point(int a, int b, int c)
+        public PointZ() { }
+        public PointZ(int a, int b, int c)
         {
             x = a;
             y = b;
@@ -101,7 +101,7 @@
     {
         // should have no problems convert between compatible beans...
         PointStrings input = new PointStrings("37", "-9");
-        Point point = MAPPER.convertValue(input, Point.class);
+        PointZ point = MAPPER.convertValue(input, PointZ.class);
         assertEquals(37, point.x);
         assertEquals(-9, point.y);
         // z not included in input, will be whatever default constructor provides
@@ -124,7 +124,7 @@
         try {
             MAPPER.readValue("{\"boolProp\":\"foobar\"}", BooleanBean.class);
         } catch (JsonMappingException e) {
-            verifyException(e, "from String value (\"foobar\")");
+            verifyException(e, "Can not deserialize value of type boolean from String");
         }
     }
 
@@ -137,7 +137,7 @@
         assertEquals("foo", a2.getData());
     }
 
-    // [JACKSON-710]: should work regardless of wrapping...
+    // should work regardless of wrapping...
     public void testWrapping() throws Exception
     {
         ObjectMapper wrappingMapper = new ObjectMapper();
@@ -182,15 +182,15 @@
     
     private void _convertAndVerifyPoint(ObjectMapper m)
     {
-        final Point input = new Point(1, 2, 3);
-        Point output = m.convertValue(input, Point.class);
+        final PointZ input = new PointZ(1, 2, 3);
+        PointZ output = m.convertValue(input, PointZ.class);
         assertEquals(1, output.x);
         assertEquals(2, output.y);
         assertEquals(3, output.z);
     }
 
     /**
-     * Need to test "shortcuts" introduced by [Issue-11]
+     * Need to test "shortcuts" introduced by [databind#11]
      */
     public void testIssue11() throws Exception
     {
diff --git a/src/test/java/com/fasterxml/jackson/databind/convert/TestUpdateValue.java b/src/test/java/com/fasterxml/jackson/databind/convert/TestUpdateValue.java
index 5698edd..ef86c5f 100644
--- a/src/test/java/com/fasterxml/jackson/databind/convert/TestUpdateValue.java
+++ b/src/test/java/com/fasterxml/jackson/databind/convert/TestUpdateValue.java
@@ -70,8 +70,10 @@
         @Override
         public DataA deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
             if (p.getCurrentToken() != JsonToken.START_OBJECT) {
-                throw ctxt.mappingException("Wrong current token, expected START_OBJECT, got: %s",
+                ctxt.reportWrongTokenException(p, JsonToken.START_OBJECT,
+                        "Wrong current token, expected START_OBJECT, got: %s",
                         p.getCurrentToken());
+                // never gets here
             }
             /*JsonNode node =*/ p.readValueAsTree();
 
diff --git a/src/test/java/com/fasterxml/jackson/databind/creators/ArrayDelegatorCreatorForCollectionTest.java b/src/test/java/com/fasterxml/jackson/databind/creators/ArrayDelegatorCreatorForCollectionTest.java
index c0cb961..4110008 100644
--- a/src/test/java/com/fasterxml/jackson/databind/creators/ArrayDelegatorCreatorForCollectionTest.java
+++ b/src/test/java/com/fasterxml/jackson/databind/creators/ArrayDelegatorCreatorForCollectionTest.java
@@ -7,6 +7,7 @@
 
 import com.fasterxml.jackson.databind.*;
 
+// for [databind#1392] (regression in 2.7 due to separation of array-delegating creator)
 public class ArrayDelegatorCreatorForCollectionTest extends BaseMapTest
 {
     @JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY)
diff --git a/src/test/java/com/fasterxml/jackson/databind/creators/BuilderSimpleTest.java b/src/test/java/com/fasterxml/jackson/databind/creators/BuilderSimpleTest.java
index 16f5bfd..3ae76e7 100644
--- a/src/test/java/com/fasterxml/jackson/databind/creators/BuilderSimpleTest.java
+++ b/src/test/java/com/fasterxml/jackson/databind/creators/BuilderSimpleTest.java
@@ -4,6 +4,7 @@
 
 import com.fasterxml.jackson.annotation.JsonAnySetter;
 import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
 import com.fasterxml.jackson.annotation.JsonProperty;
 import com.fasterxml.jackson.annotation.JsonSetter;
 import com.fasterxml.jackson.core.JsonProcessingException;
@@ -302,19 +303,46 @@
      */
 
     private final ObjectMapper MAPPER = new ObjectMapper();
-    
+
     public void testSimple() throws Exception
     {
         String json = "{\"x\":1,\"y\":2}";
         Object o = MAPPER.readValue(json, ValueClassXY.class);
         assertNotNull(o);
-    	    assertSame(ValueClassXY.class, o.getClass());
-    	    ValueClassXY value = (ValueClassXY) o;
-    	    // note: ctor adds one to both values
-    	    assertEquals(value._x, 2);
-    	    assertEquals(value._y, 3);
+        assertSame(ValueClassXY.class, o.getClass());
+        ValueClassXY value = (ValueClassXY) o;
+        // note: ctor adds one to both values
+        assertEquals(value._x, 2);
+        assertEquals(value._y, 3);
     }
 
+    // related to [databind#1214]
+    public void testSimpleWithIgnores() throws Exception
+    {
+        // 'z' is unknown, and would fail by default:
+        String json = "{\"x\":1,\"y\":2,\"z\":3}";
+        Object o = null;
+
+        try {
+            o = MAPPER.readValue(json, ValueClassXY.class);
+            fail("Should not pass");
+        } catch (JsonMappingException e) {
+            verifyException(e, "Unrecognized field \"z\"");
+        }
+
+        // but with config overrides should pass
+        ObjectMapper ignorantMapper = new ObjectMapper();
+        ignorantMapper.configOverride(SimpleBuilderXY.class)
+                .setIgnorals(JsonIgnoreProperties.Value.forIgnoreUnknown(true));
+        o = ignorantMapper.readValue(json, ValueClassXY.class);
+        assertNotNull(o);
+        assertSame(ValueClassXY.class, o.getClass());
+        ValueClassXY value = (ValueClassXY) o;
+        // note: ctor adds one to both values
+        assertEquals(value._x, 2);
+        assertEquals(value._y, 3);
+    }
+    
     public void testMultiAccess() throws Exception
     {
         String json = "{\"c\":3,\"a\":2,\"b\":-9}";
diff --git a/src/test/java/com/fasterxml/jackson/databind/creators/CreatorPropertiesTest.java b/src/test/java/com/fasterxml/jackson/databind/creators/CreatorPropertiesTest.java
index b3bc4c4..93ad973 100644
--- a/src/test/java/com/fasterxml/jackson/databind/creators/CreatorPropertiesTest.java
+++ b/src/test/java/com/fasterxml/jackson/databind/creators/CreatorPropertiesTest.java
@@ -2,7 +2,7 @@
 
 import java.beans.ConstructorProperties;
 
-import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.annotation.*;
 import com.fasterxml.jackson.databind.*;
 
 public class CreatorPropertiesTest extends BaseMapTest
diff --git a/src/test/java/com/fasterxml/jackson/databind/creators/DelegatingArrayCreator1804Test.java b/src/test/java/com/fasterxml/jackson/databind/creators/DelegatingArrayCreator1804Test.java
new file mode 100644
index 0000000..328f4bc
--- /dev/null
+++ b/src/test/java/com/fasterxml/jackson/databind/creators/DelegatingArrayCreator1804Test.java
@@ -0,0 +1,41 @@
+package com.fasterxml.jackson.databind.creators;
+
+import java.util.List;
+
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonValue;
+import com.fasterxml.jackson.databind.BaseMapTest;
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+public class DelegatingArrayCreator1804Test extends BaseMapTest
+{
+    public static class MyTypeImpl extends MyType {
+        private final List<Integer> values;
+
+        MyTypeImpl(List<Integer> values) {
+            this.values = values;
+        }
+
+        @Override
+        public List<Integer> getValues() {
+            return values;
+        }
+    }
+
+    static abstract class MyType {
+        @JsonValue
+        public abstract List<Integer> getValues();
+
+        @JsonCreator(mode=JsonCreator.Mode.DELEGATING)
+        public static MyType of(List<Integer> values) {
+            return new MyTypeImpl(values);
+        }
+    }
+
+
+    public void testDelegatingArray1804() throws Exception {
+        ObjectMapper mapper = new ObjectMapper();
+        MyType thing = mapper.readValue("[]", MyType.class);
+        assertNotNull(thing);
+    }
+}
diff --git a/src/test/java/com/fasterxml/jackson/failing/DelegatingCreatorImplicitNames1001Test.java b/src/test/java/com/fasterxml/jackson/databind/creators/DelegatingCreatorImplicitNames1001Test.java
similarity index 96%
rename from src/test/java/com/fasterxml/jackson/failing/DelegatingCreatorImplicitNames1001Test.java
rename to src/test/java/com/fasterxml/jackson/databind/creators/DelegatingCreatorImplicitNames1001Test.java
index 2de303e..ee354cb 100644
--- a/src/test/java/com/fasterxml/jackson/failing/DelegatingCreatorImplicitNames1001Test.java
+++ b/src/test/java/com/fasterxml/jackson/databind/creators/DelegatingCreatorImplicitNames1001Test.java
@@ -1,4 +1,4 @@
-package com.fasterxml.jackson.failing;
+package com.fasterxml.jackson.databind.creators;
 
 import com.fasterxml.jackson.annotation.*;
 import com.fasterxml.jackson.databind.*;
@@ -21,7 +21,7 @@
         }
 
         // not needed strictly speaking, but added for good measure
-        @JsonCreator(mode=JsonCreator.Mode.DELEGATING)
+        @JsonCreator
         public static D make(String value) {
             String[] split = value.split(":");
             return new D(split[0], split[1]);
diff --git a/src/test/java/com/fasterxml/jackson/databind/creators/EnumCreatorTest.java b/src/test/java/com/fasterxml/jackson/databind/creators/EnumCreatorTest.java
new file mode 100644
index 0000000..1cf89c2
--- /dev/null
+++ b/src/test/java/com/fasterxml/jackson/databind/creators/EnumCreatorTest.java
@@ -0,0 +1,310 @@
+package com.fasterxml.jackson.databind.creators;
+
+import java.math.BigDecimal;
+import java.util.*;
+
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonGetter;
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+import com.fasterxml.jackson.core.type.TypeReference;
+
+import com.fasterxml.jackson.databind.*;
+import com.fasterxml.jackson.databind.deser.Deserializers;
+import com.fasterxml.jackson.databind.deser.std.EnumDeserializer;
+import com.fasterxml.jackson.databind.introspect.AnnotatedMethod;
+import com.fasterxml.jackson.databind.module.SimpleModule;
+
+public class EnumCreatorTest extends BaseMapTest
+{
+    protected enum EnumWithCreator {
+        A, B;
+
+        @JsonCreator
+        public static EnumWithCreator fromEnum(String str) {
+            if ("enumA".equals(str)) return A;
+            if ("enumB".equals(str)) return B;
+            return null;
+        }
+    }
+
+    protected enum EnumWithBDCreator {
+        E5, E8;
+
+        @JsonCreator
+        public static EnumWithBDCreator create(BigDecimal bd) {
+            if (bd.longValue() == 5L) return E5;
+            if (bd.longValue() == 8L) return E8;
+            return null;
+        }
+    }
+
+    protected enum TestEnumFromInt
+    {
+        ENUM_A(1), ENUM_B(2), ENUM_C(3);
+        
+        private final int id;
+        
+        private TestEnumFromInt(int id) {
+            this.id = id;
+        }
+        
+        @JsonCreator public static TestEnumFromInt fromId(int id) {
+            for (TestEnumFromInt e: values()) {
+                if (e.id == id) return e;
+            }
+            return null;
+        }
+    }
+
+    static enum EnumWithPropertiesModeJsonCreator {
+        TEST1,
+        TEST2,
+        TEST3;
+       
+        @JsonGetter("name")
+        public String getName() {
+            return name();
+        }
+       
+        @JsonCreator(mode = JsonCreator.Mode.PROPERTIES)
+        public static EnumWithPropertiesModeJsonCreator create(@JsonProperty("name") String name) {
+            return EnumWithPropertiesModeJsonCreator.valueOf(name);
+        }
+    }
+
+    static enum EnumWithDelegateModeJsonCreator {
+        TEST1,
+        TEST2,
+        TEST3;
+
+        @JsonGetter("name")
+        public String getName() {
+            return name();
+        }
+
+        @JsonCreator(mode = JsonCreator.Mode.DELEGATING)
+        public static EnumWithDelegateModeJsonCreator create(JsonNode json) {
+            return EnumWithDelegateModeJsonCreator.valueOf(json.get("name").asText());
+        }
+    }
+    
+    // [databind#324]: exception from creator method
+    protected enum TestEnum324
+    {
+        A, B;
+        
+        @JsonCreator public static TestEnum324 creator(String arg) {
+            throw new RuntimeException("Foobar!");
+        }
+    }
+
+    // [databind#745]
+    static class DelegatingDeserializers extends Deserializers.Base
+    {
+        @Override
+        public JsonDeserializer<?> findEnumDeserializer(final Class<?> type, final DeserializationConfig config, final BeanDescription beanDesc) throws JsonMappingException {
+            final Collection<AnnotatedMethod> factoryMethods = beanDesc.getFactoryMethods();
+            if (factoryMethods != null) {
+                for (AnnotatedMethod am : factoryMethods) {
+                    final JsonCreator creator = am.getAnnotation(JsonCreator.class);
+                    if (creator != null) {
+                        return EnumDeserializer.deserializerForCreator(config, type, am, null, null);
+                    }
+                }
+            }
+            return null;
+        }
+    }
+
+    // [databind#745]
+    static class DelegatingDeserializersModule extends SimpleModule
+    {
+        private static final long serialVersionUID = 1L;
+
+        @Override
+        public void setupModule(final SetupContext context) {
+            context.addDeserializers(new DelegatingDeserializers());
+        }
+    }
+
+    // [databind#929]: support multi-arg enum creator
+    static enum Enum929
+    {
+        A, B, C;
+
+        @JsonCreator(mode = JsonCreator.Mode.PROPERTIES)
+        static Enum929 forValues(@JsonProperty("id") int intProp,
+                                 @JsonProperty("name") String name)
+        {
+            return Enum929.valueOf(name);
+        }
+    }
+
+    static enum MyEnum960
+    {
+        VALUE, BOGUS;
+        
+        @JsonCreator
+        public static MyEnum960 getInstance() {
+            return VALUE;
+        }
+    }
+
+    static class MyEnum960Wrapper {
+        public MyEnum960 value;
+    }
+
+    static enum Enum1291 {
+
+        V1("val1"),
+        V2("val2"),
+        V3("val3"),
+        V4("val4"),
+        V5("val5"),
+        V6("val6");
+
+        private final String name;
+
+        Enum1291(String name) {
+            this.name = name;
+        }
+
+        public static Enum1291 fromString(String name) {
+            for (Enum1291 type : Enum1291.values()) {
+                if (type.name.equals(name)) {
+                    return type;
+                }
+            }
+            return Enum1291.valueOf(name.toUpperCase());
+        }
+
+        @Override
+        public String toString() {
+            return name;
+        }
+    }
+
+    /*
+    /**********************************************************
+    /* Test methods
+    /**********************************************************
+     */
+
+    protected final ObjectMapper MAPPER = new ObjectMapper();
+
+    public void testCreatorEnums() throws Exception {
+        EnumWithCreator value = MAPPER.readValue("\"enumA\"", EnumWithCreator.class);
+        assertEquals(EnumWithCreator.A, value);
+    }
+
+    public void testCreatorEnumsFromBigDecimal() throws Exception {
+        EnumWithBDCreator value = MAPPER.readValue("\"8.0\"", EnumWithBDCreator.class);
+        assertEquals(EnumWithBDCreator.E8, value);
+    }
+
+    public void testEnumWithCreatorEnumMaps() throws Exception {
+        EnumMap<EnumWithCreator,String> value = MAPPER.readValue("{\"enumA\":\"value\"}",
+                new TypeReference<EnumMap<EnumWithCreator,String>>() {});
+        assertEquals("value", value.get(EnumWithCreator.A));
+    }
+
+    public void testEnumWithCreatorMaps() throws Exception {
+        HashMap<EnumWithCreator,String> value = MAPPER.readValue("{\"enumA\":\"value\"}",
+                new TypeReference<java.util.HashMap<EnumWithCreator,String>>() {});
+        assertEquals("value", value.get(EnumWithCreator.A));
+    }
+
+    public void testEnumWithCreatorEnumSets() throws Exception {
+        EnumSet<EnumWithCreator> value = MAPPER.readValue("[\"enumA\"]",
+                new TypeReference<EnumSet<EnumWithCreator>>() {});
+        assertTrue(value.contains(EnumWithCreator.A));
+    }
+
+    public void testJsonCreatorPropertiesWithEnum() throws Exception
+    {
+        EnumWithPropertiesModeJsonCreator type1 = MAPPER.readValue("{\"name\":\"TEST1\", \"description\":\"TEST\"}", EnumWithPropertiesModeJsonCreator.class);
+        assertSame(EnumWithPropertiesModeJsonCreator.TEST1, type1);
+        
+        EnumWithPropertiesModeJsonCreator type2 = MAPPER.readValue("{\"name\":\"TEST3\", \"description\":\"TEST\"}", EnumWithPropertiesModeJsonCreator.class);
+        assertSame(EnumWithPropertiesModeJsonCreator.TEST3, type2);
+     
+    }
+    
+    public void testJsonCreatorDelagateWithEnum() throws Exception {
+        final ObjectMapper mapper = new ObjectMapper();
+        
+        EnumWithDelegateModeJsonCreator type1 = mapper.readValue("{\"name\":\"TEST1\", \"description\":\"TEST\"}", EnumWithDelegateModeJsonCreator.class);
+        assertSame(EnumWithDelegateModeJsonCreator.TEST1, type1);
+        
+        EnumWithDelegateModeJsonCreator type2 = mapper.readValue("{\"name\":\"TEST3\", \"description\":\"TEST\"}", EnumWithDelegateModeJsonCreator.class);
+        assertSame(EnumWithDelegateModeJsonCreator.TEST3, type2);
+     
+    }
+
+    public void testEnumsFromInts() throws Exception
+    {
+        Object ob = MAPPER.readValue("1 ", TestEnumFromInt.class);
+        assertEquals(TestEnumFromInt.class, ob.getClass());
+        assertSame(TestEnumFromInt.ENUM_A, ob);
+    }
+
+    // [databind#324]
+    public void testExceptionFromCreator() throws Exception
+    {
+        try {
+            /*TestEnum324 e =*/ MAPPER.readValue(quote("xyz"), TestEnum324.class);
+            fail("Should throw exception");
+        } catch (JsonMappingException e) {
+            verifyException(e, "foobar");
+        }
+    }
+    
+    // [databind#745]
+    public void testDeserializerForCreatorWithEnumMaps() throws Exception
+    {
+        final ObjectMapper mapper = new ObjectMapper();
+        mapper.registerModule(new DelegatingDeserializersModule());
+        EnumMap<EnumWithCreator,String> value = mapper.readValue("{\"enumA\":\"value\"}",
+                new TypeReference<EnumMap<EnumWithCreator,String>>() {});
+        assertEquals("value", value.get(EnumWithCreator.A));
+    }
+
+    // for [databind#929]
+    public void testMultiArgEnumCreator() throws Exception
+    {
+        Enum929 v = MAPPER.readValue("{\"id\":3,\"name\":\"B\"}", Enum929.class);
+        assertEquals(Enum929.B, v);
+    }
+    
+    // for [databind#960]
+    public void testNoArgEnumCreator() throws Exception
+    {
+        MyEnum960 v = MAPPER.readValue("{\"value\":\"bogus\"}", MyEnum960.class);
+        assertEquals(MyEnum960.VALUE, v);
+    }
+
+    // for [databind#1291]
+    public void testEnumCreators1291() throws Exception
+    {
+        ObjectMapper mapper = new ObjectMapper();
+        String json = mapper.writeValueAsString(Enum1291.V2);
+        Enum1291 result = mapper.readValue(json, Enum1291.class);
+        assertSame(Enum1291.V2, result);
+    }
+
+    // for [databind#1389]
+    public void testMultiArgEnumInCollections() throws Exception
+    {
+        EnumSet<Enum929> valueEnumSet = MAPPER.readValue("[{\"id\":3,\"name\":\"B\"}, {\"id\":3,\"name\":\"A\"}]",
+                new TypeReference<EnumSet<Enum929>>() {});
+        assertEquals(2, valueEnumSet.size());
+        assertTrue(valueEnumSet.contains(Enum929.A));
+        assertTrue(valueEnumSet.contains(Enum929.B));
+        List<Enum929> valueList = MAPPER.readValue("[{\"id\":3,\"name\":\"B\"}, {\"id\":3,\"name\":\"A\"}, {\"id\":3,\"name\":\"B\"}]",
+                new TypeReference<List<Enum929>>() {});
+        assertEquals(3, valueList.size());
+        assertEquals(Enum929.B, valueList.get(2));
+    }
+
+}
diff --git a/src/test/java/com/fasterxml/jackson/databind/creators/FailOnNullCreatorTest.java b/src/test/java/com/fasterxml/jackson/databind/creators/FailOnNullCreatorTest.java
new file mode 100644
index 0000000..52416f4
--- /dev/null
+++ b/src/test/java/com/fasterxml/jackson/databind/creators/FailOnNullCreatorTest.java
@@ -0,0 +1,60 @@
+package com.fasterxml.jackson.databind.creators;
+
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.databind.*;
+
+/**
+ * Tests to ensure that deserialization fails when a bean property has a null value
+ * Relates to <a href="https://github.com/FasterXML/jackson-databind/issues/988">issue #988</a>
+ */
+public class FailOnNullCreatorTest extends BaseMapTest
+{
+    static class Person {
+        String name;
+        Integer age;
+
+        @JsonCreator
+        public Person(@JsonProperty(value="name") String name,
+                      @JsonProperty(value="age") int age)
+        {
+            this.name = name;
+            this.age = age;
+        }
+    }
+
+    private final ObjectReader POINT_READER = objectMapper().readerFor(Person.class);
+
+    public void testRequiredNonNullParam() throws Exception
+    {
+        Person p;
+        // First: fine if feature is not enabled
+        p = POINT_READER.readValue(aposToQuotes("{}"));
+        assertEquals(null, p.name);
+        assertEquals(Integer.valueOf(0), p.age);
+
+        // Second: fine if feature is enabled but default value is not null
+        ObjectReader r = POINT_READER.with(DeserializationFeature.FAIL_ON_NULL_CREATOR_PROPERTIES);
+        p = POINT_READER.readValue(aposToQuotes("{'name':'John', 'age': null}"));
+        assertEquals("John", p.name);
+        assertEquals(Integer.valueOf(0), p.age);
+
+        // Third: throws exception if property is missing
+        try {
+            r.readValue(aposToQuotes("{}"));
+            fail("Should not pass third test");
+        } catch (JsonMappingException e) {
+            verifyException(e, "Null value for creator property 'name'");
+        }
+
+        // Fourth: throws exception if property is set to null explicitly
+        try {
+            r.readValue(aposToQuotes("{'age': 5, 'name': null}"));
+            fail("Should not pass fourth test");
+        } catch (JsonMappingException e) {
+            verifyException(e, "Null value for creator property 'name'");
+        }
+    }
+
+
+}
diff --git a/src/test/java/com/fasterxml/jackson/databind/creators/InnerClassCreatorTest.java b/src/test/java/com/fasterxml/jackson/databind/creators/InnerClassCreatorTest.java
new file mode 100644
index 0000000..c235388
--- /dev/null
+++ b/src/test/java/com/fasterxml/jackson/databind/creators/InnerClassCreatorTest.java
@@ -0,0 +1,92 @@
+package com.fasterxml.jackson.databind.creators;
+
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.databind.*;
+
+// For [databind#1501], [databind#1502], [databind#1503]; mostly to
+// test that for non-static inner classes constructors are ignored
+// and no Creators should be processed (since they can not be made
+// to work in standard way anyway).
+public class InnerClassCreatorTest extends BaseMapTest
+{
+    static class Something1501 {
+        public InnerSomething1501 a;
+
+        // important: must name the parameter (param names module, or explicit)
+        @JsonCreator
+        public Something1501(@JsonProperty("a") InnerSomething1501 a) { this.a = a; }
+
+        public Something1501(boolean bogus) { a = new InnerSomething1501(); }
+
+        class InnerSomething1501 {
+            @JsonCreator
+            public InnerSomething1501() { }
+        }
+    }
+
+    static class Something1502 {
+        @JsonProperty
+        public InnerSomething1502 a;
+
+        @JsonCreator
+        public Something1502(InnerSomething1502 a) {}
+
+        class InnerSomething1502 {
+            @JsonCreator
+            public InnerSomething1502() {}
+        }
+    }    
+
+    static class Outer1503 {
+        public InnerClass1503 innerClass;
+
+        class InnerClass1503 {
+            public Generic<?> generic;
+            public InnerClass1503(@JsonProperty("generic") Generic<?> generic) {}
+        }
+
+        static class Generic<T> {
+            public int ignored;
+        }
+    }
+
+    private final ObjectMapper MAPPER = new ObjectMapper();
+    {
+        MAPPER.disable(SerializationFeature.FAIL_ON_EMPTY_BEANS);
+    }
+
+    // Used to trigger `ArrayIndexOutOfBoundsException` for missing creator property index
+    public void testIssue1501() throws Exception
+    {
+        String ser = MAPPER.writeValueAsString(new Something1501(false));
+        try {
+            MAPPER.readValue(ser, Something1501.class);
+            fail("Should not pass");
+        } catch (JsonMappingException e) {
+            verifyException(e, "Can not construct instance");
+            verifyException(e, "InnerSomething1501");
+            verifyException(e, "can only instantiate non-static inner class by using default");
+        }
+    }    
+
+    public void testIssue1502() throws Exception
+    {
+        String ser = MAPPER.writeValueAsString(new Something1502(null));
+        try {
+            MAPPER.readValue(ser, Something1502.class);
+            fail("Should not pass");
+        } catch (JsonMappingException e) {
+            verifyException(e, "Can not construct instance");
+            verifyException(e, "InnerSomething1502");
+            verifyException(e, "can only instantiate non-static inner class by using default");
+        }
+    }
+
+    public void testIssue1503() throws Exception
+    {
+        String ser = MAPPER.writeValueAsString(new Outer1503());
+        Outer1503 result = MAPPER.readValue(ser, Outer1503.class);
+        assertNotNull(result);
+    }
+}
diff --git a/src/test/java/com/fasterxml/jackson/databind/creators/TestConstructFromMap.java b/src/test/java/com/fasterxml/jackson/databind/creators/TestConstructFromMap.java
index 873a556..84e8c7c 100644
--- a/src/test/java/com/fasterxml/jackson/databind/creators/TestConstructFromMap.java
+++ b/src/test/java/com/fasterxml/jackson/databind/creators/TestConstructFromMap.java
@@ -1,6 +1,5 @@
 package com.fasterxml.jackson.databind.creators;
 
-import java.awt.Point; // just for convenience
 import java.math.BigDecimal;
 import java.util.*;
 
diff --git a/src/test/java/com/fasterxml/jackson/databind/creators/TestCreators2.java b/src/test/java/com/fasterxml/jackson/databind/creators/TestCreators2.java
index 1e24e5d..f075bcb 100644
--- a/src/test/java/com/fasterxml/jackson/databind/creators/TestCreators2.java
+++ b/src/test/java/com/fasterxml/jackson/databind/creators/TestCreators2.java
@@ -276,7 +276,7 @@
             MAPPER.readValue(quote("abc"), IgnoredCtor.class);
             fail("Should have caught missing constructor problem");
         } catch (JsonMappingException e) {
-            verifyException(e, "no single-String constructor/factory method");
+            verifyException(e, "no String-argument constructor/factory method");
         }
     }
 
diff --git a/src/test/java/com/fasterxml/jackson/databind/creators/TestCreatorsWithIdentity.java b/src/test/java/com/fasterxml/jackson/databind/creators/TestCreatorsWithIdentity.java
index 1975038..b064424 100644
--- a/src/test/java/com/fasterxml/jackson/databind/creators/TestCreatorsWithIdentity.java
+++ b/src/test/java/com/fasterxml/jackson/databind/creators/TestCreatorsWithIdentity.java
@@ -25,7 +25,6 @@
 	    }
 	}
 
-
 	public static class Child {
 	    @JsonProperty
 	    Parent parent;
@@ -50,5 +49,6 @@
 	    assertNotNull(parent);
 	    Child child = JSON_MAPPER.readValue(childStr, Child.class);
 	    assertNotNull(child);
+	    assertNotNull(child.parent);
 	}
 }
diff --git a/src/test/java/com/fasterxml/jackson/databind/creators/TestCustomValueInstDefaults.java b/src/test/java/com/fasterxml/jackson/databind/creators/TestCustomValueInstDefaults.java
new file mode 100644
index 0000000..e9793e3
--- /dev/null
+++ b/src/test/java/com/fasterxml/jackson/databind/creators/TestCustomValueInstDefaults.java
@@ -0,0 +1,555 @@
+package com.fasterxml.jackson.databind.creators;
+
+import java.io.IOException;
+
+import com.fasterxml.jackson.annotation.*;
+import com.fasterxml.jackson.core.Version;
+import com.fasterxml.jackson.databind.*;
+import com.fasterxml.jackson.databind.deser.SettableBeanProperty;
+import com.fasterxml.jackson.databind.deser.ValueInstantiator;
+import com.fasterxml.jackson.databind.deser.ValueInstantiators;
+import com.fasterxml.jackson.databind.deser.impl.PropertyValueBuffer;
+import com.fasterxml.jackson.databind.deser.std.StdValueInstantiator;
+import com.fasterxml.jackson.databind.module.SimpleModule;
+
+/**
+ * Exercises a custom value instantiator with an overridden
+ * {@link ValueInstantiator#createFromObjectWith(DeserializationContext, SettableBeanProperty[], PropertyValueBuffer)}
+ * as well as the {@link PropertyValueBuffer#hasParameter(SettableBeanProperty)}
+ * and {@link PropertyValueBuffer#getParameter(SettableBeanProperty)} methods.
+ */
+@SuppressWarnings("serial")
+public class TestCustomValueInstDefaults extends BaseTest
+{
+    static class Bucket
+    {
+        static final int DEFAULT_A = 111;
+        static final int DEFAULT_B = 222;
+        static final String DEFAULT_C = "defaultC";
+        static final String DEFAULT_D = "defaultD";
+
+        final int a;
+        final int b;
+        final String c;
+        final String d;
+
+        @JsonCreator
+        public Bucket(
+                @JsonProperty("a") int a,
+                @JsonProperty("b") int b,
+                @JsonProperty("c") String c,
+                @JsonProperty("d") String d)
+        {
+            this.a = a;
+            this.b = b;
+            this.c = c;
+            this.d = d;
+        }
+    }
+
+    static class BigBucket
+    {
+        static final int DEFAULT_I = 555;
+        static final String DEFAULT_S = "defaultS";
+
+        final int
+                i01, i02, i03, i04, i05, i06, i07, i08,
+                i09, i10, i11, i12, i13, i14, i15, i16;
+
+        final String
+                s01, s02, s03, s04, s05, s06, s07, s08,
+                s09, s10, s11, s12, s13, s14, s15, s16;
+
+        @JsonCreator
+        public BigBucket(
+                @JsonProperty("i01") int i01,
+                @JsonProperty("i02") int i02,
+                @JsonProperty("i03") int i03,
+                @JsonProperty("i04") int i04,
+                @JsonProperty("i05") int i05,
+                @JsonProperty("i06") int i06,
+                @JsonProperty("i07") int i07,
+                @JsonProperty("i08") int i08,
+                @JsonProperty("i09") int i09,
+                @JsonProperty("i10") int i10,
+                @JsonProperty("i11") int i11,
+                @JsonProperty("i12") int i12,
+                @JsonProperty("i13") int i13,
+                @JsonProperty("i14") int i14,
+                @JsonProperty("i15") int i15,
+                @JsonProperty("i16") int i16,
+                @JsonProperty("s01") String s01,
+                @JsonProperty("s02") String s02,
+                @JsonProperty("s03") String s03,
+                @JsonProperty("s04") String s04,
+                @JsonProperty("s05") String s05,
+                @JsonProperty("s06") String s06,
+                @JsonProperty("s07") String s07,
+                @JsonProperty("s08") String s08,
+                @JsonProperty("s09") String s09,
+                @JsonProperty("s10") String s10,
+                @JsonProperty("s11") String s11,
+                @JsonProperty("s12") String s12,
+                @JsonProperty("s13") String s13,
+                @JsonProperty("s14") String s14,
+                @JsonProperty("s15") String s15,
+                @JsonProperty("s16") String s16,
+                // It is not clear why PropertyValueBuffer uses the BitSet for
+                // exactly 32 params.  The primitive int has 32 bits, so
+                // couldn't the int be used there?  We add this 33rd dummy
+                // parameter just in case PropertyValueBuffer is refactored to
+                // to so.
+                @JsonProperty("dummy") boolean dummy) {
+            this.i01 = i01; this.i02 = i02; this.i03 = i03; this.i04 = i04;
+            this.i05 = i05; this.i06 = i06; this.i07 = i07; this.i08 = i08;
+            this.i09 = i09; this.i10 = i10; this.i11 = i11; this.i12 = i12;
+            this.i13 = i13; this.i14 = i14; this.i15 = i15; this.i16 = i16;
+            this.s01 = s01; this.s02 = s02; this.s03 = s03; this.s04 = s04;
+            this.s05 = s05; this.s06 = s06; this.s07 = s07; this.s08 = s08;
+            this.s09 = s09; this.s10 = s10; this.s11 = s11; this.s12 = s12;
+            this.s13 = s13; this.s14 = s14; this.s15 = s15; this.s16 = s16;
+        }
+    }
+
+    static class BucketInstantiator extends StdValueInstantiator
+    {
+        BucketInstantiator(StdValueInstantiator src)
+        {
+            super(src);
+        }
+
+        @Override
+        public Object createFromObjectWith(
+                DeserializationContext ctxt,
+                SettableBeanProperty[] props,
+                PropertyValueBuffer buffer) throws JsonMappingException
+        {
+            int a = Bucket.DEFAULT_A;
+            int b = Bucket.DEFAULT_B;
+            String c = Bucket.DEFAULT_C;
+            String d = Bucket.DEFAULT_D;
+            for (SettableBeanProperty prop : props) {
+                if (buffer.hasParameter(prop)) {
+                    if (prop.getName().equals("a")) {
+                        a = (Integer) buffer.getParameter(prop);
+                    } else if (prop.getName().equals("b")) {
+                        b = (Integer) buffer.getParameter(prop);
+                    } else if (prop.getName().equals("c")) {
+                        c = (String) buffer.getParameter(prop);
+                    } else if (prop.getName().equals("d")) {
+                        d = (String) buffer.getParameter(prop);
+                    }
+                }
+            }
+            return new Bucket(a, b, c, d);
+        }
+    }
+
+    static class BigBucketInstantiator extends StdValueInstantiator
+    {
+        BigBucketInstantiator(StdValueInstantiator src)
+        {
+            super(src);
+        }
+
+        @Override
+        public Object createFromObjectWith(
+                DeserializationContext ctxt,
+                SettableBeanProperty[] props,
+                PropertyValueBuffer buffer) throws JsonMappingException
+        {
+            int i01 = BigBucket.DEFAULT_I;
+            int i02 = BigBucket.DEFAULT_I;
+            int i03 = BigBucket.DEFAULT_I;
+            int i04 = BigBucket.DEFAULT_I;
+            int i05 = BigBucket.DEFAULT_I;
+            int i06 = BigBucket.DEFAULT_I;
+            int i07 = BigBucket.DEFAULT_I;
+            int i08 = BigBucket.DEFAULT_I;
+            int i09 = BigBucket.DEFAULT_I;
+            int i10 = BigBucket.DEFAULT_I;
+            int i11 = BigBucket.DEFAULT_I;
+            int i12 = BigBucket.DEFAULT_I;
+            int i13 = BigBucket.DEFAULT_I;
+            int i14 = BigBucket.DEFAULT_I;
+            int i15 = BigBucket.DEFAULT_I;
+            int i16 = BigBucket.DEFAULT_I;
+            String s01 = BigBucket.DEFAULT_S;
+            String s02 = BigBucket.DEFAULT_S;
+            String s03 = BigBucket.DEFAULT_S;
+            String s04 = BigBucket.DEFAULT_S;
+            String s05 = BigBucket.DEFAULT_S;
+            String s06 = BigBucket.DEFAULT_S;
+            String s07 = BigBucket.DEFAULT_S;
+            String s08 = BigBucket.DEFAULT_S;
+            String s09 = BigBucket.DEFAULT_S;
+            String s10 = BigBucket.DEFAULT_S;
+            String s11 = BigBucket.DEFAULT_S;
+            String s12 = BigBucket.DEFAULT_S;
+            String s13 = BigBucket.DEFAULT_S;
+            String s14 = BigBucket.DEFAULT_S;
+            String s15 = BigBucket.DEFAULT_S;
+            String s16 = BigBucket.DEFAULT_S;
+            for (SettableBeanProperty prop : props) {
+                if (buffer.hasParameter(prop)) {
+                    String name = prop.getName();
+                    Object value = buffer.getParameter(prop);
+                    if (name.equals("i01")) i01 = (Integer) value;
+                    else if (name.equals("i02")) i02 = (Integer) value;
+                    else if (name.equals("i03")) i03 = (Integer) value;
+                    else if (name.equals("i04")) i04 = (Integer) value;
+                    else if (name.equals("i05")) i05 = (Integer) value;
+                    else if (name.equals("i06")) i06 = (Integer) value;
+                    else if (name.equals("i07")) i07 = (Integer) value;
+                    else if (name.equals("i08")) i08 = (Integer) value;
+                    else if (name.equals("i09")) i09 = (Integer) value;
+                    else if (name.equals("i10")) i10 = (Integer) value;
+                    else if (name.equals("i11")) i11 = (Integer) value;
+                    else if (name.equals("i12")) i12 = (Integer) value;
+                    else if (name.equals("i13")) i13 = (Integer) value;
+                    else if (name.equals("i14")) i14 = (Integer) value;
+                    else if (name.equals("i15")) i15 = (Integer) value;
+                    else if (name.equals("i16")) i16 = (Integer) value;
+                    else if (name.equals("s01")) s01 = (String) value;
+                    else if (name.equals("s02")) s02 = (String) value;
+                    else if (name.equals("s03")) s03 = (String) value;
+                    else if (name.equals("s04")) s04 = (String) value;
+                    else if (name.equals("s05")) s05 = (String) value;
+                    else if (name.equals("s06")) s06 = (String) value;
+                    else if (name.equals("s07")) s07 = (String) value;
+                    else if (name.equals("s08")) s08 = (String) value;
+                    else if (name.equals("s09")) s09 = (String) value;
+                    else if (name.equals("s10")) s10 = (String) value;
+                    else if (name.equals("s11")) s11 = (String) value;
+                    else if (name.equals("s12")) s12 = (String) value;
+                    else if (name.equals("s13")) s13 = (String) value;
+                    else if (name.equals("s14")) s14 = (String) value;
+                    else if (name.equals("s15")) s15 = (String) value;
+                    else if (name.equals("s16")) s16 = (String) value;
+                }
+            }
+            return new BigBucket(
+                    i01, i02, i03, i04, i05, i06, i07, i08,
+                    i09, i10, i11, i12, i13, i14, i15, i16,
+                    s01, s02, s03, s04, s05, s06, s07, s08,
+                    s09, s10, s11, s12, s13, s14, s15, s16,
+                    false);
+        }
+    }
+
+    static class BucketInstantiators implements ValueInstantiators
+    {
+        @Override
+        public ValueInstantiator findValueInstantiator(
+                DeserializationConfig config,
+                BeanDescription beanDesc,
+                ValueInstantiator defaultInstantiator)
+        {
+            if (defaultInstantiator instanceof StdValueInstantiator) {
+                if (beanDesc.getBeanClass() == Bucket.class) {
+                    return new BucketInstantiator(
+                            (StdValueInstantiator) defaultInstantiator);
+                }
+                if (beanDesc.getBeanClass() == BigBucket.class) {
+                    return new BigBucketInstantiator(
+                            (StdValueInstantiator) defaultInstantiator);
+                }
+            }
+            return defaultInstantiator;
+        }
+    }
+
+    static class BucketModule extends SimpleModule
+    {
+        @Override
+        public void setupModule(SetupContext context)
+        {
+            context.addValueInstantiators(new BucketInstantiators());
+        }
+    }
+
+    static class ClassWith32Props {
+        @JsonCreator
+        public ClassWith32Props(@JsonProperty("p1") String p1,
+                @JsonProperty("p2") String p2,
+                @JsonProperty("p3") String p3, @JsonProperty("p4") String p4,
+                @JsonProperty("p5") String p5, @JsonProperty("p6") String p6,
+                @JsonProperty("p7") String p7, @JsonProperty("p8") String p8,
+                @JsonProperty("p9") String p9, @JsonProperty("p10") String p10,
+                @JsonProperty("p11") String p11, @JsonProperty("p12") String p12,
+                @JsonProperty("p13") String p13, @JsonProperty("p14") String p14,
+                @JsonProperty("p15") String p15, @JsonProperty("p16") String p16,
+                @JsonProperty("p17") String p17, @JsonProperty("p18") String p18,
+                @JsonProperty("p19") String p19, @JsonProperty("p20") String p20,
+                @JsonProperty("p21") String p21, @JsonProperty("p22") String p22,
+                @JsonProperty("p23") String p23, @JsonProperty("p24") String p24,
+                @JsonProperty("p25") String p25, @JsonProperty("p26") String p26,
+                @JsonProperty("p27") String p27, @JsonProperty("p28") String p28,
+                @JsonProperty("p29") String p29, @JsonProperty("p30") String p30,
+                @JsonProperty("p31") String p31, @JsonProperty("p32") String p32) {
+            this.p1 = p1;
+            this.p2 = p2;
+            this.p3 = p3;
+            this.p4 = p4;
+            this.p5 = p5;
+            this.p6 = p6;
+            this.p7 = p7;
+            this.p8 = p8;
+            this.p9 = p9;
+            this.p10 = p10;
+            this.p11 = p11;
+            this.p12 = p12;
+            this.p13 = p13;
+            this.p14 = p14;
+            this.p15 = p15;
+            this.p16 = p16;
+            this.p17 = p17;
+            this.p18 = p18;
+            this.p19 = p19;
+            this.p20 = p20;
+            this.p21 = p21;
+            this.p22 = p22;
+            this.p23 = p23;
+            this.p24 = p24;
+            this.p25 = p25;
+            this.p26 = p26;
+            this.p27 = p27;
+            this.p28 = p28;
+            this.p29 = p29;
+            this.p30 = p30;
+            this.p31 = p31;
+            this.p32 = p32;
+        }
+
+        public final String p1, p2, p3, p4;
+        public final String p5, p6, p7, p8;
+        public final String p9, p10, p11, p12;
+        public final String p13, p14, p15, p16;
+        public final String p17, p18, p19, p20;
+        public final String p21, p22, p23, p24;
+        public final String p25, p26, p27, p28;
+        public final String p29, p30, p31, p32;
+    }
+
+    static class VerifyingValueInstantiator extends StdValueInstantiator {
+        protected VerifyingValueInstantiator(StdValueInstantiator src) {
+            super(src);
+        }
+
+        @Override
+        public Object createFromObjectWith(DeserializationContext ctxt, SettableBeanProperty[] props, PropertyValueBuffer buffer) throws IOException {
+            for (SettableBeanProperty prop : props) {
+                assertTrue("prop " + prop.getName() + " was expected to have buffer.hasParameter(prop) be true but was false", buffer.hasParameter(prop));
+            }
+            return super.createFromObjectWith(ctxt, props, buffer);
+        }
+    }
+
+    // [databind#1432]
+    
+    public static class ClassWith32Module extends SimpleModule {
+        public ClassWith32Module() {
+            super("test", Version.unknownVersion());
+        }
+
+        @Override
+        public void setupModule(SetupContext context) {
+            context.addValueInstantiators(new ValueInstantiators.Base() {
+                @Override
+                public ValueInstantiator findValueInstantiator(DeserializationConfig config,
+                        BeanDescription beanDesc, ValueInstantiator defaultInstantiator) {
+                    if (beanDesc.getBeanClass() == ClassWith32Props.class) {
+                        return new VerifyingValueInstantiator((StdValueInstantiator)
+                                defaultInstantiator);
+                    }
+                    return defaultInstantiator;
+                }
+            });
+        }
+    }
+
+    /*
+    /**********************************************************
+    /* Test methods
+    /**********************************************************
+     */
+    
+    // When all values are in the source, no defaults should be used.
+    public void testAllPresent() throws Exception
+    {
+        ObjectMapper mapper = new ObjectMapper();
+        mapper.registerModule(new BucketModule());
+
+        Bucket allPresent = mapper.readValue(
+                "{\"a\":8,\"b\":9,\"c\":\"y\",\"d\":\"z\"}",
+                Bucket.class);
+
+        assertEquals(8, allPresent.a);
+        assertEquals(9, allPresent.b);
+        assertEquals("y", allPresent.c);
+        assertEquals("z", allPresent.d);
+    }
+
+    // When no values are in the source, all defaults should be used.
+    public void testAllAbsent() throws Exception
+    {
+        ObjectMapper mapper = new ObjectMapper();
+        mapper.registerModule(new BucketModule());
+
+        Bucket allAbsent = mapper.readValue(
+                "{}",
+                Bucket.class);
+
+        assertEquals(Bucket.DEFAULT_A, allAbsent.a);
+        assertEquals(Bucket.DEFAULT_B, allAbsent.b);
+        assertEquals(Bucket.DEFAULT_C, allAbsent.c);
+        assertEquals(Bucket.DEFAULT_D, allAbsent.d);
+    }
+
+    // When some values are in the source and some are not, defaults should only
+    // be used for the missing values.
+    public void testMixedPresentAndAbsent() throws Exception
+    {
+        ObjectMapper mapper = new ObjectMapper();
+        mapper.registerModule(new BucketModule());
+
+        Bucket aAbsent = mapper.readValue(
+                "{\"b\":9,\"c\":\"y\",\"d\":\"z\"}",
+                Bucket.class);
+
+        assertEquals(Bucket.DEFAULT_A, aAbsent.a);
+        assertEquals(9, aAbsent.b);
+        assertEquals("y", aAbsent.c);
+        assertEquals("z", aAbsent.d);
+
+        Bucket bAbsent = mapper.readValue(
+                "{\"a\":8,\"c\":\"y\",\"d\":\"z\"}",
+                Bucket.class);
+
+        assertEquals(8, bAbsent.a);
+        assertEquals(Bucket.DEFAULT_B, bAbsent.b);
+        assertEquals("y", bAbsent.c);
+        assertEquals("z", bAbsent.d);
+
+        Bucket cAbsent = mapper.readValue(
+                "{\"a\":8,\"b\":9,\"d\":\"z\"}",
+                Bucket.class);
+
+        assertEquals(8, cAbsent.a);
+        assertEquals(9, cAbsent.b);
+        assertEquals(Bucket.DEFAULT_C, cAbsent.c);
+        assertEquals("z", cAbsent.d);
+
+        Bucket dAbsent = mapper.readValue(
+                "{\"a\":8,\"b\":9,\"c\":\"y\"}",
+                Bucket.class);
+
+        assertEquals(8, dAbsent.a);
+        assertEquals(9, dAbsent.b);
+        assertEquals("y", dAbsent.c);
+        assertEquals(Bucket.DEFAULT_D, dAbsent.d);
+    }
+
+    // Ensure that 0 is not mistaken for a missing int value.
+    public void testPresentZeroPrimitive() throws Exception
+    {
+        ObjectMapper mapper = new ObjectMapper();
+        mapper.registerModule(new BucketModule());
+
+        Bucket aZeroRestAbsent = mapper.readValue(
+                "{\"a\":0}",
+                Bucket.class);
+
+        assertEquals(0, aZeroRestAbsent.a);
+        assertEquals(Bucket.DEFAULT_B, aZeroRestAbsent.b);
+        assertEquals(Bucket.DEFAULT_C, aZeroRestAbsent.c);
+        assertEquals(Bucket.DEFAULT_D, aZeroRestAbsent.d);
+    }
+
+    // Ensure that null is not mistaken for a missing String value.
+    public void testPresentNullReference() throws Exception
+    {
+        ObjectMapper mapper = new ObjectMapper();
+        mapper.registerModule(new BucketModule());
+
+        Bucket cNullRestAbsent = mapper.readValue(
+                "{\"c\":null}",
+                Bucket.class);
+
+        assertEquals(Bucket.DEFAULT_A, cNullRestAbsent.a);
+        assertEquals(Bucket.DEFAULT_B, cNullRestAbsent.b);
+        assertEquals(null, cNullRestAbsent.c);
+        assertEquals(Bucket.DEFAULT_D, cNullRestAbsent.d);
+    }
+
+    // When we have more than 32 creator parameters, the buffer will use a
+    // BitSet instead of a primitive int to keep track of which parameters it
+    // has seen.  Ensure that nothing breaks in that case.
+    public void testMoreThan32CreatorParams() throws Exception
+    {
+        ObjectMapper mapper = new ObjectMapper();
+        mapper.registerModule(new BucketModule());
+
+        BigBucket big = mapper.readValue(
+                "{\"i03\":0,\"i11\":1,\"s05\":null,\"s08\":\"x\"}",
+                BigBucket.class);
+
+        assertEquals(BigBucket.DEFAULT_I, big.i01);
+        assertEquals(BigBucket.DEFAULT_I, big.i02);
+        assertEquals(0, big.i03);
+        assertEquals(BigBucket.DEFAULT_I, big.i04);
+        assertEquals(BigBucket.DEFAULT_I, big.i05);
+        assertEquals(BigBucket.DEFAULT_I, big.i06);
+        assertEquals(BigBucket.DEFAULT_I, big.i07);
+        assertEquals(BigBucket.DEFAULT_I, big.i08);
+        assertEquals(BigBucket.DEFAULT_I, big.i09);
+        assertEquals(BigBucket.DEFAULT_I, big.i10);
+        assertEquals(1, big.i11);
+        assertEquals(BigBucket.DEFAULT_I, big.i12);
+        assertEquals(BigBucket.DEFAULT_I, big.i13);
+        assertEquals(BigBucket.DEFAULT_I, big.i14);
+        assertEquals(BigBucket.DEFAULT_I, big.i15);
+        assertEquals(BigBucket.DEFAULT_I, big.i16);
+        assertEquals(BigBucket.DEFAULT_S, big.s01);
+        assertEquals(BigBucket.DEFAULT_S, big.s02);
+        assertEquals(BigBucket.DEFAULT_S, big.s03);
+        assertEquals(BigBucket.DEFAULT_S, big.s04);
+        assertEquals(null, big.s05);
+        assertEquals(BigBucket.DEFAULT_S, big.s06);
+        assertEquals(BigBucket.DEFAULT_S, big.s07);
+        assertEquals("x", big.s08);
+        assertEquals(BigBucket.DEFAULT_S, big.s09);
+        assertEquals(BigBucket.DEFAULT_S, big.s10);
+        assertEquals(BigBucket.DEFAULT_S, big.s11);
+        assertEquals(BigBucket.DEFAULT_S, big.s12);
+        assertEquals(BigBucket.DEFAULT_S, big.s13);
+        assertEquals(BigBucket.DEFAULT_S, big.s14);
+        assertEquals(BigBucket.DEFAULT_S, big.s15);
+        assertEquals(BigBucket.DEFAULT_S, big.s16);
+    }
+
+    // [databind#1432]
+    public void testClassWith32CreatorParams() throws Exception
+    {
+        StringBuilder sb = new StringBuilder()
+                .append("{\n");
+        for (int i = 1; i <= 32; ++i) {
+            sb.append("\"p").append(i).append("\" : \"NotNull")
+                .append(i).append("\"");
+            if (i < 32) {
+                sb.append(",\n");
+            }
+        }
+        sb.append("\n}\n");
+        String json = sb.toString();
+        ObjectMapper mapper = new ObjectMapper()
+                .registerModule(new ClassWith32Module());
+        ClassWith32Props result = mapper.readValue(json, ClassWith32Props.class);
+        // let's assume couple of first, last ones suffice
+        assertEquals("NotNull1", result.p1);
+        assertEquals("NotNull2", result.p2);
+        assertEquals("NotNull31", result.p31);
+        assertEquals("NotNull32", result.p32);
+    }
+}
+
diff --git a/src/test/java/com/fasterxml/jackson/databind/creators/TestValueInstantiator.java b/src/test/java/com/fasterxml/jackson/databind/creators/TestValueInstantiator.java
index 60771fe..744d3d0 100644
--- a/src/test/java/com/fasterxml/jackson/databind/creators/TestValueInstantiator.java
+++ b/src/test/java/com/fasterxml/jackson/databind/creators/TestValueInstantiator.java
@@ -12,7 +12,7 @@
 import com.fasterxml.jackson.databind.type.TypeFactory;
 
 /**
- * Test related to [JACKSON-580] (allow specifying custom instantiators)
+ * Test custom instantiators.
  */
 public class TestValueInstantiator extends BaseMapTest
 {
@@ -43,8 +43,12 @@
         }
     }
 
-    static abstract class InstantiatorBase extends ValueInstantiator
+    static abstract class InstantiatorBase extends ValueInstantiator.Base
     {
+        public InstantiatorBase() {
+            super(Object.class);
+        }
+
         @Override
         public String getValueTypeDesc() {
             return "UNKNOWN";
@@ -153,8 +157,10 @@
         }
     }
     
-    static class MyDelegateBeanInstantiator extends ValueInstantiator
+    static class MyDelegateBeanInstantiator extends ValueInstantiator.Base
     {
+        public MyDelegateBeanInstantiator() { super(Object.class); }
+
         @Override
         public String getValueTypeDesc() { return "xxx"; }
         
@@ -188,8 +194,10 @@
         }
     }
 
-    static class MyDelegateListInstantiator extends ValueInstantiator
+    static class MyDelegateListInstantiator extends ValueInstantiator.Base
     {
+        public MyDelegateListInstantiator() { super(Object.class); }
+
         @Override
         public String getValueTypeDesc() { return "xxx"; }
         
@@ -225,8 +233,10 @@
         }
     }
 
-    static class MyDelegateMapInstantiator extends ValueInstantiator
+    static class MyDelegateMapInstantiator extends ValueInstantiator.Base
     {
+        public MyDelegateMapInstantiator() { super(Object.class); }
+
         @Override
         public String getValueTypeDesc() { return "xxx"; }
         
@@ -567,4 +577,30 @@
         assertEquals("foo", bean.a);
         assertEquals(3, bean.b);
     }
+
+    // @since 2.8
+    public void testErrorMessageForMissingCtor() throws Exception
+    {
+        // first fail, check message from JSON Object (no default ctor)
+        try {
+            MAPPER.readValue("{ }", MyBean.class);
+            fail("Should not succeed");
+        } catch (JsonMappingException e) {
+            verifyException(e, "Can not construct instance of");
+            verifyException(e, "missing default constructor");
+        }
+    }
+
+    // @since 2.8
+    public void testErrorMessageForMissingStringCtor() throws Exception
+    {
+        // then from JSON String
+        try {
+            MAPPER.readValue("\"foo\"", MyBean.class);
+            fail("Should not succeed");
+        } catch (JsonMappingException e) {
+            verifyException(e, "Can not construct instance of");
+            verifyException(e, "no String-argument constructor/factory");
+        }
+    }
 }
diff --git a/src/test/java/com/fasterxml/jackson/databind/creators/TestValueUpdate.java b/src/test/java/com/fasterxml/jackson/databind/creators/TestValueUpdate.java
index 3c7feae..759f618 100644
--- a/src/test/java/com/fasterxml/jackson/databind/creators/TestValueUpdate.java
+++ b/src/test/java/com/fasterxml/jackson/databind/creators/TestValueUpdate.java
@@ -36,13 +36,22 @@
         }
     }
 
-    // [Issue#318] (and Scala module issue #83]
+    private final ObjectMapper MAPPER = new ObjectMapper();
+    
+    // [databind#318] (and Scala module issue #83]
     public void testValueUpdateWithCreator() throws Exception
     {
         Bean bean = new Bean("abc", "def");
-        new ObjectMapper().readerFor(Bean.class).withValueToUpdate(bean).readValue("{\"a\":\"ghi\",\"b\":\"jkl\"}");
+        MAPPER.readerFor(Bean.class).withValueToUpdate(bean).readValue("{\"a\":\"ghi\",\"b\":\"jkl\"}");
         assertEquals("ghi", bean.getA());
         assertEquals("jkl", bean.getB());
     }
 
+    public void testValueUpdateOther() throws Exception
+    {
+        Bean bean = new Bean("abc", "def");
+        ObjectReader r = MAPPER.reader().withValueToUpdate(bean);
+        // but, changed our minds, no update
+        r = r.withValueToUpdate(null);
+    }
 }
diff --git a/src/test/java/com/fasterxml/jackson/databind/deser/AnySetter349Test.java b/src/test/java/com/fasterxml/jackson/databind/deser/AnySetter349Test.java
new file mode 100644
index 0000000..5ff1d2b
--- /dev/null
+++ b/src/test/java/com/fasterxml/jackson/databind/deser/AnySetter349Test.java
@@ -0,0 +1,49 @@
+package com.fasterxml.jackson.databind.deser;
+
+import java.util.*;
+
+import com.fasterxml.jackson.annotation.*;
+
+import com.fasterxml.jackson.databind.*;
+
+// test(s) for [databind#349]
+public class AnySetter349Test extends BaseMapTest
+{
+    static class Bean349
+    {
+        public String type;
+    
+        private Map<String, Object> props = new HashMap<>();
+    
+        @JsonAnySetter
+        public void addProperty(String key, Object value) {
+            props.put(key, value);
+        }
+    
+        @JsonAnyGetter
+        public Map<String, Object> getProperties() {
+            return props;
+        }
+    
+        @JsonUnwrapped
+        public IdentityDTO349 identity;
+    }
+
+    static class IdentityDTO349 {
+        public int x, y;
+    }
+    
+    public void testUnwrappedWithAny() throws Exception
+    {
+        final ObjectMapper mapper = objectMapper();
+        final String json = aposToQuotes(
+"{ 'type' : 'IST',\n"
+//+" 'spacename' : 'Foo Models',\n"
+//+" 'name' : 'BLAH-New',\n"
+//+" 'description' : 'namespace.name: X THIN FIR.DR-WD12-New',\n"
++" 'ZoomLinks': [ 'foofoofoofoo', 'barbarbarbar' ] }"
+                );
+        Bean349 value = mapper.readValue(json,  Bean349.class);
+        assertNotNull(value);
+    }
+}
diff --git a/src/test/java/com/fasterxml/jackson/databind/deser/DateDeserializationTest.java b/src/test/java/com/fasterxml/jackson/databind/deser/DateDeserializationTest.java
new file mode 100644
index 0000000..8a7a0b5
--- /dev/null
+++ b/src/test/java/com/fasterxml/jackson/databind/deser/DateDeserializationTest.java
@@ -0,0 +1,578 @@
+package com.fasterxml.jackson.databind.deser;
+
+import java.math.BigInteger;
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.Locale;
+import java.util.TimeZone;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.fasterxml.jackson.core.JsonParseException;
+import com.fasterxml.jackson.databind.BaseMapTest;
+import com.fasterxml.jackson.databind.JsonMappingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.exc.InvalidFormatException;
+
+@SuppressWarnings("javadoc")
+public class DateDeserializationTest
+    extends BaseMapTest
+{
+    private static final String LOCAL_TZ = "GMT+2";
+
+    private static final DateFormat FORMAT = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSXXX");
+    
+    static class Annot_TimeZone {
+        @JsonFormat(timezone="GMT+4")
+        private java.util.Date date;
+    }
+
+    static class Annot_Pattern {
+        @JsonFormat(pattern="'*'d MMM yyyy HH:mm:ss'*'")
+        private java.util.Date pattern;
+
+        @JsonFormat(pattern="'*'d MMM yyyy HH:mm:ss'*'", locale="FR")
+        private java.util.Date pattern_FR;
+
+        @JsonFormat(pattern="'*'d MMM yyyy HH:mm:ss'*'", timezone="GMT+4")
+        private java.util.Date pattern_GMT4;
+
+        @JsonFormat(pattern="'*'d MMM yyyy HH:mm:ss'*'", locale="FR", timezone="GMT+4")
+        private java.util.Date pattern_FR_GMT4;
+    }
+
+    static class DateAsStringBean {
+        @JsonFormat(shape=JsonFormat.Shape.STRING, pattern="/yyyy/MM/dd/")
+        public Date date;
+    }
+
+    static class DateAsStringBeanGermany {
+        @JsonFormat(shape=JsonFormat.Shape.STRING, pattern="/yyyy/MM/dd/", locale="fr_FR")
+        public Date date;
+    }
+
+    private ObjectMapper MAPPER;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        // Create an ObjectMapper with its timezone set to something other than the default (UTC).
+        // This way we can verify that serialization and deserialization actually consider the time
+        // zone set on the mapper.
+        ObjectMapper m = new ObjectMapper();
+        m.setTimeZone(TimeZone.getTimeZone(LOCAL_TZ));
+        MAPPER = m;
+        
+        FORMAT.setTimeZone(TimeZone.getTimeZone("UTC"));
+    }
+
+    /*
+    /**********************************************************
+    /* Test methods
+    /**********************************************************
+     */
+
+    /**
+     * Test the various timezone/offset representations
+     */
+    public void testDateUtilISO8601_Timezone() throws Exception
+    {
+        // Complete offset, with ':' between hours and minutes
+        verify( MAPPER, "2000-01-02T03:04:05.678+01:00", judate(2000, 1, 2,   3, 4, 5, 678, "GMT+1"));
+        // Complete offset, without ':' between hours and minutes
+        verify( MAPPER, "2000-01-02T03:04:05.678+0100",  judate(2000, 1, 2,   3, 4, 5, 678, "GMT+1"));
+        // Hour offset (no minutes)
+        verify( MAPPER, "2000-01-02T03:04:05.678+01",    judate(2000, 1, 2,   3, 4, 5, 678, "GMT+1"));
+
+        // 'zulu' offset
+        verify( MAPPER, "2000-01-02T03:04:05.678Z",      judate(2000, 1, 2,   3, 4, 5, 678, "UTC"));
+
+        // ---------------------------------------------------------------------------------------------
+        // WARNING:
+        //   According to ISO8601, hours and minutes of the offset must be expressed with 2 digits 
+        //   (not more, not less), i.e. Z or +hh:mm or -hh:mm. See https://www.w3.org/TR/NOTE-datetime. 
+        //
+        //   The forms below should be refused but some are accepted by the StdDateFormat. They are 
+        //   included in the test to detect any change in behavior in futur releases...
+        // ---------------------------------------------------------------------------------------------
+
+        // Interpreted as if there was no timezone, therefore producing a date with the TZ set on the mapper
+        // FIXME it is probably better to refuse these cases instead of silently creating dates in local tz...
+        verify( MAPPER, "2000-01-02T03:04:05.678+",        judate(2000, 1, 2,   3, 4, 5, 678, LOCAL_TZ));
+        verify( MAPPER, "2000-01-02T03:04:05.678+1",       judate(2000, 1, 2,   3, 4, 5, 678, LOCAL_TZ));
+            // FIXME this should probably give GMT+1
+        verify( MAPPER, "2000-01-02T03:04:05.678+001",     judate(2000, 1, 2,   3, 4, 5, 678, LOCAL_TZ));
+        verify( MAPPER, "2000-01-02T03:04:05.678+00:",     judate(2000, 1, 2,   3, 4, 5, 678, LOCAL_TZ));
+        verify( MAPPER, "2000-01-02T03:04:05.678+00:001",  judate(2000, 1, 2,   3, 4, 5, 678, LOCAL_TZ));
+        verify( MAPPER, "2000-01-02T03:04:05.678+001:001", judate(2000, 1, 2,   3, 4, 5, 678, LOCAL_TZ));
+
+        // Considering the above forms have been accepted, it is strange the following are refused...
+        failure( MAPPER, "2000-01-02T03:04:05.678+1:");      // FIXME
+        failure( MAPPER, "2000-01-02T03:04:05.678+00:1");    // FIXME
+    }
+
+    /**
+     * Test the millis
+     */
+    public void testDateUtilISO8601_DateTimeMillis() throws Exception 
+    {    
+        // WITH timezone (from 4 to 0 digits)
+        failure(MAPPER, "2000-01-02T03:04:05.6789+01:00");
+        verify( MAPPER, "2000-01-02T03:04:05.678+01:00", judate(2000, 1, 2,   3, 4, 5, 678, "GMT+1"));
+        verify( MAPPER, "2000-01-02T03:04:05.67+01:00",  judate(2000, 1, 2,   3, 4, 5, 670, "GMT+1"));
+        verify( MAPPER, "2000-01-02T03:04:05.6+01:00",   judate(2000, 1, 2,   3, 4, 5, 600, "GMT+1"));
+        verify( MAPPER, "2000-01-02T03:04:05+01:00",     judate(2000, 1, 2,   3, 4, 5, 000, "GMT+1"));
+
+        
+        // WITH timezone Z (from 4 to 0 digits)
+        verify( MAPPER, "2000-01-02T03:04:05.6789Z", judate(2000, 1, 2,   3, 4, 11, 789, "UTC"));
+            // FIXME the .6789 millis are interpreted as 6789 millisecondes or 6.789 seconds!
+        verify( MAPPER, "2000-01-02T03:04:05.678Z", judate(2000, 1, 2,   3, 4, 5, 678, "UTC"));
+        verify( MAPPER, "2000-01-02T03:04:05.67Z",  judate(2000, 1, 2,   3, 4, 5,  67, "UTC"));
+           // FIXME should be 670 millis instead of 67
+        verify( MAPPER, "2000-01-02T03:04:05.6Z",   judate(2000, 1, 2,   3, 4, 5,   6, "UTC"));
+           // FIXME should be 600 millis instead of 6
+        verify( MAPPER, "2000-01-02T03:04:05Z",     judate(2000, 1, 2,   3, 4, 5,   0, "UTC"));
+        
+
+        // WITHOUT timezone (from 4 to 0 digits)
+        verify(MAPPER, "2000-01-02T03:04:05.6789",       judate(2000, 1, 2,   3, 4, 11, 789, LOCAL_TZ));
+            // FIXME: the .6789 millis are interpreted as 6789 millisecondes or 6.789 seconds!
+        
+        verify( MAPPER, "2000-01-02T03:04:05.678",       judate(2000, 1, 2,   3, 4,  5, 678, LOCAL_TZ));
+        verify( MAPPER, "2000-01-02T03:04:05.67",        judate(2000, 1, 2,   3, 5, 12, 000, LOCAL_TZ));
+            // FIXME: the .67 millis are interpreted as 67 seconds.
+        
+        verify( MAPPER, "2000-01-02T03:04:05.6",         judate(2000, 1, 2,   3, 4,  5, 600, LOCAL_TZ));
+        verify( MAPPER, "2000-01-02T03:04:05",           judate(2000, 1, 2,   3, 4,  5, 000, LOCAL_TZ));
+        
+        
+        // ---------------------------------------------------------------------------------------------
+        // WARNING:
+        //   RFC339 includes an Internet profile of the ISO 8601 standard for representation of dates 
+        //   and times using the Gregorian calendar (https://tools.ietf.org/html/rfc3339).
+        //
+        //   The RFC defines a partial time with the following BNF notation (chapter 5.6):
+        //      time-hour       = 2DIGIT  ; 00-23
+        //      time-minute     = 2DIGIT  ; 00-59
+        //      time-second     = 2DIGIT  ; 00-58, 00-59, 00-60 based on leap second rules
+        //      time-secfrac    = "." 1*DIGIT
+        //      partial-time    = time-hour ":" time-minute ":" time-second [time-secfrac]
+        //
+        //   The second fraction (ie the millis) is optional and can be ommitted. However, a fraction
+        //   with only a dot (.) and no digit is not allowed.
+        //
+        //   The forms below should be refused but some are accepted by the StdDateFormat. They are 
+           //   included in the test to detect any change in behavior in futur releases...
+        // ---------------------------------------------------------------------------------------------
+        
+        // millis part with only a dot (.) and no digits
+        verify( MAPPER, "2000-01-02T03:04:05.+01:00",    judate(2000, 1, 2,   3, 4, 5, 000, "GMT+1"));
+        verify( MAPPER, "2000-01-02T03:04:05.",          judate(2000, 1, 2,   3, 4, 5, 000, LOCAL_TZ));
+        failure(MAPPER, "2000-01-02T03:04:05.Z");	     // FIXME this one fails, but not the others...
+    }
+
+
+    /**
+     * Date+Time representations
+     * 
+     * NOTE: millis are not tested here since they are covered by another test case
+     */
+    public void testDateUtilISO8601_DateTime() throws Exception 
+    {
+        // Full representation with a timezone
+        verify(MAPPER, "2000-01-02T03:04:05+01:00",  judate(2000, 1, 2,   3, 4, 5, 0, "GMT+1"));
+
+        // No timezone --> the one configured on the ObjectMapper must be used
+        verify(MAPPER, "2000-01-02T03:04:05",        judate(2000, 1, 2,   3, 4, 5, 0, LOCAL_TZ));
+
+        // Hours, minutes and seconds are mandatory when time is specified
+        failure(MAPPER, "2000-01-02T");
+        failure(MAPPER, "2000-01-02T03");
+        failure(MAPPER, "2000-01-02T03:");
+        failure(MAPPER, "2000-01-02T03:04");
+        failure(MAPPER, "2000-01-02T03:04:");
+
+        // Although hours, minutes and seconds are mandatory, they can sometimes be omitted 
+        // if a TZ is specified... !!??
+        failure(MAPPER, "2000-01-02T+01:00");
+        failure(MAPPER, "2000-01-02T03+01:00");
+        failure(MAPPER, "2000-01-02T03:+01:00");
+        verify( MAPPER, "2000-01-02T03:04+01:00",   judate(2000, 1, 2,   3, 4, 0, 0, "GMT+1"));    // FIXME should be refused
+        failure(MAPPER, "2000-01-02T03:04:+01:00");
+        
+        failure(MAPPER, "2000-01-02TZ");
+        failure(MAPPER, "2000-01-02T03Z");
+        failure(MAPPER, "2000-01-02T03:Z");
+        failure(MAPPER, "2000-01-02T03:04Z");
+        failure(MAPPER, "2000-01-02T03:04:Z");
+
+        
+        // ---------------------------------------------------------------------------------------------
+        // WARNING:
+        //   ISO8601 (https://en.wikipedia.org/wiki/ISO_8601#Times) and its RFC339 profile 
+        //   (https://tools.ietf.org/html/rfc3339, chapter 5.6) seem to require 2 DIGITS for 
+        //   the hours, minutes and seconds.
+        //
+        //   The following forms should therefore be refused but are accepted by Jackson (and 
+        //   java.text.SimpleDateFormat). They are verified here to detect any changes in future
+        //   releases.
+        //
+        // ---------------------------------------------------------------------------------------------
+        
+        // FIXME As highlighted in the tests below, the behaviour is not consistent and largely 
+        // depends on wether a timezone and or millis are specified or not.
+        // The tests assert the behavior with different number of digits for hour, min and sec.
+        // Behavior should be the SAME whatever the timezone and/or the millis.
+        
+        // seconds (no TZ)
+        verify( MAPPER, "2000-01-02T03:04:5",           judate(2000, 1, 2,   3, 4, 5, 0, LOCAL_TZ));
+        verify( MAPPER, "2000-01-02T03:04:5.000",       judate(2000, 1, 2,   3, 4, 5, 0, LOCAL_TZ));
+        failure(MAPPER, "2000-01-02T03:04:005");
+        
+        // seconds (+01:00)
+        failure(MAPPER, "2000-01-02T03:04:5+01:00");
+        failure(MAPPER, "2000-01-02T03:04:5.000+01:00");
+        failure(MAPPER, "2000-01-02T03:04:005+01:00");
+        
+        // seconds (Z)
+        failure(MAPPER, "2000-01-02T03:04:5Z");
+        verify( MAPPER, "2000-01-02T03:04:5.000Z",      judate(2000, 1, 2,   3, 4, 5, 0, "UTC"));
+        failure(MAPPER, "2000-01-02T03:04:005Z");
+        
+
+        // minutes (no TZ)
+        verify( MAPPER, "2000-01-02T03:4:05",           judate(2000, 1, 2,   3, 4, 5, 0, LOCAL_TZ));
+        verify( MAPPER, "2000-01-02T03:4:05.000",       judate(2000, 1, 2,   3, 4, 5, 0, LOCAL_TZ));
+        failure(MAPPER, "2000-01-02T03:004:05");
+        
+        // minutes (+01:00)
+        failure(MAPPER, "2000-01-02T03:4:05+01:00");
+        failure(MAPPER, "2000-01-02T03:4:05.000+01:00");
+        failure(MAPPER, "2000-01-02T03:004:05+01:00");
+        
+        // minutes (Z)
+        verify( MAPPER, "2000-01-02T03:4:05Z",          judate(2000, 1, 2,   3, 4, 5, 0, "UTC"));
+        verify( MAPPER, "2000-01-02T03:4:05.000Z",      judate(2000, 1, 2,   3, 4, 5, 0, "UTC"));
+        verify( MAPPER, "2000-01-02T03:004:05Z",        judate(2000, 1, 2,   3, 4, 5, 0, "UTC"));
+
+
+        // hour (no TZ)
+        verify( MAPPER, "2000-01-02T3:04:05",           judate(2000, 1, 2,   3, 4, 5, 0, LOCAL_TZ));
+        verify( MAPPER, "2000-01-02T3:04:05.000",       judate(2000, 1, 2,   3, 4, 5, 0, LOCAL_TZ));
+        failure(MAPPER, "2000-01-02T003:04:05");
+
+        // hour (+01:00)
+        failure(MAPPER, "2000-01-02T3:04:05+01:00");
+        failure(MAPPER, "2000-01-02T3:04:05.000+01:00");
+        failure(MAPPER, "2000-01-02T003:04:05+01:00");
+
+        // hour (Z)
+        verify( MAPPER, "2000-01-02T3:04:05Z",         judate(2000, 1, 2,   3, 4, 5, 0, "UTC"));
+        verify( MAPPER, "2000-01-02T3:04:05.000Z",     judate(2000, 1, 2,   3, 4, 5, 0, "UTC"));
+        verify( MAPPER, "2000-01-02T003:04:05Z",       judate(2000, 1, 2,   3, 4, 5, 0, "UTC"));
+    }
+
+
+    /**
+     * Date-only representations (no Time part)
+     * 
+     * NOTE: time part is not tested here since they it is covered by another test case
+     */
+    public void testDateUtilISO8601_Date() throws Exception
+    {
+        // Date is constructed with the timezone of the ObjectMapper. Time part is set to zero.
+        verify(MAPPER, "2000-01-02", judate(2000, 1, 2,   0, 0, 0, 0, LOCAL_TZ));
+        
+        
+        // ---------------------------------------------------------------------------------------------
+        // WARNING:
+        //   ISO8601 (https://en.wikipedia.org/wiki/ISO_8601#Times) and its RFC339 profile 
+        //   (https://tools.ietf.org/html/rfc3339, chapter 5.6) seem to require 2 DIGITS for 
+        //   the month and dayofweek but 4 DIGITS for the year.
+        //
+        //   The following forms should therefore be refused but are accepted by Jackson (and 
+        //   java.text.SimpleDateFormat). They are verified here to detect any changes in future
+        //   releases.
+        // ---------------------------------------------------------------------------------------------
+
+        // day
+        verify(  MAPPER, "2000-01-2",      judate(2000, 1, 2,   0, 0, 0, 0, LOCAL_TZ));
+        failure( MAPPER, "2000-01-002");
+        
+        // month
+        verify(  MAPPER, "2000-1-02",      judate(2000, 1, 2,   0, 0, 0, 0, LOCAL_TZ));
+        failure( MAPPER, "2000-001-02");
+        
+        // year
+        failure( MAPPER, "20000-01-02");
+        failure( MAPPER, "200-01-02"  );
+        failure( MAPPER, "20-01-02"   );
+        verify(  MAPPER, "2-01-02",        judate(2, 1, 2,   0, 0, 0, 0, LOCAL_TZ));    // FIXME Why accept 1 digit and refuse they other cases??
+    }
+
+
+    /**
+     * DateTime as numeric representation
+     */
+    public void testDateUtil_Numeric() throws Exception
+    {
+        {
+            long now = 123456789L;
+            verify( MAPPER,                now, new java.util.Date(now) ); // as a long
+            verify( MAPPER, Long.toString(now), new java.util.Date(now) ); // as a string
+        }
+        {
+            /* As of 1.5.0, should be ok to pass as JSON String, as long
+             * as it is plain timestamp (all numbers, 64-bit)
+             */
+            long now = 1321992375446L;
+            verify( MAPPER,                now, new java.util.Date(now) );    // as a long
+            verify( MAPPER, Long.toString(now), new java.util.Date(now) );  // as a string
+        }
+        {
+            // #267: should handle negative timestamps too; like 12 hours before 1.1.1970
+            long now = - (24 * 3600 * 1000L);
+            verify( MAPPER,                now, new java.util.Date(now) );    // as a long
+            verify( MAPPER, Long.toString(now), new java.util.Date(now) );  // as a string
+        }
+
+        // value larger than a long (Long.MAX_VALUE+1)
+        BigInteger tooLarge = BigInteger.valueOf(Long.MAX_VALUE).add( BigInteger.valueOf(1) );
+        failure(MAPPER, tooLarge, JsonParseException.class);    // FIXME: InvalidFormatException is thrown everywhere else...
+        failure(MAPPER, tooLarge.toString());
+
+        // decimal value
+        failure(MAPPER, 0.0, JsonMappingException.class);        // FIXME: InvalidFormatException is thrown everywhere else...
+        failure(MAPPER, "0.0");
+    }
+
+
+    /**
+     * Note: may be these cases are already covered by {@link #testDateUtil_Annotation_PatternAndLocale()}
+     */
+    public void testDateUtil_Annotation() throws Exception
+    {
+        // Build the input JSON and expected value
+        String json = aposToQuotes("{'date':'/2005/05/25/'}");
+        java.util.Date expected = judate(2005, 05, 25, 0, 0, 0, 0, LOCAL_TZ);
+        
+        
+        // Read it to make sure the format specified by the annotation is taken into account
+        {
+            DateAsStringBean result = MAPPER.readValue(json, DateAsStringBean.class);
+            assertNotNull(result);
+            assertEquals( expected, result.date );
+        }
+        {
+            DateAsStringBean result = MAPPER.readerFor(DateAsStringBean.class)
+                    .with(Locale.GERMANY)
+                    .readValue(json);
+            assertNotNull(result);
+            assertEquals( expected, result.date );
+        }
+        
+        // or, via annotations
+        {
+            DateAsStringBeanGermany result = MAPPER.readerFor(DateAsStringBeanGermany.class)
+                                                   .readValue(json);
+            assertNotNull(result);
+            assertEquals( expected, result.date );
+        }
+    }
+
+    /**
+     * Test a POJO annotated with @JsonFormat to force an pattern.
+     * Alternate with different combination of Locale and TimeZone.
+     */
+    public void testDateUtil_Annotation_PatternAndLocale() throws Exception
+    {
+        // Change the default locale set on the ObjectMapper to something else than the default.
+        // This way we know if the default is correctly taken into account
+        ObjectMapper mapper = MAPPER.copy();
+        mapper.setLocale( Locale.ITALY );
+
+        // Build the JSON string. This is a mixed of ITALIAN and FRENCH (no ENGLISH because this 
+        // would be the default).
+        String json = aposToQuotes("{ 'pattern': '*1 giu 2000 01:02:03*', 'pattern_FR': '*01 juin 2000 01:02:03*', 'pattern_GMT4': '*1 giu 2000 01:02:03*', 'pattern_FR_GMT4': '*1 juin 2000 01:02:03*'}");
+        Annot_Pattern result = mapper.readValue(json, Annot_Pattern.class);
+
+        assertNotNull(result);
+        assertEquals( judate(2000, 6, 1, 1, 2, 3, 0, LOCAL_TZ), result.pattern        );
+        assertEquals( judate(2000, 6, 1, 1, 2, 3, 0, LOCAL_TZ), result.pattern_FR     );
+        assertEquals( judate(2000, 6, 1, 1, 2, 3, 0, "GMT+4"),  result.pattern_GMT4    );
+        assertEquals( judate(2000, 6, 1, 1, 2, 3, 0, "GMT+4"),  result.pattern_FR_GMT4 );
+    }
+
+    /**
+     * Test a POJO annotated with @JsonFormat to force a default TimeZone
+     * other than the one set on the ObjectMapper when the JSON doesn't contain any.
+     */
+    public void testDateUtil_Annotation_TimeZone() throws Exception
+    {
+        // WITHOUT timezone
+        {
+            String json = aposToQuotes("{ 'date': '2000-01-02T03:04:05.678' }");
+            Annot_TimeZone result = MAPPER.readValue(json, Annot_TimeZone.class);
+            
+            assertNotNull(result);
+            assertEquals( judate(2000, 1, 2, 3, 4, 5, 678, "GMT+4"), result.date);
+        }
+        
+        // WITH timezone
+        //   --> the annotation acts as the "default" timezone. The timezone specified
+        //       in the JSON should be considered first.
+        {
+            String json = aposToQuotes("{ 'date': '2000-01-02T03:04:05.678+01:00' }");
+            Annot_TimeZone result = MAPPER.readValue(json, Annot_TimeZone.class);
+            
+            assertNotNull(result);
+            assertEquals( judate(2000, 1, 2, 3, 4, 5, 678, "GMT+1"), result.date);
+        }
+    }
+
+    /**
+     * ObjectMapper configured with a custom date format that does NOT handle the TIMEZONE.
+     * Dates must be constructed with the time zone set on the ObjectMapper.
+     */
+    public void testDateUtil_customDateFormat_withoutTZ() throws Exception
+    {
+        // FIXME
+        //
+        // The general rule with the StdDateFormat is:
+        //     the TimeZone of the ObjectMapper is used if the JSON doesn't hold
+        //     any timezone/offset information.
+        //
+        // This rule remains valid with the @JsonFormat annotation unless it forces
+        // an explicit timezeone, in which case the latter takes precedence.
+        //
+        // One would expect the same behavior when the StdDateFormat is replaced by a 
+        // custom DateFormat on the ObjectMapper. In other words, the timezone of the 
+        // DateFormat is of no importance: the ObjectMapper's default should be used
+        // whenever it is needed.
+        
+        
+        // Test first with a non default TZ on the ObjectMapper
+        // --> OK: the mapper's default TZ is used to parse the date.
+        {
+            DateFormat df = new SimpleDateFormat("yyyy-MM-dd'X'HH:mm:ss");
+            df.setTimeZone( TimeZone.getTimeZone("GMT+4") );    // TZ different from mapper's default
+            
+            ObjectMapper mapper = new ObjectMapper();
+            mapper.setTimeZone( TimeZone.getTimeZone(LOCAL_TZ) );
+            mapper.setDateFormat(df);
+            
+            // The mapper's default TZ is used...
+            verify(mapper, "2000-01-02X04:00:00", judate(2000, 1, 2, 4, 00, 00, 00, LOCAL_TZ));
+        }
+        
+        // Test a second time with the default TZ on the ObjectMapper
+        // Note it is important NOT TO CALL mapper.setTimeZone(...) in this test..
+        // --> KO: the custom format's TZ is used instead of the mapper's default as above.
+        //
+        {
+            DateFormat df = new SimpleDateFormat("yyyy-MM-dd'X'HH:mm:ss");
+            df.setTimeZone( TimeZone.getTimeZone("GMT+4") );    // TZ different from mapper's default
+            
+            ObjectMapper mapper = new ObjectMapper();
+            mapper.setDateFormat(df);
+            
+            // FIXME mapper's default TZ should have been used
+            verify(mapper, "2000-01-02X04:00:00", judate(2000, 1, 2, 4, 00, 00, 00, "GMT+4"));
+        }
+    }
+
+    /**
+     * ObjectMapper configured with a custom date format that DOES handle the TIMEZONE.
+     * Dates must be constructed from the timezone of the input, regardless of the one
+     * of the ObjectMapper.
+     */
+    public void testDateUtil_customDateFormat_withTZ() throws Exception
+    {
+        ObjectMapper mapper = new ObjectMapper();
+        DateFormat df = new SimpleDateFormat("yyyy-MM-dd'X'HH:mm:ssZ");
+        df.setTimeZone(TimeZone.getTimeZone("GMT+4"));    // use a timezone different than the ObjectMapper and the system default
+        mapper.setDateFormat(df);
+
+        verify(mapper, "2000-01-02X03:04:05+0300", judate(2000, 1, 2, 3, 4, 5, 00, "GMT+3"));
+    }
+
+    /*
+    /**********************************************************
+    /* Helper methods
+    /**********************************************************
+     */
+
+    /**
+     * Create a {@link java.util.Date} with all the fields set to the given value.
+     * 
+     * @param year year
+     * @param month month (1-12)
+     * @param day day of month (1-31)
+     * @param hour hour (0-23)
+     * @param minutes minutes (0-59)
+     * @param seconds seconds (0-59)
+     * @param millis millis
+     * @param tz timezone id as accepted by {@link TimeZone#getTimeZone(String)}
+     * @return a new {@link Date} instance
+     */
+    private static Date judate(int year, int month, int day, int hour, int minutes, int seconds, int millis, String tz) 
+    {
+        Calendar cal = Calendar.getInstance();
+        cal.setLenient(false);
+        cal.set(year, month-1, day, hour, minutes, seconds);
+        cal.set(Calendar.MILLISECOND, millis);
+        cal.setTimeZone(TimeZone.getTimeZone(tz));
+        
+        return cal.getTime();
+    }
+
+    private static void verify(ObjectMapper mapper, Object input, Date expected) throws Exception {
+        // Deserialize using the supplied ObjectMapper
+        Date actual = read(mapper, input, java.util.Date.class);
+
+        // Test against the expected
+        if( expected==null && actual==null) {
+            return;
+        }
+        if( expected==null && actual != null) {
+            fail("Failed to deserialize "+input+", actual: '"+FORMAT.format(actual)+"', expected: <null>'");
+        }
+        if( expected != null && actual == null ) {
+            fail("Failed to deserialize "+input+", actual: <null>, expected: '"+FORMAT.format(expected)+"'");
+        }
+        if( actual.getTime() != expected.getTime() ) {
+            fail("Failed to deserialize "+input+", actual: '"+FORMAT.format(actual)+"', expected: '"+FORMAT.format(expected)+"'");
+        }
+    }
+
+    private static void failure(ObjectMapper mapper, Object input) throws Exception {
+        failure(mapper, input, InvalidFormatException.class);
+    }
+
+    private static void failure(ObjectMapper mapper, Object input, Class<? extends Exception> exceptionType) throws Exception {
+        try {
+            Date date = read(mapper, input, java.util.Date.class);
+            fail("Input "+input+" should not have been accepted but was deserialized into "+FORMAT.format(date));
+        }
+        catch(Exception e) {
+            // Is it the expected exception ?
+            if( ! exceptionType.isAssignableFrom(e.getClass()) ) {
+                fail("Wrong exception thrown when reading "+input+", actual: "+e.getClass().getName() + "("+e.getMessage()+"), expected: "+exceptionType.getName());
+            }
+        }
+    }
+
+    private static <T> T read(ObjectMapper mapper, Object input, Class<T> type) throws Exception {
+        // Construct the json representation from the input
+        String json = input.toString();
+        if( !(input instanceof Number) ) {
+            json = "\""+json+"\"";
+        }
+
+        // Deserialize using the supplied ObjectMapper
+        return (T) mapper.readValue(json, type);
+    }
+}
diff --git a/src/test/java/com/fasterxml/jackson/databind/deser/EnumDefaultReadTest.java b/src/test/java/com/fasterxml/jackson/databind/deser/EnumDefaultReadTest.java
new file mode 100644
index 0000000..f1ef94f
--- /dev/null
+++ b/src/test/java/com/fasterxml/jackson/databind/deser/EnumDefaultReadTest.java
@@ -0,0 +1,229 @@
+package com.fasterxml.jackson.databind.deser;
+
+import java.io.IOException;
+
+import com.fasterxml.jackson.annotation.*;
+
+import com.fasterxml.jackson.databind.*;
+import com.fasterxml.jackson.databind.exc.InvalidFormatException;
+
+public class EnumDefaultReadTest extends BaseMapTest
+{
+    enum SimpleEnum {
+        ZERO,
+        ONE;
+    }
+    
+    enum SimpleEnumWithDefault {
+        @JsonEnumDefaultValue
+        ZERO,
+        ONE;
+    }
+    
+    enum CustomEnum {
+        ZERO(0),
+        ONE(1);
+    
+        private final int number;
+    
+        CustomEnum(final int number) {
+            this.number = number;
+        }
+    
+        @JsonValue
+        int getNumber() {
+            return this.number;
+        }
+    }
+
+    enum CustomEnumWithDefault {
+        @JsonEnumDefaultValue
+        ZERO(0),
+        ONE(1);
+    
+        private final int number;
+    
+        CustomEnumWithDefault(final int number) {
+            this.number = number;
+        }
+    
+        @JsonValue
+        int getNumber() {
+            return this.number;
+        }
+    }
+
+    /*
+    /**********************************************************
+    /* Test methods
+    /**********************************************************
+     */
+    private final ObjectMapper MAPPER = new ObjectMapper();
+
+    public void testWithoutCustomFeatures() throws Exception
+    {
+        final ObjectReader r = MAPPER.reader();
+
+        _verifyOkDeserialization(r, "ZERO", SimpleEnum.class, SimpleEnum.ZERO);
+        _verifyOkDeserialization(r, "ONE", SimpleEnum.class, SimpleEnum.ONE);
+        _verifyOkDeserialization(r, "0", SimpleEnum.class, SimpleEnum.ZERO);
+        _verifyOkDeserialization(r, "1", SimpleEnum.class, SimpleEnum.ONE);
+        _verifyFailingDeserialization(r, "TWO", SimpleEnum.class);
+        _verifyFailingDeserialization(r, "2", SimpleEnum.class);
+
+        _verifyOkDeserialization(r, "ZERO", SimpleEnumWithDefault.class, SimpleEnumWithDefault.ZERO);
+        _verifyOkDeserialization(r, "ONE", SimpleEnumWithDefault.class, SimpleEnumWithDefault.ONE);
+        _verifyFailingDeserialization(r, "TWO", SimpleEnumWithDefault.class);
+        _verifyOkDeserialization(r, "0", SimpleEnumWithDefault.class, SimpleEnumWithDefault.ZERO);
+        _verifyOkDeserialization(r, "1", SimpleEnumWithDefault.class, SimpleEnumWithDefault.ONE);
+        _verifyFailingDeserialization(r, "2", SimpleEnumWithDefault.class);
+
+        _verifyFailingDeserialization(r, "ZERO", CustomEnum.class);
+        _verifyFailingDeserialization(r, "ONE", CustomEnum.class);
+        _verifyFailingDeserialization(r, "TWO", CustomEnum.class);
+        _verifyOkDeserialization(r, "0", CustomEnum.class, CustomEnum.ZERO);
+        _verifyOkDeserialization(r, "1", CustomEnum.class, CustomEnum.ONE);
+        _verifyFailingDeserialization(r, "2", CustomEnum.class);
+
+        _verifyFailingDeserialization(r, "ZERO", CustomEnumWithDefault.class);
+        _verifyFailingDeserialization(r, "ONE", CustomEnumWithDefault.class);
+        _verifyFailingDeserialization(r, "TWO", CustomEnumWithDefault.class);
+        _verifyOkDeserialization(r, "0", CustomEnumWithDefault.class, CustomEnumWithDefault.ZERO);
+        _verifyOkDeserialization(r, "1", CustomEnumWithDefault.class, CustomEnumWithDefault.ONE);
+        _verifyFailingDeserialization(r, "2", CustomEnumWithDefault.class);
+    }
+
+    public void testWithFailOnNumbers() throws Exception
+    {
+        ObjectReader r = MAPPER.reader()
+                .with(DeserializationFeature.FAIL_ON_NUMBERS_FOR_ENUMS);
+
+        _verifyOkDeserialization(r, "ZERO", SimpleEnum.class, SimpleEnum.ZERO);
+        _verifyOkDeserialization(r, "ONE", SimpleEnum.class, SimpleEnum.ONE);
+        _verifyFailingDeserialization(r, "TWO", SimpleEnum.class);
+        _verifyFailingDeserialization(r, "0", SimpleEnum.class);
+        _verifyFailingDeserialization(r, "1", SimpleEnum.class);
+        _verifyFailingDeserialization(r, "2", SimpleEnum.class);
+
+        _verifyOkDeserialization(r, "ZERO", SimpleEnumWithDefault.class, SimpleEnumWithDefault.ZERO);
+        _verifyOkDeserialization(r, "ONE", SimpleEnumWithDefault.class, SimpleEnumWithDefault.ONE);
+        _verifyFailingDeserialization(r, "TWO", SimpleEnumWithDefault.class);
+        _verifyFailingDeserialization(r, "0", SimpleEnumWithDefault.class);
+        _verifyFailingDeserialization(r, "1", SimpleEnumWithDefault.class);
+        _verifyFailingDeserialization(r, "2", SimpleEnumWithDefault.class);
+
+        _verifyFailingDeserialization(r, "ZERO", CustomEnum.class);
+        _verifyFailingDeserialization(r, "ONE", CustomEnum.class);
+        _verifyFailingDeserialization(r, "TWO", CustomEnum.class);
+        _verifyOkDeserialization(r, "0", CustomEnum.class, CustomEnum.ZERO);
+        _verifyOkDeserialization(r, "1", CustomEnum.class, CustomEnum.ONE);
+        _verifyFailingDeserialization(r, "2", CustomEnum.class);
+
+        _verifyFailingDeserialization(r, "ZERO", CustomEnumWithDefault.class);
+        _verifyFailingDeserialization(r, "ONE", CustomEnumWithDefault.class);
+        _verifyFailingDeserialization(r, "TWO", CustomEnumWithDefault.class);
+        _verifyOkDeserialization(r, "0", CustomEnumWithDefault.class, CustomEnumWithDefault.ZERO);
+        _verifyOkDeserialization(r, "1", CustomEnumWithDefault.class, CustomEnumWithDefault.ONE);
+        _verifyFailingDeserialization(r, "2", CustomEnumWithDefault.class);
+    }
+
+    public void testWithReadUnknownAsDefault() throws Exception
+    {
+        ObjectReader r = MAPPER.reader()
+                .with(DeserializationFeature.READ_UNKNOWN_ENUM_VALUES_USING_DEFAULT_VALUE);
+
+        _verifyOkDeserialization(r, "ZERO", SimpleEnum.class, SimpleEnum.ZERO);
+        _verifyOkDeserialization(r, "ONE", SimpleEnum.class, SimpleEnum.ONE);
+        _verifyFailingDeserialization(r, "TWO", SimpleEnum.class);
+        _verifyOkDeserialization(r, "0", SimpleEnum.class, SimpleEnum.ZERO);
+        _verifyOkDeserialization(r, "1", SimpleEnum.class, SimpleEnum.ONE);
+        _verifyFailingDeserialization(r, "2", SimpleEnum.class);
+
+        _verifyOkDeserialization(r, "ZERO", SimpleEnumWithDefault.class, SimpleEnumWithDefault.ZERO);
+        _verifyOkDeserialization(r, "ONE", SimpleEnumWithDefault.class, SimpleEnumWithDefault.ONE);
+        _verifyOkDeserialization(r, "TWO", SimpleEnumWithDefault.class, SimpleEnumWithDefault.ZERO);
+        _verifyOkDeserialization(r, "0", SimpleEnumWithDefault.class, SimpleEnumWithDefault.ZERO);
+        _verifyOkDeserialization(r, "1", SimpleEnumWithDefault.class, SimpleEnumWithDefault.ONE);
+        _verifyOkDeserialization(r, "2", SimpleEnumWithDefault.class, SimpleEnumWithDefault.ZERO);
+
+        _verifyFailingDeserialization(r, "ZERO", CustomEnum.class);
+        _verifyFailingDeserialization(r, "ONE", CustomEnum.class);
+        _verifyFailingDeserialization(r, "TWO", CustomEnum.class);
+        _verifyOkDeserialization(r, "0", CustomEnum.class, CustomEnum.ZERO);
+        _verifyOkDeserialization(r, "1", CustomEnum.class, CustomEnum.ONE);
+        _verifyFailingDeserialization(r, "2", CustomEnum.class);
+
+        _verifyOkDeserialization(r, "ZERO", CustomEnumWithDefault.class, CustomEnumWithDefault.ZERO);
+        _verifyOkDeserialization(r, "ONE", CustomEnumWithDefault.class, CustomEnumWithDefault.ZERO);
+        _verifyOkDeserialization(r, "TWO", CustomEnumWithDefault.class, CustomEnumWithDefault.ZERO);
+        _verifyOkDeserialization(r, "0", CustomEnumWithDefault.class, CustomEnumWithDefault.ZERO);
+        _verifyOkDeserialization(r, "1", CustomEnumWithDefault.class, CustomEnumWithDefault.ONE);
+        _verifyOkDeserialization(r, "2", CustomEnumWithDefault.class, CustomEnumWithDefault.ZERO);
+    }
+
+    public void testWithFailOnNumbersAndReadUnknownAsDefault()
+        throws Exception
+    {
+        ObjectReader r = MAPPER.reader()
+                          .with(DeserializationFeature.FAIL_ON_NUMBERS_FOR_ENUMS)
+                          .with(DeserializationFeature.READ_UNKNOWN_ENUM_VALUES_USING_DEFAULT_VALUE);
+
+        _verifyOkDeserialization(r, "ZERO", SimpleEnum.class, SimpleEnum.ZERO);
+        _verifyOkDeserialization(r, "ONE", SimpleEnum.class, SimpleEnum.ONE);
+
+        _verifyFailingDeserialization(r, "TWO", SimpleEnum.class);
+        _verifyFailingDeserialization(r, "0", SimpleEnum.class);
+        _verifyFailingDeserialization(r, "1", SimpleEnum.class);
+        _verifyFailingDeserialization(r, "2", SimpleEnum.class);
+
+        _verifyOkDeserialization(r, "ZERO", SimpleEnumWithDefault.class, SimpleEnumWithDefault.ZERO);
+        _verifyOkDeserialization(r, "ONE", SimpleEnumWithDefault.class, SimpleEnumWithDefault.ONE);
+        _verifyOkDeserialization(r, "TWO", SimpleEnumWithDefault.class, SimpleEnumWithDefault.ZERO);
+
+        _verifyFailingDeserialization(r, "ZERO", CustomEnum.class);
+        _verifyFailingDeserialization(r, "ONE", CustomEnum.class);
+        _verifyFailingDeserialization(r, "TWO", CustomEnum.class);
+
+        _verifyOkDeserialization(r, "0", CustomEnum.class, CustomEnum.ZERO);
+        _verifyOkDeserialization(r, "1", CustomEnum.class, CustomEnum.ONE);
+
+        _verifyFailingDeserialization(r, "2", CustomEnum.class);
+
+        _verifyOkDeserialization(r, "ZERO", CustomEnumWithDefault.class, CustomEnumWithDefault.ZERO);
+        _verifyOkDeserialization(r, "ONE", CustomEnumWithDefault.class, CustomEnumWithDefault.ZERO);
+        _verifyOkDeserialization(r, "TWO", CustomEnumWithDefault.class, CustomEnumWithDefault.ZERO);
+        _verifyOkDeserialization(r, "0", CustomEnumWithDefault.class, CustomEnumWithDefault.ZERO);
+        _verifyOkDeserialization(r, "1", CustomEnumWithDefault.class, CustomEnumWithDefault.ONE);
+
+        // 
+        // The three tests below fail; Jackson throws an exception on the basis that
+        // "FAIL_ON_NUMBERS_FOR_ENUMS" is enabled. I claim the default value should be returned instead.
+        _verifyOkDeserialization(r, "0", SimpleEnumWithDefault.class, SimpleEnumWithDefault.ZERO);
+        _verifyOkDeserialization(r, "1", SimpleEnumWithDefault.class, SimpleEnumWithDefault.ZERO);
+        _verifyOkDeserialization(r, "2", SimpleEnumWithDefault.class, SimpleEnumWithDefault.ZERO);
+        
+        // Fails. Jackson throws an exception on the basis that "FAIL_ON_NUMBERS_FOR_ENUMS"
+        // is enabled, but the default value should have been returned instead.
+        _verifyOkDeserialization(r, "2", CustomEnumWithDefault.class, CustomEnumWithDefault.ZERO);
+    }
+
+    private <T> void _verifyOkDeserialization(ObjectReader reader, String fromValue,
+            Class<T> toValueType, T expValue)
+        throws IOException
+    {
+        assertEquals(expValue, reader.forType(toValueType).readValue(quote(fromValue)));
+    }
+
+    private <T> void _verifyFailingDeserialization(final ObjectReader reader,
+            final String fromValue, final Class<T> toValueType)
+        throws IOException
+    {
+        try {
+            reader.forType(toValueType).readValue(quote(fromValue));
+            fail("Deserialization should have failed");
+        } catch (InvalidFormatException e) {
+            verifyException(e, "Can not deserialize value of type");
+            /* Expected. */
+        }
+    }
+}
diff --git a/src/test/java/com/fasterxml/jackson/databind/deser/TestEnumDeserialization.java b/src/test/java/com/fasterxml/jackson/databind/deser/EnumDeserializationTest.java
similarity index 68%
rename from src/test/java/com/fasterxml/jackson/databind/deser/TestEnumDeserialization.java
rename to src/test/java/com/fasterxml/jackson/databind/deser/EnumDeserializationTest.java
index 752cd5e..a1b6782 100644
--- a/src/test/java/com/fasterxml/jackson/databind/deser/TestEnumDeserialization.java
+++ b/src/test/java/com/fasterxml/jackson/databind/deser/EnumDeserializationTest.java
@@ -1,7 +1,6 @@
 package com.fasterxml.jackson.databind.deser;
 
 import java.io.IOException;
-import java.math.BigDecimal;
 import java.util.*;
 import java.util.concurrent.TimeUnit;
 
@@ -10,13 +9,12 @@
 import com.fasterxml.jackson.core.type.TypeReference;
 import com.fasterxml.jackson.databind.*;
 import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
-import com.fasterxml.jackson.databind.deser.std.EnumDeserializer;
+import com.fasterxml.jackson.databind.deser.std.FromStringDeserializer;
 import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
-import com.fasterxml.jackson.databind.introspect.AnnotatedMethod;
 import com.fasterxml.jackson.databind.module.SimpleModule;
 
 @SuppressWarnings("serial")
-public class TestEnumDeserialization
+public class EnumDeserializationTest
     extends BaseMapTest
 {
     enum TestEnum { JACKSON, RULES, OK; }
@@ -48,28 +46,6 @@
             return TestEnum.valueOf(jp.getText().toUpperCase());
         }
     }
-
-    protected enum EnumWithCreator {
-        A, B;
-
-        @JsonCreator
-        public static EnumWithCreator fromEnum(String str) {
-            if ("enumA".equals(str)) return A;
-            if ("enumB".equals(str)) return B;
-            return null;
-        }
-    }
-
-    protected enum EnumWithBDCreator {
-        E5, E8;
-
-        @JsonCreator
-        public static EnumWithBDCreator create(BigDecimal bd) {
-            if (bd.longValue() == 5L) return E5;
-            if (bd.longValue() == 8L) return E8;
-            return null;
-        }
-    }
     
     protected enum LowerCaseEnum {
         A, B, C;
@@ -93,61 +69,6 @@
         @JsonProperty Map<TestEnum, String> map;
     }
 
-    protected enum TestEnumFor834
-    {
-        ENUM_A(1), ENUM_B(2), ENUM_C(3);
-        
-        private final int id;
-        
-        private TestEnumFor834(int id) {
-            this.id = id;
-        }
-        
-        @JsonCreator public static TestEnumFor834 fromId(int id) {
-            for (TestEnumFor834 e: values()) {
-                if (e.id == id) return e;
-            }
-            return null;
-        }
-    }
-
-    // [Issue#324]: exception from creator method
-    protected enum TestEnum324
-    {
-        A, B;
-        
-        @JsonCreator public static TestEnum324 creator(String arg) {
-            throw new RuntimeException("Foobar!");
-        }
-    }
-
-    // [databind#745]
-    static class DelegatingDeserializers extends Deserializers.Base
-    {
-        @Override
-        public JsonDeserializer<?> findEnumDeserializer(final Class<?> type, final DeserializationConfig config, final BeanDescription beanDesc) throws JsonMappingException {
-            final Collection<AnnotatedMethod> factoryMethods = beanDesc.getFactoryMethods();
-            if (factoryMethods != null) {
-                for (AnnotatedMethod am : factoryMethods) {
-                    final JsonCreator creator = am.getAnnotation(JsonCreator.class);
-                    if (creator != null) {
-                        return EnumDeserializer.deserializerForCreator(config, type, am);
-                    }
-                }
-            }
-            return null;
-        }
-    }
-
-    // [databind#745]
-    static class DelegatingDeserializersModule extends SimpleModule
-    {
-        @Override
-        public void setupModule(final SetupContext context) {
-            context.addDeserializers(new DelegatingDeserializers());
-        }
-    }
-
     // [databind#677]
     static enum EnumWithPropertyAnno {
         @JsonProperty("a")
@@ -173,10 +94,96 @@
             return name().toLowerCase();
         };
     }
+
+    static enum EnumWithDefaultAnno {
+        A, B,
+
+        @JsonEnumDefaultValue
+        OTHER;
+    }
+
+    static enum EnumWithDefaultAnnoAndConstructor {
+        A, B,
+
+        @JsonEnumDefaultValue
+        OTHER;
+
+        @JsonCreator public static EnumWithDefaultAnnoAndConstructor fromId(String value) {
+            for (EnumWithDefaultAnnoAndConstructor e: values()) {
+                if (e.name().toLowerCase().equals(value)) return e;
+            }
+            return null;
+        }
+    }
+
+    // // 
     
+    public enum AnEnum {
+        ZERO,
+        ONE
+    }
+
+    public static class AnEnumDeserializer extends FromStringDeserializer<AnEnum> {
+
+        public AnEnumDeserializer() {
+            super(AnEnum.class);
+        }
+
+        @Override
+        protected AnEnum _deserialize(String value, DeserializationContext ctxt) throws IOException {
+            try {
+                return AnEnum.valueOf(value);
+            } catch (IllegalArgumentException e) {
+                return (AnEnum) ctxt.handleWeirdStringValue(AnEnum.class, value,
+                        "Undefined AnEnum code");
+            }
+        }
+    }
+
+    public static class AnEnumKeyDeserializer extends KeyDeserializer {
+
+        @Override
+        public Object deserializeKey(String key, DeserializationContext ctxt) throws IOException {
+            try {
+                return AnEnum.valueOf(key);
+            } catch (IllegalArgumentException e) {
+                return ctxt.handleWeirdKey(AnEnum.class, key, "Undefined AnEnum code");
+            }
+        }
+    }
+
+
+    @JsonDeserialize(using = AnEnumDeserializer.class, keyUsing = AnEnumKeyDeserializer.class)
+    public enum LanguageCodeMixin {
+    }
+
+    public static class EnumModule extends SimpleModule {
+        @Override
+        public void setupModule(SetupContext context) {
+            context.setMixInAnnotations(AnEnum.class, LanguageCodeMixin.class);
+        }
+
+        public static ObjectMapper setupObjectMapper(ObjectMapper mapper) {
+            final EnumModule module = new EnumModule();
+            mapper.registerModule(module);
+            return mapper;
+        }
+    }
+
+    // [databind#1626]
+    enum NumberEnum {
+        @JsonProperty("2")
+        EN2,
+        @JsonProperty("0")
+        EN0,
+        @JsonProperty("1")
+        EN1
+        ;
+    }
+
     /*
     /**********************************************************
-    /* Tests
+    /* Test methods
     /**********************************************************
      */
 
@@ -200,12 +207,10 @@
         // and no more content beyond that...
         assertFalse(jp.hasCurrentToken());
 
-        /* Then alternative with index (0 means first entry)
-         */
+        // Then alternative with index (0 means first entry)
         assertEquals(TestEnum.JACKSON, MAPPER.readValue(" 0 ", TestEnum.class));
 
-        /* Then error case: unrecognized value
-         */
+        // Then error case: unrecognized value
         try {
             /*Object result =*/ MAPPER.readValue("\"NO-SUCH-VALUE\"", TestEnum.class);
             fail("Expected an exception for bogus enum value...");
@@ -252,16 +257,6 @@
         assertEquals(EnumWithSubClass.A, value);
     }
 
-    public void testCreatorEnums() throws Exception {
-        EnumWithCreator value = MAPPER.readValue("\"enumA\"", EnumWithCreator.class);
-        assertEquals(EnumWithCreator.A, value);
-    }
-
-    public void testCreatorEnumsFromBigDecimal() throws Exception {
-        EnumWithBDCreator value = MAPPER.readValue("\"8.0\"", EnumWithBDCreator.class);
-        assertEquals(EnumWithBDCreator.E8, value);
-    }
-
     public void testToStringEnums() throws Exception
     {
         // can't reuse global one due to reconfig
@@ -295,7 +290,8 @@
             value = r.readValue("1");
             fail("Expected an error");
         } catch (JsonMappingException e) {
-            verifyException(e, "Not allowed to deserialize Enum value out of JSON number");
+            verifyException(e, "Can not deserialize");
+            verifyException(e, "not allowed to deserialize Enum value out of number: disable");
         }
 
         // and [databind#684]
@@ -303,7 +299,9 @@
             value = r.readValue(quote("1"));
             fail("Expected an error");
         } catch (JsonMappingException e) {
-            verifyException(e, "Not allowed to deserialize Enum value out of JSON number");
+            verifyException(e, "Can not deserialize");
+            // 26-Jan-2017, tatu: as per [databind#1505], should fail bit differently
+            verifyException(e, "value not one of declared Enum");
         }
     }
 
@@ -341,25 +339,7 @@
         assertEquals(Integer.valueOf(13), map.get(EnumWithJsonValue.A));
     }
 
-    public void testEnumWithCreatorEnumMaps() throws Exception {
-          EnumMap<EnumWithCreator,String> value = MAPPER.readValue("{\"enumA\":\"value\"}",
-                  new TypeReference<EnumMap<EnumWithCreator,String>>() {});
-          assertEquals("value", value.get(EnumWithCreator.A));
-    }
-
-    public void testEnumWithCreatorMaps() throws Exception {
-          java.util.HashMap<EnumWithCreator,String> value = MAPPER.readValue("{\"enumA\":\"value\"}",
-                  new TypeReference<java.util.HashMap<EnumWithCreator,String>>() {});
-          assertEquals("value", value.get(EnumWithCreator.A));
-    }
-
-    public void testEnumWithCreatorEnumSets() throws Exception {
-          EnumSet<EnumWithCreator> value = MAPPER.readValue("[\"enumA\"]",
-                  new TypeReference<EnumSet<EnumWithCreator>>() {});
-          assertTrue(value.contains(EnumWithCreator.A));
-    }
-
-    // [JACKSON-810], ability to ignore unknown Enum values:
+    // Ability to ignore unknown Enum values:
 
     public void testAllowUnknownEnumValuesReadAsNull() throws Exception
     {
@@ -392,17 +372,10 @@
              MAPPER.readValue("{\"map\":{\"NO-SUCH-VALUE\":\"val\"}}", ClassWithEnumMapKey.class);
              fail("Expected an exception for bogus enum value...");
          } catch (JsonMappingException jex) {
-             verifyException(jex, "Can not construct Map key");
+             verifyException(jex, "Can not deserialize Map key of type com.fasterxml.jackson.databind.deser");
          }
     }
 
-    public void testEnumsFromInts() throws Exception
-    {
-        Object ob = MAPPER.readValue("1 ", TestEnumFor834.class);
-        assertEquals(TestEnumFor834.class, ob.getClass());
-        assertSame(TestEnumFor834.ENUM_A, ob);
-    }
-
     // [databind#141]: allow mapping of empty String into null
     public void testEnumsWithEmpty() throws Exception
     {
@@ -421,18 +394,7 @@
        // not sure this is totally safe but...
        assertEquals(TestEnum.JACKSON, mapper.readValue(quote("jackson"), TestEnum.class));
     }
-    
-    // [databind#324]
-    public void testExceptionFromCreator() throws Exception
-    {
-        try {
-            /*TestEnum324 e =*/ MAPPER.readValue(quote("xyz"), TestEnum324.class);
-            fail("Should throw exception");
-        } catch (JsonMappingException e) {
-            verifyException(e, "foobar");
-        }
-    }
-    
+
     // [databind#381]
     public void testUnwrappedEnum() throws Exception {
         final ObjectMapper mapper = new ObjectMapper();
@@ -445,10 +407,12 @@
         final ObjectMapper mapper = new ObjectMapper();
         mapper.disable(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS);
         try {
-            assertEquals(TestEnum.JACKSON, mapper.readValue("[" + quote("JACKSON") + "]", TestEnum.class));
-            fail("Exception was not thrown on deserializing a single array element of type enum");
+            Object v = mapper.readValue("[" + quote("JACKSON") + "]",
+                    TestEnum.class);
+            fail("Exception was not thrown on deserializing a single array element of type enum; instead got: "+v);
         } catch (JsonMappingException exp) {
             //exception as thrown correctly
+            verifyException(exp, "Can not deserialize");
         }
     }
 
@@ -464,16 +428,6 @@
         assertSame(TestEnum.values()[1], en);
     }
 
-    // [databind#745]
-    public void testDeserializerForCreatorWithEnumMaps() throws Exception
-    {
-        final ObjectMapper mapper = new ObjectMapper();
-        mapper.registerModule(new DelegatingDeserializersModule());
-        EnumMap<EnumWithCreator,String> value = mapper.readValue("{\"enumA\":\"value\"}",
-            new TypeReference<EnumMap<EnumWithCreator,String>>() {});
-        assertEquals("value", value.get(EnumWithCreator.A));
-    }
-
     public void testEnumWithJsonPropertyRename() throws Exception
     {
         String json = MAPPER.writeValueAsString(new EnumWithPropertyAnno[] {
@@ -506,4 +460,73 @@
                 .without(DeserializationFeature.READ_ENUMS_USING_TO_STRING)
                 .readValue(quote("A"));
         assertSame(Enum1161.A, result);
-    }}
+    }
+    
+    public void testEnumWithDefaultAnnotation() throws Exception {
+        final ObjectMapper mapper = new ObjectMapper();
+        mapper.enable(DeserializationFeature.READ_UNKNOWN_ENUM_VALUES_USING_DEFAULT_VALUE);
+
+        EnumWithDefaultAnno myEnum = mapper.readValue("\"foo\"", EnumWithDefaultAnno.class);
+        assertSame(EnumWithDefaultAnno.OTHER, myEnum);
+    }
+
+    public void testEnumWithDefaultAnnotationUsingIndexInBound1() throws Exception {
+        final ObjectMapper mapper = new ObjectMapper();
+        mapper.enable(DeserializationFeature.READ_UNKNOWN_ENUM_VALUES_USING_DEFAULT_VALUE);
+
+        EnumWithDefaultAnno myEnum = mapper.readValue("1", EnumWithDefaultAnno.class);
+        assertSame(EnumWithDefaultAnno.B, myEnum);
+    }
+
+    public void testEnumWithDefaultAnnotationUsingIndexInBound2() throws Exception {
+        final ObjectMapper mapper = new ObjectMapper();
+        mapper.enable(DeserializationFeature.READ_UNKNOWN_ENUM_VALUES_USING_DEFAULT_VALUE);
+
+        EnumWithDefaultAnno myEnum = mapper.readValue("2", EnumWithDefaultAnno.class);
+        assertSame(EnumWithDefaultAnno.OTHER, myEnum);
+    }
+
+    public void testEnumWithDefaultAnnotationUsingIndexSameAsLength() throws Exception {
+        final ObjectMapper mapper = new ObjectMapper();
+        mapper.enable(DeserializationFeature.READ_UNKNOWN_ENUM_VALUES_USING_DEFAULT_VALUE);
+
+        EnumWithDefaultAnno myEnum = mapper.readValue("3", EnumWithDefaultAnno.class);
+        assertSame(EnumWithDefaultAnno.OTHER, myEnum);
+    }
+
+    public void testEnumWithDefaultAnnotationUsingIndexOutOfBound() throws Exception {
+        final ObjectMapper mapper = new ObjectMapper();
+        mapper.enable(DeserializationFeature.READ_UNKNOWN_ENUM_VALUES_USING_DEFAULT_VALUE);
+
+        EnumWithDefaultAnno myEnum = mapper.readValue("4", EnumWithDefaultAnno.class);
+        assertSame(EnumWithDefaultAnno.OTHER, myEnum);
+    }
+
+    public void testEnumWithDefaultAnnotationWithConstructor() throws Exception {
+        final ObjectMapper mapper = new ObjectMapper();
+        mapper.enable(DeserializationFeature.READ_UNKNOWN_ENUM_VALUES_USING_DEFAULT_VALUE);
+
+        EnumWithDefaultAnnoAndConstructor myEnum = mapper.readValue("\"foo\"", EnumWithDefaultAnnoAndConstructor.class);
+        assertNull("When using a constructor, the default value annotation shouldn't be used.", myEnum);
+    }
+
+    public void testExceptionFromCustomEnumKeyDeserializer() {
+        ObjectMapper objectMapper = new ObjectMapper();
+        objectMapper.registerModule(new EnumModule());
+        try {
+            objectMapper.readValue("{\"TWO\": \"dumpling\"}",
+                    new TypeReference<Map<AnEnum, String>>() {});
+            fail("No exception");
+        } catch (IOException e) {
+            assertTrue(e.getMessage().contains("Undefined AnEnum"));
+        }
+    }
+
+    // [databind#1626]
+    public void testNumericEnumName() throws Exception
+    {
+        String json = MAPPER.writeValueAsString(NumberEnum.EN2);
+        assertEquals(quote("2"), json);
+        assertEquals(NumberEnum.EN2, MAPPER.readValue(json, NumberEnum.class));
+    }
+}
diff --git a/src/test/java/com/fasterxml/jackson/databind/deser/ExceptionFromCustomEnumKeyDeserializerTest.java b/src/test/java/com/fasterxml/jackson/databind/deser/ExceptionFromCustomEnumKeyDeserializerTest.java
deleted file mode 100644
index 6b8ea10..0000000
--- a/src/test/java/com/fasterxml/jackson/databind/deser/ExceptionFromCustomEnumKeyDeserializerTest.java
+++ /dev/null
@@ -1,99 +0,0 @@
-/******************************************************************************
- * * This data and information is proprietary to, and a valuable trade secret
- * * of, Basis Technology Corp.  It is given in confidence by Basis Technology
- * * and may only be used as permitted under the license agreement under which
- * * it has been distributed, and in no other way.
- * *
- * * Copyright (c) 2015 Basis Technology Corporation All rights reserved.
- * *
- * * The technical data and information provided herein are provided with
- * * `limited rights', and the computer software provided herein is provided
- * * with `restricted rights' as those terms are defined in DAR and ASPR
- * * 7-104.9(a).
- ******************************************************************************/
-
-package com.fasterxml.jackson.databind.deser;
-
-import java.io.IOException;
-import java.util.Map;
-
-import org.junit.Test;
-
-import com.fasterxml.jackson.core.type.TypeReference;
-import com.fasterxml.jackson.databind.BaseMapTest;
-import com.fasterxml.jackson.databind.DeserializationContext;
-import com.fasterxml.jackson.databind.KeyDeserializer;
-import com.fasterxml.jackson.databind.ObjectMapper;
-import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
-import com.fasterxml.jackson.databind.deser.std.FromStringDeserializer;
-import com.fasterxml.jackson.databind.module.SimpleModule;
-
-@SuppressWarnings("serial")
-public class ExceptionFromCustomEnumKeyDeserializerTest
-    extends BaseMapTest
-{
-    public enum AnEnum {
-        ZERO,
-        ONE
-    }
-
-    public static class AnEnumDeserializer extends FromStringDeserializer<AnEnum> {
-
-        public AnEnumDeserializer() {
-            super(AnEnum.class);
-        }
-
-        //CHECKSTYLE:OFF
-        @Override
-        protected AnEnum _deserialize(String value, DeserializationContext ctxt) throws IOException {
-            try {
-                return AnEnum.valueOf(value);
-            } catch (IllegalArgumentException e) {
-                throw ctxt.weirdKeyException(AnEnum.class, value, "Undefined AnEnum code");
-            }
-        }
-    }
-
-    public static class AnEnumKeyDeserializer extends KeyDeserializer {
-
-        @Override
-        public Object deserializeKey(String key, DeserializationContext ctxt) throws IOException {
-            try {
-                return AnEnum.valueOf(key);
-            } catch (IllegalArgumentException e) {
-                throw ctxt.weirdKeyException(AnEnum.class, key, "Undefined AnEnum code");
-            }
-        }
-    }
-
-
-    @JsonDeserialize(using = AnEnumDeserializer.class, keyUsing = AnEnumKeyDeserializer.class)
-    public enum LanguageCodeMixin {
-    }
-
-    public static class EnumModule extends SimpleModule {
-        @Override
-        public void setupModule(SetupContext context) {
-            context.setMixInAnnotations(AnEnum.class, LanguageCodeMixin.class);
-        }
-
-        public static ObjectMapper setupObjectMapper(ObjectMapper mapper) {
-            final EnumModule module = new EnumModule();
-            mapper.registerModule(module);
-            return mapper;
-        }
-    }
-
-    @Test
-    public void testLostMessage() {
-        ObjectMapper objectMapper = new ObjectMapper();
-        objectMapper.registerModule(new EnumModule());
-        try {
-            objectMapper.readValue("{\"TWO\": \"dumpling\"}", new TypeReference<Map<AnEnum, String>>() {});
-        } catch (IOException e) {
-            assertTrue(e.getMessage().contains("Undefined AnEnum"));
-            return;
-        }
-        fail("No exception");
-    }
-}
diff --git a/src/test/java/com/fasterxml/jackson/databind/deser/TestJDKAtomicTypes.java b/src/test/java/com/fasterxml/jackson/databind/deser/JDKAtomicTypesTest.java
similarity index 93%
rename from src/test/java/com/fasterxml/jackson/databind/deser/TestJDKAtomicTypes.java
rename to src/test/java/com/fasterxml/jackson/databind/deser/JDKAtomicTypesTest.java
index d505256..a3236cf 100644
--- a/src/test/java/com/fasterxml/jackson/databind/deser/TestJDKAtomicTypes.java
+++ b/src/test/java/com/fasterxml/jackson/databind/deser/JDKAtomicTypesTest.java
@@ -7,8 +7,9 @@
 import com.fasterxml.jackson.annotation.*;
 import com.fasterxml.jackson.databind.ObjectMapper;
 import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
+import com.fasterxml.jackson.databind.annotation.JsonSerialize;
 
-public class TestJDKAtomicTypes
+public class JDKAtomicTypesTest
     extends com.fasterxml.jackson.databind.BaseMapTest
 {
     @JsonTypeInfo(use = JsonTypeInfo.Id.NAME)
@@ -86,6 +87,13 @@
         public LCStringWrapper() { }
     }
 
+    @JsonPropertyOrder({ "a", "b" })
+    static class Issue1256Bean {
+        @JsonSerialize(as=AtomicReference.class)
+        public Object a = new AtomicReference<Object>();
+        public AtomicReference<Object> b = new AtomicReference<Object>();
+    }
+
     /*
     /**********************************************************
     /* Test methods
@@ -251,6 +259,15 @@
         assertEquals("foobar", w.value.get());
     }
 
+    public void testEmpty1256() throws Exception
+    {
+        ObjectMapper mapper = new ObjectMapper();
+        mapper.setSerializationInclusion(JsonInclude.Include.NON_ABSENT);
+
+        String json = mapper.writeValueAsString(new Issue1256Bean());
+        assertEquals("{}", json);
+    }
+
     // [databind#1307]
     @SuppressWarnings("unchecked")
     public void testNullValueHandling() throws Exception
diff --git a/src/test/java/com/fasterxml/jackson/databind/deser/JDKNumberDeserTest.java b/src/test/java/com/fasterxml/jackson/databind/deser/JDKNumberDeserTest.java
new file mode 100644
index 0000000..c224f88
--- /dev/null
+++ b/src/test/java/com/fasterxml/jackson/databind/deser/JDKNumberDeserTest.java
@@ -0,0 +1,251 @@
+package com.fasterxml.jackson.databind.deser;
+
+import java.io.IOException;
+import java.io.StringReader;
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.util.List;
+import java.util.Map;
+
+import com.fasterxml.jackson.core.*;
+import com.fasterxml.jackson.databind.*;
+import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
+
+public class JDKNumberDeserTest extends BaseMapTest
+{
+    /*
+    /**********************************************************************
+    /* Helper classes, beans
+    /**********************************************************************
+     */
+
+    static class MyBeanHolder {
+        public Long id;
+        public MyBeanDefaultValue defaultValue;
+    }
+
+    static class MyBeanDefaultValue
+    {
+        public MyBeanValue value;
+    }
+
+    @JsonDeserialize(using=MyBeanDeserializer.class)
+    static class MyBeanValue {
+        public BigDecimal decimal;
+        public MyBeanValue() { this(null); }
+        public MyBeanValue(BigDecimal d) { this.decimal = d; }
+    }
+
+    /*
+    /**********************************************************************
+    /* Helper classes, serializers/deserializers/resolvers
+    /**********************************************************************
+     */
+    
+    static class MyBeanDeserializer extends JsonDeserializer<MyBeanValue>
+    {
+        @Override
+        public MyBeanValue deserialize(JsonParser jp, DeserializationContext ctxt)
+                throws IOException
+        {
+            return new MyBeanValue(jp.getDecimalValue());
+        }
+    }
+
+    /*
+    /**********************************************************************
+    /* Unit tests
+    /**********************************************************************
+     */
+
+    final ObjectMapper MAPPER = new ObjectMapper();
+    
+    public void testNaN() throws Exception
+    {
+        Float result = MAPPER.readValue(" \"NaN\"", Float.class);
+        assertEquals(Float.valueOf(Float.NaN), result);
+
+        Double d = MAPPER.readValue(" \"NaN\"", Double.class);
+        assertEquals(Double.valueOf(Double.NaN), d);
+
+        Number num = MAPPER.readValue(" \"NaN\"", Number.class);
+        assertEquals(Double.valueOf(Double.NaN), num);
+    }
+
+    public void testDoubleInf() throws Exception
+    {
+        Double result = MAPPER.readValue(" \""+Double.POSITIVE_INFINITY+"\"", Double.class);
+        assertEquals(Double.valueOf(Double.POSITIVE_INFINITY), result);
+
+        result = MAPPER.readValue(" \""+Double.NEGATIVE_INFINITY+"\"", Double.class);
+        assertEquals(Double.valueOf(Double.NEGATIVE_INFINITY), result);
+    }
+
+    public void testEmptyAsNumber() throws Exception
+    {
+        assertNull(MAPPER.readValue(quote(""), Integer.class));
+        assertNull(MAPPER.readValue(quote(""), Long.class));
+        assertNull(MAPPER.readValue(quote(""), Float.class));
+        assertNull(MAPPER.readValue(quote(""), Double.class));
+        assertNull(MAPPER.readValue(quote(""), BigInteger.class));
+        assertNull(MAPPER.readValue(quote(""), BigDecimal.class));
+    }
+
+    public void testDeserializeDecimalHappyPath() throws Exception {
+        String json = "{\"defaultValue\": { \"value\": 123 } }";
+        MyBeanHolder result = MAPPER.readValue(json, MyBeanHolder.class);
+        assertEquals(BigDecimal.valueOf(123), result.defaultValue.value.decimal);
+    }
+
+    public void testDeserializeDecimalProperException() throws Exception {
+        String json = "{\"defaultValue\": { \"value\": \"123\" } }";
+        try {
+            MAPPER.readValue(json, MyBeanHolder.class);
+            fail("should have raised exception");
+        } catch (JsonProcessingException e) {
+            verifyException(e, "not numeric");
+        }
+    }
+
+    public void testDeserializeDecimalProperExceptionWhenIdSet() throws Exception {
+        String json = "{\"id\": 5, \"defaultValue\": { \"value\": \"123\" } }";
+        try {
+            MyBeanHolder result = MAPPER.readValue(json, MyBeanHolder.class);
+            fail("should have raised exception instead value was set to " + result.defaultValue.value.decimal.toString());
+        } catch (JsonProcessingException e) {
+            verifyException(e, "not numeric");
+        }
+    }
+
+    // And then [databind#852]
+    public void testScientificNotationAsStringForNumber() throws Exception
+    {
+        Object ob = MAPPER.readValue("\"3E-8\"", Number.class);
+        assertEquals(Double.class, ob.getClass());
+        ob = MAPPER.readValue("\"3e-8\"", Number.class);
+        assertEquals(Double.class, ob.getClass());
+        ob = MAPPER.readValue("\"300000000\"", Number.class);
+        assertEquals(Integer.class, ob.getClass());
+        ob = MAPPER.readValue("\"123456789012\"", Number.class);
+        assertEquals(Long.class, ob.getClass());
+    }
+
+    public void testIntAsNumber() throws Exception
+    {
+        /* Even if declared as 'generic' type, should return using most
+         * efficient type... here, Integer
+         */
+        Number result = MAPPER.readValue(" 123 ", Number.class);
+        assertEquals(Integer.valueOf(123), result);
+    }
+
+    public void testLongAsNumber() throws Exception
+    {
+        // And beyond int range, should get long
+        long exp = 1234567890123L;
+        Number result = MAPPER.readValue(String.valueOf(exp), Number.class);
+        assertEquals(Long.valueOf(exp), result);
+    }
+
+    public void testBigIntAsNumber() throws Exception
+    {
+        // and after long, BigInteger
+        BigInteger biggie = new BigInteger("1234567890123456789012345678901234567890");
+        Number result = MAPPER.readValue(biggie.toString(), Number.class);
+        assertEquals(BigInteger.class, biggie.getClass());
+        assertEquals(biggie, result);
+    }
+
+    public void testIntTypeOverride() throws Exception
+    {
+        /* Slight twist; as per [JACKSON-100], can also request binding
+         * to BigInteger even if value would fit in Integer
+         */
+        ObjectReader r = MAPPER.reader(DeserializationFeature.USE_BIG_INTEGER_FOR_INTS);
+
+        BigInteger exp = BigInteger.valueOf(123L);
+
+        // first test as any Number
+        Number result = r.forType(Number.class).readValue(" 123 ");
+        assertEquals(BigInteger.class, result.getClass());
+        assertEquals(exp, result);
+
+        // then as any Object
+        /*Object value =*/ r.forType(Object.class).readValue("123");
+        assertEquals(BigInteger.class, result.getClass());
+        assertEquals(exp, result);
+
+        // and as JsonNode
+        JsonNode node = r.readTree("  123");
+        assertTrue(node.isBigInteger());
+        assertEquals(123, node.asInt());
+    }
+
+    public void testDoubleAsNumber() throws Exception
+    {
+        Number result = MAPPER.readValue(new StringReader(" 1.0 "), Number.class);
+        assertEquals(Double.valueOf(1.0), result);
+    }
+
+    public void testFpTypeOverrideSimple() throws Exception
+    {
+        ObjectReader r = MAPPER.reader(DeserializationFeature.USE_BIG_DECIMAL_FOR_FLOATS);
+        BigDecimal dec = new BigDecimal("0.1");
+
+        // First test generic stand-alone Number
+        Number result = r.forType(Number.class).readValue(dec.toString());
+        assertEquals(BigDecimal.class, result.getClass());
+        assertEquals(dec, result);
+
+        // Then plain old Object
+        Object value = r.forType(Object.class).readValue(dec.toString());
+        assertEquals(BigDecimal.class, result.getClass());
+        assertEquals(dec, value);
+
+        JsonNode node = r.readTree(dec.toString());
+        assertTrue(node.isBigDecimal());
+        assertEquals(dec.doubleValue(), node.asDouble());
+    }
+
+    public void testFpTypeOverrideStructured() throws Exception
+    {
+        ObjectReader r = MAPPER.reader(DeserializationFeature.USE_BIG_DECIMAL_FOR_FLOATS);
+
+        BigDecimal dec = new BigDecimal("-19.37");
+        // List element types
+        @SuppressWarnings("unchecked")
+        List<Object> list = (List<Object>) r.forType(List.class).readValue("[ "+dec.toString()+" ]");
+        assertEquals(1, list.size());
+        Object val = list.get(0);
+        assertEquals(BigDecimal.class, val.getClass());
+        assertEquals(dec, val);
+
+        // and a map
+        Map<?,?> map = r.forType(Map.class).readValue("{ \"a\" : "+dec.toString()+" }");
+        assertEquals(1, map.size());
+        val = map.get("a");
+        assertEquals(BigDecimal.class, val.getClass());
+        assertEquals(dec, val);
+    }
+
+    // [databind#504]
+    public void testForceIntsToLongs() throws Exception
+    {
+        ObjectReader r = MAPPER.reader(DeserializationFeature.USE_LONG_FOR_INTS);
+
+        Object ob = r.forType(Object.class).readValue("42");
+        assertEquals(Long.class, ob.getClass());
+        assertEquals(Long.valueOf(42L), ob);
+
+        Number n = r.forType(Number.class).readValue("42");
+        assertEquals(Long.class, n.getClass());
+        assertEquals(Long.valueOf(42L), n);
+
+        // and one more: should get proper node as well
+        JsonNode node = r.readTree("42");
+        if (!node.isLong()) {
+            fail("Expected LongNode, got: "+node.getClass().getName());
+        }
+        assertEquals(42, node.asInt());
+    }
+}
diff --git a/src/test/java/com/fasterxml/jackson/databind/deser/JDKScalarsTest.java b/src/test/java/com/fasterxml/jackson/databind/deser/JDKScalarsTest.java
new file mode 100644
index 0000000..7679745
--- /dev/null
+++ b/src/test/java/com/fasterxml/jackson/databind/deser/JDKScalarsTest.java
@@ -0,0 +1,1002 @@
+package com.fasterxml.jackson.databind.deser;
+
+import java.io.*;
+import java.math.BigDecimal;
+import java.math.BigInteger;
+
+import org.junit.Assert;
+
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.core.*;
+import com.fasterxml.jackson.databind.*;
+
+/**
+ * Unit tests for verifying handling of simple basic non-structured
+ * types; primitives (and/or their wrappers), Strings.
+ */
+public class JDKScalarsTest
+    extends BaseMapTest
+{
+    final static String NAN_STRING = "NaN";
+
+    final static class BooleanBean {
+        boolean _v;
+        void setV(boolean v) { _v = v; }
+    }
+
+    static class BooleanWrapper {
+        public Boolean wrapper;
+        public boolean primitive;
+        
+        protected Boolean ctor;
+        
+        @JsonCreator
+        public BooleanWrapper(@JsonProperty("ctor") Boolean foo) {
+            ctor = foo;
+        }
+    }
+    
+    static class IntBean {
+        int _v;
+        void setV(int v) { _v = v; }
+    }
+
+    final static class DoubleBean {
+        double _v;
+        void setV(double v) { _v = v; }
+    }
+
+    final static class FloatBean {
+        float _v;
+        void setV(float v) { _v = v; }
+    }
+    
+    final static class CharacterBean {
+        char _v;
+        void setV(char v) { _v = v; }
+        char getV() { return _v; }
+    }
+    
+    final static class CharacterWrapperBean {
+        Character _v;
+        void setV(Character v) { _v = v; }
+        Character getV() { return _v; }
+    }
+
+    /**
+     * Also, let's ensure that it's ok to override methods.
+     */
+    static class IntBean2
+        extends IntBean
+    {
+        @Override
+        void setV(int v2) { super.setV(v2+1); }
+    }
+
+    static class PrimitivesBean
+    {
+        public boolean booleanValue = true;
+        public byte byteValue = 3;
+        public char charValue = 'a';
+        public short shortValue = 37;
+        public int intValue = 1;
+        public long longValue = 100L;
+        public float floatValue = 0.25f;
+        public double doubleValue = -1.0;
+    }
+
+    static class WrappersBean
+    {
+        public Boolean booleanValue;
+        public Byte byteValue;
+        public Character charValue;
+        public Short shortValue;
+        public Integer intValue;
+        public Long longValue;
+        public Float floatValue;
+        public Double doubleValue;
+    }
+
+    private final ObjectMapper MAPPER = new ObjectMapper();
+
+    /*
+    /**********************************************************
+    /* Scalar tests for boolean
+    /**********************************************************
+     */
+
+    public void testBooleanPrimitive() throws Exception
+    {
+        // first, simple case:
+        BooleanBean result = MAPPER.readValue(new StringReader("{\"v\":true}"), BooleanBean.class);
+        assertTrue(result._v);
+        result = MAPPER.readValue(new StringReader("{\"v\":null}"), BooleanBean.class);
+        assertNotNull(result);
+        assertFalse(result._v);
+        // [databind#1480]
+        result = MAPPER.readValue(new StringReader("{\"v\":1}"), BooleanBean.class);
+        assertNotNull(result);
+        assertTrue(result._v);
+
+        // should work with arrays too..
+        boolean[] array = MAPPER.readValue(new StringReader("[ null ]"), boolean[].class);
+        assertNotNull(array);
+        assertEquals(1, array.length);
+        assertFalse(array[0]);
+
+    }
+        
+    public void testBooleanPrimitiveArrayUnwrap() throws Exception
+    {
+        // [databind#381]
+        final ObjectMapper mapper = new ObjectMapper();
+        mapper.enable(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS);
+        BooleanBean result = mapper.readValue(new StringReader("{\"v\":[true]}"), BooleanBean.class);
+        assertTrue(result._v);
+        
+        try {
+            mapper.readValue(new StringReader("[{\"v\":[true,true]}]"), BooleanBean.class);
+            fail("Did not throw exception while reading a value from a multi value array with UNWRAP_SINGLE_VALUE_ARRAY feature enabled");
+        } catch (JsonMappingException exp) {
+            //threw exception as required
+        }
+        
+        result = mapper.readValue(new StringReader("{\"v\":[null]}"), BooleanBean.class);
+        assertNotNull(result);
+        assertFalse(result._v);
+        
+        result = mapper.readValue(new StringReader("[{\"v\":[null]}]"), BooleanBean.class);
+        assertNotNull(result);
+        assertFalse(result._v);
+        
+        boolean[] array = mapper.readValue(new StringReader("[ [ null ] ]"), boolean[].class);
+        assertNotNull(array);
+        assertEquals(1, array.length);
+        assertFalse(array[0]);
+    }
+
+    /**
+     * Simple unit test to verify that we can map boolean values to
+     * java.lang.Boolean.
+     */
+    public void testBooleanWrapper() throws Exception
+    {
+        Boolean result = MAPPER.readValue(new StringReader("true"), Boolean.class);
+        assertEquals(Boolean.TRUE, result);
+        result = MAPPER.readValue(new StringReader("false"), Boolean.class);
+        assertEquals(Boolean.FALSE, result);
+
+        // should accept ints too, (0 == false, otherwise true)
+        result = MAPPER.readValue("0", Boolean.class);
+        assertEquals(Boolean.FALSE, result);
+        result = MAPPER.readValue("1", Boolean.class);
+        assertEquals(Boolean.TRUE, result);
+    }
+
+    // Test for verifying that Long values are coerced to boolean correctly as well
+    public void testLongToBoolean() throws Exception
+    {
+        long value = 1L + Integer.MAX_VALUE;
+        BooleanWrapper b = MAPPER.readValue("{\"primitive\" : "+value+", \"wrapper\":"+value+", \"ctor\":"+value+"}",
+                BooleanWrapper.class);
+        assertEquals(Boolean.TRUE, b.wrapper);
+        assertTrue(b.primitive);
+        assertEquals(Boolean.TRUE, b.ctor);
+
+        // but ensure we can also get `false`
+        b = MAPPER.readValue("{\"primitive\" : 0 , \"wrapper\":0, \"ctor\":0}",
+                BooleanWrapper.class);
+        assertEquals(Boolean.FALSE, b.wrapper);
+        assertFalse(b.primitive);
+        assertEquals(Boolean.FALSE, b.ctor);
+    }
+
+    /*
+    /**********************************************************
+    /* Scalar tests for integral types
+    /**********************************************************
+     */
+
+    public void testIntPrimitive() throws Exception
+    {
+        // first, simple case:
+        IntBean result = MAPPER.readValue(new StringReader("{\"v\":3}"), IntBean.class);
+        assertEquals(3, result._v);
+        result = MAPPER.readValue(new StringReader("{\"v\":null}"), IntBean.class);
+        assertNotNull(result);
+        assertEquals(0, result._v);
+
+        // should work with arrays too..
+        int[] array = MAPPER.readValue(new StringReader("[ null ]"), int[].class);
+        assertNotNull(array);
+        assertEquals(1, array.length);
+        assertEquals(0, array[0]);
+        
+        // [Issue#381]
+        final ObjectMapper mapper = new ObjectMapper();
+        mapper.disable(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS);
+        try {
+            mapper.readValue(new StringReader("{\"v\":[3]}"), IntBean.class);
+            fail("Did not throw exception when reading a value from a single value array with the UNWRAP_SINGLE_VALUE_ARRAYS feature disabled");
+        } catch (JsonMappingException exp) {
+            //Correctly threw exception
+        }
+        
+        mapper.enable(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS);
+        
+        result = mapper.readValue(new StringReader("{\"v\":[3]}"), IntBean.class);
+        assertEquals(3, result._v);
+        
+        result = mapper.readValue(new StringReader("[{\"v\":[3]}]"), IntBean.class);
+        assertEquals(3, result._v);
+        
+        try {
+            mapper.readValue("[{\"v\":[3,3]}]", IntBean.class);
+            fail("Did not throw exception while reading a value from a multi value array with UNWRAP_SINGLE_VALUE_ARRAY feature enabled");
+        } catch (JsonMappingException exp) {
+            //threw exception as required
+        }
+        
+        result = mapper.readValue("{\"v\":[null]}", IntBean.class);
+        assertNotNull(result);
+        assertEquals(0, result._v);
+
+        array = mapper.readValue("[ [ null ] ]", int[].class);
+        assertNotNull(array);
+        assertEquals(1, array.length);
+        assertEquals(0, array[0]);
+    }
+
+    public void testByteWrapper() throws Exception
+    {
+        Byte result = MAPPER.readValue(new StringReader("   -42\t"), Byte.class);
+        assertEquals(Byte.valueOf((byte)-42), result);
+
+        // Also: should be able to coerce floats, strings:
+        result = MAPPER.readValue(new StringReader(" \"-12\""), Byte.class);
+        assertEquals(Byte.valueOf((byte)-12), result);
+
+        result = MAPPER.readValue(new StringReader(" 39.07"), Byte.class);
+        assertEquals(Byte.valueOf((byte)39), result);
+    }
+
+    public void testShortWrapper() throws Exception
+    {
+        Short result = MAPPER.readValue(new StringReader("37"), Short.class);
+        assertEquals(Short.valueOf((short)37), result);
+
+        // Also: should be able to coerce floats, strings:
+        result = MAPPER.readValue(new StringReader(" \"-1009\""), Short.class);
+        assertEquals(Short.valueOf((short)-1009), result);
+
+        result = MAPPER.readValue(new StringReader("-12.9"), Short.class);
+        assertEquals(Short.valueOf((short)-12), result);
+    }
+
+    public void testCharacterWrapper() throws Exception
+    {
+        // First: canonical value is 1-char string
+        Character result = MAPPER.readValue(new StringReader("\"a\""), Character.class);
+        assertEquals(Character.valueOf('a'), result);
+
+        // But can also pass in ascii code
+        result = MAPPER.readValue(new StringReader(" "+((int) 'X')), Character.class);
+        assertEquals(Character.valueOf('X'), result);
+        
+        final CharacterWrapperBean wrapper = MAPPER.readValue(new StringReader("{\"v\":null}"), CharacterWrapperBean.class);
+        assertNotNull(wrapper);
+        assertNull(wrapper.getV());
+        
+        final ObjectMapper mapper = new ObjectMapper();
+        mapper.enable(DeserializationFeature.FAIL_ON_NULL_FOR_PRIMITIVES);
+        try {
+            mapper.readValue("{\"v\":null}", CharacterBean.class);
+            fail("Attempting to deserialize a 'null' JSON reference into a 'char' property did not throw an exception");
+        } catch (JsonMappingException exp) {
+            //Exception thrown as required
+        }
+
+        mapper.disable(DeserializationFeature.FAIL_ON_NULL_FOR_PRIMITIVES);  
+        final CharacterBean charBean = MAPPER.readValue(new StringReader("{\"v\":null}"), CharacterBean.class);
+        assertNotNull(wrapper);
+        assertEquals('\u0000', charBean.getV());
+    }
+
+    public void testIntWrapper() throws Exception
+    {
+        Integer result = MAPPER.readValue(new StringReader("   -42\t"), Integer.class);
+        assertEquals(Integer.valueOf(-42), result);
+
+        // Also: should be able to coerce floats, strings:
+        result = MAPPER.readValue(new StringReader(" \"-1200\""), Integer.class);
+        assertEquals(Integer.valueOf(-1200), result);
+
+        result = MAPPER.readValue(new StringReader(" 39.07"), Integer.class);
+        assertEquals(Integer.valueOf(39), result);
+    }
+
+    public void testLongWrapper() throws Exception
+    {
+        Long result = MAPPER.readValue(new StringReader("12345678901"), Long.class);
+        assertEquals(Long.valueOf(12345678901L), result);
+
+        // Also: should be able to coerce floats, strings:
+        result = MAPPER.readValue(new StringReader(" \"-9876\""), Long.class);
+        assertEquals(Long.valueOf(-9876), result);
+
+        result = MAPPER.readValue(new StringReader("1918.3"), Long.class);
+        assertEquals(Long.valueOf(1918), result);
+    }
+    
+    /**
+     * Beyond simple case, let's also ensure that method overriding works as
+     * expected.
+     */
+    public void testIntWithOverride() throws Exception
+    {
+        IntBean2 result = MAPPER.readValue(new StringReader("{\"v\":8}"), IntBean2.class);
+        assertEquals(9, result._v);
+    }
+
+    /*
+    /**********************************************************
+    /* Scalar tests for floating point types
+    /**********************************************************
+     */
+
+    public void testDoublePrimitive() throws Exception
+    {
+        // first, simple case:
+        // bit tricky with binary fps but...
+        final double value = 0.016;
+        DoubleBean result = MAPPER.readValue(new StringReader("{\"v\":"+value+"}"), DoubleBean.class);
+        assertEquals(value, result._v);
+        // then [JACKSON-79]:
+        result = MAPPER.readValue(new StringReader("{\"v\":null}"), DoubleBean.class);
+        assertNotNull(result);
+        assertEquals(0.0, result._v);
+
+        // should work with arrays too..
+        double[] array = MAPPER.readValue(new StringReader("[ null ]"), double[].class);
+        assertNotNull(array);
+        assertEquals(1, array.length);
+        assertEquals(0.0, array[0]);
+    }
+
+    /* Note: dealing with floating-point values is tricky; not sure if
+     * we can really use equality tests here... JDK does have decent
+     * conversions though, to retain accuracy and round-trippability.
+     * But still...
+     */
+    public void testFloatWrapper() throws Exception
+    {
+        // Also: should be able to coerce floats, strings:
+        String[] STRS = new String[] {
+            "1.0", "0.0", "-0.3", "0.7", "42.012", "-999.0", NAN_STRING
+        };
+
+        for (String str : STRS) {
+            Float exp = Float.valueOf(str);
+            Float result;
+
+            if (NAN_STRING != str) {
+                // First, as regular floating point value
+                result = MAPPER.readValue(new StringReader(str), Float.class);
+                assertEquals(exp, result);
+            }
+
+            // and then as coerced String:
+            result = MAPPER.readValue(new StringReader(" \""+str+"\""), Float.class);
+            assertEquals(exp, result);
+        }
+    }
+
+    public void testDoubleWrapper() throws Exception
+    {
+        // Also: should be able to coerce doubles, strings:
+        String[] STRS = new String[] {
+            "1.0", "0.0", "-0.3", "0.7", "42.012", "-999.0", NAN_STRING
+        };
+
+        for (String str : STRS) {
+            Double exp = Double.valueOf(str);
+            Double result;
+
+            // First, as regular double value
+            if (NAN_STRING != str) {
+                result = MAPPER.readValue(str, Double.class);
+               assertEquals(exp, result);
+            }
+            // and then as coerced String:
+            result = MAPPER.readValue(new StringReader(" \""+str+"\""), Double.class);
+            assertEquals(exp, result);
+        }
+    }
+
+    public void testDoubleAsArray() throws Exception
+    {
+        final ObjectMapper mapper = new ObjectMapper();
+        mapper.disable(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS);
+        final double value = 0.016;
+        try {
+            mapper.readValue(new StringReader("{\"v\":[" + value + "]}"), DoubleBean.class);
+            fail("Did not throw exception when reading a value from a single value array with the UNWRAP_SINGLE_VALUE_ARRAYS feature disabled");
+        } catch (JsonMappingException exp) {
+            //Correctly threw exception
+        }
+        
+        mapper.enable(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS);
+        
+        DoubleBean result = mapper.readValue(new StringReader("{\"v\":[" + value + "]}"),
+                DoubleBean.class);
+        assertEquals(value, result._v);
+        
+        result = mapper.readValue(new StringReader("[{\"v\":[" + value + "]}]"), DoubleBean.class);
+        assertEquals(value, result._v);
+        
+        try {
+            mapper.readValue(new StringReader("[{\"v\":[" + value + "," + value + "]}]"), DoubleBean.class);
+            fail("Did not throw exception while reading a value from a multi value array with UNWRAP_SINGLE_VALUE_ARRAY feature enabled");
+        } catch (JsonMappingException exp) {
+            //threw exception as required
+        }
+        
+        result = mapper.readValue(new StringReader("{\"v\":[null]}"), DoubleBean.class);
+        assertNotNull(result);
+        assertEquals(0d, result._v);
+
+        double[] array = mapper.readValue(new StringReader("[ [ null ] ]"), double[].class);
+        assertNotNull(array);
+        assertEquals(1, array.length);
+        assertEquals(0d, array[0]);
+    }
+
+    public void testDoublePrimitiveNonNumeric() throws Exception
+    {
+        // first, simple case:
+        // bit tricky with binary fps but...
+        double value = Double.POSITIVE_INFINITY;
+        DoubleBean result = MAPPER.readValue(new StringReader("{\"v\":\""+value+"\"}"), DoubleBean.class);
+        assertEquals(value, result._v);
+        
+        // should work with arrays too..
+        double[] array = MAPPER.readValue(new StringReader("[ \"Infinity\" ]"), double[].class);
+        assertNotNull(array);
+        assertEquals(1, array.length);
+        assertEquals(Double.POSITIVE_INFINITY, array[0]);
+    }
+    
+    public void testFloatPrimitiveNonNumeric() throws Exception
+    {
+        // bit tricky with binary fps but...
+        float value = Float.POSITIVE_INFINITY;
+        FloatBean result = MAPPER.readValue(new StringReader("{\"v\":\""+value+"\"}"), FloatBean.class);
+        assertEquals(value, result._v);
+        
+        // should work with arrays too..
+        float[] array = MAPPER.readValue(new StringReader("[ \"Infinity\" ]"), float[].class);
+        assertNotNull(array);
+        assertEquals(1, array.length);
+        assertEquals(Float.POSITIVE_INFINITY, array[0]);
+    }
+
+    /*
+    /**********************************************************
+    /* Scalar tests, other
+    /**********************************************************
+     */
+
+    public void testEmptyToNullCoercionForPrimitives() throws Exception {
+        _testEmptyToNullCoercion(int.class, Integer.valueOf(0));
+        _testEmptyToNullCoercion(long.class, Long.valueOf(0));
+        _testEmptyToNullCoercion(double.class, Double.valueOf(0.0));
+        _testEmptyToNullCoercion(float.class, Float.valueOf(0.0f));
+    }
+
+    private void _testEmptyToNullCoercion(Class<?> primType, Object emptyValue) throws Exception
+    {
+        final String EMPTY = "\"\"";
+
+        // as per [databind#1095] should only allow coercion from empty String,
+        // if `null` is acceptable
+        ObjectReader intR = MAPPER.readerFor(primType);
+        assertEquals(emptyValue, intR.readValue(EMPTY));
+        try {
+            intR.with(DeserializationFeature.FAIL_ON_NULL_FOR_PRIMITIVES)
+                .readValue("\"\"");
+            fail("Should not have passed");
+        } catch (JsonMappingException e) {
+            verifyException(e, "Can not map Empty String");
+        }
+    }
+
+    public void testBase64Variants() throws Exception
+    {
+        final byte[] INPUT = "abcdefghijklmnopqrstuvwxyz1234567890abcdefghijklmnopqrstuvwxyz1234567890X".getBytes("UTF-8");
+        
+        // default encoding is "MIME, no linefeeds", so:
+        Assert.assertArrayEquals(INPUT, MAPPER.readValue(
+                quote("YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXoxMjM0NTY3ODkwYWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXoxMjM0NTY3ODkwWA=="),
+                byte[].class));
+        ObjectReader reader = MAPPER.readerFor(byte[].class);
+        Assert.assertArrayEquals(INPUT, (byte[]) reader.with(Base64Variants.MIME_NO_LINEFEEDS).readValue(
+                quote("YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXoxMjM0NTY3ODkwYWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXoxMjM0NTY3ODkwWA=="
+        )));
+
+        // but others should be slightly different
+        Assert.assertArrayEquals(INPUT, (byte[]) reader.with(Base64Variants.MIME).readValue(
+                quote("YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXoxMjM0NTY3ODkwYWJjZGVmZ2hpamtsbW5vcHFyc3R1\\ndnd4eXoxMjM0NTY3ODkwWA=="
+        )));
+        Assert.assertArrayEquals(INPUT, (byte[]) reader.with(Base64Variants.MODIFIED_FOR_URL).readValue(
+                quote("YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXoxMjM0NTY3ODkwYWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXoxMjM0NTY3ODkwWA"
+        )));
+        // PEM mandates 64 char lines:
+        Assert.assertArrayEquals(INPUT, (byte[]) reader.with(Base64Variants.PEM).readValue(
+                quote("YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXoxMjM0NTY3ODkwYWJjZGVmZ2hpamts\\nbW5vcHFyc3R1dnd4eXoxMjM0NTY3ODkwWA=="
+        )));
+    }    
+    /*
+    /**********************************************************
+    /* Simple non-primitive types
+    /**********************************************************
+     */
+
+    public void testSingleString() throws Exception
+    {
+        String value = "FOO!";
+        String result = MAPPER.readValue(new StringReader("\""+value+"\""), String.class);
+        assertEquals(value, result);
+    }
+    
+    public void testSingleStringWrapped() throws Exception
+    {
+        final ObjectMapper mapper = new ObjectMapper();
+        mapper.disable(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS);
+        
+        String value = "FOO!";
+        try {
+            mapper.readValue(new StringReader("[\""+value+"\"]"), String.class);
+            fail("Exception not thrown when attempting to unwrap a single value 'String' array into a simple String");
+        } catch (JsonMappingException exp) {
+            //exception thrown correctly
+        }
+        
+        mapper.enable(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS);
+        
+        try {
+            mapper.readValue(new StringReader("[\""+value+"\",\""+value+"\"]"), String.class);
+            fail("Exception not thrown when attempting to unwrap a single value 'String' array that contained more than one value into a simple String");
+        } catch (JsonMappingException exp) {
+            //exception thrown correctly
+        }
+        
+        String result = mapper.readValue(new StringReader("[\""+value+"\"]"), String.class);
+        assertEquals(value, result);
+    }
+
+    public void testBigDecimal() throws Exception
+    {
+        final ObjectMapper mapper = objectMapper();
+        mapper.disable(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS);
+        
+        BigDecimal value = new BigDecimal("0.001");
+        BigDecimal result = mapper.readValue(value.toString(), BigDecimal.class);
+        assertEquals(value, result);
+        try {
+            mapper.readValue("[" + value.toString() + "]", BigDecimal.class);
+            fail("Exception was not thrown when attempting to read a single value array of BigDecimal when UNWRAP_SINGLE_VALUE_ARRAYS feature is disabled");
+        } catch (JsonMappingException exp) {
+            //Exception was thrown correctly
+        }
+        
+        mapper.enable(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS);
+        result = mapper.readValue("[" + value.toString() + "]", BigDecimal.class);
+        assertEquals(value, result);
+        
+        try {
+            mapper.readValue("[" + value.toString() + "," + value.toString() + "]", BigDecimal.class);
+            fail("Exception was not thrown when attempting to read a muti value array of BigDecimal when UNWRAP_SINGLE_VALUE_ARRAYS feature is enabled");
+        } catch (JsonMappingException exp) {
+            //Exception was thrown correctly
+        }
+    }
+
+    public void testBigInteger() throws Exception
+    {
+        final ObjectMapper mapper = objectMapper();
+        mapper.disable(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS);
+        
+        BigInteger value = new BigInteger("-1234567890123456789012345567809");
+        BigInteger result = mapper.readValue(new StringReader(value.toString()), BigInteger.class);
+        assertEquals(value, result);
+        
+        //Issue#381
+        try {
+            mapper.readValue("[" + value.toString() + "]", BigInteger.class);
+            fail("Exception was not thrown when attempting to read a single value array of BigInteger when UNWRAP_SINGLE_VALUE_ARRAYS feature is disabled");
+        } catch (JsonMappingException exp) {
+            //Exception was thrown correctly
+        }
+        
+        mapper.enable(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS);
+        result = mapper.readValue("[" + value.toString() + "]", BigInteger.class);
+        assertEquals(value, result);
+        
+        try {
+            mapper.readValue("[" + value.toString() + "," + value.toString() + "]", BigInteger.class);
+            fail("Exception was not thrown when attempting to read a muti value array of BigInteger when UNWRAP_SINGLE_VALUE_ARRAYS feature is enabled");
+        } catch (JsonMappingException exp) {
+            //Exception was thrown correctly
+        }        
+    }
+
+    /*
+    /**********************************************************
+    /* Sequence tests
+    /**********************************************************
+     */
+
+    /**
+     * Then a unit test to verify that we can conveniently bind sequence of
+     * space-separate simple values
+     */
+    public void testSequenceOfInts() throws Exception
+    {
+        final int NR_OF_INTS = 100;
+
+        StringBuilder sb = new StringBuilder();
+        for (int i = 0; i < NR_OF_INTS; ++i) {
+            sb.append(" ");
+            sb.append(i);
+        }
+        JsonParser jp = MAPPER.getFactory().createParser(sb.toString());
+        for (int i = 0; i < NR_OF_INTS; ++i) {
+            Integer result = MAPPER.readValue(jp, Integer.class);
+            assertEquals(Integer.valueOf(i), result);
+        }
+        jp.close();
+    }
+
+    /*
+    /**********************************************************
+    /* Single-element as array tests
+    /**********************************************************
+     */
+    
+    // [databind#381]
+    public void testSingleElementScalarArrays() throws Exception {
+        final int intTest = 932832;
+        final double doubleTest = 32.3234;
+        final long longTest = 2374237428374293423L;
+        final short shortTest = (short) intTest;
+        final float floatTest = 84.3743f;
+        final byte byteTest = (byte) 43;
+        final char charTest = 'c';
+
+        final ObjectMapper mapper = new ObjectMapper();
+        mapper.enable(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS);
+
+        final int intValue = mapper.readValue(asArray(intTest), Integer.TYPE);
+        assertEquals(intTest, intValue);
+        final Integer integerWrapperValue = mapper.readValue(asArray(Integer.valueOf(intTest)), Integer.class);
+        assertEquals(Integer.valueOf(intTest), integerWrapperValue);
+
+        final double doubleValue = mapper.readValue(asArray(doubleTest), Double.class);
+        assertEquals(doubleTest, doubleValue);
+        final Double doubleWrapperValue = mapper.readValue(asArray(Double.valueOf(doubleTest)), Double.class);
+        assertEquals(Double.valueOf(doubleTest), doubleWrapperValue);
+
+        final long longValue = mapper.readValue(asArray(longTest), Long.TYPE);
+        assertEquals(longTest, longValue);
+        final Long longWrapperValue = mapper.readValue(asArray(Long.valueOf(longTest)), Long.class);
+        assertEquals(Long.valueOf(longTest), longWrapperValue);
+
+        final short shortValue = mapper.readValue(asArray(shortTest), Short.TYPE);
+        assertEquals(shortTest, shortValue);
+        final Short shortWrapperValue = mapper.readValue(asArray(Short.valueOf(shortTest)), Short.class);
+        assertEquals(Short.valueOf(shortTest), shortWrapperValue);
+
+        final float floatValue = mapper.readValue(asArray(floatTest), Float.TYPE);
+        assertEquals(floatTest, floatValue);
+        final Float floatWrapperValue = mapper.readValue(asArray(Float.valueOf(floatTest)), Float.class);
+        assertEquals(Float.valueOf(floatTest), floatWrapperValue);
+
+        final byte byteValue = mapper.readValue(asArray(byteTest), Byte.TYPE);
+        assertEquals(byteTest, byteValue);
+        final Byte byteWrapperValue = mapper.readValue(asArray(Byte.valueOf(byteTest)), Byte.class);
+        assertEquals(Byte.valueOf(byteTest), byteWrapperValue);
+
+        final char charValue = mapper.readValue(asArray(quote(String.valueOf(charTest))), Character.TYPE);
+        assertEquals(charTest, charValue);
+        final Character charWrapperValue = mapper.readValue(asArray(quote(String.valueOf(charTest))), Character.class);
+        assertEquals(Character.valueOf(charTest), charWrapperValue);
+
+        final boolean booleanTrueValue = mapper.readValue(asArray(true), Boolean.TYPE);
+        assertTrue(booleanTrueValue);
+
+        final boolean booleanFalseValue = mapper.readValue(asArray(false), Boolean.TYPE);
+        assertFalse(booleanFalseValue);
+
+        final Boolean booleanWrapperTrueValue = mapper.readValue(asArray(Boolean.valueOf(true)), Boolean.class);
+        assertEquals(Boolean.TRUE, booleanWrapperTrueValue);
+    }
+
+    public void testSingleElementArrayDisabled() throws Exception {
+        final ObjectMapper mapper = new ObjectMapper();
+        mapper.disable(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS);
+        try {
+            mapper.readValue("[42]", Integer.class);
+            fail("Single value array didn't throw an exception when DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS is disabled");
+        } catch (JsonMappingException exp) {
+            //Exception was thrown correctly
+        }
+        try {
+            mapper.readValue("[42]", Integer.TYPE);
+            fail("Single value array didn't throw an exception when DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS is disabled");
+        } catch (JsonMappingException exp) {
+            //Exception was thrown correctly
+        }
+
+        try {
+            mapper.readValue("[42.273]", Double.class);
+            fail("Single value array didn't throw an exception when DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS is disabled");
+        } catch (JsonMappingException exp) {
+            //Exception was thrown correctly
+        }
+        try {
+            mapper.readValue("[42.2723]", Double.TYPE);
+            fail("Single value array didn't throw an exception when DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS is disabled");
+        } catch (JsonMappingException exp) {
+            //Exception was thrown correctly
+        }
+
+        try {
+            mapper.readValue("[42342342342342]", Long.class);
+            fail("Single value array didn't throw an exception when DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS is disabled");
+        } catch (JsonMappingException exp) {
+            //Exception was thrown correctly
+        }
+        try {
+            mapper.readValue("[42342342342342342]", Long.TYPE);
+            fail("Single value array didn't throw an exception when DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS is disabled");
+        } catch (JsonMappingException exp) {
+            //Exception was thrown correctly
+        }
+
+        try {
+            mapper.readValue("[42]", Short.class);
+            fail("Single value array didn't throw an exception when DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS is disabled");
+        } catch (JsonMappingException exp) {
+            //Exception was thrown correctly
+        }
+        try {
+            mapper.readValue("[42]", Short.TYPE);
+            fail("Single value array didn't throw an exception when DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS is disabled");
+        } catch (JsonMappingException exp) {
+            //Exception was thrown correctly
+        }
+
+        try {
+            mapper.readValue("[327.2323]", Float.class);
+            fail("Single value array didn't throw an exception when DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS is disabled");
+        } catch (JsonMappingException exp) {
+            //Exception was thrown correctly
+        }
+        try {
+            mapper.readValue("[82.81902]", Float.TYPE);
+            fail("Single value array didn't throw an exception when DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS is disabled");
+        } catch (JsonMappingException exp) {
+            //Exception was thrown correctly
+        }
+
+        try {
+            mapper.readValue("[22]", Byte.class);
+            fail("Single value array didn't throw an exception when DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS is disabled");
+        } catch (JsonMappingException exp) {
+            //Exception was thrown correctly
+        }
+        try {
+            mapper.readValue("[22]", Byte.TYPE);
+            fail("Single value array didn't throw an exception when DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS is disabled");
+        } catch (JsonMappingException exp) {
+            //Exception was thrown correctly
+        }
+
+        try {
+            mapper.readValue("['d']", Character.class);
+            fail("Single value array didn't throw an exception when DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS is disabled");
+        } catch (JsonMappingException exp) {
+            //Exception was thrown correctly
+        }
+        try {
+            mapper.readValue("['d']", Character.TYPE);
+            fail("Single value array didn't throw an exception when DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS is disabled");
+        } catch (JsonMappingException exp) {
+            //Exception was thrown correctly
+        }
+
+        try {
+            mapper.readValue("[true]", Boolean.class);
+            fail("Single value array didn't throw an exception when DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS is disabled");
+        } catch (JsonMappingException exp) {
+            //Exception was thrown correctly
+        }
+        try {
+            mapper.readValue("[true]", Boolean.TYPE);
+            fail("Single value array didn't throw an exception when DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS is disabled");
+        } catch (JsonMappingException exp) {
+            //Exception was thrown correctly
+        }
+    }
+
+    public void testMultiValueArrayException() throws IOException {
+        final ObjectMapper mapper = new ObjectMapper();
+        mapper.enable(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS);
+        
+        try {
+            mapper.readValue("[42,42]", Integer.class);
+            fail("Single value array didn't throw an exception when DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS is disabled");
+        } catch (JsonMappingException exp) {
+            //Exception was thrown correctly
+        }
+        try {
+            mapper.readValue("[42,42]", Integer.TYPE);
+            fail("Single value array didn't throw an exception when DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS is disabled");
+        } catch (JsonMappingException exp) {
+            //Exception was thrown correctly
+        }
+        
+        try {
+            mapper.readValue("[42.273,42.273]", Double.class);
+            fail("Single value array didn't throw an exception when DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS is disabled");
+        } catch (JsonMappingException exp) {
+            //Exception was thrown correctly
+        }
+        try {
+            mapper.readValue("[42.2723,42.273]", Double.TYPE);
+            fail("Single value array didn't throw an exception when DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS is disabled");
+        } catch (JsonMappingException exp) {
+            //Exception was thrown correctly
+        }
+        
+        try {
+            mapper.readValue("[42342342342342,42342342342342]", Long.class);
+            fail("Single value array didn't throw an exception when DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS is disabled");
+        } catch (JsonMappingException exp) {
+            //Exception was thrown correctly
+        }
+        try {
+            mapper.readValue("[42342342342342342,42342342342342]", Long.TYPE);
+            fail("Single value array didn't throw an exception when DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS is disabled");
+        } catch (JsonMappingException exp) {
+            //Exception was thrown correctly
+        }
+        
+        try {
+            mapper.readValue("[42,42]", Short.class);
+            fail("Single value array didn't throw an exception when DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS is disabled");
+        } catch (JsonMappingException exp) {
+            //Exception was thrown correctly
+        }
+        try {
+            mapper.readValue("[42,42]", Short.TYPE);
+            fail("Single value array didn't throw an exception when DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS is disabled");
+        } catch (JsonMappingException exp) {
+            //Exception was thrown correctly
+        }
+        
+        try {
+            mapper.readValue("[327.2323,327.2323]", Float.class);
+            fail("Single value array didn't throw an exception when DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS is disabled");
+        } catch (JsonMappingException exp) {
+            //Exception was thrown correctly
+        }
+        try {
+            mapper.readValue("[82.81902,327.2323]", Float.TYPE);
+            fail("Single value array didn't throw an exception when DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS is disabled");
+        } catch (JsonMappingException exp) {
+            //Exception was thrown correctly
+        }
+        
+        try {
+            mapper.readValue("[22,23]", Byte.class);
+            fail("Single value array didn't throw an exception when DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS is disabled");
+        } catch (JsonMappingException exp) {
+            //Exception was thrown correctly
+        }
+        try {
+            mapper.readValue("[22,23]", Byte.TYPE);
+            fail("Single value array didn't throw an exception when DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS is disabled");
+        } catch (JsonMappingException exp) {
+            //Exception was thrown correctly
+        }
+        
+        try {
+            mapper.readValue(asArray(quote("c") + ","  + quote("d")), Character.class);
+            
+            fail("Single value array didn't throw an exception when DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS is disabled");
+        } catch (JsonMappingException exp) {
+            //Exception was thrown correctly
+        }
+        try {
+            mapper.readValue(asArray(quote("c") + ","  + quote("d")), Character.TYPE);
+            fail("Single value array didn't throw an exception when DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS is disabled");
+        } catch (JsonMappingException exp) {
+            //Exception was thrown correctly
+        }
+        
+        try {
+            mapper.readValue("[true,false]", Boolean.class);
+            fail("Single value array didn't throw an exception when DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS is disabled");
+        } catch (JsonMappingException exp) {
+            //Exception was thrown correctly
+        }
+        try {
+            mapper.readValue("[true,false]", Boolean.TYPE);
+            fail("Single value array didn't throw an exception when DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS is disabled");
+        } catch (JsonMappingException exp) {
+            //Exception was thrown correctly
+        }
+    }
+
+    private static String asArray(Object value) {
+        final String stringVal = value.toString();
+        return new StringBuilder(stringVal.length() + 2).append("[").append(stringVal).append("]").toString();
+    }
+
+    /*
+    /**********************************************************
+    /* Empty String coercion, handling
+    /**********************************************************
+     */
+
+    // by default, should return nulls, n'est pas?
+    public void testEmptyStringForWrappers() throws IOException
+    {
+        WrappersBean bean;
+
+        // by default, ok to rely on defaults
+        bean = MAPPER.readValue("{\"booleanValue\":\"\"}", WrappersBean.class);
+        assertNull(bean.booleanValue);
+        bean = MAPPER.readValue("{\"byteValue\":\"\"}", WrappersBean.class);
+        assertNull(bean.byteValue);
+
+        // char/Character is different... not sure if this should work or not:
+        bean = MAPPER.readValue("{\"charValue\":\"\"}", WrappersBean.class);
+        assertNull(bean.charValue);
+
+        bean = MAPPER.readValue("{\"shortValue\":\"\"}", WrappersBean.class);
+        assertNull(bean.shortValue);
+        bean = MAPPER.readValue("{\"intValue\":\"\"}", WrappersBean.class);
+        assertNull(bean.intValue);
+        bean = MAPPER.readValue("{\"longValue\":\"\"}", WrappersBean.class);
+        assertNull(bean.longValue);
+        bean = MAPPER.readValue("{\"floatValue\":\"\"}", WrappersBean.class);
+        assertNull(bean.floatValue);
+        bean = MAPPER.readValue("{\"doubleValue\":\"\"}", WrappersBean.class);
+        assertNull(bean.doubleValue);
+    }
+
+    public void testEmptyStringForPrimitives() throws IOException
+    {
+        PrimitivesBean bean;
+        bean = MAPPER.readValue("{\"booleanValue\":\"\"}", PrimitivesBean.class);
+        assertFalse(bean.booleanValue);
+        bean = MAPPER.readValue("{\"byteValue\":\"\"}", PrimitivesBean.class);
+        assertEquals((byte) 0, bean.byteValue);
+        bean = MAPPER.readValue("{\"charValue\":\"\"}", PrimitivesBean.class);
+        assertEquals((char) 0, bean.charValue);
+        bean = MAPPER.readValue("{\"shortValue\":\"\"}", PrimitivesBean.class);
+        assertEquals((short) 0, bean.shortValue);
+        bean = MAPPER.readValue("{\"intValue\":\"\"}", PrimitivesBean.class);
+        assertEquals(0, bean.intValue);
+        bean = MAPPER.readValue("{\"longValue\":\"\"}", PrimitivesBean.class);
+        assertEquals(0L, bean.longValue);
+        bean = MAPPER.readValue("{\"floatValue\":\"\"}", PrimitivesBean.class);
+        assertEquals(0.0f, bean.floatValue);
+        bean = MAPPER.readValue("{\"doubleValue\":\"\"}", PrimitivesBean.class);
+        assertEquals(0.0, bean.doubleValue);
+    }
+}
+
diff --git a/src/test/java/com/fasterxml/jackson/databind/deser/JDKStringLikeTypesTest.java b/src/test/java/com/fasterxml/jackson/databind/deser/JDKStringLikeTypesTest.java
new file mode 100644
index 0000000..cef00c1
--- /dev/null
+++ b/src/test/java/com/fasterxml/jackson/databind/deser/JDKStringLikeTypesTest.java
@@ -0,0 +1,477 @@
+package com.fasterxml.jackson.databind.deser;
+
+import java.io.*;
+import java.net.*;
+import java.nio.ByteBuffer;
+import java.nio.charset.Charset;
+import java.util.Currency;
+import java.util.Locale;
+import java.util.UUID;
+import java.util.regex.Pattern;
+
+import com.fasterxml.jackson.annotation.*;
+import com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility;
+import com.fasterxml.jackson.core.Base64Variants;
+import com.fasterxml.jackson.core.JsonParser;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.*;
+import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
+import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
+import com.fasterxml.jackson.databind.exc.InvalidFormatException;
+import com.fasterxml.jackson.databind.module.SimpleModule;
+import com.fasterxml.jackson.databind.util.TokenBuffer;
+
+public class JDKStringLikeTypesTest extends BaseMapTest
+{
+    static class ParamClassBean
+    {
+         public String name = "bar";
+         public Class<String> clazz ;
+
+         public ParamClassBean() { }
+         public ParamClassBean(String name) {
+             this.name = name;
+             clazz = String.class;
+         }
+    }
+
+    // [databind#429]
+    static class StackTraceBean {
+        public final static int NUM = 13;
+
+        @JsonProperty("Location")
+        @JsonDeserialize(using=MyStackTraceElementDeserializer.class)
+        protected StackTraceElement location;    
+    }
+
+    @SuppressWarnings("serial")
+    static class MyStackTraceElementDeserializer extends StdDeserializer<StackTraceElement>
+    {
+        public MyStackTraceElementDeserializer() { super(StackTraceElement.class); }
+        
+        @Override
+        public StackTraceElement deserialize(JsonParser jp,
+                DeserializationContext ctxt) throws IOException, JsonProcessingException {
+            jp.skipChildren();
+            return new StackTraceElement("a", "b", "b", StackTraceBean.NUM);
+        }
+        
+    }
+
+    /*
+    /**********************************************************
+    /* Test methods
+    /**********************************************************
+     */
+
+    private final ObjectMapper MAPPER = objectMapper();
+
+    // [databind#239]
+    public void testByteBuffer() throws Exception
+    {
+        byte[] INPUT = new byte[] { 1, 3, 9, -1, 6 };
+        String exp = MAPPER.writeValueAsString(INPUT);
+        ByteBuffer result = MAPPER.readValue(exp,  ByteBuffer.class); 
+        assertNotNull(result);
+        assertEquals(INPUT.length, result.remaining());
+        for (int i = 0; i < INPUT.length; ++i) {
+            assertEquals(INPUT[i], result.get());
+        }
+        assertEquals(0, result.remaining());
+    }
+
+    public void testCharset() throws Exception
+    {
+        Charset UTF8 = Charset.forName("UTF-8");
+        assertSame(UTF8, MAPPER.readValue(quote("UTF-8"), Charset.class));
+    }
+    
+    public void testClass() throws IOException
+    {
+        ObjectMapper mapper = new ObjectMapper();
+        assertSame(String.class, mapper.readValue(quote("java.lang.String"), Class.class));
+
+        // then primitive types
+        assertSame(Boolean.TYPE, mapper.readValue(quote("boolean"), Class.class));
+        assertSame(Byte.TYPE, mapper.readValue(quote("byte"), Class.class));
+        assertSame(Short.TYPE, mapper.readValue(quote("short"), Class.class));
+        assertSame(Character.TYPE, mapper.readValue(quote("char"), Class.class));
+        assertSame(Integer.TYPE, mapper.readValue(quote("int"), Class.class));
+        assertSame(Long.TYPE, mapper.readValue(quote("long"), Class.class));
+        assertSame(Float.TYPE, mapper.readValue(quote("float"), Class.class));
+        assertSame(Double.TYPE, mapper.readValue(quote("double"), Class.class));
+        assertSame(Void.TYPE, mapper.readValue(quote("void"), Class.class));
+    }
+
+    public void testClassWithParams() throws IOException
+    {
+        String json = MAPPER.writeValueAsString(new ParamClassBean("Foobar"));
+
+        ParamClassBean result = MAPPER.readValue(json, ParamClassBean.class);
+        assertEquals("Foobar", result.name);
+        assertSame(String.class, result.clazz);
+    }
+
+    public void testClassAsArray() throws Exception
+    {
+        final ObjectMapper mapper = new ObjectMapper();        
+        Class<?> result = mapper
+                    .readerFor(Class.class)
+                    .with(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS)
+                    .readValue(quote(String.class.getName()));
+        assertEquals(String.class, result);
+
+        try {
+            mapper
+                .readerFor(Class.class)
+                .without(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS)
+                .readValue("[" + quote(String.class.getName()) + "]");
+            fail("Did not throw exception when UNWRAP_SINGLE_VALUE_ARRAYS feature was disabled and attempted to read a Class array containing one element");
+        } catch (JsonMappingException e) {
+            verifyException(e, "out of START_ARRAY token");
+        }
+
+        try {
+           mapper
+               .readerFor(Class.class)
+               .with(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS)
+               .readValue("[" + quote(Object.class.getName()) + "," + quote(Object.class.getName()) +"]"); 
+           fail("Did not throw exception when UNWRAP_SINGLE_VALUE_ARRAYS feature was enabled and attempted to read a Class array containing two elements");
+        } catch (JsonMappingException e) {
+            verifyException(e, "more than a single value in");
+        }               
+        result = mapper
+                .readerFor(Class.class)
+                .with(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS)
+                .readValue("[" + quote(String.class.getName()) + "]");
+        assertEquals(String.class, result);
+    }
+
+    public void testCurrency() throws IOException
+    {
+        Currency usd = Currency.getInstance("USD");
+        assertEquals(usd, new ObjectMapper().readValue(quote("USD"), Currency.class));
+    }
+
+    public void testFile() throws Exception
+    {
+        // Not portable etc... has to do:
+        File src = new File("/test").getAbsoluteFile();
+        String abs = src.getAbsolutePath();
+
+        // escape backslashes (for portability with windows)
+        String json = MAPPER.writeValueAsString(abs);
+        File result = MAPPER.readValue(json, File.class);
+        assertEquals(abs, result.getAbsolutePath());
+
+        // Then #170
+        final ObjectMapper mapper2 = new ObjectMapper();
+        mapper2.setVisibility(PropertyAccessor.CREATOR, Visibility.NONE);
+
+        result = mapper2.readValue(json, File.class);
+        assertEquals(abs, result.getAbsolutePath());
+    }
+
+    public void testLocale() throws IOException
+    {
+        assertEquals(new Locale("en"), MAPPER.readValue(quote("en"), Locale.class));
+        assertEquals(new Locale("es", "ES"), MAPPER.readValue(quote("es_ES"), Locale.class));
+        assertEquals(new Locale("FI", "fi", "savo"),
+                MAPPER.readValue(quote("fi_FI_savo"), Locale.class));
+        assertEquals(new Locale("en", "US"),
+                MAPPER.readValue(quote("en-US"), Locale.class));
+
+        // [databind#1123]
+        Locale loc = MAPPER.readValue(quote(""), Locale.class);
+        assertSame(Locale.ROOT, loc);
+    }
+
+    public void testCharSequence() throws IOException
+    {
+        CharSequence cs = MAPPER.readValue("\"abc\"", CharSequence.class);
+        assertEquals(String.class, cs.getClass());
+        assertEquals("abc", cs.toString());
+    }
+
+    public void testInetAddress() throws IOException
+    {
+        InetAddress address = MAPPER.readValue(quote("127.0.0.1"), InetAddress.class);
+        assertEquals("127.0.0.1", address.getHostAddress());
+
+        // should we try resolving host names? That requires connectivity... 
+        final String HOST = "google.com";
+        address = MAPPER.readValue(quote(HOST), InetAddress.class);
+        assertEquals(HOST, address.getHostName());
+    }
+
+    public void testInetSocketAddress() throws IOException
+    {
+        InetSocketAddress address = MAPPER.readValue(quote("127.0.0.1"), InetSocketAddress.class);
+        assertEquals("127.0.0.1", address.getAddress().getHostAddress());
+
+        InetSocketAddress ip6 = MAPPER.readValue(
+                quote("2001:db8:85a3:8d3:1319:8a2e:370:7348"), InetSocketAddress.class);
+        assertEquals("2001:db8:85a3:8d3:1319:8a2e:370:7348", ip6.getAddress().getHostAddress());
+
+        InetSocketAddress ip6port = MAPPER.readValue(
+                quote("[2001:db8:85a3:8d3:1319:8a2e:370:7348]:443"), InetSocketAddress.class);
+        assertEquals("2001:db8:85a3:8d3:1319:8a2e:370:7348", ip6port.getAddress().getHostAddress());
+        assertEquals(443, ip6port.getPort());
+
+        // should we try resolving host names? That requires connectivity...
+        final String HOST = "www.google.com";
+        address = MAPPER.readValue(quote(HOST), InetSocketAddress.class);
+        assertEquals(HOST, address.getHostName());
+
+        final String HOST_AND_PORT = HOST+":80";
+        address = MAPPER.readValue(quote(HOST_AND_PORT), InetSocketAddress.class);
+        assertEquals(HOST, address.getHostName());
+        assertEquals(80, address.getPort());
+    }
+
+    public void testRegexps() throws IOException
+    {
+        final String PATTERN_STR = "abc:\\s?(\\d+)";
+        Pattern exp = Pattern.compile(PATTERN_STR);
+        /* Ok: easiest way is to just serialize first; problem
+         * is the backslash
+         */
+        String json = MAPPER.writeValueAsString(exp);
+        Pattern result = MAPPER.readValue(json, Pattern.class);
+        assertEquals(exp.pattern(), result.pattern());
+    }
+    public void testStackTraceElement() throws Exception
+    {
+        StackTraceElement elem = null;
+        try {
+            throw new IllegalStateException();
+        } catch (Exception e) {
+            elem = e.getStackTrace()[0];
+        }
+        String json = MAPPER.writeValueAsString(elem);
+        StackTraceElement back = MAPPER.readValue(json, StackTraceElement.class);
+        
+        assertEquals("testStackTraceElement", back.getMethodName());
+        assertEquals(elem.getLineNumber(), back.getLineNumber());
+        assertEquals(elem.getClassName(), back.getClassName());
+        assertEquals(elem.isNativeMethod(), back.isNativeMethod());
+        assertTrue(back.getClassName().endsWith("JDKStringLikeTypesTest"));
+        assertFalse(back.isNativeMethod());
+    }
+
+    // [databind#429]
+    public void testStackTraceElementWithCustom() throws Exception
+    {
+        // first, via bean that contains StackTraceElement
+        StackTraceBean bean = MAPPER.readValue(aposToQuotes("{'Location':'foobar'}"),
+                StackTraceBean.class);
+        assertNotNull(bean);
+        assertNotNull(bean.location);
+        assertEquals(StackTraceBean.NUM, bean.location.getLineNumber());
+
+        // and then directly, iff registered
+        ObjectMapper mapper = new ObjectMapper();
+        SimpleModule module = new SimpleModule();
+        module.addDeserializer(StackTraceElement.class, new MyStackTraceElementDeserializer());
+        mapper.registerModule(module);
+        
+        StackTraceElement elem = mapper.readValue("123", StackTraceElement.class);
+        assertNotNull(elem);
+        assertEquals(StackTraceBean.NUM, elem.getLineNumber());
+ 
+        // and finally, even as part of real exception
+        
+        IOException ioe = mapper.readValue(aposToQuotes("{'stackTrace':[ 123, 456 ]}"),
+                IOException.class);
+        assertNotNull(ioe);
+        StackTraceElement[] traces = ioe.getStackTrace();
+        assertNotNull(traces);
+        assertEquals(2, traces.length);
+        assertEquals(StackTraceBean.NUM, traces[0].getLineNumber());
+        assertEquals(StackTraceBean.NUM, traces[1].getLineNumber());
+    }
+
+    public void testStringBuilder() throws Exception
+    {
+        StringBuilder sb = MAPPER.readValue(quote("abc"), StringBuilder.class);
+        assertEquals("abc", sb.toString());
+    }
+
+    public void testURI() throws Exception
+    {
+        final ObjectReader reader = MAPPER.readerFor(URI.class);
+        final URI value = new URI("http://foo.com");
+        assertEquals(value, reader.readValue("\""+value.toString()+"\""));
+
+        // Also: empty String should be handled properly
+        URI result = reader.readValue(quote(""));
+        assertNotNull(result);
+        assertEquals(URI.create(""), result);
+        
+        // and finally: broken URI should give proper failure
+        try {
+            result = reader.readValue(quote("a b"));
+            fail("Should not accept malformed URI, instead got: "+result);
+        } catch (InvalidFormatException e) {
+            verifyException(e, "not a valid textual representation");
+        }
+    }
+
+    public void testURIAsArray() throws Exception
+    {
+        final ObjectReader reader = MAPPER.readerFor(URI.class);
+        final URI value = new URI("http://foo.com");
+        try {
+            reader.without(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS)
+                .readValue("[\""+value.toString()+"\"]");
+            fail("Did not throw exception for single value array when UNWRAP_SINGLE_VALUE_ARRAYS is disabled");
+        } catch (JsonMappingException e) {
+            verifyException(e, "out of START_ARRAY token");
+        }
+        
+        try {
+            reader.with(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS)
+                    .readValue("[\""+value.toString()+"\",\""+value.toString()+"\"]");
+            fail("Did not throw exception for single value array when there were multiple values");
+        } catch (JsonMappingException e) {
+            verifyException(e, "more than a single value in the array");
+        }
+        assertEquals(value,
+                reader.with(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS)
+                .readValue("[\""+value.toString()+"\"]"));
+    }
+
+    public void testURL() throws Exception
+    {
+        URL exp = new URL("http://foo.com");
+        assertEquals(exp, MAPPER.readValue("\""+exp.toString()+"\"", URL.class));
+
+        // trivial case; null to null, embedded URL to URL
+        TokenBuffer buf = new TokenBuffer(null, false);
+        buf.writeObject(null);
+        assertNull(MAPPER.readValue(buf.asParser(), URL.class));
+        buf.close();
+
+        // then, URLitself come as is:
+        buf = new TokenBuffer(null, false);
+        buf.writeObject(exp);
+        assertSame(exp, MAPPER.readValue(buf.asParser(), URL.class));
+        buf.close();
+
+        // and finally, invalid URL should be handled appropriately too
+        try {
+            URL result = MAPPER.readValue(quote("a b"), URL.class);
+            fail("Should not accept malformed URI, instead got: "+result);
+        } catch (InvalidFormatException e) {
+            verifyException(e, "not a valid textual representation");
+        }
+    }
+
+    public void testUUID() throws Exception
+    {
+        final ObjectMapper mapper = objectMapper();
+        
+        final String NULL_UUID = "00000000-0000-0000-0000-000000000000";
+        // first, couple of generated UUIDs:
+        for (String value : new String[] {
+                "76e6d183-5f68-4afa-b94a-922c1fdb83f8",
+                "540a88d1-e2d8-4fb1-9396-9212280d0a7f",
+                "2c9e441d-1cd0-472d-9bab-69838f877574",
+                "591b2869-146e-41d7-8048-e8131f1fdec5",
+                "82994ac2-7b23-49f2-8cc5-e24cf6ed77be",
+                "00000007-0000-0000-0000-000000000000"
+        }) {
+            
+            mapper.disable(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS);
+            
+            UUID uuid = UUID.fromString(value);
+            assertEquals(uuid,
+                    mapper.readValue(quote(value), UUID.class));
+            
+            try {
+                mapper.readValue("[" + quote(value) + "]", UUID.class);
+                fail("Exception was not thrown when UNWRAP_SINGLE_VALUE_ARRAYS is disabled and attempted to read a single value array as a single element");
+            } catch (JsonMappingException exp) {
+                //Exception thrown successfully
+            }
+            
+            mapper.enable(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS);
+            
+            assertEquals(uuid,
+                    mapper.readValue("[" + quote(value) + "]", UUID.class));
+            
+            try {
+                mapper.readValue("[" + quote(value) + "," + quote(value) + "]", UUID.class);
+                fail("Exception was not thrown when UNWRAP_SINGLE_VALUE_ARRAYS is enabled and attempted to read a multi value array as a single element");
+            } catch (JsonMappingException exp) {
+                //Exception thrown successfully
+            }
+        }
+        // then use templating; note that these are not exactly valid UUIDs
+        // wrt spec (type bits etc), but JDK UUID should deal ok
+        final String TEMPL = NULL_UUID;
+        final String chars = "123456789abcdefABCDEF";
+
+        for (int i = 0; i < chars.length(); ++i) {
+            String value = TEMPL.replace('0', chars.charAt(i));
+            assertEquals(UUID.fromString(value).toString(),
+                    mapper.readValue(quote(value), UUID.class).toString());
+        }
+
+        // also: see if base64 encoding works as expected
+        String base64 = Base64Variants.getDefaultVariant().encode(new byte[16]);
+        assertEquals(UUID.fromString(NULL_UUID),
+                mapper.readValue(quote(base64), UUID.class));
+    }
+
+    public void testUUIDInvalid() throws Exception
+    {
+        // and finally, exception handling too [databind#1000], for invalid cases
+        try {
+            MAPPER.readValue(quote("abcde"), UUID.class);
+            fail("Should fail on invalid UUID string");
+        } catch (InvalidFormatException e) {
+            verifyException(e, "UUID has to be represented by standard");
+        }
+        try {
+            MAPPER.readValue(quote("76e6d183-5f68-4afa-b94a-922c1fdb83fx"), UUID.class);
+            fail("Should fail on invalid UUID string");
+        } catch (InvalidFormatException e) {
+            verifyException(e, "non-hex character 'x'");
+        }
+        // should also test from-bytes version, but that's trickier... leave for now.
+    }
+
+    public void testUUIDAux() throws Exception
+    {
+        // [JACKSON-393] fix:
+        final UUID value = UUID.fromString("76e6d183-5f68-4afa-b94a-922c1fdb83f8");
+
+        // first, null should come as null
+        TokenBuffer buf = new TokenBuffer(null, false);
+        buf.writeObject(null);
+        assertNull(MAPPER.readValue(buf.asParser(), UUID.class));
+        buf.close();
+
+        // then, UUID itself come as is:
+        buf = new TokenBuffer(null, false);
+        buf.writeObject(value);
+        assertSame(value, MAPPER.readValue(buf.asParser(), UUID.class));
+
+        // and finally from byte[]
+        // oh crap; JDK UUID just... sucks. Not even byte[] accessors or constructors? Huh?
+        ByteArrayOutputStream bytes = new ByteArrayOutputStream();
+        DataOutputStream out = new DataOutputStream(bytes);
+        out.writeLong(value.getMostSignificantBits());
+        out.writeLong(value.getLeastSignificantBits());
+        byte[] data = bytes.toByteArray();
+        assertEquals(16, data.length);
+        
+        buf.writeObject(data);
+
+        UUID value2 = MAPPER.readValue(buf.asParser(), UUID.class);
+        
+        assertEquals(value, value2);
+        buf.close();
+    }
+}
diff --git a/src/test/java/com/fasterxml/jackson/databind/deser/KeyDeser1429Test.java b/src/test/java/com/fasterxml/jackson/databind/deser/KeyDeser1429Test.java
new file mode 100644
index 0000000..7922928
--- /dev/null
+++ b/src/test/java/com/fasterxml/jackson/databind/deser/KeyDeser1429Test.java
@@ -0,0 +1,48 @@
+package com.fasterxml.jackson.databind.deser;
+
+import java.util.Map;
+
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonValue;
+import com.fasterxml.jackson.core.type.TypeReference;
+import com.fasterxml.jackson.databind.*;
+
+public class KeyDeser1429Test extends BaseMapTest
+{
+    static class FullName {
+        private String _firstname, _lastname;
+
+        private FullName(String firstname, String lastname) {
+            _firstname = firstname;
+            _lastname = lastname;
+        }
+
+        @JsonCreator
+        public static FullName valueOf(String value) {
+            String[] mySplit = value.split("\\.");
+            return new FullName(mySplit[0], mySplit[1]);
+        }
+
+        public static FullName valueOf(String firstname, String lastname) {
+            return new FullName(firstname, lastname);
+        }
+
+        @JsonValue
+        @Override
+        public String toString() {
+            return _firstname + "." + _lastname;
+        }
+    }
+
+    public void testDeserializeKeyViaFactory() throws Exception
+    {
+        Map<FullName, Double> map =
+            new ObjectMapper().readValue("{\"first.last\": 42}",
+                    new TypeReference<Map<FullName, Double>>() { });
+        Map.Entry<FullName, Double> entry = map.entrySet().iterator().next();
+        FullName key = entry.getKey();
+        assertEquals(key._firstname, "first");
+        assertEquals(key._lastname, "last");
+        assertEquals(entry.getValue().doubleValue(), 42, 0);
+    }
+}
diff --git a/src/test/java/com/fasterxml/jackson/databind/deser/TestNullHandling.java b/src/test/java/com/fasterxml/jackson/databind/deser/NullHandlingTest.java
similarity index 64%
rename from src/test/java/com/fasterxml/jackson/databind/deser/TestNullHandling.java
rename to src/test/java/com/fasterxml/jackson/databind/deser/NullHandlingTest.java
index 550e8b7..21eeb3c 100644
--- a/src/test/java/com/fasterxml/jackson/databind/deser/TestNullHandling.java
+++ b/src/test/java/com/fasterxml/jackson/databind/deser/NullHandlingTest.java
@@ -12,9 +12,10 @@
 import com.fasterxml.jackson.annotation.JsonTypeInfo;
 import com.fasterxml.jackson.core.*;
 import com.fasterxml.jackson.databind.*;
+import com.fasterxml.jackson.databind.deser.JDKScalarsTest.PrimitivesBean;
 import com.fasterxml.jackson.databind.module.SimpleModule;
 
-public class TestNullHandling extends BaseMapTest
+public class NullHandlingTest extends BaseMapTest
 {
     static class FunnyNullDeserializer extends JsonDeserializer<String>
     {
@@ -40,7 +41,7 @@
             return this.any;
         }
     }
-
+    
     // [databind#1601]
     static class RootData {
         public String name;
@@ -78,12 +79,21 @@
         }
     }
 
+    private final ObjectMapper MAPPER = objectMapper();
+
     /*
     /**********************************************************
     /* Test methods
     /**********************************************************
      */
 
+    public void testNull() throws Exception
+    {
+        // null doesn't really have a type, fake by assuming Object
+        Object result = MAPPER.readValue("   null", Object.class);
+        assertNull(result);
+    }  
+    
     public void testAnySetterNulls() throws Exception {
         ObjectMapper mapper = new ObjectMapper();
         SimpleModule module = new SimpleModule("test", Version.unknownVersion());
@@ -109,7 +119,6 @@
         assertEquals("funny", result.getAny().get(fieldName));
     }
 
-    // Test for [JACKSON-643]
     public void testCustomRootNulls() throws Exception
     {
         ObjectMapper mapper = new ObjectMapper();
@@ -129,7 +138,83 @@
         assertEquals("funny", str);
     }
 
-    // Test for [#407]
+    public void testNullForPrimitives() throws IOException
+    {
+        // by default, ok to rely on defaults
+        PrimitivesBean bean = MAPPER.readValue(
+                "{\"intValue\":null, \"booleanValue\":null, \"doubleValue\":null}",
+                PrimitivesBean.class);
+        assertNotNull(bean);
+        assertEquals(0, bean.intValue);
+        assertEquals(false, bean.booleanValue);
+        assertEquals(0.0, bean.doubleValue);
+
+        bean = MAPPER.readValue("{\"byteValue\":null, \"longValue\":null, \"floatValue\":null}",
+                PrimitivesBean.class);
+        assertNotNull(bean);
+        assertEquals((byte) 0, bean.byteValue);
+        assertEquals(0L, bean.longValue);
+        assertEquals(0.0f, bean.floatValue);
+        
+        // but not when enabled
+        final ObjectReader reader = MAPPER
+                .readerFor(PrimitivesBean.class)
+                .with(DeserializationFeature.FAIL_ON_NULL_FOR_PRIMITIVES);
+        // boolean
+        try {
+            reader.readValue("{\"booleanValue\":null}");
+            fail("Expected failure for boolean + null");
+        } catch (JsonMappingException e) {
+            verifyException(e, "Can not map JSON null into type boolean");
+        }
+        // byte/char/short/int/long
+        try {
+            reader.readValue("{\"byteValue\":null}");
+            fail("Expected failure for byte + null");
+        } catch (JsonMappingException e) {
+            verifyException(e, "Can not map JSON null into type byte");
+        }
+        try {
+            reader.readValue("{\"charValue\":null}");
+            fail("Expected failure for char + null");
+        } catch (JsonMappingException e) {
+            verifyException(e, "Can not map JSON null into type char");
+        }
+        try {
+            reader.readValue("{\"shortValue\":null}");
+            fail("Expected failure for short + null");
+        } catch (JsonMappingException e) {
+            verifyException(e, "Can not map JSON null into type short");
+        }
+        try {
+            reader.readValue("{\"intValue\":null}");
+            fail("Expected failure for int + null");
+        } catch (JsonMappingException e) {
+            verifyException(e, "Can not map JSON null into type int");
+        }
+        try {
+            reader.readValue("{\"longValue\":null}");
+            fail("Expected failure for long + null");
+        } catch (JsonMappingException e) {
+            verifyException(e, "Can not map JSON null into type long");
+        }
+
+        // float/double
+        try {
+            reader.readValue("{\"floatValue\":null}");
+            fail("Expected failure for float + null");
+        } catch (JsonMappingException e) {
+            verifyException(e, "Can not map JSON null into type float");
+        }
+        try {
+            reader.readValue("{\"doubleValue\":null}");
+            fail("Expected failure for double + null");
+        } catch (JsonMappingException e) {
+            verifyException(e, "Can not map JSON null into type double");
+        }
+    }
+    
+    // [databind#407]
     public void testListOfNulls() throws Exception
     {
         ObjectMapper mapper = new ObjectMapper();
@@ -178,19 +263,19 @@
     }
 
     // [databind#1601]
-    public void testPolymorphicDataNull() throws Exception {
-        ObjectMapper mapper = new ObjectMapper();
+    public void testPolymorphicDataNull() throws Exception
+    {
         String typeA =
                 "{\"name\":\"TypeAData\", \"type\":\"TypeA\", \"proxy\":{\"aValue\":\"This works!\"}}";
-        RootData typeAData = mapper.readValue(typeA, RootData.class);
+        RootData typeAData = MAPPER.readValue(typeA, RootData.class);
         assertEquals("No value for aValue!?", "This works!", ((TypeA) typeAData.proxy).aValue);
         String typeB =
                 "{\"name\":\"TypeBData\", \"type\":\"TypeB\", \"proxy\":{\"bValue\":\"This works too!\"}}";
-        RootData typeBData = mapper.readValue(typeB, RootData.class);
+        RootData typeBData = MAPPER.readValue(typeB, RootData.class);
         assertEquals("No value for bValue!?", "This works too!", ((TypeB) typeBData.proxy).bValue);
         String typeBNull =
                 "{\"name\":\"TypeBData\", \"type\":\"TypeB\", \"proxy\": null}";
-        RootData typeBNullData = mapper.readValue(typeBNull, RootData.class);
+        RootData typeBNullData = MAPPER.readValue(typeBNull, RootData.class);
         assertNull("Proxy should be null!", typeBNullData.proxy);
     }
 }
diff --git a/src/test/java/com/fasterxml/jackson/databind/deser/NumberDeserTest.java b/src/test/java/com/fasterxml/jackson/databind/deser/NumberDeserTest.java
deleted file mode 100644
index b5bcf9c..0000000
--- a/src/test/java/com/fasterxml/jackson/databind/deser/NumberDeserTest.java
+++ /dev/null
@@ -1,132 +0,0 @@
-package com.fasterxml.jackson.databind.deser;
-
-import java.io.IOException;
-import java.math.BigDecimal;
-import java.math.BigInteger;
-
-import com.fasterxml.jackson.core.*;
-import com.fasterxml.jackson.databind.*;
-import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
-
-public class NumberDeserTest extends BaseMapTest
-{
-    /*
-    /**********************************************************************
-    /* Helper classes, beans
-    /**********************************************************************
-     */
-
-    static class MyBeanHolder {
-        public Long id;
-        public MyBeanDefaultValue defaultValue;
-    }
-
-    static class MyBeanDefaultValue
-    {
-        public MyBeanValue value;
-    }
-
-    @JsonDeserialize(using=MyBeanDeserializer.class)
-    static class MyBeanValue {
-        public BigDecimal decimal;
-        public MyBeanValue() { this(null); }
-        public MyBeanValue(BigDecimal d) { this.decimal = d; }
-    }
-
-    /*
-    /**********************************************************************
-    /* Helper classes, serializers/deserializers/resolvers
-    /**********************************************************************
-     */
-    
-    static class MyBeanDeserializer extends JsonDeserializer<MyBeanValue>
-    {
-        @Override
-        public MyBeanValue deserialize(JsonParser jp, DeserializationContext ctxt)
-                throws IOException
-        {
-            return new MyBeanValue(jp.getDecimalValue());
-        }
-    }
-
-    /*
-    /**********************************************************************
-    /* Unit tests
-    /**********************************************************************
-     */
-
-    final ObjectMapper MAPPER = new ObjectMapper();
-    
-    public void testNaN() throws Exception
-    {
-        Float result = MAPPER.readValue(" \"NaN\"", Float.class);
-        assertEquals(Float.valueOf(Float.NaN), result);
-
-        Double d = MAPPER.readValue(" \"NaN\"", Double.class);
-        assertEquals(Double.valueOf(Double.NaN), d);
-
-        Number num = MAPPER.readValue(" \"NaN\"", Number.class);
-        assertEquals(Double.valueOf(Double.NaN), num);
-    }
-
-    public void testDoubleInf() throws Exception
-    {
-        Double result = MAPPER.readValue(" \""+Double.POSITIVE_INFINITY+"\"", Double.class);
-        assertEquals(Double.valueOf(Double.POSITIVE_INFINITY), result);
-
-        result = MAPPER.readValue(" \""+Double.NEGATIVE_INFINITY+"\"", Double.class);
-        assertEquals(Double.valueOf(Double.NEGATIVE_INFINITY), result);
-    }
-
-    // [JACKSON-349]
-    public void testEmptyAsNumber() throws Exception
-    {
-        assertNull(MAPPER.readValue(quote(""), Integer.class));
-        assertNull(MAPPER.readValue(quote(""), Long.class));
-        assertNull(MAPPER.readValue(quote(""), Float.class));
-        assertNull(MAPPER.readValue(quote(""), Double.class));
-        assertNull(MAPPER.readValue(quote(""), BigInteger.class));
-        assertNull(MAPPER.readValue(quote(""), BigDecimal.class));
-    }
-
-    // // Tests for [JACKSON-668]
-
-    public void testDeserializeDecimalHappyPath() throws Exception {
-        String json = "{\"defaultValue\": { \"value\": 123 } }";
-        MyBeanHolder result = MAPPER.readValue(json, MyBeanHolder.class);
-        assertEquals(BigDecimal.valueOf(123), result.defaultValue.value.decimal);
-    }
-
-    public void testDeserializeDecimalProperException() throws Exception {
-        String json = "{\"defaultValue\": { \"value\": \"123\" } }";
-        try {
-            MAPPER.readValue(json, MyBeanHolder.class);
-            fail("should have raised exception");
-        } catch (JsonProcessingException e) {
-            verifyException(e, "not numeric");
-        }
-    }
-
-    public void testDeserializeDecimalProperExceptionWhenIdSet() throws Exception {
-        String json = "{\"id\": 5, \"defaultValue\": { \"value\": \"123\" } }";
-        try {
-            MyBeanHolder result = MAPPER.readValue(json, MyBeanHolder.class);
-            fail("should have raised exception instead value was set to " + result.defaultValue.value.decimal.toString());
-        } catch (JsonProcessingException e) {
-            verifyException(e, "not numeric");
-        }
-    }
-
-    // And then [databind#852]
-    public void testScientificNotationForString() throws Exception
-    {
-        Object ob = MAPPER.readValue("\"3E-8\"", Number.class);
-        assertEquals(Double.class, ob.getClass());
-        ob = MAPPER.readValue("\"3e-8\"", Number.class);
-        assertEquals(Double.class, ob.getClass());
-        ob = MAPPER.readValue("\"300000000\"", Number.class);
-        assertEquals(Integer.class, ob.getClass());
-        ob = MAPPER.readValue("\"123456789012\"", Number.class);
-        assertEquals(Long.class, ob.getClass());
-    }
-}
diff --git a/src/test/java/com/fasterxml/jackson/failing/ReadWriteOnlyProp935Test.java b/src/test/java/com/fasterxml/jackson/databind/deser/ReadOrWriteOnlyTest.java
similarity index 67%
rename from src/test/java/com/fasterxml/jackson/failing/ReadWriteOnlyProp935Test.java
rename to src/test/java/com/fasterxml/jackson/databind/deser/ReadOrWriteOnlyTest.java
index afb93ab..0afd3ff 100644
--- a/src/test/java/com/fasterxml/jackson/failing/ReadWriteOnlyProp935Test.java
+++ b/src/test/java/com/fasterxml/jackson/databind/deser/ReadOrWriteOnlyTest.java
@@ -1,9 +1,11 @@
-package com.fasterxml.jackson.failing;
+package com.fasterxml.jackson.databind.deser;
+
+import java.beans.ConstructorProperties;
 
 import com.fasterxml.jackson.annotation.JsonProperty;
 import com.fasterxml.jackson.databind.*;
 
-public class ReadWriteOnlyProp935Test extends BaseMapTest
+public class ReadOrWriteOnlyTest extends BaseMapTest
 {
     // for [databind#935], verify read/write-only cases
     static class ReadXWriteY {
@@ -47,7 +49,22 @@
         public void setLastName(String n) {
             lastName = n;
         }
-    }    
+    }
+
+    // for [databind#1345], emulate way Lombok embellishes classes
+    static class Foo1345 {
+        @JsonProperty(access=JsonProperty.Access.READ_ONLY)
+        public String id;
+        public String name;
+
+        @ConstructorProperties({ "id", "name" })
+        public Foo1345(String id, String name) {
+            this.id = id;
+            this.name = name;
+        }
+
+        protected Foo1345() { }
+    }
 
     /*
     /**********************************************************
@@ -56,7 +73,7 @@
      */
 
     private final ObjectMapper MAPPER = new ObjectMapper();
-    
+
     // [databind#935]
     public void testReadOnlyAndWriteOnly() throws Exception
     {
@@ -65,14 +82,22 @@
 
         ReadXWriteY result = MAPPER.readValue("{\"x\":5, \"y\":6}", ReadXWriteY.class);
         assertNotNull(result);
-        assertEquals(0, result.x);
+        assertEquals(1, result.x);
         assertEquals(6, result.y);
     }
 
-    public void testReadOnl935() throws Exception
+    public void testReadOnly935() throws Exception
     {
         String json = MAPPER.writeValueAsString(new Pojo935());
         Pojo935 result = MAPPER.readValue(json, Pojo935.class);
         assertNotNull(result);
     }
+
+    public void testReadOnly1345() throws Exception
+    {
+        Foo1345 result = MAPPER.readValue("{\"name\":\"test\"}", Foo1345.class);
+        assertNotNull(result);
+        assertEquals("test", result.name);
+        assertNull(result.id);
+    }
 }
diff --git a/src/test/java/com/fasterxml/jackson/databind/deser/TestAnnotationIgnore.java b/src/test/java/com/fasterxml/jackson/databind/deser/TestAnnotationIgnore.java
index b254a4f..74c656c 100644
--- a/src/test/java/com/fasterxml/jackson/databind/deser/TestAnnotationIgnore.java
+++ b/src/test/java/com/fasterxml/jackson/databind/deser/TestAnnotationIgnore.java
@@ -47,8 +47,7 @@
     
     public void testSimpleIgnore() throws Exception
     {
-        SizeClassIgnore result = MAPPER.readValue
-            ("{ \"x\":1, \"y\" : 2 }",
+        SizeClassIgnore result = MAPPER.readValue("{ \"x\":1, \"y\" : 2 }",
              SizeClassIgnore.class);
         // x should be set, y not
         assertEquals(1, result._x);
diff --git a/src/test/java/com/fasterxml/jackson/databind/deser/TestAnyProperties.java b/src/test/java/com/fasterxml/jackson/databind/deser/TestAnyProperties.java
index 5b8c104..fb7ef8e 100644
--- a/src/test/java/com/fasterxml/jackson/databind/deser/TestAnyProperties.java
+++ b/src/test/java/com/fasterxml/jackson/databind/deser/TestAnyProperties.java
@@ -135,6 +135,33 @@
         }
     }
     
+	static class JsonAnySetterOnMap {
+		public int id;
+
+		@JsonAnySetter
+		protected HashMap<String, String> other = new HashMap<String, String>();
+
+		@JsonAnyGetter
+		public Map<String, String> any() {
+			return other;
+		}
+
+	}
+
+	static class JsonAnySetterOnNullMap {
+		public int id;
+
+		@JsonAnySetter
+		protected HashMap<String, String> other;
+
+		@JsonAnyGetter
+		public Map<String, String> any() {
+			return other;
+		}
+
+	}
+
+    
     /*
     /**********************************************************
     /* Test methods
@@ -224,6 +251,21 @@
         assertEquals("xyz", ((Impl) ob).value);
     }
     
+	public void testJsonAnySetterOnMap() throws Exception {
+		JsonAnySetterOnMap result = MAPPER.readValue("{\"id\":2,\"name\":\"Joe\", \"city\":\"New Jersey\"}",
+		        JsonAnySetterOnMap.class);
+		assertEquals(2, result.id);
+		assertEquals("Joe", result.other.get("name"));
+		assertEquals("New Jersey", result.other.get("city"));
+	}
+
+	public void testJsonAnySetterOnNullMap() throws Exception {
+		JsonAnySetterOnNullMap result = MAPPER.readValue("{\"id\":2,\"name\":\"Joe\", \"city\":\"New Jersey\"}",
+		        JsonAnySetterOnNullMap.class);
+		assertEquals(2, result.id);
+		assertNull(result.other);
+	}
+    
     /*
     /**********************************************************
     /* Private helper methods
diff --git a/src/test/java/com/fasterxml/jackson/databind/deser/TestBeanDeserializer.java b/src/test/java/com/fasterxml/jackson/databind/deser/TestBeanDeserializer.java
index e679d99..cd1a506 100644
--- a/src/test/java/com/fasterxml/jackson/databind/deser/TestBeanDeserializer.java
+++ b/src/test/java/com/fasterxml/jackson/databind/deser/TestBeanDeserializer.java
@@ -292,28 +292,6 @@
         assertNull(result);
     }
 
-    // [Databind#540]
-    public void testPOJOFromEmptyArray() throws Exception
-    {
-        final String JSON = "  [\n]";
-        assertFalse(MAPPER.isEnabled(DeserializationFeature.ACCEPT_EMPTY_ARRAY_AS_NULL_OBJECT));
-        // first, verify default settings which do not accept empty Array
-        ObjectMapper mapper = new ObjectMapper();
-        try {
-            mapper.readValue(JSON, Bean.class);
-            fail("Should not accept Empty Array for POJO by default");
-        } catch (JsonProcessingException e) {
-            verifyException(e, "START_ARRAY token");
-            assertValidLocation(e.getLocation());
-        }
-
-        // should be ok to enable dynamically:
-        ObjectReader r = MAPPER.readerFor(Bean.class)
-                .with(DeserializationFeature.ACCEPT_EMPTY_ARRAY_AS_NULL_OBJECT);
-        Bean result = r.readValue(JSON);
-        assertNull(result);
-    }
-
     // [databind#120]
     public void testModifyArrayDeserializer() throws Exception
     {
diff --git a/src/test/java/com/fasterxml/jackson/databind/deser/TestDateDeserialization.java b/src/test/java/com/fasterxml/jackson/databind/deser/TestDateDeserialization.java
index ba1ef58..3224a61 100644
--- a/src/test/java/com/fasterxml/jackson/databind/deser/TestDateDeserialization.java
+++ b/src/test/java/com/fasterxml/jackson/databind/deser/TestDateDeserialization.java
@@ -263,6 +263,28 @@
         assertEquals(0, c.get(Calendar.MILLISECOND));
     }
 
+    // [databind#1657]: no timezone should use configured default
+    public void testDateUtilISO8601NoTimezoneNonDefault() throws Exception
+    {
+        // In first case, no timezone -> SHOULD use configured timezone
+        ObjectReader r = MAPPER.readerFor(Date.class);
+        TimeZone tz = TimeZone.getTimeZone("GMT-2");
+        Date date1 = r.with(tz)
+                .readValue(quote("1970-01-01T00:00:00.000"));
+        // Second case, should use specified timezone, not configured
+        Date date2 = r.with(TimeZone.getTimeZone("GMT+5"))
+                .readValue(quote("1970-01-01T00:00:00.000-02:00"));
+        assertEquals(date1, date2);
+
+        // also verify actual value, in GMT
+        Calendar c = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
+        c.setTime(date1);
+        assertEquals(1970, c.get(Calendar.YEAR));
+        assertEquals(Calendar.JANUARY, c.get(Calendar.MONTH));
+        assertEquals(1, c.get(Calendar.DAY_OF_MONTH));
+        assertEquals(2, c.get(Calendar.HOUR_OF_DAY));
+    }
+
     // [Issue#338]
     public void testDateUtilISO8601NoMilliseconds() throws Exception
     {
@@ -296,7 +318,7 @@
         assertEquals(0, c.get(Calendar.MILLISECOND));
         */
     }
-    
+
     public void testDateUtilISO8601JustDate() throws Exception
     {
         // Plain date (no time)
@@ -516,7 +538,7 @@
             MAPPER.readValue(quote("foobar"), Date.class);
             fail("Should have failed with an exception");
         } catch (InvalidFormatException e) {
-            verifyException(e, "Can not construct instance");
+            verifyException(e, "Can not deserialize value of type java.util.Date from String");
             assertEquals("foobar", e.getValue());
             assertEquals(Date.class, e.getTargetType());
         } catch (Exception e) {
diff --git a/src/test/java/com/fasterxml/jackson/databind/deser/TestIgnoredTypes.java b/src/test/java/com/fasterxml/jackson/databind/deser/TestIgnoredTypes.java
index d610e03..01b5c51 100644
--- a/src/test/java/com/fasterxml/jackson/databind/deser/TestIgnoredTypes.java
+++ b/src/test/java/com/fasterxml/jackson/databind/deser/TestIgnoredTypes.java
@@ -8,18 +8,13 @@
 import com.fasterxml.jackson.databind.module.SimpleModule;
 
 /**
- * Test for [JACKSON-429]
+ * Test for type-based ignoral, both via annotations (<code>JsonIgnoreType</code>)
+ * and "config overrides" (2.8 and above).
  */
 public class TestIgnoredTypes extends BaseMapTest
 {
-    /*
-    /**********************************************************
-    /* Annotated helper classes
-    /**********************************************************
-     */
-    
     @JsonIgnoreType
-    class IgnoredType { // note: non-static, can't be deserializer
+    class IgnoredType { // note: non-static, can't be deserialized
         public IgnoredType(IgnoredType src) { }
     }
 
@@ -49,17 +44,31 @@
     @JsonIgnoreType
     static abstract class PersonMixin {
     }
-    
+
+    static class Wrapper {
+        public int value = 3;
+        public Wrapped wrapped = new Wrapped(7);
+    }
+
+    static class Wrapped {
+        public int x;
+
+        // make default ctor fail
+        public Wrapped() { throw new RuntimeException("Should not be called"); }
+        public Wrapped(int x0) { x = x0; }
+    }
+
     /*
     /**********************************************************
     /* Unit tests
     /**********************************************************
      */
-
+    
     public void testIgnoredType() throws Exception
     {
+        final ObjectMapper mapper = objectMapper();
+
         // First: should be ok in general, even though couldn't build deserializer (due to non-static inner class):
-        ObjectMapper mapper = new ObjectMapper();
         NonIgnoredType bean = mapper.readValue("{\"value\":13}", NonIgnoredType.class);
         assertNotNull(bean);
         assertEquals(13, bean.value);
@@ -90,4 +99,19 @@
         String json = mapper.writeValueAsString(persons);
         assertEquals("[{\"name\":\"Bob\"}]", json);
     }
+
+    public void testIgnoreUsingConfigOverride() throws Exception
+    {
+        final ObjectMapper mapper = objectMapper();
+        mapper.configOverride(Wrapped.class).setIsIgnoredType(true);
+
+        // serialize , first
+        String json = mapper.writeValueAsString(new Wrapper());
+        assertEquals(aposToQuotes("{'value':3}"), json);
+
+        // then deserialize
+        Wrapper result = mapper.readValue(aposToQuotes("{'value':5,'wrapped':false}"),
+                Wrapper.class);
+        assertEquals(5, result.value);
+    }
 }
diff --git a/src/test/java/com/fasterxml/jackson/databind/deser/TestJdkTypes.java b/src/test/java/com/fasterxml/jackson/databind/deser/TestJdkTypes.java
deleted file mode 100644
index cc6ab51..0000000
--- a/src/test/java/com/fasterxml/jackson/databind/deser/TestJdkTypes.java
+++ /dev/null
@@ -1,746 +0,0 @@
-package com.fasterxml.jackson.databind.deser;
-
-import java.io.*;
-import java.net.*;
-import java.nio.ByteBuffer;
-import java.nio.charset.Charset;
-import java.util.Currency;
-import java.util.List;
-import java.util.Locale;
-import java.util.regex.Pattern;
-
-import com.fasterxml.jackson.annotation.*;
-import com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility;
-import com.fasterxml.jackson.core.JsonParser;
-import com.fasterxml.jackson.core.JsonProcessingException;
-import com.fasterxml.jackson.databind.*;
-import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
-import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
-import com.fasterxml.jackson.databind.module.SimpleModule;
-
-public class TestJdkTypes extends BaseMapTest
-{
-    static class PrimitivesBean
-    {
-        public boolean booleanValue = true;
-        public byte byteValue = 3;
-        public char charValue = 'a';
-        public short shortValue = 37;
-        public int intValue = 1;
-        public long longValue = 100L;
-        public float floatValue = 0.25f;
-        public double doubleValue = -1.0;
-    }
-
-    static class WrappersBean
-    {
-        public Boolean booleanValue;
-        public Byte byteValue;
-        public Character charValue;
-        public Short shortValue;
-        public Integer intValue;
-        public Long longValue;
-        public Float floatValue;
-        public Double doubleValue;
-    }
-
-    static class ParamClassBean
-    {
-         public String name = "bar";
-         public Class<String> clazz ;
-
-         public ParamClassBean() { }
-         public ParamClassBean(String name) {
-             this.name = name;
-             clazz = String.class;
-         }
-    }
-
-    static class BooleanBean {
-        public Boolean wrapper;
-        public boolean primitive;
-        
-        protected Boolean ctor;
-        
-        @JsonCreator
-        public BooleanBean(@JsonProperty("ctor") Boolean foo) {
-            ctor = foo;
-        }
-    }
-
-    // [databind#429]
-    static class StackTraceBean {
-        public final static int NUM = 13;
-
-        @JsonProperty("Location")
-        @JsonDeserialize(using=MyStackTraceElementDeserializer.class)
-        protected StackTraceElement location;    
-    }
-
-    @SuppressWarnings("serial")
-    static class MyStackTraceElementDeserializer extends StdDeserializer<StackTraceElement>
-    {
-        public MyStackTraceElementDeserializer() { super(StackTraceElement.class); }
-        
-        @Override
-        public StackTraceElement deserialize(JsonParser jp,
-                DeserializationContext ctxt) throws IOException, JsonProcessingException {
-            jp.skipChildren();
-            return new StackTraceElement("a", "b", "b", StackTraceBean.NUM);
-        }
-        
-    }
-    
-    /*
-    /**********************************************************
-    /* Test methods
-    /**********************************************************
-     */
-
-    private final ObjectMapper MAPPER = objectMapper();
-
-    /**
-     * Related to issues [JACKSON-155], [#170].
-     */
-    public void testFile() throws Exception
-    {
-        // Not portable etc... has to do:
-        File src = new File("/test").getAbsoluteFile();
-        String abs = src.getAbsolutePath();
-
-        // escape backslashes (for portability with windows)
-        String json = MAPPER.writeValueAsString(abs);
-        File result = MAPPER.readValue(json, File.class);
-        assertEquals(abs, result.getAbsolutePath());
-
-        // Then #170
-        final ObjectMapper mapper2 = new ObjectMapper();
-        mapper2.setVisibility(PropertyAccessor.CREATOR, Visibility.NONE);
-
-        result = mapper2.readValue(json, File.class);
-        assertEquals(abs, result.getAbsolutePath());
-    }
-
-    public void testRegexps() throws IOException
-    {
-        final String PATTERN_STR = "abc:\\s?(\\d+)";
-        Pattern exp = Pattern.compile(PATTERN_STR);
-        /* Ok: easiest way is to just serialize first; problem
-         * is the backslash
-         */
-        String json = MAPPER.writeValueAsString(exp);
-        Pattern result = MAPPER.readValue(json, Pattern.class);
-        assertEquals(exp.pattern(), result.pattern());
-    }
-
-    public void testCurrency() throws IOException
-    {
-        Currency usd = Currency.getInstance("USD");
-        assertEquals(usd, new ObjectMapper().readValue(quote("USD"), Currency.class));
-    }
-
-    public void testLocale() throws IOException
-    {
-        assertEquals(new Locale("en"), MAPPER.readValue(quote("en"), Locale.class));
-        assertEquals(new Locale("es", "ES"), MAPPER.readValue(quote("es_ES"), Locale.class));
-        assertEquals(new Locale("FI", "fi", "savo"),
-                MAPPER.readValue(quote("fi_FI_savo"), Locale.class));
-        assertEquals(new Locale("en", "US"),
-                MAPPER.readValue(quote("en-US"), Locale.class));
-
-        // [databind#1123]
-        Locale loc = MAPPER.readValue(quote(""), Locale.class);
-        assertSame(Locale.ROOT, loc);
-    }
-
-    public void testNullForPrimitives() throws IOException
-    {
-        // by default, ok to rely on defaults
-        PrimitivesBean bean = MAPPER.readValue("{\"intValue\":null, \"booleanValue\":null, \"doubleValue\":null}",
-                PrimitivesBean.class);
-        assertNotNull(bean);
-        assertEquals(0, bean.intValue);
-        assertEquals(false, bean.booleanValue);
-        assertEquals(0.0, bean.doubleValue);
-
-        bean = MAPPER.readValue("{\"byteValue\":null, \"longValue\":null, \"floatValue\":null}",
-                PrimitivesBean.class);
-        assertNotNull(bean);
-        assertEquals((byte) 0, bean.byteValue);
-        assertEquals(0L, bean.longValue);
-        assertEquals(0.0f, bean.floatValue);
-        
-        // but not when enabled
-        final ObjectMapper mapper2 = new ObjectMapper();
-        mapper2.configure(DeserializationFeature.FAIL_ON_NULL_FOR_PRIMITIVES, true);
-
-        // boolean
-        try {
-            mapper2.readValue("{\"booleanValue\":null}", PrimitivesBean.class);
-            fail("Expected failure for boolean + null");
-        } catch (JsonMappingException e) {
-            verifyException(e, "Can not map JSON null into type boolean");
-        }
-        // byte/char/short/int/long
-        try {
-            mapper2.readValue("{\"byteValue\":null}", PrimitivesBean.class);
-            fail("Expected failure for byte + null");
-        } catch (JsonMappingException e) {
-            verifyException(e, "Can not map JSON null into type byte");
-        }
-        try {
-            mapper2.readValue("{\"charValue\":null}", PrimitivesBean.class);
-            fail("Expected failure for char + null");
-        } catch (JsonMappingException e) {
-            verifyException(e, "Can not map JSON null into type char");
-        }
-        try {
-            mapper2.readValue("{\"shortValue\":null}", PrimitivesBean.class);
-            fail("Expected failure for short + null");
-        } catch (JsonMappingException e) {
-            verifyException(e, "Can not map JSON null into type short");
-        }
-        try {
-            mapper2.readValue("{\"intValue\":null}", PrimitivesBean.class);
-            fail("Expected failure for int + null");
-        } catch (JsonMappingException e) {
-            verifyException(e, "Can not map JSON null into type int");
-        }
-        try {
-            mapper2.readValue("{\"longValue\":null}", PrimitivesBean.class);
-            fail("Expected failure for long + null");
-        } catch (JsonMappingException e) {
-            verifyException(e, "Can not map JSON null into type long");
-        }
-
-        // float/double
-        try {
-            mapper2.readValue("{\"floatValue\":null}", PrimitivesBean.class);
-            fail("Expected failure for float + null");
-        } catch (JsonMappingException e) {
-            verifyException(e, "Can not map JSON null into type float");
-        }
-        try {
-            mapper2.readValue("{\"doubleValue\":null}", PrimitivesBean.class);
-            fail("Expected failure for double + null");
-        } catch (JsonMappingException e) {
-            verifyException(e, "Can not map JSON null into type double");
-        }
-    }
-    
-    /**
-     * Test for [JACKSON-483], allow handling of CharSequence
-     */
-    public void testCharSequence() throws IOException
-    {
-        CharSequence cs = MAPPER.readValue("\"abc\"", CharSequence.class);
-        assertEquals(String.class, cs.getClass());
-        assertEquals("abc", cs.toString());
-    }
-    
-    // [JACKSON-484]
-    public void testInetAddress() throws IOException
-    {
-        InetAddress address = MAPPER.readValue(quote("127.0.0.1"), InetAddress.class);
-        assertEquals("127.0.0.1", address.getHostAddress());
-
-        // should we try resolving host names? That requires connectivity... 
-        final String HOST = "google.com";
-        address = MAPPER.readValue(quote(HOST), InetAddress.class);
-        assertEquals(HOST, address.getHostName());
-    }
-
-    public void testInetSocketAddress() throws IOException
-    {
-        InetSocketAddress address = MAPPER.readValue(quote("127.0.0.1"), InetSocketAddress.class);
-        assertEquals("127.0.0.1", address.getAddress().getHostAddress());
-
-        InetSocketAddress ip6 = MAPPER.readValue(
-                quote("2001:db8:85a3:8d3:1319:8a2e:370:7348"), InetSocketAddress.class);
-        assertEquals("2001:db8:85a3:8d3:1319:8a2e:370:7348", ip6.getAddress().getHostAddress());
-
-        InetSocketAddress ip6port = MAPPER.readValue(
-                quote("[2001:db8:85a3:8d3:1319:8a2e:370:7348]:443"), InetSocketAddress.class);
-        assertEquals("2001:db8:85a3:8d3:1319:8a2e:370:7348", ip6port.getAddress().getHostAddress());
-        assertEquals(443, ip6port.getPort());
-
-        // should we try resolving host names? That requires connectivity...
-        final String HOST = "www.google.com";
-        address = MAPPER.readValue(quote(HOST), InetSocketAddress.class);
-        assertEquals(HOST, address.getHostName());
-
-        final String HOST_AND_PORT = HOST+":80";
-        address = MAPPER.readValue(quote(HOST_AND_PORT), InetSocketAddress.class);
-        assertEquals(HOST, address.getHostName());
-        assertEquals(80, address.getPort());
-    }
-
-    // [JACKSON-597]
-    public void testClass() throws IOException
-    {
-        ObjectMapper mapper = new ObjectMapper();
-        assertSame(String.class, mapper.readValue(quote("java.lang.String"), Class.class));
-
-        // then primitive types
-        assertSame(Boolean.TYPE, mapper.readValue(quote("boolean"), Class.class));
-        assertSame(Byte.TYPE, mapper.readValue(quote("byte"), Class.class));
-        assertSame(Short.TYPE, mapper.readValue(quote("short"), Class.class));
-        assertSame(Character.TYPE, mapper.readValue(quote("char"), Class.class));
-        assertSame(Integer.TYPE, mapper.readValue(quote("int"), Class.class));
-        assertSame(Long.TYPE, mapper.readValue(quote("long"), Class.class));
-        assertSame(Float.TYPE, mapper.readValue(quote("float"), Class.class));
-        assertSame(Double.TYPE, mapper.readValue(quote("double"), Class.class));
-        assertSame(Void.TYPE, mapper.readValue(quote("void"), Class.class));
-    }
-
-    // [JACKSON-605]
-    public void testClassWithParams() throws IOException
-    {
-        String json = MAPPER.writeValueAsString(new ParamClassBean("Foobar"));
-
-        ParamClassBean result = MAPPER.readValue(json, ParamClassBean.class);
-        assertEquals("Foobar", result.name);
-        assertSame(String.class, result.clazz);
-    }
-
-    // by default, should return nulls, n'est pas?
-    public void testEmptyStringForWrappers() throws IOException
-    {
-        WrappersBean bean;
-
-        // by default, ok to rely on defaults
-        bean = MAPPER.readValue("{\"booleanValue\":\"\"}", WrappersBean.class);
-        assertNull(bean.booleanValue);
-        bean = MAPPER.readValue("{\"byteValue\":\"\"}", WrappersBean.class);
-        assertNull(bean.byteValue);
-
-        // char/Character is different... not sure if this should work or not:
-        bean = MAPPER.readValue("{\"charValue\":\"\"}", WrappersBean.class);
-        assertNull(bean.charValue);
-
-        bean = MAPPER.readValue("{\"shortValue\":\"\"}", WrappersBean.class);
-        assertNull(bean.shortValue);
-        bean = MAPPER.readValue("{\"intValue\":\"\"}", WrappersBean.class);
-        assertNull(bean.intValue);
-        bean = MAPPER.readValue("{\"longValue\":\"\"}", WrappersBean.class);
-        assertNull(bean.longValue);
-        bean = MAPPER.readValue("{\"floatValue\":\"\"}", WrappersBean.class);
-        assertNull(bean.floatValue);
-        bean = MAPPER.readValue("{\"doubleValue\":\"\"}", WrappersBean.class);
-        assertNull(bean.doubleValue);
-    }
-
-    // for [JACKSON-616]
-    // @since 1.9
-    public void testEmptyStringForPrimitives() throws IOException
-    {
-        PrimitivesBean bean;
-        bean = MAPPER.readValue("{\"booleanValue\":\"\"}", PrimitivesBean.class);
-        assertFalse(bean.booleanValue);
-        bean = MAPPER.readValue("{\"byteValue\":\"\"}", PrimitivesBean.class);
-        assertEquals((byte) 0, bean.byteValue);
-        bean = MAPPER.readValue("{\"charValue\":\"\"}", PrimitivesBean.class);
-        assertEquals((char) 0, bean.charValue);
-        bean = MAPPER.readValue("{\"shortValue\":\"\"}", PrimitivesBean.class);
-        assertEquals((short) 0, bean.shortValue);
-        bean = MAPPER.readValue("{\"intValue\":\"\"}", PrimitivesBean.class);
-        assertEquals(0, bean.intValue);
-        bean = MAPPER.readValue("{\"longValue\":\"\"}", PrimitivesBean.class);
-        assertEquals(0L, bean.longValue);
-        bean = MAPPER.readValue("{\"floatValue\":\"\"}", PrimitivesBean.class);
-        assertEquals(0.0f, bean.floatValue);
-        bean = MAPPER.readValue("{\"doubleValue\":\"\"}", PrimitivesBean.class);
-        assertEquals(0.0, bean.doubleValue);
-    }
-
-    // for [JACKSON-652]
-    // @since 1.9
-    public void testUntypedWithJsonArrays() throws Exception
-    {
-        // by default we get:
-        Object ob = MAPPER.readValue("[1]", Object.class);
-        assertTrue(ob instanceof List<?>);
-
-        // but can change to produce Object[]:
-        MAPPER.configure(DeserializationFeature.USE_JAVA_ARRAY_FOR_JSON_ARRAY, true);
-        ob = MAPPER.readValue("[1]", Object.class);
-        assertEquals(Object[].class, ob.getClass());
-    }
-
-    // Test for verifying that Long values are coerced to boolean correctly as well
-    public void testLongToBoolean() throws Exception
-    {
-        long value = 1L + Integer.MAX_VALUE;
-        BooleanBean b = MAPPER.readValue("{\"primitive\" : "+value+", \"wrapper\":"+value+", \"ctor\":"+value+"}",
-                    BooleanBean.class);
-        assertEquals(Boolean.TRUE, b.wrapper);
-        assertTrue(b.primitive);
-        assertEquals(Boolean.TRUE, b.ctor);
-    }
-
-    // [JACKSON-789]
-    public void testCharset() throws Exception
-    {
-        Charset UTF8 = Charset.forName("UTF-8");
-        assertSame(UTF8, MAPPER.readValue(quote("UTF-8"), Charset.class));
-    }
-
-    // [JACKSON-888]
-    public void testStackTraceElement() throws Exception
-    {
-        StackTraceElement elem = null;
-        try {
-            throw new IllegalStateException();
-        } catch (Exception e) {
-            elem = e.getStackTrace()[0];
-        }
-        String json = MAPPER.writeValueAsString(elem);
-        StackTraceElement back = MAPPER.readValue(json, StackTraceElement.class);
-        
-        assertEquals("testStackTraceElement", back.getMethodName());
-        assertEquals(elem.getLineNumber(), back.getLineNumber());
-        assertEquals(elem.getClassName(), back.getClassName());
-        assertEquals(elem.isNativeMethod(), back.isNativeMethod());
-        assertTrue(back.getClassName().endsWith("TestJdkTypes"));
-        assertFalse(back.isNativeMethod());
-    }
-
-    // [Issue#239]
-    public void testByteBuffer() throws Exception
-    {
-        byte[] INPUT = new byte[] { 1, 3, 9, -1, 6 };
-        String exp = MAPPER.writeValueAsString(INPUT);
-        ByteBuffer result = MAPPER.readValue(exp,  ByteBuffer.class); 
-        assertNotNull(result);
-        assertEquals(INPUT.length, result.remaining());
-        for (int i = 0; i < INPUT.length; ++i) {
-            assertEquals(INPUT[i], result.get());
-        }
-        assertEquals(0, result.remaining());
-    }
-
-    public void testStringBuilder() throws Exception
-    {
-        StringBuilder sb = MAPPER.readValue(quote("abc"), StringBuilder.class);
-        assertEquals("abc", sb.toString());
-    }
-    
-    // [Issue#429]
-    public void testStackTraceElementWithCustom() throws Exception
-    {
-        // first, via bean that contains StackTraceElement
-        StackTraceBean bean = MAPPER.readValue(aposToQuotes("{'Location':'foobar'}"),
-                StackTraceBean.class);
-        assertNotNull(bean);
-        assertNotNull(bean.location);
-        assertEquals(StackTraceBean.NUM, bean.location.getLineNumber());
-
-        // and then directly, iff registered
-        ObjectMapper mapper = new ObjectMapper();
-        SimpleModule module = new SimpleModule();
-        module.addDeserializer(StackTraceElement.class, new MyStackTraceElementDeserializer());
-        mapper.registerModule(module);
-        
-        StackTraceElement elem = mapper.readValue("123", StackTraceElement.class);
-        assertNotNull(elem);
-        assertEquals(StackTraceBean.NUM, elem.getLineNumber());
- 
-        // and finally, even as part of real exception
-        
-        IOException ioe = mapper.readValue(aposToQuotes("{'stackTrace':[ 123, 456 ]}"),
-                IOException.class);
-        assertNotNull(ioe);
-        StackTraceElement[] traces = ioe.getStackTrace();
-        assertNotNull(traces);
-        assertEquals(2, traces.length);
-        assertEquals(StackTraceBean.NUM, traces[0].getLineNumber());
-        assertEquals(StackTraceBean.NUM, traces[1].getLineNumber());
-    }
-    
-    /*
-    /**********************************************************
-    /* Single-array handling tests
-    /**********************************************************
-     */
-    
-    // [Issue#381]
-    public void testSingleElementArray() throws Exception {
-        final int intTest = 932832;
-        final double doubleTest = 32.3234;
-        final long longTest = 2374237428374293423L;
-        final short shortTest = (short) intTest;
-        final float floatTest = 84.3743f;
-        final byte byteTest = (byte) 43;
-        final char charTest = 'c';
-
-        final ObjectMapper mapper = new ObjectMapper();
-        mapper.enable(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS);
-
-        final int intValue = mapper.readValue(asArray(intTest), Integer.TYPE);
-        assertEquals(intTest, intValue);
-        final Integer integerWrapperValue = mapper.readValue(asArray(Integer.valueOf(intTest)), Integer.class);
-        assertEquals(Integer.valueOf(intTest), integerWrapperValue);
-
-        final double doubleValue = mapper.readValue(asArray(doubleTest), Double.class);
-        assertEquals(doubleTest, doubleValue);
-        final Double doubleWrapperValue = mapper.readValue(asArray(Double.valueOf(doubleTest)), Double.class);
-        assertEquals(Double.valueOf(doubleTest), doubleWrapperValue);
-
-        final long longValue = mapper.readValue(asArray(longTest), Long.TYPE);
-        assertEquals(longTest, longValue);
-        final Long longWrapperValue = mapper.readValue(asArray(Long.valueOf(longTest)), Long.class);
-        assertEquals(Long.valueOf(longTest), longWrapperValue);
-
-        final short shortValue = mapper.readValue(asArray(shortTest), Short.TYPE);
-        assertEquals(shortTest, shortValue);
-        final Short shortWrapperValue = mapper.readValue(asArray(Short.valueOf(shortTest)), Short.class);
-        assertEquals(Short.valueOf(shortTest), shortWrapperValue);
-
-        final float floatValue = mapper.readValue(asArray(floatTest), Float.TYPE);
-        assertEquals(floatTest, floatValue);
-        final Float floatWrapperValue = mapper.readValue(asArray(Float.valueOf(floatTest)), Float.class);
-        assertEquals(Float.valueOf(floatTest), floatWrapperValue);
-
-        final byte byteValue = mapper.readValue(asArray(byteTest), Byte.TYPE);
-        assertEquals(byteTest, byteValue);
-        final Byte byteWrapperValue = mapper.readValue(asArray(Byte.valueOf(byteTest)), Byte.class);
-        assertEquals(Byte.valueOf(byteTest), byteWrapperValue);
-
-        final char charValue = mapper.readValue(asArray(quote(String.valueOf(charTest))), Character.TYPE);
-        assertEquals(charTest, charValue);
-        final Character charWrapperValue = mapper.readValue(asArray(quote(String.valueOf(charTest))), Character.class);
-        assertEquals(Character.valueOf(charTest), charWrapperValue);
-
-        final boolean booleanTrueValue = mapper.readValue(asArray(true), Boolean.TYPE);
-        assertTrue(booleanTrueValue);
-
-        final boolean booleanFalseValue = mapper.readValue(asArray(false), Boolean.TYPE);
-        assertFalse(booleanFalseValue);
-
-        final Boolean booleanWrapperTrueValue = mapper.readValue(asArray(Boolean.valueOf(true)), Boolean.class);
-        assertEquals(Boolean.TRUE, booleanWrapperTrueValue);
-    }
-
-    private static String asArray(Object value) {
-        final String stringVal = value.toString();
-        return new StringBuilder(stringVal.length() + 2).append("[").append(stringVal).append("]").toString();
-    }
-
-    public void testSingleElementArrayException() throws Exception {
-        final ObjectMapper mapper = new ObjectMapper();
-        mapper.disable(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS);
-        try {
-            mapper.readValue("[42]", Integer.class);
-            fail("Single value array didn't throw an exception when DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS is disabled");
-        } catch (JsonMappingException exp) {
-            //Exception was thrown correctly
-        }
-        try {
-            mapper.readValue("[42]", Integer.TYPE);
-            fail("Single value array didn't throw an exception when DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS is disabled");
-        } catch (JsonMappingException exp) {
-            //Exception was thrown correctly
-        }
-
-        try {
-            mapper.readValue("[42.273]", Double.class);
-            fail("Single value array didn't throw an exception when DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS is disabled");
-        } catch (JsonMappingException exp) {
-            //Exception was thrown correctly
-        }
-        try {
-            mapper.readValue("[42.2723]", Double.TYPE);
-            fail("Single value array didn't throw an exception when DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS is disabled");
-        } catch (JsonMappingException exp) {
-            //Exception was thrown correctly
-        }
-
-        try {
-            mapper.readValue("[42342342342342]", Long.class);
-            fail("Single value array didn't throw an exception when DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS is disabled");
-        } catch (JsonMappingException exp) {
-            //Exception was thrown correctly
-        }
-        try {
-            mapper.readValue("[42342342342342342]", Long.TYPE);
-            fail("Single value array didn't throw an exception when DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS is disabled");
-        } catch (JsonMappingException exp) {
-            //Exception was thrown correctly
-        }
-
-        try {
-            mapper.readValue("[42]", Short.class);
-            fail("Single value array didn't throw an exception when DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS is disabled");
-        } catch (JsonMappingException exp) {
-            //Exception was thrown correctly
-        }
-        try {
-            mapper.readValue("[42]", Short.TYPE);
-            fail("Single value array didn't throw an exception when DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS is disabled");
-        } catch (JsonMappingException exp) {
-            //Exception was thrown correctly
-        }
-
-        try {
-            mapper.readValue("[327.2323]", Float.class);
-            fail("Single value array didn't throw an exception when DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS is disabled");
-        } catch (JsonMappingException exp) {
-            //Exception was thrown correctly
-        }
-        try {
-            mapper.readValue("[82.81902]", Float.TYPE);
-            fail("Single value array didn't throw an exception when DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS is disabled");
-        } catch (JsonMappingException exp) {
-            //Exception was thrown correctly
-        }
-
-        try {
-            mapper.readValue("[22]", Byte.class);
-            fail("Single value array didn't throw an exception when DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS is disabled");
-        } catch (JsonMappingException exp) {
-            //Exception was thrown correctly
-        }
-        try {
-            mapper.readValue("[22]", Byte.TYPE);
-            fail("Single value array didn't throw an exception when DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS is disabled");
-        } catch (JsonMappingException exp) {
-            //Exception was thrown correctly
-        }
-
-        try {
-            mapper.readValue("['d']", Character.class);
-            fail("Single value array didn't throw an exception when DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS is disabled");
-        } catch (JsonMappingException exp) {
-            //Exception was thrown correctly
-        }
-        try {
-            mapper.readValue("['d']", Character.TYPE);
-            fail("Single value array didn't throw an exception when DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS is disabled");
-        } catch (JsonMappingException exp) {
-            //Exception was thrown correctly
-        }
-
-        try {
-            mapper.readValue("[true]", Boolean.class);
-            fail("Single value array didn't throw an exception when DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS is disabled");
-        } catch (JsonMappingException exp) {
-            //Exception was thrown correctly
-        }
-        try {
-            mapper.readValue("[true]", Boolean.TYPE);
-            fail("Single value array didn't throw an exception when DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS is disabled");
-        } catch (JsonMappingException exp) {
-            //Exception was thrown correctly
-        }
-    }
-
-    public void testMultiValueArrayException() throws IOException {
-        final ObjectMapper mapper = new ObjectMapper();
-        mapper.enable(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS);
-        
-        try {
-            mapper.readValue("[42,42]", Integer.class);
-            fail("Single value array didn't throw an exception when DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS is disabled");
-        } catch (JsonMappingException exp) {
-            //Exception was thrown correctly
-        }
-        try {
-            mapper.readValue("[42,42]", Integer.TYPE);
-            fail("Single value array didn't throw an exception when DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS is disabled");
-        } catch (JsonMappingException exp) {
-            //Exception was thrown correctly
-        }
-        
-        try {
-            mapper.readValue("[42.273,42.273]", Double.class);
-            fail("Single value array didn't throw an exception when DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS is disabled");
-        } catch (JsonMappingException exp) {
-            //Exception was thrown correctly
-        }
-        try {
-            mapper.readValue("[42.2723,42.273]", Double.TYPE);
-            fail("Single value array didn't throw an exception when DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS is disabled");
-        } catch (JsonMappingException exp) {
-            //Exception was thrown correctly
-        }
-        
-        try {
-            mapper.readValue("[42342342342342,42342342342342]", Long.class);
-            fail("Single value array didn't throw an exception when DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS is disabled");
-        } catch (JsonMappingException exp) {
-            //Exception was thrown correctly
-        }
-        try {
-            mapper.readValue("[42342342342342342,42342342342342]", Long.TYPE);
-            fail("Single value array didn't throw an exception when DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS is disabled");
-        } catch (JsonMappingException exp) {
-            //Exception was thrown correctly
-        }
-        
-        try {
-            mapper.readValue("[42,42]", Short.class);
-            fail("Single value array didn't throw an exception when DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS is disabled");
-        } catch (JsonMappingException exp) {
-            //Exception was thrown correctly
-        }
-        try {
-            mapper.readValue("[42,42]", Short.TYPE);
-            fail("Single value array didn't throw an exception when DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS is disabled");
-        } catch (JsonMappingException exp) {
-            //Exception was thrown correctly
-        }
-        
-        try {
-            mapper.readValue("[327.2323,327.2323]", Float.class);
-            fail("Single value array didn't throw an exception when DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS is disabled");
-        } catch (JsonMappingException exp) {
-            //Exception was thrown correctly
-        }
-        try {
-            mapper.readValue("[82.81902,327.2323]", Float.TYPE);
-            fail("Single value array didn't throw an exception when DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS is disabled");
-        } catch (JsonMappingException exp) {
-            //Exception was thrown correctly
-        }
-        
-        try {
-            mapper.readValue("[22,23]", Byte.class);
-            fail("Single value array didn't throw an exception when DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS is disabled");
-        } catch (JsonMappingException exp) {
-            //Exception was thrown correctly
-        }
-        try {
-            mapper.readValue("[22,23]", Byte.TYPE);
-            fail("Single value array didn't throw an exception when DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS is disabled");
-        } catch (JsonMappingException exp) {
-            //Exception was thrown correctly
-        }
-        
-        try {
-            mapper.readValue(asArray(quote("c") + ","  + quote("d")), Character.class);
-            
-            fail("Single value array didn't throw an exception when DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS is disabled");
-        } catch (JsonMappingException exp) {
-            //Exception was thrown correctly
-        }
-        try {
-            mapper.readValue(asArray(quote("c") + ","  + quote("d")), Character.TYPE);
-            fail("Single value array didn't throw an exception when DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS is disabled");
-        } catch (JsonMappingException exp) {
-            //Exception was thrown correctly
-        }
-        
-        try {
-            mapper.readValue("[true,false]", Boolean.class);
-            fail("Single value array didn't throw an exception when DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS is disabled");
-        } catch (JsonMappingException exp) {
-            //Exception was thrown correctly
-        }
-        try {
-            mapper.readValue("[true,false]", Boolean.TYPE);
-            fail("Single value array didn't throw an exception when DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS is disabled");
-        } catch (JsonMappingException exp) {
-            //Exception was thrown correctly
-        }
-    }
-}
diff --git a/src/test/java/com/fasterxml/jackson/databind/deser/TestMapDeserialization.java b/src/test/java/com/fasterxml/jackson/databind/deser/TestMapDeserialization.java
index 5828bd7..76d9ee6 100644
--- a/src/test/java/com/fasterxml/jackson/databind/deser/TestMapDeserialization.java
+++ b/src/test/java/com/fasterxml/jackson/databind/deser/TestMapDeserialization.java
@@ -57,7 +57,7 @@
         }
     }
 
-    // Issue #142
+    // [databind#142]
     public static class EnumMapContainer {
         @JsonTypeInfo(use=JsonTypeInfo.Id.CLASS, include=JsonTypeInfo.As.PROPERTY, property="@class")
         public EnumMap<KeyEnum,ITestType> testTypes;
@@ -298,31 +298,6 @@
         assertNull(result.get(""));
     }
 
-    // [Databind#540]
-    public void testMapFromEmptyArray() throws Exception
-    {
-        final String JSON = "  [\n]";
-        assertFalse(MAPPER.isEnabled(DeserializationFeature.ACCEPT_EMPTY_ARRAY_AS_NULL_OBJECT));
-        // first, verify default settings which do not accept empty Array
-        ObjectMapper mapper = new ObjectMapper();
-        try {
-            mapper.readValue(JSON, Map.class);
-            fail("Should not accept Empty Array for Map by default");
-        } catch (JsonProcessingException e) {
-            verifyException(e, "START_ARRAY token");
-        }
-        // should be ok to enable dynamically:
-        ObjectReader r = MAPPER.readerFor(Map.class)
-                .with(DeserializationFeature.ACCEPT_EMPTY_ARRAY_AS_NULL_OBJECT);
-
-        Map<?,?> result = r.readValue(JSON);
-        assertNull(result);
-
-        EnumMap<?,?> result2 = r.forType(new TypeReference<EnumMap<Key,String>>() { })
-                .readValue(JSON);
-        assertNull(result2);
-    }
-
     /*
     /**********************************************************
     /* Test methods, maps with enums
diff --git a/src/test/java/com/fasterxml/jackson/databind/deser/TestSimpleTypes.java b/src/test/java/com/fasterxml/jackson/databind/deser/TestSimpleTypes.java
deleted file mode 100644
index 80150a2..0000000
--- a/src/test/java/com/fasterxml/jackson/databind/deser/TestSimpleTypes.java
+++ /dev/null
@@ -1,784 +0,0 @@
-package com.fasterxml.jackson.databind.deser;
-
-import java.io.*;
-import java.math.BigDecimal;
-import java.math.BigInteger;
-import java.net.URL;
-import java.net.URI;
-import java.util.*;
-
-import org.junit.Assert;
-
-import com.fasterxml.jackson.core.*;
-import com.fasterxml.jackson.databind.*;
-import com.fasterxml.jackson.databind.exc.InvalidFormatException;
-import com.fasterxml.jackson.databind.util.TokenBuffer;
-
-/**
- * Unit tests for verifying handling of simple basic non-structured
- * types; primitives (and/or their wrappers), Strings.
- */
-public class TestSimpleTypes
-    extends BaseMapTest
-{
-    final static String NAN_STRING = "NaN";
-
-    final static class BooleanBean {
-        boolean _v;
-        void setV(boolean v) { _v = v; }
-    }
-
-    static class IntBean {
-        int _v;
-        void setV(int v) { _v = v; }
-    }
-
-    final static class DoubleBean {
-        double _v;
-        void setV(double v) { _v = v; }
-    }
-
-    final static class FloatBean {
-        float _v;
-        void setV(float v) { _v = v; }
-    }
-    
-    final static class CharacterBean {
-        char _v;
-        void setV(char v) { _v = v; }
-        char getV() { return _v; }
-    }
-    
-    final static class CharacterWrapperBean {
-        Character _v;
-        void setV(Character v) { _v = v; }
-        Character getV() { return _v; }
-    }
-
-    /**
-     * Also, let's ensure that it's ok to override methods.
-     */
-    static class IntBean2
-        extends IntBean
-    {
-        @Override
-        void setV(int v2) { super.setV(v2+1); }
-    }
-
-    /*
-    /**********************************************************
-    /* Then tests for primitives
-    /**********************************************************
-     */
-
-    private final ObjectMapper MAPPER = new ObjectMapper();
-
-    public void testBooleanPrimitive() throws Exception
-    {
-        // first, simple case:
-        BooleanBean result = MAPPER.readValue(new StringReader("{\"v\":true}"), BooleanBean.class);
-        assertTrue(result._v);
-        // then [JACKSON-79]:
-        result = MAPPER.readValue(new StringReader("{\"v\":null}"), BooleanBean.class);
-        assertNotNull(result);
-        assertFalse(result._v);
-
-        // should work with arrays too..
-        boolean[] array = MAPPER.readValue(new StringReader("[ null ]"), boolean[].class);
-        assertNotNull(array);
-        assertEquals(1, array.length);
-        assertFalse(array[0]);
-        
-        // [Issue#381]
-        final ObjectMapper mapper = new ObjectMapper();
-        mapper.enable(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS);
-        result = mapper.readValue(new StringReader("{\"v\":[true]}"), BooleanBean.class);
-        assertTrue(result._v);
-        
-        try {
-            mapper.readValue(new StringReader("[{\"v\":[true,true]}]"), BooleanBean.class);
-            fail("Did not throw exception while reading a value from a multi value array with UNWRAP_SINGLE_VALUE_ARRAY feature enabled");
-        } catch (JsonMappingException exp) {
-            //threw exception as required
-        }
-        
-        result = mapper.readValue(new StringReader("{\"v\":[null]}"), BooleanBean.class);
-        assertNotNull(result);
-        assertFalse(result._v);
-        
-        result = mapper.readValue(new StringReader("[{\"v\":[null]}]"), BooleanBean.class);
-        assertNotNull(result);
-        assertFalse(result._v);
-        
-        array = mapper.readValue(new StringReader("[ [ null ] ]"), boolean[].class);
-        assertNotNull(array);
-        assertEquals(1, array.length);
-        assertFalse(array[0]);
-    }
-
-    public void testIntPrimitive() throws Exception
-    {
-        // first, simple case:
-        IntBean result = MAPPER.readValue(new StringReader("{\"v\":3}"), IntBean.class);
-        assertEquals(3, result._v);
-        // then [JACKSON-79]:
-        result = MAPPER.readValue(new StringReader("{\"v\":null}"), IntBean.class);
-        assertNotNull(result);
-        assertEquals(0, result._v);
-
-        // should work with arrays too..
-        int[] array = MAPPER.readValue(new StringReader("[ null ]"), int[].class);
-        assertNotNull(array);
-        assertEquals(1, array.length);
-        assertEquals(0, array[0]);
-        
-        // [Issue#381]
-        final ObjectMapper mapper = new ObjectMapper();
-        mapper.disable(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS);
-        try {
-            mapper.readValue(new StringReader("{\"v\":[3]}"), IntBean.class);
-            fail("Did not throw exception when reading a value from a single value array with the UNWRAP_SINGLE_VALUE_ARRAYS feature disabled");
-        } catch (JsonMappingException exp) {
-            //Correctly threw exception
-        }
-        
-        mapper.enable(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS);
-        
-        result = mapper.readValue(new StringReader("{\"v\":[3]}"), IntBean.class);
-        assertEquals(3, result._v);
-        
-        result = mapper.readValue(new StringReader("[{\"v\":[3]}]"), IntBean.class);
-        assertEquals(3, result._v);
-        
-        try {
-            mapper.readValue(new StringReader("[{\"v\":[3,3]}]"), IntBean.class);
-            fail("Did not throw exception while reading a value from a multi value array with UNWRAP_SINGLE_VALUE_ARRAY feature enabled");
-        } catch (JsonMappingException exp) {
-            //threw exception as required
-        }
-        
-        result = mapper.readValue(new StringReader("{\"v\":[null]}"), IntBean.class);
-        assertNotNull(result);
-        assertEquals(0, result._v);
-
-        array = mapper.readValue(new StringReader("[ [ null ] ]"), int[].class);
-        assertNotNull(array);
-        assertEquals(1, array.length);
-        assertEquals(0, array[0]);
-    }
-
-    public void testDoublePrimitive() throws Exception
-    {
-        // first, simple case:
-        // bit tricky with binary fps but...
-        double value = 0.016;
-        DoubleBean result = MAPPER.readValue(new StringReader("{\"v\":"+value+"}"), DoubleBean.class);
-        assertEquals(value, result._v);
-        // then [JACKSON-79]:
-        result = MAPPER.readValue(new StringReader("{\"v\":null}"), DoubleBean.class);
-        assertNotNull(result);
-        assertEquals(0.0, result._v);
-
-        // should work with arrays too..
-        double[] array = MAPPER.readValue(new StringReader("[ null ]"), double[].class);
-        assertNotNull(array);
-        assertEquals(1, array.length);
-        assertEquals(0.0, array[0]);
-        
-        // [Issue#381]
-        final ObjectMapper mapper = new ObjectMapper();
-        mapper.disable(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS);
-        try {
-            mapper.readValue(new StringReader("{\"v\":[" + value + "]}"), DoubleBean.class);
-            fail("Did not throw exception when reading a value from a single value array with the UNWRAP_SINGLE_VALUE_ARRAYS feature disabled");
-        } catch (JsonMappingException exp) {
-            //Correctly threw exception
-        }
-        
-        mapper.enable(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS);
-        
-        result = mapper.readValue(new StringReader("{\"v\":[" + value + "]}"), DoubleBean.class);
-        assertEquals(value, result._v);
-        
-        result = mapper.readValue(new StringReader("[{\"v\":[" + value + "]}]"), DoubleBean.class);
-        assertEquals(value, result._v);
-        
-        try {
-            mapper.readValue(new StringReader("[{\"v\":[" + value + "," + value + "]}]"), DoubleBean.class);
-            fail("Did not throw exception while reading a value from a multi value array with UNWRAP_SINGLE_VALUE_ARRAY feature enabled");
-        } catch (JsonMappingException exp) {
-            //threw exception as required
-        }
-        
-        result = mapper.readValue(new StringReader("{\"v\":[null]}"), DoubleBean.class);
-        assertNotNull(result);
-        assertEquals(0d, result._v);
-
-        array = mapper.readValue(new StringReader("[ [ null ] ]"), double[].class);
-        assertNotNull(array);
-        assertEquals(1, array.length);
-        assertEquals(0d, array[0]);
-    }
-
-    public void testDoublePrimitiveNonNumeric() throws Exception
-    {
-        // first, simple case:
-        // bit tricky with binary fps but...
-        double value = Double.POSITIVE_INFINITY;
-        DoubleBean result = MAPPER.readValue(new StringReader("{\"v\":\""+value+"\"}"), DoubleBean.class);
-        assertEquals(value, result._v);
-        
-        // should work with arrays too..
-        double[] array = MAPPER.readValue(new StringReader("[ \"Infinity\" ]"), double[].class);
-        assertNotNull(array);
-        assertEquals(1, array.length);
-        assertEquals(Double.POSITIVE_INFINITY, array[0]);
-    }
-    
-    public void testFloatPrimitiveNonNumeric() throws Exception
-    {
-        // bit tricky with binary fps but...
-        float value = Float.POSITIVE_INFINITY;
-        FloatBean result = MAPPER.readValue(new StringReader("{\"v\":\""+value+"\"}"), FloatBean.class);
-        assertEquals(value, result._v);
-        
-        // should work with arrays too..
-        float[] array = MAPPER.readValue(new StringReader("[ \"Infinity\" ]"), float[].class);
-        assertNotNull(array);
-        assertEquals(1, array.length);
-        assertEquals(Float.POSITIVE_INFINITY, array[0]);
-    }
-    
-    /**
-     * Beyond simple case, let's also ensure that method overriding works as
-     * expected.
-     */
-    public void testIntWithOverride() throws Exception
-    {
-        IntBean2 result = MAPPER.readValue(new StringReader("{\"v\":8}"), IntBean2.class);
-        assertEquals(9, result._v);
-    }
-
-    public void testEmptyToNullCoercionForPrimitives() throws Exception {
-        _testEmptyToNullCoercion(int.class, Integer.valueOf(0));
-        _testEmptyToNullCoercion(long.class, Long.valueOf(0));
-        _testEmptyToNullCoercion(double.class, Double.valueOf(0.0));
-        _testEmptyToNullCoercion(float.class, Float.valueOf(0.0f));
-    }
-
-    private void _testEmptyToNullCoercion(Class<?> primType, Object emptyValue) throws Exception
-    {
-        final String EMPTY = "\"\"";
-
-        // as per [databind#1095] should only allow coercion from empty String,
-        // if `null` is acceptable
-        ObjectReader intR = MAPPER.readerFor(primType);
-        assertEquals(emptyValue, intR.readValue(EMPTY));
-        try {
-            intR.with(DeserializationFeature.FAIL_ON_NULL_FOR_PRIMITIVES)
-                .readValue("\"\"");
-            fail("Should not have passed");
-        } catch (JsonMappingException e) {
-            verifyException(e, "Can not map Empty String");
-        }
-    }
-    
-    /*
-    /**********************************************************
-    /* Then tests for wrappers
-    /**********************************************************
-     */
-
-    /**
-     * Simple unit test to verify that we can map boolean values to
-     * java.lang.Boolean.
-     */
-    public void testBooleanWrapper() throws Exception
-    {
-        Boolean result = MAPPER.readValue(new StringReader("true"), Boolean.class);
-        assertEquals(Boolean.TRUE, result);
-        result = MAPPER.readValue(new StringReader("false"), Boolean.class);
-        assertEquals(Boolean.FALSE, result);
-
-        // [JACKSON-78]: should accept ints too, (0 == false, otherwise true)
-        result = MAPPER.readValue(new StringReader("0"), Boolean.class);
-        assertEquals(Boolean.FALSE, result);
-        result = MAPPER.readValue(new StringReader("1"), Boolean.class);
-        assertEquals(Boolean.TRUE, result);
-    }
-
-    public void testByteWrapper() throws Exception
-    {
-        Byte result = MAPPER.readValue(new StringReader("   -42\t"), Byte.class);
-        assertEquals(Byte.valueOf((byte)-42), result);
-
-        // Also: should be able to coerce floats, strings:
-        result = MAPPER.readValue(new StringReader(" \"-12\""), Byte.class);
-        assertEquals(Byte.valueOf((byte)-12), result);
-
-        result = MAPPER.readValue(new StringReader(" 39.07"), Byte.class);
-        assertEquals(Byte.valueOf((byte)39), result);
-    }
-
-    public void testShortWrapper() throws Exception
-    {
-        Short result = MAPPER.readValue(new StringReader("37"), Short.class);
-        assertEquals(Short.valueOf((short)37), result);
-
-        // Also: should be able to coerce floats, strings:
-        result = MAPPER.readValue(new StringReader(" \"-1009\""), Short.class);
-        assertEquals(Short.valueOf((short)-1009), result);
-
-        result = MAPPER.readValue(new StringReader("-12.9"), Short.class);
-        assertEquals(Short.valueOf((short)-12), result);
-    }
-
-    public void testCharacterWrapper() throws Exception
-    {
-        // First: canonical value is 1-char string
-        Character result = MAPPER.readValue(new StringReader("\"a\""), Character.class);
-        assertEquals(Character.valueOf('a'), result);
-
-        // But can also pass in ascii code
-        result = MAPPER.readValue(new StringReader(" "+((int) 'X')), Character.class);
-        assertEquals(Character.valueOf('X'), result);
-        
-        final CharacterWrapperBean wrapper = MAPPER.readValue(new StringReader("{\"v\":null}"), CharacterWrapperBean.class);
-        assertNotNull(wrapper);
-        assertNull(wrapper.getV());
-        
-        final ObjectMapper mapper = new ObjectMapper();
-        mapper.enable(DeserializationFeature.FAIL_ON_NULL_FOR_PRIMITIVES);
-        try {
-            mapper.readValue("{\"v\":null}", CharacterBean.class);
-            fail("Attempting to deserialize a 'null' JSON reference into a 'char' property did not throw an exception");
-        } catch (JsonMappingException exp) {
-            //Exception thrown as required
-        }
-
-        mapper.disable(DeserializationFeature.FAIL_ON_NULL_FOR_PRIMITIVES);  
-        final CharacterBean charBean = MAPPER.readValue(new StringReader("{\"v\":null}"), CharacterBean.class);
-        assertNotNull(wrapper);
-        assertEquals('\u0000', charBean.getV());
-    }
-
-    public void testIntWrapper() throws Exception
-    {
-        Integer result = MAPPER.readValue(new StringReader("   -42\t"), Integer.class);
-        assertEquals(Integer.valueOf(-42), result);
-
-        // Also: should be able to coerce floats, strings:
-        result = MAPPER.readValue(new StringReader(" \"-1200\""), Integer.class);
-        assertEquals(Integer.valueOf(-1200), result);
-
-        result = MAPPER.readValue(new StringReader(" 39.07"), Integer.class);
-        assertEquals(Integer.valueOf(39), result);
-    }
-
-    public void testLongWrapper() throws Exception
-    {
-        Long result = MAPPER.readValue(new StringReader("12345678901"), Long.class);
-        assertEquals(Long.valueOf(12345678901L), result);
-
-        // Also: should be able to coerce floats, strings:
-        result = MAPPER.readValue(new StringReader(" \"-9876\""), Long.class);
-        assertEquals(Long.valueOf(-9876), result);
-
-        result = MAPPER.readValue(new StringReader("1918.3"), Long.class);
-        assertEquals(Long.valueOf(1918), result);
-    }
-
-    /* Note: dealing with floating-point values is tricky; not sure if
-     * we can really use equality tests here... JDK does have decent
-     * conversions though, to retain accuracy and round-trippability.
-     * But still...
-     */
-    public void testFloatWrapper() throws Exception
-    {
-        // Also: should be able to coerce floats, strings:
-        String[] STRS = new String[] {
-            "1.0", "0.0", "-0.3", "0.7", "42.012", "-999.0", NAN_STRING
-        };
-
-        for (String str : STRS) {
-            Float exp = Float.valueOf(str);
-            Float result;
-
-            if (NAN_STRING != str) {
-                // First, as regular floating point value
-                result = MAPPER.readValue(new StringReader(str), Float.class);
-                assertEquals(exp, result);
-            }
-
-            // and then as coerced String:
-            result = MAPPER.readValue(new StringReader(" \""+str+"\""), Float.class);
-            assertEquals(exp, result);
-        }
-    }
-
-    public void testDoubleWrapper() throws Exception
-    {
-        // Also: should be able to coerce doubles, strings:
-        String[] STRS = new String[] {
-            "1.0", "0.0", "-0.3", "0.7", "42.012", "-999.0", NAN_STRING
-        };
-
-        for (String str : STRS) {
-            Double exp = Double.valueOf(str);
-            Double result;
-
-            // First, as regular double value
-            if (NAN_STRING != str) {
-                result = MAPPER.readValue(str, Double.class);
-            	assertEquals(exp, result);
-            }
-            // and then as coerced String:
-            result = MAPPER.readValue(new StringReader(" \""+str+"\""), Double.class);
-            assertEquals(exp, result);
-        }
-    }
-
-    // as per [Issue#42], allow Base64 variant use as well
-    public void testBase64Variants() throws Exception
-    {
-        final byte[] INPUT = "abcdefghijklmnopqrstuvwxyz1234567890abcdefghijklmnopqrstuvwxyz1234567890X".getBytes("UTF-8");
-        
-        // default encoding is "MIME, no linefeeds", so:
-        Assert.assertArrayEquals(INPUT, MAPPER.readValue(
-                quote("YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXoxMjM0NTY3ODkwYWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXoxMjM0NTY3ODkwWA=="),
-                byte[].class));
-        ObjectReader reader = MAPPER.readerFor(byte[].class);
-        Assert.assertArrayEquals(INPUT, (byte[]) reader.with(Base64Variants.MIME_NO_LINEFEEDS).readValue(
-                quote("YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXoxMjM0NTY3ODkwYWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXoxMjM0NTY3ODkwWA=="
-        )));
-
-        // but others should be slightly different
-        Assert.assertArrayEquals(INPUT, (byte[]) reader.with(Base64Variants.MIME).readValue(
-                quote("YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXoxMjM0NTY3ODkwYWJjZGVmZ2hpamtsbW5vcHFyc3R1\\ndnd4eXoxMjM0NTY3ODkwWA=="
-        )));
-        Assert.assertArrayEquals(INPUT, (byte[]) reader.with(Base64Variants.MODIFIED_FOR_URL).readValue(
-                quote("YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXoxMjM0NTY3ODkwYWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXoxMjM0NTY3ODkwWA"
-        )));
-        // PEM mandates 64 char lines:
-        Assert.assertArrayEquals(INPUT, (byte[]) reader.with(Base64Variants.PEM).readValue(
-                quote("YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXoxMjM0NTY3ODkwYWJjZGVmZ2hpamts\\nbW5vcHFyc3R1dnd4eXoxMjM0NTY3ODkwWA=="
-        )));
-    }    
-    /*
-    /**********************************************************
-    /* Simple non-primitive types
-    /**********************************************************
-     */
-
-    public void testSingleString() throws Exception
-    {
-        String value = "FOO!";
-        String result = MAPPER.readValue(new StringReader("\""+value+"\""), String.class);
-        assertEquals(value, result);
-    }
-    
-    public void testSingleStringWrapped() throws Exception
-    {
-        final ObjectMapper mapper = new ObjectMapper();
-        mapper.disable(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS);
-        
-        String value = "FOO!";
-        try {
-            mapper.readValue(new StringReader("[\""+value+"\"]"), String.class);
-            fail("Exception not thrown when attempting to unwrap a single value 'String' array into a simple String");
-        } catch (JsonMappingException exp) {
-            //exception thrown correctly
-        }
-        
-        mapper.enable(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS);
-        
-        try {
-            mapper.readValue(new StringReader("[\""+value+"\",\""+value+"\"]"), String.class);
-            fail("Exception not thrown when attempting to unwrap a single value 'String' array that contained more than one value into a simple String");
-        } catch (JsonMappingException exp) {
-            //exception thrown correctly
-        }
-        
-        String result = mapper.readValue(new StringReader("[\""+value+"\"]"), String.class);
-        assertEquals(value, result);
-    }
-
-    public void testNull() throws Exception
-    {
-        // null doesn't really have a type, fake by assuming Object
-        Object result = MAPPER.readValue("   null", Object.class);
-        assertNull(result);
-    }  
-
-    public void testClass() throws Exception
-    {
-        final ObjectMapper mapper = new ObjectMapper();        
-        mapper.disable(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS);        
-        
-        Class<?> result = mapper.readValue(quote(String.class.getName()), Class.class);
-        assertEquals(String.class, result);
-        
-        //[Issue#381]
-        try {
-            mapper.readValue("[" + quote(String.class.getName()) + "]", Class.class);
-            fail("Did not throw exception when UNWRAP_SINGLE_VALUE_ARRAYS feature was disabled and attempted to read a Class array containing one element");
-        } catch (JsonMappingException exp) {
-            
-        }
-        
-        mapper.enable(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS);
-        
-        try {
-           mapper.readValue("[" + quote(Object.class.getName()) + "," + quote(Object.class.getName()) +"]", Class.class); 
-           fail("Did not throw exception when UNWRAP_SINGLE_VALUE_ARRAYS feature was enabled and attempted to read a Class array containing two elements");
-        } catch (JsonMappingException exp) {
-            
-        }               
-        result = mapper.readValue("[" + quote(String.class.getName()) + "]", Class.class);
-        assertEquals(String.class, result);
-    }
-
-    public void testBigDecimal() throws Exception
-    {
-        final ObjectMapper mapper = objectMapper();
-        mapper.disable(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS);
-        
-        BigDecimal value = new BigDecimal("0.001");
-        BigDecimal result = mapper.readValue(value.toString(), BigDecimal.class);
-        assertEquals(value, result);
-        
-        //Issue#381
-        try {
-            mapper.readValue("[" + value.toString() + "]", BigDecimal.class);
-            fail("Exception was not thrown when attempting to read a single value array of BigDecimal when UNWRAP_SINGLE_VALUE_ARRAYS feature is disabled");
-        } catch (JsonMappingException exp) {
-            //Exception was thrown correctly
-        }
-        
-        mapper.enable(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS);
-        result = mapper.readValue("[" + value.toString() + "]", BigDecimal.class);
-        assertEquals(value, result);
-        
-        try {
-            mapper.readValue("[" + value.toString() + "," + value.toString() + "]", BigDecimal.class);
-            fail("Exception was not thrown when attempting to read a muti value array of BigDecimal when UNWRAP_SINGLE_VALUE_ARRAYS feature is enabled");
-        } catch (JsonMappingException exp) {
-            //Exception was thrown correctly
-        }
-    }
-
-    public void testBigInteger() throws Exception
-    {
-        final ObjectMapper mapper = objectMapper();
-        mapper.disable(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS);
-        
-        BigInteger value = new BigInteger("-1234567890123456789012345567809");
-        BigInteger result = mapper.readValue(new StringReader(value.toString()), BigInteger.class);
-        assertEquals(value, result);
-        
-        //Issue#381
-        try {
-            mapper.readValue("[" + value.toString() + "]", BigInteger.class);
-            fail("Exception was not thrown when attempting to read a single value array of BigInteger when UNWRAP_SINGLE_VALUE_ARRAYS feature is disabled");
-        } catch (JsonMappingException exp) {
-            //Exception was thrown correctly
-        }
-        
-        mapper.enable(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS);
-        result = mapper.readValue("[" + value.toString() + "]", BigInteger.class);
-        assertEquals(value, result);
-        
-        try {
-            mapper.readValue("[" + value.toString() + "," + value.toString() + "]", BigInteger.class);
-            fail("Exception was not thrown when attempting to read a muti value array of BigInteger when UNWRAP_SINGLE_VALUE_ARRAYS feature is enabled");
-        } catch (JsonMappingException exp) {
-            //Exception was thrown correctly
-        }        
-    }
-
-    public void testUUID() throws Exception
-    {
-        final ObjectMapper mapper = objectMapper();
-        
-        final String NULL_UUID = "00000000-0000-0000-0000-000000000000";
-        // first, couple of generated UUIDs:
-        for (String value : new String[] {
-                "76e6d183-5f68-4afa-b94a-922c1fdb83f8",
-                "540a88d1-e2d8-4fb1-9396-9212280d0a7f",
-                "2c9e441d-1cd0-472d-9bab-69838f877574",
-                "591b2869-146e-41d7-8048-e8131f1fdec5",
-                "82994ac2-7b23-49f2-8cc5-e24cf6ed77be",
-                "00000007-0000-0000-0000-000000000000"
-        }) {
-            
-            mapper.disable(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS);
-            
-            UUID uuid = UUID.fromString(value);
-            assertEquals(uuid,
-                    mapper.readValue(quote(value), UUID.class));
-            
-            try {
-                mapper.readValue("[" + quote(value) + "]", UUID.class);
-                fail("Exception was not thrown when UNWRAP_SINGLE_VALUE_ARRAYS is disabled and attempted to read a single value array as a single element");
-            } catch (JsonMappingException exp) {
-                //Exception thrown successfully
-            }
-            
-            mapper.enable(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS);
-            
-            assertEquals(uuid,
-                    mapper.readValue("[" + quote(value) + "]", UUID.class));
-            
-            try {
-                mapper.readValue("[" + quote(value) + "," + quote(value) + "]", UUID.class);
-                fail("Exception was not thrown when UNWRAP_SINGLE_VALUE_ARRAYS is enabled and attempted to read a multi value array as a single element");
-            } catch (JsonMappingException exp) {
-                //Exception thrown successfully
-            }
-        }
-        // then use templating; note that these are not exactly valid UUIDs
-        // wrt spec (type bits etc), but JDK UUID should deal ok
-        final String TEMPL = NULL_UUID;
-        final String chars = "123456789abcdefABCDEF";
-
-        for (int i = 0; i < chars.length(); ++i) {
-            String value = TEMPL.replace('0', chars.charAt(i));
-            assertEquals(UUID.fromString(value).toString(),
-                    mapper.readValue(quote(value), UUID.class).toString());
-        }
-
-        // also: see if base64 encoding works as expected
-        String base64 = Base64Variants.getDefaultVariant().encode(new byte[16]);
-        assertEquals(UUID.fromString(NULL_UUID),
-                mapper.readValue(quote(base64), UUID.class));
-    }
-
-    public void testUUIDInvalid() throws Exception
-    {
-        // and finally, exception handling too [databind#1000], for invalid cases
-        try {
-            MAPPER.readValue(quote("abcde"), UUID.class);
-            fail("Should fail on invalid UUID string");
-        } catch (InvalidFormatException e) {
-            verifyException(e, "UUID has to be represented by standard");
-        }
-        try {
-            MAPPER.readValue(quote("76e6d183-5f68-4afa-b94a-922c1fdb83fx"), UUID.class);
-            fail("Should fail on invalid UUID string");
-        } catch (InvalidFormatException e) {
-            verifyException(e, "non-hex character 'x'");
-        }
-        // should also test from-bytes version, but that's trickier... leave for now.
-    }
-
-    public void testUUIDAux() throws Exception
-    {
-        // [JACKSON-393] fix:
-        final UUID value = UUID.fromString("76e6d183-5f68-4afa-b94a-922c1fdb83f8");
-
-        // first, null should come as null
-        TokenBuffer buf = new TokenBuffer(null, false);
-        buf.writeObject(null);
-        assertNull(MAPPER.readValue(buf.asParser(), UUID.class));
-        buf.close();
-
-        // then, UUID itself come as is:
-        buf = new TokenBuffer(null, false);
-        buf.writeObject(value);
-        assertSame(value, MAPPER.readValue(buf.asParser(), UUID.class));
-
-        // and finally from byte[]
-        // oh crap; JDK UUID just... sucks. Not even byte[] accessors or constructors? Huh?
-        ByteArrayOutputStream bytes = new ByteArrayOutputStream();
-        DataOutputStream out = new DataOutputStream(bytes);
-        out.writeLong(value.getMostSignificantBits());
-        out.writeLong(value.getLeastSignificantBits());
-        byte[] data = bytes.toByteArray();
-        assertEquals(16, data.length);
-        
-        buf.writeObject(data);
-
-        UUID value2 = MAPPER.readValue(buf.asParser(), UUID.class);
-        
-        assertEquals(value, value2);
-        buf.close();
-    }
-
-    public void testURL() throws Exception
-    {
-        URL value = new URL("http://foo.com");
-        assertEquals(value, MAPPER.readValue("\""+value.toString()+"\"", URL.class));
-
-        // trivial case; null to null, embedded URL to URL
-        TokenBuffer buf = new TokenBuffer(null, false);
-        buf.writeObject(null);
-        assertNull(MAPPER.readValue(buf.asParser(), URL.class));
-        buf.close();
-
-        // then, URLitself come as is:
-        buf = new TokenBuffer(null, false);
-        buf.writeObject(value);
-        assertSame(value, MAPPER.readValue(buf.asParser(), URL.class));
-        buf.close();
-    }
-
-    public void testURI() throws Exception
-    {
-        final ObjectMapper mapper = new ObjectMapper();
-        
-        URI value = new URI("http://foo.com");
-        assertEquals(value, mapper.readValue("\""+value.toString()+"\"", URI.class));
-        
-        //[Issue#381]
-        mapper.disable(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS);
-        try {            
-            assertEquals(value, mapper.readValue("[\""+value.toString()+"\"]", URI.class));
-            fail("Did not throw exception for single value array when UNWRAP_SINGLE_VALUE_ARRAYS is disabled");
-        } catch (JsonMappingException exp) {
-            //exception thrown successfully
-        }
-        
-        try {
-            assertEquals(value, mapper.readValue("[\""+value.toString()+"\",\""+value.toString()+"\"]", URI.class));
-            fail("Did not throw exception for single value array when there were multiple values");
-        } catch (JsonMappingException exp) {
-            //exception thrown successfully
-        }
-        
-        mapper.enable(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS);
-        assertEquals(value, mapper.readValue("[\""+value.toString()+"\"]", URI.class));
-
-        // [#398]
-        value = mapper.readValue(quote(""), URI.class);
-        assertNotNull(value);
-        assertEquals(URI.create(""), value);
-    }
-
-    /*
-    /**********************************************************
-    /* Sequence tests
-    /**********************************************************
-     */
-
-    /**
-     * Then a unit test to verify that we can conveniently bind sequence of
-     * space-separate simple values
-     */
-    public void testSequenceOfInts() throws Exception
-    {
-        final int NR_OF_INTS = 100;
-
-        StringBuilder sb = new StringBuilder();
-        for (int i = 0; i < NR_OF_INTS; ++i) {
-            sb.append(" ");
-            sb.append(i);
-        }
-        JsonParser jp = MAPPER.getFactory().createParser(sb.toString());
-        for (int i = 0; i < NR_OF_INTS; ++i) {
-            Integer result = MAPPER.readValue(jp, Integer.class);
-            assertEquals(Integer.valueOf(i), result);
-        }
-        jp.close();
-    }
-}
-
diff --git a/src/test/java/com/fasterxml/jackson/databind/deser/TestUntypedDeserialization.java b/src/test/java/com/fasterxml/jackson/databind/deser/TestUntypedDeserialization.java
index d5bb225..eaf2bc8 100644
--- a/src/test/java/com/fasterxml/jackson/databind/deser/TestUntypedDeserialization.java
+++ b/src/test/java/com/fasterxml/jackson/databind/deser/TestUntypedDeserialization.java
@@ -92,15 +92,19 @@
         }
     }
 
-    static class Untyped989 {
+    static class DelegatingUntyped {
         protected Object value;
         
         @JsonCreator // delegating
-        public Untyped989(Object v) {
+        public DelegatingUntyped(Object v) {
             value = v;
         }
     }
-    
+
+    static class WrappedUntyped1460 {
+        public Object value;
+    }
+
     /*
     /**********************************************************
     /* Test methods
@@ -253,8 +257,8 @@
 
     public void testNestedUntyped989() throws IOException
     {
-        Untyped989 pojo;
-        ObjectReader r = MAPPER.readerFor(Untyped989.class);
+        DelegatingUntyped pojo;
+        ObjectReader r = MAPPER.readerFor(DelegatingUntyped.class);
 
         pojo = r.readValue("[]");
         assertTrue(pojo.value instanceof List);
@@ -266,4 +270,29 @@
         pojo = r.readValue("{\"a\":[]}");
         assertTrue(pojo.value instanceof Map);
     }
+
+    public void testUntypedWithJsonArrays() throws Exception
+    {
+        // by default we get:
+        Object ob = MAPPER.readValue("[1]", Object.class);
+        assertTrue(ob instanceof List<?>);
+
+        // but can change to produce Object[]:
+        MAPPER.configure(DeserializationFeature.USE_JAVA_ARRAY_FOR_JSON_ARRAY, true);
+        ob = MAPPER.readValue("[1]", Object.class);
+        assertEquals(Object[].class, ob.getClass());
+    }
+
+    public void testUntypedIntAsLong() throws Exception
+    {
+        final String JSON = aposToQuotes("{'value':3}");
+        WrappedUntyped1460 w = MAPPER.readerFor(WrappedUntyped1460.class)
+                .readValue(JSON);
+        assertEquals(Integer.valueOf(3), w.value);
+
+        w = MAPPER.readerFor(WrappedUntyped1460.class)
+                .with(DeserializationFeature.USE_LONG_FOR_INTS)
+                .readValue(JSON);
+        assertEquals(Long.valueOf(3), w.value);
+    }
 }
diff --git a/src/test/java/com/fasterxml/jackson/databind/deser/TestValueAnnotations.java b/src/test/java/com/fasterxml/jackson/databind/deser/TestValueAnnotations.java
index 6603745..e14ad18 100644
--- a/src/test/java/com/fasterxml/jackson/databind/deser/TestValueAnnotations.java
+++ b/src/test/java/com/fasterxml/jackson/databind/deser/TestValueAnnotations.java
@@ -67,13 +67,13 @@
         public RootStringDeserializer() { super(RootString.class); }
 
         @Override
-        public RootString deserialize(JsonParser jp, DeserializationContext ctxt)
-            throws IOException, JsonProcessingException
+        public RootString deserialize(JsonParser p, DeserializationContext ctxt)
+            throws IOException
         {
-            if (jp.getCurrentToken() == JsonToken.VALUE_STRING) {
-                return new RootStringImpl(jp.getText());
+            if (p.hasToken(JsonToken.VALUE_STRING)) {
+                return new RootStringImpl(p.getText());
             }
-            throw ctxt.mappingException(_valueClass);
+            return (RootString) ctxt.handleUnexpectedToken(_valueClass, p);
         }
     }
 
diff --git a/src/test/java/com/fasterxml/jackson/databind/deser/UntypedNumbersTest.java b/src/test/java/com/fasterxml/jackson/databind/deser/UntypedNumbersTest.java
deleted file mode 100644
index 2de4389..0000000
--- a/src/test/java/com/fasterxml/jackson/databind/deser/UntypedNumbersTest.java
+++ /dev/null
@@ -1,137 +0,0 @@
-package com.fasterxml.jackson.databind.deser;
-
-import java.io.*;
-import java.math.BigDecimal;
-import java.math.BigInteger;
-import java.util.*;
-
-
-import com.fasterxml.jackson.databind.*;
-
-/**
- * Unit tests for verifying handling of non-specific numeric types.
- */
-public class UntypedNumbersTest
-    extends BaseMapTest
-{
-    private final ObjectMapper MAPPER = objectMapper();
-
-    public void testIntAsNumber() throws Exception
-    {
-        /* Even if declared as 'generic' type, should return using most
-         * efficient type... here, Integer
-         */
-        Number result = MAPPER.readValue(" 123 ", Number.class);
-        assertEquals(Integer.valueOf(123), result);
-    }
-
-    public void testLongAsNumber() throws Exception
-    {
-        // And beyond int range, should get long
-        long exp = 1234567890123L;
-        Number result = MAPPER.readValue(String.valueOf(exp), Number.class);
-        assertEquals(Long.valueOf(exp), result);
-    }
-
-    public void testBigIntAsNumber() throws Exception
-    {
-        // and after long, BigInteger
-        BigInteger biggie = new BigInteger("1234567890123456789012345678901234567890");
-        Number result = MAPPER.readValue(biggie.toString(), Number.class);
-        assertEquals(BigInteger.class, biggie.getClass());
-        assertEquals(biggie, result);
-    }
-
-    public void testIntTypeOverride() throws Exception
-    {
-        /* Slight twist; as per [JACKSON-100], can also request binding
-         * to BigInteger even if value would fit in Integer
-         */
-        ObjectReader r = MAPPER.reader(DeserializationFeature.USE_BIG_INTEGER_FOR_INTS);
-
-        BigInteger exp = BigInteger.valueOf(123L);
-
-        // first test as any Number
-        Number result = r.forType(Number.class).readValue(" 123 ");
-        assertEquals(BigInteger.class, result.getClass());
-        assertEquals(exp, result);
-
-        // then as any Object
-        /*Object value =*/ r.forType(Object.class).readValue("123");
-        assertEquals(BigInteger.class, result.getClass());
-        assertEquals(exp, result);
-
-        // and as JsonNode
-        JsonNode node = r.readTree("  123");
-        assertTrue(node.isBigInteger());
-        assertEquals(123, node.asInt());
-    }
-
-    public void testDoubleAsNumber() throws Exception
-    {
-        Number result = MAPPER.readValue(new StringReader(" 1.0 "), Number.class);
-        assertEquals(Double.valueOf(1.0), result);
-    }
-
-    public void testFpTypeOverrideSimple() throws Exception
-    {
-        ObjectReader r = MAPPER.reader(DeserializationFeature.USE_BIG_DECIMAL_FOR_FLOATS);
-        BigDecimal dec = new BigDecimal("0.1");
-
-        // First test generic stand-alone Number
-        Number result = r.forType(Number.class).readValue(dec.toString());
-        assertEquals(BigDecimal.class, result.getClass());
-        assertEquals(dec, result);
-
-        // Then plain old Object
-        Object value = r.forType(Object.class).readValue(dec.toString());
-        assertEquals(BigDecimal.class, result.getClass());
-        assertEquals(dec, value);
-
-        JsonNode node = r.readTree(dec.toString());
-        assertTrue(node.isBigDecimal());
-        assertEquals(dec.doubleValue(), node.asDouble());
-    }
-
-    public void testFpTypeOverrideStructured() throws Exception
-    {
-        ObjectReader r = MAPPER.reader(DeserializationFeature.USE_BIG_DECIMAL_FOR_FLOATS);
-
-        BigDecimal dec = new BigDecimal("-19.37");
-        // List element types
-        @SuppressWarnings("unchecked")
-        List<Object> list = (List<Object>) r.forType(List.class).readValue("[ "+dec.toString()+" ]");
-        assertEquals(1, list.size());
-        Object val = list.get(0);
-        assertEquals(BigDecimal.class, val.getClass());
-        assertEquals(dec, val);
-
-        // and a map
-        Map<?,?> map = r.forType(Map.class).readValue("{ \"a\" : "+dec.toString()+" }");
-        assertEquals(1, map.size());
-        val = map.get("a");
-        assertEquals(BigDecimal.class, val.getClass());
-        assertEquals(dec, val);
-    }
-
-    // [databind#504]
-    public void testForceIntsToLongs() throws Exception
-    {
-        ObjectReader r = MAPPER.reader(DeserializationFeature.USE_LONG_FOR_INTS);
-
-        Object ob = r.forType(Object.class).readValue("42");
-        assertEquals(Long.class, ob.getClass());
-        assertEquals(Long.valueOf(42L), ob);
-
-        Number n = r.forType(Number.class).readValue("42");
-        assertEquals(Long.class, n.getClass());
-        assertEquals(Long.valueOf(42L), n);
-
-        // and one more: should get proper node as well
-        JsonNode node = r.readTree("42");
-        if (!node.isLong()) {
-            fail("Expected LongNode, got: "+node.getClass().getName());
-        }
-        assertEquals(42, node.asInt());
-    }
-}
diff --git a/src/test/java/com/fasterxml/jackson/databind/deser/builder/BuilderWithUnwrappedTest.java b/src/test/java/com/fasterxml/jackson/databind/deser/builder/BuilderWithUnwrappedTest.java
new file mode 100644
index 0000000..89726cb
--- /dev/null
+++ b/src/test/java/com/fasterxml/jackson/databind/deser/builder/BuilderWithUnwrappedTest.java
@@ -0,0 +1,246 @@
+package com.fasterxml.jackson.databind.deser.builder;
+
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.annotation.JsonUnwrapped;
+import com.fasterxml.jackson.databind.BaseMapTest;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
+import com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder;
+
+public class BuilderWithUnwrappedTest extends BaseMapTest {
+    /*
+     *************************************
+     * Mock classes
+     *************************************
+     */
+
+    final static class Name {
+        private final String first;
+        private final String last;
+
+        @JsonCreator
+        Name(
+                @JsonProperty("first_name") String first,
+                @JsonProperty("last_name") String last
+        ) {
+            this.first = first;
+            this.last = last;
+        }
+
+        String getFirst() {
+            return first;
+        }
+
+        String getLast() {
+            return last;
+        }
+    }
+
+    @JsonDeserialize(builder = Person.Builder.class)
+    final static class Person {
+        private final long id;
+        private final Name name;
+        private final int age;
+        private final boolean alive;
+
+        private Person(Builder builder) {
+            id = builder.id;
+            name = builder.name;
+            age = builder.age;
+            alive = builder.alive;
+        }
+
+        long getId() {
+            return id;
+        }
+
+        Name getName() {
+            return name;
+        }
+
+        int getAge() {
+            return age;
+        }
+
+        boolean isAlive() {
+            return alive;
+        }
+
+        @JsonPOJOBuilder(withPrefix = "set")
+        final static class Builder {
+            private final long id;
+            private Name name;
+            private int age;
+            private boolean alive;
+
+            Builder(@JsonProperty("person_id") long id) {
+                this.id = id;
+            }
+
+            @JsonUnwrapped
+            void setName(Name name) {
+                this.name = name;
+            }
+
+            @JsonProperty("years_old")
+            void setAge(int age) {
+                this.age = age;
+            }
+
+            @JsonProperty("living")
+            void setAlive(boolean alive) {
+                this.alive = alive;
+            }
+
+            Person build() {
+                return new Person(this);
+            }
+        }
+    }
+
+    @JsonDeserialize(builder = Animal.Builder.class)
+    final static class Animal {
+        private final long id;
+        private final Name name;
+        private final int age;
+        private final boolean alive;
+
+        private Animal(Builder builder) {
+            id = builder.id;
+            name = builder.name;
+            age = builder.age;
+            alive = builder.alive;
+        }
+
+        long getId() {
+            return id;
+        }
+
+        Name getName() {
+            return name;
+        }
+
+        int getAge() {
+            return age;
+        }
+
+        boolean isAlive() {
+            return alive;
+        }
+
+        @JsonPOJOBuilder(withPrefix = "set")
+        final static class Builder {
+            private final long id;
+            private Name name;
+            private int age;
+            private final boolean alive;
+
+            Builder(
+                    @JsonProperty("animal_id") long id,
+                    @JsonProperty("living") boolean alive
+            ) {
+                this.id = id;
+                this.alive = alive;
+            }
+
+            @JsonUnwrapped
+            void setName(Name name) {
+                this.name = name;
+            }
+
+            @JsonProperty("years_old")
+            void setAge(int age) {
+                this.age = age;
+            }
+
+            Animal build() {
+                return new Animal(this);
+            }
+        }
+    }
+
+    /*
+     *************************************
+     * Unit tests
+     *************************************
+     */
+
+    public void testWithUnwrappedAndCreatorSingleParameterAtBeginning() throws Exception {
+        final String json = aposToQuotes("{'person_id':1234,'first_name':'John','last_name':'Doe','years_old':30,'living':true}");
+
+        final ObjectMapper mapper = new ObjectMapper();
+        Person person = mapper.readValue(json, Person.class);
+        assertEquals(1234, person.getId());
+        assertNotNull(person.getName());
+        assertEquals("John", person.getName().getFirst());
+        assertEquals("Doe", person.getName().getLast());
+        assertEquals(30, person.getAge());
+        assertEquals(true, person.isAlive());
+    }
+
+    public void testWithUnwrappedAndCreatorSingleParameterInMiddle() throws Exception {
+        final String json = aposToQuotes("{'first_name':'John','last_name':'Doe','person_id':1234,'years_old':30,'living':true}");
+
+        final ObjectMapper mapper = new ObjectMapper();
+        Person person = mapper.readValue(json, Person.class);
+        assertEquals(1234, person.getId());
+        assertNotNull(person.getName());
+        assertEquals("John", person.getName().getFirst());
+        assertEquals("Doe", person.getName().getLast());
+        assertEquals(30, person.getAge());
+        assertEquals(true, person.isAlive());
+    }
+
+    public void testWithUnwrappedAndCreatorSingleParameterAtEnd() throws Exception {
+        final String json = aposToQuotes("{'first_name':'John','last_name':'Doe','years_old':30,'living':true,'person_id':1234}");
+
+        final ObjectMapper mapper = new ObjectMapper();
+        Person person = mapper.readValue(json, Person.class);
+        assertEquals(1234, person.getId());
+        assertNotNull(person.getName());
+        assertEquals("John", person.getName().getFirst());
+        assertEquals("Doe", person.getName().getLast());
+        assertEquals(30, person.getAge());
+        assertEquals(true, person.isAlive());
+    }
+
+    public void testWithUnwrappedAndCreatorMultipleParametersAtBeginning() throws Exception {
+        final String json = aposToQuotes("{'animal_id':1234,'living':true,'first_name':'John','last_name':'Doe','years_old':30}");
+
+        final ObjectMapper mapper = new ObjectMapper();
+        Animal animal = mapper.readValue(json, Animal.class);
+        assertEquals(1234, animal.getId());
+        assertNotNull(animal.getName());
+        assertEquals("John", animal.getName().getFirst());
+        assertEquals("Doe", animal.getName().getLast());
+        assertEquals(30, animal.getAge());
+        assertEquals(true, animal.isAlive());
+    }
+
+    public void testWithUnwrappedAndCreatorMultipleParametersInMiddle() throws Exception {
+        final String json = aposToQuotes("{'first_name':'John','animal_id':1234,'last_name':'Doe','living':true,'years_old':30}");
+
+        final ObjectMapper mapper = new ObjectMapper();
+        Animal animal = mapper.readValue(json, Animal.class);
+        assertEquals(1234, animal.getId());
+        assertNotNull(animal.getName());
+        assertEquals("John", animal.getName().getFirst());
+        assertEquals("Doe", animal.getName().getLast());
+        assertEquals(30, animal.getAge());
+        assertEquals(true, animal.isAlive());
+    }
+
+    public void testWithUnwrappedAndCreatorMultipleParametersAtEnd() throws Exception {
+        final String json = aposToQuotes("{'first_name':'John','last_name':'Doe','years_old':30,'living':true,'animal_id':1234}");
+
+        final ObjectMapper mapper = new ObjectMapper();
+        Animal animal = mapper.readValue(json, Animal.class);
+        assertEquals(1234, animal.getId());
+        assertNotNull(animal.getName());
+        assertEquals("John", animal.getName().getFirst());
+        assertEquals("Doe", animal.getName().getLast());
+        assertEquals(30, animal.getAge());
+        assertEquals(true, animal.isAlive());
+    }
+}
diff --git a/src/test/java/com/fasterxml/jackson/databind/deser/exc/ExceptionPathTest.java b/src/test/java/com/fasterxml/jackson/databind/deser/exc/ExceptionPathTest.java
new file mode 100644
index 0000000..c4a87bb
--- /dev/null
+++ b/src/test/java/com/fasterxml/jackson/databind/deser/exc/ExceptionPathTest.java
@@ -0,0 +1,46 @@
+package com.fasterxml.jackson.databind.deser.exc;
+
+import com.fasterxml.jackson.annotation.*;
+
+import com.fasterxml.jackson.databind.*;
+
+public class ExceptionPathTest extends BaseMapTest
+{
+    static class Outer {
+        public Inner inner = new Inner();
+    }
+
+    static class Inner {
+        public int x;
+
+        @JsonCreator public static Inner create(@JsonProperty("x") int x) {
+            throw new RuntimeException("test-exception");
+        }
+    }
+
+    /*
+    /**********************************************************
+    /* Test methods
+    /**********************************************************
+     */
+    
+    private final ObjectMapper MAPPER = new ObjectMapper();
+
+    public void testReferenceChainForInnerClass() throws Exception
+    {
+        String json = MAPPER.writeValueAsString(new Outer());
+        try {
+            MAPPER.readValue(json, Outer.class);
+            fail("Should not pass");
+        } catch (JsonMappingException e) {
+            JsonMappingException.Reference reference = e.getPath().get(0);
+            assertEquals(getClass().getName()+"$Outer[\"inner\"]",
+                    reference.toString());
+        }
+    }
+
+    public static void main(String[] args)
+    {
+        System.err.println("Int, full: "+Integer.TYPE.getName());
+    }
+}
diff --git a/src/test/java/com/fasterxml/jackson/databind/deser/TestExceptionDeserialization.java b/src/test/java/com/fasterxml/jackson/databind/deser/exc/TestExceptionDeserialization.java
similarity index 75%
rename from src/test/java/com/fasterxml/jackson/databind/deser/TestExceptionDeserialization.java
rename to src/test/java/com/fasterxml/jackson/databind/deser/exc/TestExceptionDeserialization.java
index a784100..d89bfd6 100644
--- a/src/test/java/com/fasterxml/jackson/databind/deser/TestExceptionDeserialization.java
+++ b/src/test/java/com/fasterxml/jackson/databind/deser/exc/TestExceptionDeserialization.java
@@ -1,4 +1,4 @@
-package com.fasterxml.jackson.databind.deser;
+package com.fasterxml.jackson.databind.deser.exc;
 
 import java.io.IOException;
 import java.util.*;
@@ -44,7 +44,7 @@
     {
         @JsonCreator MyNoArgException() { }
     }
-    
+
     /*
     /**********************************************************
     /* Tests
@@ -89,7 +89,7 @@
         assertNotNull(exc);
     }
 
-    // [JACKSON-794]: try simulating JDK 7 behavior
+    // try simulating JDK 7 behavior
     public void testJDK7SuppressionProperty() throws IOException
     {
         Exception exc = MAPPER.readValue("{\"suppressed\":[]}", IOException.class);
@@ -113,10 +113,34 @@
         
         assertEquals(exp.getStackTrace().length, cloned.getStackTrace().length);
         for (int i = 0; i < exp.getStackTrace().length; i ++) {
-            assertEquals(exp.getStackTrace()[i], cloned.getStackTrace()[i]);
+            _assertEquality(i, exp.getStackTrace()[i], cloned.getStackTrace()[i]);
         }
     }
-    
+
+    protected void _assertEquality(int ix, StackTraceElement exp, StackTraceElement act)
+    {
+        _assertEquality(ix, "className", exp.getClassName(), act.getClassName());
+        _assertEquality(ix, "methodName", exp.getMethodName(), act.getMethodName());
+        _assertEquality(ix, "fileName", exp.getFileName(), act.getFileName());
+        _assertEquality(ix, "lineNumber", exp.getLineNumber(), act.getLineNumber());
+    }
+
+    protected void _assertEquality(int ix, String prop,
+            Object exp, Object act)
+    {
+        if (exp == null) {
+            if (act == null) {
+                return;
+            }
+        } else {
+            if (exp.equals(act)) {
+                return;
+            }
+        }
+        fail(String.format("StackTraceElement #%d, property '%s' differs: expected %s, actual %s",
+                ix, prop, exp, act));
+    }
+
     public void testSingleValueArrayDeserializationException() throws Exception {
         final ObjectMapper mapper = new ObjectMapper();
         mapper.disable(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS);
@@ -133,36 +157,17 @@
             mapper.readValue(value, IOException.class);
             fail("Exception not thrown when attempting to deserialize an IOException wrapped in a single value array with UNWRAP_SINGLE_VALUE_ARRAYS disabled");
         } catch (JsonMappingException exp2) {
-            //Exception thrown correctly
+            verifyException(exp2, "out of START_ARRAY");
         }
     }
 
-    static class NoSerdeConstructor {
-        private String strVal;
-        public String getVal() { return strVal; }
-        public NoSerdeConstructor( String strVal ) {
-            this.strVal = strVal;
-        }
-    }
-
-    // [databind#1368]
-    public void testFailingNoSerdeConstructor() throws IOException {
-        Exception e = null;
-        // cant deserialize due to unexpected constructor
-        try {
-            MAPPER.readValue( "{ \"val\": \"foo\" }", NoSerdeConstructor.class );
-            fail("Should not pass");
-        } catch (JsonMappingException e0) {
-            verifyException(e0, "No suitable constructor");
-            e = e0;
-        }
-        // but should be able to serialize new exception we got
-        String json = MAPPER.writeValueAsString(e);
-        JsonNode root = MAPPER.readTree(json);
-        String msg = root.path("message").asText();
-        String MATCH = "No suitable constructor";
-        if (!msg.contains(MATCH)) {
-            fail("Exception should contain '"+MATCH+"', does not: '"+msg+"'");
-        }
+    // mostly to help with XML module (and perhaps CSV)
+    public void testLineNumberAsString() throws IOException
+    {
+        Exception exc = MAPPER.readValue(aposToQuotes(
+                "{'message':'Test',\n'stackTrace': "
+                +"[ { 'lineNumber':'50' } ] }"
+        ), IOException.class);
+        assertNotNull(exc);
     }
 }
diff --git a/src/test/java/com/fasterxml/jackson/databind/deser/TestExceptionHandling.java b/src/test/java/com/fasterxml/jackson/databind/deser/exc/TestExceptionHandling.java
similarity index 97%
rename from src/test/java/com/fasterxml/jackson/databind/deser/TestExceptionHandling.java
rename to src/test/java/com/fasterxml/jackson/databind/deser/exc/TestExceptionHandling.java
index 6f23517..00c88ec 100644
--- a/src/test/java/com/fasterxml/jackson/databind/deser/TestExceptionHandling.java
+++ b/src/test/java/com/fasterxml/jackson/databind/deser/exc/TestExceptionHandling.java
@@ -1,4 +1,4 @@
-package com.fasterxml.jackson.databind.deser;
+package com.fasterxml.jackson.databind.deser.exc;
 
 import java.io.*;
 
@@ -23,10 +23,7 @@
     /* Test methods
     /**********************************************************
      */
-    
-    /**
-     * Verification of [JACKSON-301]
-     */
+
     public void testHandlingOfUnrecognized() throws Exception
     {
         UnrecognizedPropertyException exc = null;
diff --git a/src/test/java/com/fasterxml/jackson/databind/deser/TestExceptionHandlingWithDefaultDeserialization.java b/src/test/java/com/fasterxml/jackson/databind/deser/exc/TestExceptionHandlingWithDefaultDeserialization.java
similarity index 78%
rename from src/test/java/com/fasterxml/jackson/databind/deser/TestExceptionHandlingWithDefaultDeserialization.java
rename to src/test/java/com/fasterxml/jackson/databind/deser/exc/TestExceptionHandlingWithDefaultDeserialization.java
index 1a75d94..3888722 100644
--- a/src/test/java/com/fasterxml/jackson/databind/deser/TestExceptionHandlingWithDefaultDeserialization.java
+++ b/src/test/java/com/fasterxml/jackson/databind/deser/exc/TestExceptionHandlingWithDefaultDeserialization.java
@@ -1,4 +1,4 @@
-package com.fasterxml.jackson.databind.deser;
+package com.fasterxml.jackson.databind.deser.exc;
 
 import com.fasterxml.jackson.databind.BaseMapTest;
 import com.fasterxml.jackson.databind.JsonMappingException;
@@ -6,14 +6,12 @@
 
 import java.io.IOException;
 
-public class TestExceptionHandlingWithDefaultDeserialization extends BaseMapTest {
-
+public class TestExceptionHandlingWithDefaultDeserialization extends BaseMapTest
+{
     static class Foo {
-
         private Bar bar;
 
-        public Foo() {
-        }
+        public Foo() { }
 
         public Bar getBar() {
             return bar;
@@ -21,11 +19,9 @@
     }
 
     static class Bar {
-
         private Baz baz;
 
-        public Bar() {
-        }
+        public Bar() { }
 
         public Baz getBaz() {
             return baz;
@@ -33,11 +29,9 @@
     }
 
     static class Baz {
-
         private String qux;
 
-        public Baz() {
-        }
+        public Baz() { }
 
         public String getQux() {
             return qux;
@@ -48,6 +42,7 @@
         // given
         ObjectMapper mapper = new ObjectMapper();
         String input = "{\"bar\":{\"baz\":{qux:\"quxValue\"))}";
+        final String THIS = getClass().getName();
 
         // when
         try {
@@ -55,7 +50,7 @@
             fail("Upsss! Exception has not been thrown.");
         } catch (JsonMappingException ex) {
             // then
-            assertEquals("com.fasterxml.jackson.databind.deser.Foo[\"bar\"]->com.fasterxml.jackson.databind.deser.Bar[\"baz\"]",
+            assertEquals(THIS+"$Foo[\"bar\"]->"+THIS+"$Bar[\"baz\"]",
                     ex.getPathReference());
         }
     }
diff --git a/src/test/java/com/fasterxml/jackson/databind/deser/TestExceptionHandlingWithJsonCreatorDeserialization.java b/src/test/java/com/fasterxml/jackson/databind/deser/exc/TestExceptionHandlingWithJsonCreatorDeserialization.java
similarity index 89%
rename from src/test/java/com/fasterxml/jackson/databind/deser/TestExceptionHandlingWithJsonCreatorDeserialization.java
rename to src/test/java/com/fasterxml/jackson/databind/deser/exc/TestExceptionHandlingWithJsonCreatorDeserialization.java
index f2da339..8065bc4 100644
--- a/src/test/java/com/fasterxml/jackson/databind/deser/TestExceptionHandlingWithJsonCreatorDeserialization.java
+++ b/src/test/java/com/fasterxml/jackson/databind/deser/exc/TestExceptionHandlingWithJsonCreatorDeserialization.java
@@ -1,4 +1,4 @@
-package com.fasterxml.jackson.databind.deser;
+package com.fasterxml.jackson.databind.deser.exc;
 
 import com.fasterxml.jackson.annotation.JsonCreator;
 import com.fasterxml.jackson.annotation.JsonProperty;
@@ -53,6 +53,7 @@
         // given
         ObjectMapper mapper = new ObjectMapper();
         String input = "{\"bar\":{\"baz\":{qux:\"quxValue\"))}";
+        final String THIS = getClass().getName();
 
         // when
         try {
@@ -60,7 +61,7 @@
             fail("Upsss! Exception has not been thrown.");
         } catch (JsonMappingException ex) {
             // then
-            assertEquals("com.fasterxml.jackson.databind.deser.Foo[\"bar\"]->com.fasterxml.jackson.databind.deser.Bar[\"baz\"]",
+            assertEquals(THIS+"$Foo[\"bar\"]->"+THIS+"$Bar[\"baz\"]",
                     ex.getPathReference());
         }
     }
diff --git a/src/test/java/com/fasterxml/jackson/databind/deser/exc/TestExceptionSerialization.java b/src/test/java/com/fasterxml/jackson/databind/deser/exc/TestExceptionSerialization.java
new file mode 100644
index 0000000..07fc70a
--- /dev/null
+++ b/src/test/java/com/fasterxml/jackson/databind/deser/exc/TestExceptionSerialization.java
@@ -0,0 +1,124 @@
+package com.fasterxml.jackson.databind.deser.exc;
+
+import java.io.IOException;
+import java.util.*;
+
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+import com.fasterxml.jackson.databind.*;
+
+/**
+ * Unit tests for verifying that simple exceptions can be serialized.
+ */
+public class TestExceptionSerialization
+    extends BaseMapTest
+{
+    @SuppressWarnings("serial")
+    @JsonIgnoreProperties({ "bogus1" })
+    static class ExceptionWithIgnoral extends RuntimeException
+    {
+        public int bogus1 = 3;
+
+        public int bogus2 = 5;
+
+        protected ExceptionWithIgnoral() { }
+        public ExceptionWithIgnoral(String msg) {
+            super(msg);
+        }
+    }
+
+    // [databind#1368]
+    static class NoSerdeConstructor {
+        private String strVal;
+        public String getVal() { return strVal; }
+        public NoSerdeConstructor( String strVal ) {
+            this.strVal = strVal;
+        }
+    }
+
+    /*
+    /**********************************************************
+    /* Tests
+    /**********************************************************
+     */
+
+    private final ObjectMapper MAPPER = new ObjectMapper();
+    
+    public void testSimple() throws Exception
+    {
+        String TEST = "test exception";
+        Map<String,Object> result = writeAndMap(MAPPER, new Exception(TEST));
+        // JDK 7 has introduced a new property 'suppressed' to Throwable
+        Object ob = result.get("suppressed");
+        if (ob != null) {
+            assertEquals(5, result.size());
+        } else {
+            assertEquals(4, result.size());
+        }
+
+        assertEquals(TEST, result.get("message"));
+        assertNull(result.get("cause"));
+        assertEquals(TEST, result.get("localizedMessage"));
+
+        // hmmh. what should we get for stack traces?
+        Object traces = result.get("stackTrace");
+        if (!(traces instanceof List<?>)) {
+            fail("Expected a List for exception member 'stackTrace', got: "+traces);
+        }
+    }
+
+    // for [databind#877]
+    @SuppressWarnings("unchecked")
+    public void testIgnorals() throws Exception
+    {
+        ExceptionWithIgnoral input = new ExceptionWithIgnoral("foobar");
+        input.initCause(new IOException("surprise!"));
+
+        // First, should ignore anything with class annotations
+        String json = MAPPER
+                .writerWithDefaultPrettyPrinter()
+                .writeValueAsString(input);
+
+        Map<String,Object> result = MAPPER.readValue(json, Map.class);
+        assertEquals("foobar", result.get("message"));
+
+        assertNull(result.get("bogus1"));
+        assertNotNull(result.get("bogus2"));
+
+        // and then also remova second property with config overrides
+        ObjectMapper mapper = new ObjectMapper();
+        mapper.configOverride(ExceptionWithIgnoral.class)
+            .setIgnorals(JsonIgnoreProperties.Value.forIgnoredProperties("bogus2"));
+        String json2 = mapper
+                .writeValueAsString(new ExceptionWithIgnoral("foobar"));
+
+        Map<String,Object> result2 = mapper.readValue(json2, Map.class);
+        assertNull(result2.get("bogus1"));
+        assertNull(result2.get("bogus2"));
+
+        // and try to deserialize as well
+        ExceptionWithIgnoral output = mapper.readValue(json2, ExceptionWithIgnoral.class);
+        assertNotNull(output);
+        assertEquals("foobar", output.getMessage());
+    }
+
+    // [databind#1368]
+    public void testJsonMappingExceptionSerialization() throws IOException {
+        Exception e = null;
+        // cant deserialize due to unexpected constructor
+        try {
+            MAPPER.readValue( "{ \"val\": \"foo\" }", NoSerdeConstructor.class );
+            fail("Should not pass");
+        } catch (JsonMappingException e0) {
+            verifyException(e0, "no suitable constructor");
+            e = e0;
+        }
+        // but should be able to serialize new exception we got
+        String json = MAPPER.writeValueAsString(e);
+        JsonNode root = MAPPER.readTree(json);
+        String msg = root.path("message").asText();
+        String MATCH = "no suitable constructor";
+        if (!msg.contains(MATCH)) {
+            fail("Exception should contain '"+MATCH+"', does not: '"+msg+"'");
+        }
+    }
+}
diff --git a/src/test/java/com/fasterxml/jackson/databind/ser/TestExceptionHandling.java b/src/test/java/com/fasterxml/jackson/databind/deser/exc/TestExceptionsDuringWriting.java
similarity index 97%
rename from src/test/java/com/fasterxml/jackson/databind/ser/TestExceptionHandling.java
rename to src/test/java/com/fasterxml/jackson/databind/deser/exc/TestExceptionsDuringWriting.java
index cc1aec7..df51963 100644
--- a/src/test/java/com/fasterxml/jackson/databind/ser/TestExceptionHandling.java
+++ b/src/test/java/com/fasterxml/jackson/databind/deser/exc/TestExceptionsDuringWriting.java
@@ -1,4 +1,4 @@
-package com.fasterxml.jackson.databind.ser;
+package com.fasterxml.jackson.databind.deser.exc;
 
 import java.io.*;
 import java.util.*;
@@ -12,7 +12,7 @@
  * re-thrown or wrapped, depending)
  * with Object serialization.
  */
-public class TestExceptionHandling
+public class TestExceptionsDuringWriting
     extends BaseMapTest
 {
     /*
diff --git a/src/test/java/com/fasterxml/jackson/databind/deser/jdk/MapDeserializerCachingTest.java b/src/test/java/com/fasterxml/jackson/databind/deser/jdk/MapDeserializerCachingTest.java
new file mode 100644
index 0000000..f2eca0a
--- /dev/null
+++ b/src/test/java/com/fasterxml/jackson/databind/deser/jdk/MapDeserializerCachingTest.java
@@ -0,0 +1,52 @@
+package com.fasterxml.jackson.databind.deser.jdk;
+
+import java.io.IOException;
+import java.util.Map;
+import java.util.TreeMap;
+
+import com.fasterxml.jackson.databind.*;
+import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
+
+// for [databind#1807]
+public class MapDeserializerCachingTest extends BaseMapTest
+{
+    public static class NonAnnotatedMapHolderClass {
+        public Map<String, String> data = new TreeMap<String, String>();
+    }
+
+    public static class MapHolder {
+        @JsonDeserialize(keyUsing = MyKeyDeserializer.class)
+        public Map<String, String> data = new TreeMap<String, String>();
+    }
+
+    public static class MyKeyDeserializer extends KeyDeserializer {
+        @Override
+        public Object deserializeKey(String key, DeserializationContext ctxt) throws IOException {
+            return key + " (CUSTOM)";
+        }
+    }
+
+    /*
+    /**********************************************************
+    /* Test methods
+    /**********************************************************
+     */
+
+    public void testCachedSerialize() throws IOException {
+        ObjectMapper mapper = new ObjectMapper();
+        String json = aposToQuotes("{'data':{'1st':'onedata','2nd':'twodata'}}");
+
+        // Do deserialization with non-annotated map property
+        NonAnnotatedMapHolderClass ignored = mapper.readValue(json, NonAnnotatedMapHolderClass.class);
+        assertTrue(ignored.data.containsKey("1st"));
+        assertTrue(ignored.data.containsKey("2nd"));
+
+//mapper = new ObjectMapper();
+        
+        MapHolder model2 = mapper.readValue(json, MapHolder.class);
+        if (!model2.data.containsKey("1st (CUSTOM)")
+            || !model2.data.containsKey("2nd (CUSTOM)")) {
+            fail("Not using custom key deserializer for input: "+json+"; resulted in: "+model2.data);
+        }
+    }
+}
diff --git a/src/test/java/com/fasterxml/jackson/databind/ext/TestDOM.java b/src/test/java/com/fasterxml/jackson/databind/ext/TestDOM.java
index 2938d20..0bd5609 100644
--- a/src/test/java/com/fasterxml/jackson/databind/ext/TestDOM.java
+++ b/src/test/java/com/fasterxml/jackson/databind/ext/TestDOM.java
@@ -14,6 +14,8 @@
         "<root attr='3'><leaf>Rock &amp; Roll!</leaf><?proc instr?></root>";
     final static String SIMPLE_XML_NS =
         "<root ns:attr='abc' xmlns:ns='http://foo' />";
+
+    private final ObjectMapper MAPPER = new ObjectMapper();
     
     public void testSerializeSimpleNonNS() throws Exception
     {
@@ -21,11 +23,10 @@
         Document doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse
             (new InputSource(new StringReader(SIMPLE_XML)));
         assertNotNull(doc);
-        ObjectMapper mapper = new ObjectMapper();
         // need to strip xml declaration, if any
-        String outputRaw = mapper.writeValueAsString(doc);
+        String outputRaw = MAPPER.writeValueAsString(doc);
         // And re-parse as String, since JSON has quotes...
-        String output = mapper.readValue(outputRaw, String.class);
+        String output = MAPPER.readValue(outputRaw, String.class);
         /* ... and finally, normalize to (close to) canonical XML
          * output (single vs double quotes, xml declaration etc)
          */
@@ -34,16 +35,15 @@
 
     public void testDeserializeNonNS() throws Exception
     {
-        ObjectMapper mapper = new ObjectMapper();
         for (int i = 0; i < 2; ++i) {
             Document doc;
 
             if (i == 0) {
                 // First, as Document:
-                doc = mapper.readValue(quote(SIMPLE_XML), Document.class);
+                doc = MAPPER.readValue(quote(SIMPLE_XML), Document.class);
             } else {
                 // and then as plain Node (no difference)
-                Node node = mapper.readValue(quote(SIMPLE_XML), Node.class);
+                Node node = MAPPER.readValue(quote(SIMPLE_XML), Node.class);
                 doc = (Document) node;
             }
             Element root = doc.getDocumentElement();
@@ -66,8 +66,7 @@
     
     public void testDeserializeNS() throws Exception
     {
-        ObjectMapper mapper = new ObjectMapper();
-        Document doc = mapper.readValue(quote(SIMPLE_XML_NS), Document.class);
+        Document doc = MAPPER.readValue(quote(SIMPLE_XML_NS), Document.class);
         Element root = doc.getDocumentElement();
         assertNotNull(root);
         assertEquals("root", root.getTagName());
@@ -82,9 +81,9 @@
     }
 
     /*
-     **********************************************************
-     * Helper methods
-     **********************************************************
+    /**********************************************************
+    /* Helper methods
+    /**********************************************************
      */
 
     protected static String normalizeOutput(String output)
diff --git a/src/test/java/com/fasterxml/jackson/databind/ext/TestJdk16Types.java b/src/test/java/com/fasterxml/jackson/databind/ext/TestJava6Types.java
similarity index 92%
rename from src/test/java/com/fasterxml/jackson/databind/ext/TestJdk16Types.java
rename to src/test/java/com/fasterxml/jackson/databind/ext/TestJava6Types.java
index 2d1f6fc..84ee94a 100644
--- a/src/test/java/com/fasterxml/jackson/databind/ext/TestJdk16Types.java
+++ b/src/test/java/com/fasterxml/jackson/databind/ext/TestJava6Types.java
@@ -9,7 +9,7 @@
  * Tests to ensure that we can handle 1.6-only types, even if
  * registrations are done without direct refs
  */
-public class TestJdk16Types extends com.fasterxml.jackson.databind.BaseMapTest
+public class TestJava6Types extends com.fasterxml.jackson.databind.BaseMapTest
 {
     // for [databind#216]
     public void test16Types() throws Exception
diff --git a/src/test/java/com/fasterxml/jackson/databind/ext/TestJava7Types.java b/src/test/java/com/fasterxml/jackson/databind/ext/TestJava7Types.java
new file mode 100644
index 0000000..459978d
--- /dev/null
+++ b/src/test/java/com/fasterxml/jackson/databind/ext/TestJava7Types.java
@@ -0,0 +1,33 @@
+package com.fasterxml.jackson.databind.ext;
+
+import java.nio.file.FileSystem;
+import java.nio.file.Path;
+
+import com.fasterxml.jackson.databind.*;
+
+import com.google.common.jimfs.Configuration;
+import com.google.common.jimfs.Jimfs;
+
+/**
+ * @since 2.7
+ */
+public class TestJava7Types extends BaseMapTest
+{
+    public void testPathRoundtrip() throws Exception
+    {
+        ObjectMapper mapper = new ObjectMapper();
+
+        FileSystem fs = Jimfs.newFileSystem(Configuration.unix());
+        Path input = fs.getPath("/tmp", "foo.txt");
+
+        String json = mapper.writeValueAsString(input);
+        assertNotNull(json);
+        
+        Path p = mapper.readValue(json, Path.class);
+        assertNotNull(p);
+        
+        assertEquals(input.toUri(), p.toUri());
+        assertEquals(input, p);
+        fs.close();
+    }
+}
diff --git a/src/test/java/com/fasterxml/jackson/databind/ext/TestJdk7Types.java b/src/test/java/com/fasterxml/jackson/databind/ext/TestJdk7Types.java
deleted file mode 100644
index 1b15f33..0000000
--- a/src/test/java/com/fasterxml/jackson/databind/ext/TestJdk7Types.java
+++ /dev/null
@@ -1,28 +0,0 @@
-package com.fasterxml.jackson.databind.ext;
-
-import java.nio.file.Path;
-import java.nio.file.Paths;
-
-import com.fasterxml.jackson.databind.*;
-
-/**
- * @since 2.7
- */
-public class TestJdk7Types extends BaseMapTest
-{
-    public void testPathRoundtrip() throws Exception
-    {
-        ObjectMapper mapper = new ObjectMapper();
-    
-        // Start with serialization, actually
-        Path input = Paths.get("tmp", "foo.txt");
-
-        String json = mapper.writeValueAsString(input);
-        assertNotNull(json);
-        
-        Path p = mapper.readValue(json, Path.class);
-        assertNotNull(p);
-        
-        assertEquals(input.toUri(), p.toUri());
-    }
-}
diff --git a/src/test/java/com/fasterxml/jackson/databind/ext/TestSOAP.java b/src/test/java/com/fasterxml/jackson/databind/ext/TestSOAP.java
deleted file mode 100644
index eb78c19..0000000
--- a/src/test/java/com/fasterxml/jackson/databind/ext/TestSOAP.java
+++ /dev/null
@@ -1,20 +0,0 @@
-package com.fasterxml.jackson.databind.ext;
-
-import javax.xml.soap.Detail;
-import javax.xml.soap.SOAPException;
-import javax.xml.soap.SOAPFactory;
-
-import com.fasterxml.jackson.core.JsonProcessingException;
-import com.fasterxml.jackson.databind.ObjectMapper;
-
-public class TestSOAP extends com.fasterxml.jackson.databind.BaseMapTest {
-
-    public void testSerializeSOAP() throws SOAPException, JsonProcessingException {
-        ObjectMapper objectMapper = new ObjectMapper();
-        SOAPFactory fac = SOAPFactory.newInstance();
-        Detail detailElement = fac.createDetail();
-        detailElement.setTextContent("test");
-        String result = objectMapper.writer().writeValueAsString(detailElement);
-        assertNotNull(result);
-    }
-}
diff --git a/src/test/java/com/fasterxml/jackson/databind/filter/IgnoreCreatorProp1317Test.java b/src/test/java/com/fasterxml/jackson/databind/filter/IgnoreCreatorProp1317Test.java
new file mode 100644
index 0000000..4df9611
--- /dev/null
+++ b/src/test/java/com/fasterxml/jackson/databind/filter/IgnoreCreatorProp1317Test.java
@@ -0,0 +1,50 @@
+package com.fasterxml.jackson.databind.filter;
+
+import java.beans.ConstructorProperties;
+
+import com.fasterxml.jackson.annotation.JsonIgnore;
+
+import com.fasterxml.jackson.databind.*;
+
+public class IgnoreCreatorProp1317Test extends BaseMapTest
+{
+    static class Testing {
+        @JsonIgnore
+        public String ignore;
+
+        String notIgnore;
+
+        public Testing() {}
+
+        @ConstructorProperties({"ignore", "notIgnore"})
+        public Testing(String ignore, String notIgnore) {
+            super();
+            this.ignore = ignore;
+            this.notIgnore = notIgnore;
+        }
+
+        public String getIgnore() {
+            return ignore;
+        }
+
+        public void setIgnore(String ignore) {
+            this.ignore = ignore;
+        }
+
+        public String getNotIgnore() {
+            return notIgnore;
+        }
+
+        public void setNotIgnore(String notIgnore) {
+            this.notIgnore = notIgnore;
+        }
+    }
+
+    public void testThatJsonIgnoreWorksWithConstructorProperties() throws Exception {
+        Testing testing = new Testing("shouldBeIgnored", "notIgnore");
+        ObjectMapper om = new ObjectMapper();
+        String json = om.writeValueAsString(testing);
+        System.out.println(json);
+        assertFalse(json.contains("shouldBeIgnored"));
+    }
+}
diff --git a/src/test/java/com/fasterxml/jackson/databind/filter/IgnorePropertiesDeser1575Test.java b/src/test/java/com/fasterxml/jackson/databind/filter/IgnorePropertiesDeser1575Test.java
new file mode 100644
index 0000000..e35e09b
--- /dev/null
+++ b/src/test/java/com/fasterxml/jackson/databind/filter/IgnorePropertiesDeser1575Test.java
@@ -0,0 +1,30 @@
+package com.fasterxml.jackson.databind.filter;
+
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+import com.fasterxml.jackson.databind.*;
+
+public class IgnorePropertiesDeser1575Test extends BaseMapTest
+{
+    static class Person {
+        public String name;
+
+        @JsonProperty("person_z") // renaming this to person_p works
+        @JsonIgnoreProperties({"person_z"}) // renaming this to person_p works
+//        public Set<Person> personZ;
+        public Person personZ;
+    }
+
+    public void testIgnorePropDeser1575() throws Exception
+    {
+        String st = aposToQuotes("{ 'name': 'admin',\n"
+//                + "    'person_z': [ { 'name': 'admin' } ]"
+              + "    'person_z': { 'name': 'admin' }"
+                + "}");
+
+        ObjectMapper mapper = new ObjectMapper();
+        Person result = mapper.readValue(st, Person.class);
+        assertEquals("admin", result.name);
+    }
+}
diff --git a/src/test/java/com/fasterxml/jackson/databind/filter/IgnorePropertyOnDeserTest.java b/src/test/java/com/fasterxml/jackson/databind/filter/IgnorePropertyOnDeserTest.java
new file mode 100644
index 0000000..08b882d
--- /dev/null
+++ b/src/test/java/com/fasterxml/jackson/databind/filter/IgnorePropertyOnDeserTest.java
@@ -0,0 +1,91 @@
+package com.fasterxml.jackson.databind.filter;
+
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+import com.fasterxml.jackson.annotation.JsonPropertyOrder;
+import com.fasterxml.jackson.databind.BaseMapTest;
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+public class IgnorePropertyOnDeserTest extends BaseMapTest
+{
+    // [databind#1217]
+    static class IgnoreObject {
+        public int x = 1;
+        public int y = 2;
+    }
+
+    final static class TestIgnoreObject {
+        @JsonIgnoreProperties({ "x" })
+        public IgnoreObject obj;
+
+        @JsonIgnoreProperties({ "y" })
+        public IgnoreObject obj2;
+    }
+
+    // [databind#1595]
+    @JsonIgnoreProperties(value = {"name"}, allowSetters = true)
+    @JsonPropertyOrder(alphabetic=true)
+    static class Simple1595 {
+        private int id;
+        private String name;
+
+        public int getId() { return id; }
+        public void setId(int id) { this.id = id; }
+
+        public String getName() { return name; }
+        public void setName(String name) { this.name = name; }
+    }
+
+    /*
+    /****************************************************************
+    /* Unit tests
+    /****************************************************************
+     */
+    
+    private final ObjectMapper MAPPER = new ObjectMapper();
+
+    // [databind#1217]
+    public void testIgnoreOnProperty1217() throws Exception
+    {
+        TestIgnoreObject result = MAPPER.readValue(
+                aposToQuotes("{'obj':{'x': 10, 'y': 20}, 'obj2':{'x': 10, 'y': 20}}"),
+                TestIgnoreObject.class);
+        assertEquals(20, result.obj.y);
+        assertEquals(10, result.obj2.x);
+
+        assertEquals(1, result.obj.x);
+        assertEquals(2, result.obj2.y);
+        
+        TestIgnoreObject result1 = MAPPER.readValue(
+                  aposToQuotes("{'obj':{'x': 20, 'y': 30}, 'obj2':{'x': 20, 'y': 40}}"),
+                  TestIgnoreObject.class);
+        assertEquals(1, result1.obj.x);
+        assertEquals(30, result1.obj.y);
+       
+        assertEquals(20, result1.obj2.x);
+        assertEquals(2, result1.obj2.y);
+    }
+
+    public void testIgnoreViaConfigOverride1217() throws Exception
+    {
+        ObjectMapper mapper = new ObjectMapper();
+        mapper.configOverride(Point.class)
+            .setIgnorals(JsonIgnoreProperties.Value.forIgnoredProperties("y"));
+        Point p = mapper.readValue(aposToQuotes("{'x':1,'y':2}"), Point.class);
+        // bind 'x', but ignore 'y'
+        assertEquals(1, p.x);
+        assertEquals(0, p.y);
+    }
+
+    // [databind#1595]
+    public void testIgnoreGetterNotSetter1595() throws Exception
+    {
+        ObjectMapper mapper = new ObjectMapper();
+        Simple1595 config = new Simple1595();
+        config.setId(123);
+        config.setName("jack");
+        String json = mapper.writeValueAsString(config);
+        assertEquals(aposToQuotes("{'id':123}"), json);
+        Simple1595 des = mapper.readValue(aposToQuotes("{'id':123,'name':'jack'}"), Simple1595.class);
+        assertEquals("jack", des.getName());
+    }
+}
diff --git a/src/test/java/com/fasterxml/jackson/databind/filter/IgnorePropsForSerTest.java b/src/test/java/com/fasterxml/jackson/databind/filter/IgnorePropsForSerTest.java
index d4064a6..a8342bd 100644
--- a/src/test/java/com/fasterxml/jackson/databind/filter/IgnorePropsForSerTest.java
+++ b/src/test/java/com/fasterxml/jackson/databind/filter/IgnorePropsForSerTest.java
@@ -3,7 +3,6 @@
 import java.util.*;
 
 import com.fasterxml.jackson.annotation.*;
-
 import com.fasterxml.jackson.databind.*;
 
 public class IgnorePropsForSerTest
@@ -122,4 +121,12 @@
         assertEquals("{\"value\":{\"y\":2}}",
                 MAPPER.writeValueAsString(new WrapperWithPropIgnore2()));
     }
+
+    public void testIgnoreViaConfigOverride() throws Exception
+    {
+        ObjectMapper mapper = new ObjectMapper();
+        mapper.configOverride(Point.class)
+            .setIgnorals(JsonIgnoreProperties.Value.forIgnoredProperties("x"));
+        assertEquals("{\"y\":3}", mapper.writeValueAsString(new Point(2, 3)));
+    }
 }
diff --git a/src/test/java/com/fasterxml/jackson/databind/filter/JsonIgnoreProperties1595Test.java b/src/test/java/com/fasterxml/jackson/databind/filter/JsonIgnoreProperties1595Test.java
deleted file mode 100644
index b886e0a..0000000
--- a/src/test/java/com/fasterxml/jackson/databind/filter/JsonIgnoreProperties1595Test.java
+++ /dev/null
@@ -1,43 +0,0 @@
-package com.fasterxml.jackson.databind.filter;
-
-import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
-import com.fasterxml.jackson.annotation.JsonPropertyOrder;
-import com.fasterxml.jackson.databind.*;
-
-public class JsonIgnoreProperties1595Test extends BaseMapTest
-{
-    @JsonIgnoreProperties(value = {"name"}, allowSetters = true)
-    @JsonPropertyOrder(alphabetic=true)
-    static class Simple {
-        private int id;
-        private String name;
-
-        public int getId() {
-            return id;
-        }
-
-        public void setId(int id) {
-            this.id = id;
-        }
-
-        public String getName() {
-            return name;
-        }
-
-        public void setName(String name) {
-            this.name = name;
-        }
-    }
-
-    public void testIgnoreGetterNotSetter1595() throws Exception
-    {
-        ObjectMapper mapper = new ObjectMapper();
-        Simple config = new Simple();
-        config.setId(123);
-        config.setName("jack");
-        String json = mapper.writeValueAsString(config);
-        assertEquals(aposToQuotes("{'id':123}"), json);
-        Simple des = mapper.readValue(aposToQuotes("{'id':123,'name':'jack'}"), Simple.class);
-        assertEquals("jack", des.getName());
-    }
-}
diff --git a/src/test/java/com/fasterxml/jackson/databind/filter/JsonInclude1327Test.java b/src/test/java/com/fasterxml/jackson/databind/filter/JsonInclude1327Test.java
new file mode 100644
index 0000000..cf11a4d
--- /dev/null
+++ b/src/test/java/com/fasterxml/jackson/databind/filter/JsonInclude1327Test.java
@@ -0,0 +1,56 @@
+package com.fasterxml.jackson.databind.filter;
+
+import java.util.*;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+
+import com.fasterxml.jackson.databind.*;
+import com.fasterxml.jackson.databind.annotation.JsonSerialize;
+
+/**
+ * Unit tests for checking that alternative settings for
+ * {@link JsonSerialize#include} annotation property work
+ * as expected.
+ */
+public class JsonInclude1327Test
+    extends BaseMapTest
+{
+    @JsonInclude(JsonInclude.Include.NON_EMPTY)
+    static class Issue1327BeanEmpty {
+        public List<String> myList = new ArrayList<String>();
+    }
+
+    static class Issue1327BeanAlways {
+        @JsonInclude(JsonInclude.Include.ALWAYS)
+        public List<String> myList = new ArrayList<String>();
+    }
+
+    /*
+    /**********************************************************
+    /* Unit tests
+    /**********************************************************
+     */
+
+    // for [databind#1327]
+    public void testClassDefaultsForEmpty() throws Exception {
+        ObjectMapper om = new ObjectMapper();
+        om.setSerializationInclusion(JsonInclude.Include.NON_NULL);
+
+        final String jsonString = om.writeValueAsString(new Issue1327BeanEmpty());
+
+        if (jsonString.contains("myList")) {
+            fail("Should not contain `myList`: "+jsonString);
+        }
+    }
+
+    public void testClassDefaultsForAlways() throws Exception {
+        ObjectMapper om = new ObjectMapper();
+        om.setSerializationInclusion(JsonInclude.Include.NON_EMPTY);
+
+        final String jsonString = om.writeValueAsString(new Issue1327BeanAlways());
+
+        if (!jsonString.contains("myList")) {
+            fail("Should contain `myList` with Include.ALWAYS: "+jsonString);
+        }
+    }
+}
diff --git a/src/test/java/com/fasterxml/jackson/databind/filter/JsonIncludeTest.java b/src/test/java/com/fasterxml/jackson/databind/filter/JsonIncludeTest.java
index e5f44eb..a5aa82e 100644
--- a/src/test/java/com/fasterxml/jackson/databind/filter/JsonIncludeTest.java
+++ b/src/test/java/com/fasterxml/jackson/databind/filter/JsonIncludeTest.java
@@ -3,7 +3,9 @@
 import java.io.IOException;
 import java.util.*;
 
+import com.fasterxml.jackson.annotation.JsonCreator;
 import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonProperty;
 import com.fasterxml.jackson.annotation.JsonPropertyOrder;
 import com.fasterxml.jackson.databind.*;
 import com.fasterxml.jackson.databind.annotation.JsonSerialize;
@@ -119,10 +121,57 @@
         public NonEmptyDouble(double v) { value = v; }
     }
 
-    @JsonInclude(JsonInclude.Include.NON_EMPTY)
-    public static class Issues1327Bean {
-        public String myString = "stuff";
-        public List<String> myList = new ArrayList<String>();
+    @JsonPropertyOrder({"list", "map"})
+    static class EmptyListMapBean
+    {
+        public List<String> list = Collections.emptyList();
+
+        public Map<String,String> map = Collections.emptyMap();
+    }
+
+    // [databind#1351]
+
+    static class Issue1351Bean
+    {
+        public final String first;
+        public final double second;
+
+        public Issue1351Bean(String first, double second) {
+            this.first = first;
+            this.second = second;
+        }
+    }
+
+    @JsonInclude(JsonInclude.Include.NON_DEFAULT)
+    static abstract class Issue1351NonBeanParent
+    {
+        protected final int num;
+
+        protected Issue1351NonBeanParent(int num) {
+            this.num = num;
+        }
+
+        @JsonProperty("num")
+        public int getNum() {
+            return num;
+        }
+    }
+
+    static class Issue1351NonBean extends Issue1351NonBeanParent {
+        private String str;
+
+        @JsonCreator
+        public Issue1351NonBean(@JsonProperty("num") int num) {
+            super(num);
+        }
+
+        public String getStr() {
+            return str;
+        }
+
+        public void setStr(String str) {
+            this.str = str;
+        }
     }
 
     /*
@@ -238,15 +287,37 @@
         assertEquals("{\"i\":0}", inclMapper.writeValueAsString(zero));
     }
 
-    public void testIssue1327() throws Exception {
-        ObjectMapper om = new ObjectMapper();
-        om.setSerializationInclusion(JsonInclude.Include.NON_NULL);
+    public void testPropConfigOverridesForInclude() throws IOException
+    {
+        // First, with defaults, both included:
+        EmptyListMapBean empty = new EmptyListMapBean();
+        assertEquals(aposToQuotes("{'list':[],'map':{}}"),
+                MAPPER.writeValueAsString(empty));
+        ObjectMapper mapper;
 
-        final Issues1327Bean input = new Issues1327Bean();
-        final String jsonString = om.writeValueAsString(input);
+        // and then change inclusion criteria for either
+        mapper = new ObjectMapper();
+        mapper.configOverride(Map.class)
+            .setInclude(JsonInclude.Value.construct(JsonInclude.Include.NON_EMPTY, null));
+        assertEquals(aposToQuotes("{'list':[]}"),
+                mapper.writeValueAsString(empty));
 
-        if (jsonString.contains("myList")) {
-            fail("Should not contain `myList`: "+jsonString);
-        }
+        mapper = new ObjectMapper();
+        mapper.configOverride(List.class)
+            .setInclude(JsonInclude.Value.construct(JsonInclude.Include.NON_EMPTY, null));
+        assertEquals(aposToQuotes("{'map':{}}"),
+                mapper.writeValueAsString(empty));
+    }
+
+    // [databind#1351], [databind#1417]
+    public void testIssue1351() throws Exception
+    {
+        ObjectMapper mapper = new ObjectMapper();
+        mapper.setSerializationInclusion(JsonInclude.Include.NON_DEFAULT);
+        assertEquals(aposToQuotes("{}"),
+                mapper.writeValueAsString(new Issue1351Bean(null, (double) 0)));
+        // [databind#1417]
+        assertEquals(aposToQuotes("{}"),
+                mapper.writeValueAsString(new Issue1351NonBean(0)));
     }
 }
diff --git a/src/test/java/com/fasterxml/jackson/databind/filter/ProblemHandler1767Test.java b/src/test/java/com/fasterxml/jackson/databind/filter/ProblemHandler1767Test.java
new file mode 100644
index 0000000..05c87db
--- /dev/null
+++ b/src/test/java/com/fasterxml/jackson/databind/filter/ProblemHandler1767Test.java
@@ -0,0 +1,45 @@
+package com.fasterxml.jackson.databind.filter;
+
+import com.fasterxml.jackson.databind.*;
+import com.fasterxml.jackson.databind.deser.DeserializationProblemHandler;
+
+public class ProblemHandler1767Test extends BaseMapTest
+{
+    static class IntHandler
+            extends DeserializationProblemHandler
+    {
+        @Override
+        public Object handleWeirdStringValue(DeserializationContext ctxt,
+                Class<?> targetType,
+                String valueToConvert,
+                String failureMsg)
+        {
+            if (targetType != Integer.TYPE) {
+                return NOT_HANDLED;
+            }
+            return 1;
+        }
+    }
+
+    static class TestBean {
+        int a;
+
+        public int getA() {
+            return a;
+        }
+
+        public void setA(int a) {
+            this.a = a;
+        }
+
+    }
+
+    public void testPrimitivePropertyWithHandler() throws Exception {
+        final ObjectMapper mapper = new ObjectMapper();
+        mapper.addHandler(new IntHandler());
+        TestBean result = mapper.readValue(aposToQuotes("{'a': 'not-a-number'}"), TestBean.class);
+        assertNotNull(result);
+        assertEquals(1, result.a);
+    }
+    
+}
diff --git a/src/test/java/com/fasterxml/jackson/databind/filter/ProblemHandlerTest.java b/src/test/java/com/fasterxml/jackson/databind/filter/ProblemHandlerTest.java
new file mode 100644
index 0000000..1a9f396
--- /dev/null
+++ b/src/test/java/com/fasterxml/jackson/databind/filter/ProblemHandlerTest.java
@@ -0,0 +1,313 @@
+package com.fasterxml.jackson.databind.filter;
+
+import java.io.IOException;
+import java.util.Map;
+import java.util.UUID;
+
+import com.fasterxml.jackson.annotation.JsonTypeInfo;
+import com.fasterxml.jackson.core.JsonParser;
+import com.fasterxml.jackson.core.JsonToken;
+import com.fasterxml.jackson.databind.*;
+import com.fasterxml.jackson.databind.deser.DeserializationProblemHandler;
+import com.fasterxml.jackson.databind.exc.InvalidTypeIdException;
+import com.fasterxml.jackson.databind.jsontype.TypeIdResolver;
+
+/**
+ * Tests to exercise handler methods of {@link DeserializationProblemHandler}.
+ *
+ * @since 2.8
+ */
+public class ProblemHandlerTest extends BaseMapTest
+{
+    /*
+    /**********************************************************
+    /* Test handler types
+    /**********************************************************
+     */
+
+    static class WeirdKeyHandler
+        extends DeserializationProblemHandler
+    {
+        protected final Object key;
+
+        public WeirdKeyHandler(Object key0) {
+            key = key0;
+        }
+
+        @Override
+        public Object handleWeirdKey(DeserializationContext ctxt,
+                Class<?> rawKeyType, String keyValue,
+                String failureMsg)
+            throws IOException
+        {
+            return key;
+        }
+    }
+
+    static class WeirdNumberHandler
+        extends DeserializationProblemHandler
+    {
+        protected final Object value;
+
+        public WeirdNumberHandler(Object v0) {
+            value = v0;
+        }
+
+        @Override
+        public Object handleWeirdNumberValue(DeserializationContext ctxt,
+                Class<?> targetType, Number n,
+                String failureMsg)
+            throws IOException
+        {
+            return value;
+        }
+    }
+
+    static class WeirdStringHandler
+        extends DeserializationProblemHandler
+    {
+        protected final Object value;
+    
+        public WeirdStringHandler(Object v0) {
+            value = v0;
+        }
+    
+        @Override
+        public Object handleWeirdStringValue(DeserializationContext ctxt,
+                Class<?> targetType, String v,
+                String failureMsg)
+            throws IOException
+        {
+            return value;
+        }
+    }
+
+    static class InstantiationProblemHandler
+        extends DeserializationProblemHandler
+    {
+        protected final Object value;
+    
+        public InstantiationProblemHandler(Object v0) {
+            value = v0;
+        }
+    
+        @Override
+        public Object handleInstantiationProblem(DeserializationContext ctxt,
+                Class<?> instClass, Object argument, Throwable t)
+            throws IOException
+        {
+            return value;
+        }
+    }
+
+    static class MissingInstantiationHandler
+        extends DeserializationProblemHandler
+    {
+        protected final Object value;
+    
+        public MissingInstantiationHandler(Object v0) {
+            value = v0;
+        }
+    
+        @Override
+        public Object handleMissingInstantiator(DeserializationContext ctxt,
+                Class<?> instClass, JsonParser p, String msg)
+            throws IOException
+        {
+            p.skipChildren();
+            return value;
+        }
+    }
+
+    static class WeirdTokenHandler
+        extends DeserializationProblemHandler
+    {
+        protected final Object value;
+    
+        public WeirdTokenHandler(Object v) {
+            value = v;
+        }
+    
+        @Override
+        public Object handleUnexpectedToken(DeserializationContext ctxt,
+                Class<?> targetType, JsonToken t, JsonParser p,
+                String failureMsg)
+            throws IOException
+        {
+            return value;
+        }
+    }
+
+    static class TypeIdHandler
+        extends DeserializationProblemHandler
+    {
+        protected final Class<?> raw;
+
+        public TypeIdHandler(Class<?> r) { raw = r; }
+        
+        @Override
+        public JavaType handleUnknownTypeId(DeserializationContext ctxt,
+                JavaType baseType, String subTypeId, TypeIdResolver idResolver,
+                String failureMsg)
+            throws IOException
+        {
+            return ctxt.constructType(raw);
+        }
+    }
+
+    /*
+    /**********************************************************
+    /* Other helper types
+    /**********************************************************
+     */
+
+    static class IntKeyMapWrapper {
+        public Map<Integer,String> stuff;
+    }
+
+    @JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "type")
+    static class Base { }
+    static class BaseImpl extends Base {
+        public int a;
+    }
+
+    static class BaseWrapper {
+        public Base value;
+    }
+
+    @JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, property = "clazz")
+    static class Base2 { }
+    static class Base2Impl extends Base2 {
+        public int a;
+    }
+
+    static class Base2Wrapper {
+        public Base2 value;
+    }
+    
+    enum SingleValuedEnum {
+        A;
+    }
+
+    static class BustedCtor {
+        public final static BustedCtor INST = new BustedCtor(true);
+
+        public BustedCtor() {
+            throw new RuntimeException("Fail!");
+        }
+        private BustedCtor(boolean b) { }
+    }
+
+    static class NoDefaultCtor {
+        public int value;
+
+        public NoDefaultCtor(int v) { value = v; }
+    }
+
+    /*
+    /**********************************************************
+    /* Test methods
+    /**********************************************************
+     */
+
+    private final ObjectMapper MAPPER = new ObjectMapper();
+
+    public void testWeirdKeyHandling() throws Exception
+    {
+        ObjectMapper mapper = new ObjectMapper()
+            .addHandler(new WeirdKeyHandler(7));
+        IntKeyMapWrapper w = mapper.readValue("{\"stuff\":{\"foo\":\"abc\"}}",
+                IntKeyMapWrapper.class);
+        Map<Integer,String> map = w.stuff;
+        assertEquals(1, map.size());
+        assertEquals("abc", map.values().iterator().next());
+        assertEquals(Integer.valueOf(7), map.keySet().iterator().next());
+    }
+
+    public void testWeirdNumberHandling() throws Exception
+    {
+        ObjectMapper mapper = new ObjectMapper()
+            .addHandler(new WeirdNumberHandler(SingleValuedEnum.A))
+            ;
+        SingleValuedEnum result = mapper.readValue("3", SingleValuedEnum.class);
+        assertEquals(SingleValuedEnum.A, result);
+    }
+
+    public void testWeirdStringHandling() throws Exception
+    {
+        ObjectMapper mapper = new ObjectMapper()
+            .addHandler(new WeirdStringHandler(SingleValuedEnum.A))
+            ;
+        SingleValuedEnum result = mapper.readValue("\"B\"", SingleValuedEnum.class);
+        assertEquals(SingleValuedEnum.A, result);
+
+        // also, write [databind#1629] try this
+        mapper = new ObjectMapper()
+                .addHandler(new WeirdStringHandler(null));
+        UUID result2 = mapper.readValue(quote("not a uuid!"), UUID.class);
+        assertNull(result2);
+    }
+
+    public void testInvalidTypeId() throws Exception
+    {
+        ObjectMapper mapper = new ObjectMapper()
+            .addHandler(new TypeIdHandler(BaseImpl.class));
+        BaseWrapper w = mapper.readValue("{\"value\":{\"type\":\"foo\",\"a\":4}}",
+                BaseWrapper.class);
+        assertNotNull(w);
+        assertEquals(BaseImpl.class, w.value.getClass());
+    }
+
+
+    public void testInvalidClassAsId() throws Exception
+    {
+        ObjectMapper mapper = new ObjectMapper()
+            .addHandler(new TypeIdHandler(Base2Impl.class));
+        Base2Wrapper w = mapper.readValue("{\"value\":{\"clazz\":\"com.fizz\",\"a\":4}}",
+                Base2Wrapper.class);
+        assertNotNull(w);
+        assertEquals(Base2Impl.class, w.value.getClass());
+    }
+
+    // verify that by default we get special exception type
+    public void testInvalidTypeIdFail() throws Exception
+    {
+        try {
+            MAPPER.readValue("{\"value\":{\"type\":\"foo\",\"a\":4}}",
+                BaseWrapper.class);
+            fail("Should not pass");
+        } catch (InvalidTypeIdException e) {
+            verifyException(e, "Could not resolve type id 'foo'");
+            assertEquals(Base.class, e.getBaseType().getRawClass());
+            assertEquals("foo", e.getTypeId());
+        }
+    }
+
+    public void testInstantiationExceptionHandling() throws Exception
+    {
+        ObjectMapper mapper = new ObjectMapper()
+            .addHandler(new InstantiationProblemHandler(BustedCtor.INST));
+        BustedCtor w = mapper.readValue("{ }",
+                BustedCtor.class);
+        assertNotNull(w);
+    }
+
+    public void testMissingInstantiatorHandling() throws Exception
+    {
+        ObjectMapper mapper = new ObjectMapper()
+            .addHandler(new MissingInstantiationHandler(new NoDefaultCtor(13)))
+            ;
+        NoDefaultCtor w = mapper.readValue("{ \"x\" : true }", NoDefaultCtor.class);
+        assertNotNull(w);
+        assertEquals(13, w.value);
+    }
+
+    public void testUnexpectedTokenHandling() throws Exception
+    {
+        ObjectMapper mapper = new ObjectMapper()
+            .addHandler(new WeirdTokenHandler(Integer.valueOf(13)))
+        ;
+        Integer v = mapper.readValue("true", Integer.class);
+        assertEquals(Integer.valueOf(13), v);
+    }
+}
diff --git a/src/test/java/com/fasterxml/jackson/databind/filter/TestAnyGetterFiltering.java b/src/test/java/com/fasterxml/jackson/databind/filter/TestAnyGetterFiltering.java
index ba463d7..e579feb 100644
--- a/src/test/java/com/fasterxml/jackson/databind/filter/TestAnyGetterFiltering.java
+++ b/src/test/java/com/fasterxml/jackson/databind/filter/TestAnyGetterFiltering.java
@@ -1,14 +1,14 @@
 package com.fasterxml.jackson.databind.filter;
 
-import java.util.HashMap;
-import java.util.Map;
-
+import java.util.*;
 
 import com.fasterxml.jackson.annotation.*;
-
+import com.fasterxml.jackson.core.JsonGenerator;
 import com.fasterxml.jackson.databind.BaseMapTest;
 import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.SerializerProvider;
 import com.fasterxml.jackson.databind.ser.FilterProvider;
+import com.fasterxml.jackson.databind.ser.PropertyWriter;
 import com.fasterxml.jackson.databind.ser.impl.SimpleBeanPropertyFilter;
 import com.fasterxml.jackson.databind.ser.impl.SimpleFilterProvider;
 
@@ -34,18 +34,42 @@
         }
     }
 
+    public static class AnyBeanWithIgnores
+    {
+        private Map<String, String> properties = new LinkedHashMap<String, String>();
+        {
+            properties.put("a", "1");
+            properties.put("bogus", "2");
+            properties.put("b", "3");
+        }
+
+        @JsonAnyGetter
+        @JsonIgnoreProperties({ "bogus" })
+        public Map<String, String> anyProperties()
+        {
+            return properties;
+        }
+    }
+
     /*
     /**********************************************************
-    /* Unit tests
+    /* Test methods
     /**********************************************************
      */
-    
-    // should also work for @JsonAnyGetter, as per [JACKSON-516]
+
+    private final ObjectMapper MAPPER = new ObjectMapper();
+
     public void testAnyGetterFiltering() throws Exception
     {
-        ObjectMapper mapper = new ObjectMapper();
         FilterProvider prov = new SimpleFilterProvider().addFilter("anyFilter",
                 SimpleBeanPropertyFilter.filterOutAllExcept("b"));
-        assertEquals("{\"b\":\"2\"}", mapper.writer(prov).writeValueAsString(new AnyBean()));
+        assertEquals("{\"b\":\"2\"}", MAPPER.writer(prov).writeValueAsString(new AnyBean()));
+    }
+
+    // for [databind#1142]
+    public void testAnyGetterIgnore() throws Exception
+    {
+        assertEquals(aposToQuotes("{'a':'1','b':'3'}"),
+                MAPPER.writeValueAsString(new AnyBeanWithIgnores()));
     }
 }
diff --git a/src/test/java/com/fasterxml/jackson/databind/filter/TestJsonFilter.java b/src/test/java/com/fasterxml/jackson/databind/filter/TestJsonFilter.java
index 5e81a8c..b607af7 100644
--- a/src/test/java/com/fasterxml/jackson/databind/filter/TestJsonFilter.java
+++ b/src/test/java/com/fasterxml/jackson/databind/filter/TestJsonFilter.java
@@ -2,8 +2,12 @@
 
 import com.fasterxml.jackson.annotation.*;
 
+
+import com.fasterxml.jackson.core.JsonGenerator;
+import com.fasterxml.jackson.core.JsonStreamContext;
 import com.fasterxml.jackson.databind.*;
 import com.fasterxml.jackson.databind.ser.FilterProvider;
+import com.fasterxml.jackson.databind.ser.PropertyWriter;
 import com.fasterxml.jackson.databind.ser.impl.*;
 
 /**
@@ -19,6 +23,46 @@
         public String b = "b";
     }
 
+    @JsonFilter("checkSiblingContextFilter")
+    static class CheckSiblingContextBean {
+        public A a = new A();
+        public B b = new B();
+        @JsonFilter("checkSiblingContextFilter")
+        static class A {
+        }
+        @JsonFilter("checkSiblingContextFilter")
+        static class B {
+            public C c = new C();
+            @JsonFilter("checkSiblingContextFilter")
+            static class C {
+            }
+        }
+    }
+
+    static class CheckSiblingContextFilter extends SimpleBeanPropertyFilter {
+        @Override
+        public void serializeAsField(Object bean, JsonGenerator jgen, SerializerProvider prov, PropertyWriter writer) throws Exception {
+            JsonStreamContext sc = jgen.getOutputContext();
+
+            if (writer.getName() != null && writer.getName().equals("c")) {
+                //This assertion is failing as sc.getParent() incorrectly returns 'a'. If you comment out the member 'a'
+                // in the CheckSiblingContextBean, you'll see that the sc.getParent() correctly returns 'b'
+                assertEquals("b", sc.getParent().getCurrentName());
+            }
+            writer.serializeAsField(bean, jgen, prov);
+        }
+    }
+
+    public void testCheckSiblingContextFilter() {
+        FilterProvider prov = new SimpleFilterProvider().addFilter("checkSiblingContextFilter",
+                new CheckSiblingContextFilter());
+
+        ObjectMapper mapper = new ObjectMapper();
+        mapper.setFilterProvider(prov);
+        mapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
+        mapper.valueToTree(new CheckSiblingContextBean());
+    }
+
     // [Issue#89]
     static class Pod
     {
diff --git a/src/test/java/com/fasterxml/jackson/databind/filter/TestUnknownPropertyDeserialization.java b/src/test/java/com/fasterxml/jackson/databind/filter/TestUnknownPropertyDeserialization.java
index 1689c87..b362822 100644
--- a/src/test/java/com/fasterxml/jackson/databind/filter/TestUnknownPropertyDeserialization.java
+++ b/src/test/java/com/fasterxml/jackson/databind/filter/TestUnknownPropertyDeserialization.java
@@ -42,7 +42,7 @@
      * just marks unknown property/ies when encountered, along with
      * Json value of the property.
      */
-    final static class MyHandler
+    static class MyHandler
         extends DeserializationProblemHandler
     {
         @Override
@@ -256,7 +256,8 @@
 
     public void testPropertyIgnoralWithClass() throws Exception
     {
-        XYZWrapper2 result = MAPPER.readValue("{\"value\":{\"y\":2,\"x\":1,\"z\":3}}", XYZWrapper2.class);
+        XYZWrapper2 result = MAPPER.readValue("{\"value\":{\"y\":2,\"x\":1,\"z\":3}}",
+                XYZWrapper2.class);
         assertEquals(1, result.value.x);
     }
 
diff --git a/src/test/java/com/fasterxml/jackson/databind/format/DateFormatTest.java b/src/test/java/com/fasterxml/jackson/databind/format/DateFormatTest.java
new file mode 100644
index 0000000..19b97f7
--- /dev/null
+++ b/src/test/java/com/fasterxml/jackson/databind/format/DateFormatTest.java
@@ -0,0 +1,37 @@
+package com.fasterxml.jackson.databind.format;
+
+import java.util.Calendar;
+import java.util.Date;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.fasterxml.jackson.databind.*;
+
+public class DateFormatTest extends BaseMapTest
+{
+    protected static class DateWrapper {
+        public Date value;
+
+        public DateWrapper() { }
+        public DateWrapper(long l) { value = new Date(l); }
+        public DateWrapper(Date v) { value = v; }
+    }
+
+    public void testTypeDefaults() throws Exception
+    {
+        ObjectMapper mapper = new ObjectMapper();
+        mapper.configOverride(Date.class)
+            .setFormat(JsonFormat.Value.forPattern("yyyy.dd.MM"));
+        // First serialize, should result in this (in UTC):
+        String json = mapper.writeValueAsString(new DateWrapper(0L));
+        assertEquals(aposToQuotes("{'value':'1970.01.01'}"), json);
+
+        // and then read back
+        DateWrapper w = mapper.readValue(aposToQuotes("{'value':'1981.13.3'}"), DateWrapper.class);
+        assertNotNull(w);
+        // arbitrary TimeZone, but good enough to ensure year is right
+        Calendar c = Calendar.getInstance();
+        c.setTime(w.value);
+        assertEquals(1981, c.get(Calendar.YEAR));
+        assertEquals(Calendar.MARCH, c.get(Calendar.MONTH));
+    }
+}
diff --git a/src/test/java/com/fasterxml/jackson/databind/interop/IllegalTypesCheckTest.java b/src/test/java/com/fasterxml/jackson/databind/interop/IllegalTypesCheckTest.java
index 36bc71c..f7d1517 100644
--- a/src/test/java/com/fasterxml/jackson/databind/interop/IllegalTypesCheckTest.java
+++ b/src/test/java/com/fasterxml/jackson/databind/interop/IllegalTypesCheckTest.java
@@ -1,5 +1,7 @@
 package com.fasterxml.jackson.databind.interop;
 
+import java.util.*;
+
 import org.springframework.jacksontest.BogusApplicationContext;
 import org.springframework.jacksontest.BogusPointcutAdvisor;
 import org.springframework.jacksontest.GrantedAuthority;
@@ -31,7 +33,7 @@
     static class Authentication1872 {
          public List<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>();
     }
-    
+
     /*
     /**********************************************************
     /* Unit tests
diff --git a/src/test/java/com/fasterxml/jackson/databind/introspect/TestAutoDetect.java b/src/test/java/com/fasterxml/jackson/databind/introspect/TestAutoDetect.java
index b4a59a2..c5817bc 100644
--- a/src/test/java/com/fasterxml/jackson/databind/introspect/TestAutoDetect.java
+++ b/src/test/java/com/fasterxml/jackson/databind/introspect/TestAutoDetect.java
@@ -32,7 +32,6 @@
 
         // then by increasing visibility requirement:
         m = new ObjectMapper();
-        // note: clumsy code, but needed for Eclipse/JDK1.5 compilation (not for 1.6)
         VisibilityChecker<?> vc = m.getVisibilityChecker();
         vc = vc.withCreatorVisibility(JsonAutoDetect.Visibility.PUBLIC_ONLY);
         m.setVisibility(vc);
@@ -40,7 +39,7 @@
             m.readValue("\"abc\"", PrivateBean.class);
             fail("Expected exception for missing constructor");
         } catch (JsonProcessingException e) {
-            verifyException(e, "no single-String constructor/factory");
+            verifyException(e, "no String-argument constructor/factory");
         }
     }
 
diff --git a/src/test/java/com/fasterxml/jackson/databind/introspect/TestJacksonAnnotationIntrospector.java b/src/test/java/com/fasterxml/jackson/databind/introspect/TestJacksonAnnotationIntrospector.java
index bf56791..d506473 100644
--- a/src/test/java/com/fasterxml/jackson/databind/introspect/TestJacksonAnnotationIntrospector.java
+++ b/src/test/java/com/fasterxml/jackson/databind/introspect/TestJacksonAnnotationIntrospector.java
@@ -137,11 +137,6 @@
         private static final long serialVersionUID = 1L;
 
         @Override
-        public String findEnumValue(Enum<?> value) {
-            return value.name().toLowerCase();
-        }
-
-        @Override
         public  String[] findEnumValues(Class<?> enumType, Enum<?>[] enumValues, String[] names) {
             // kinda sorta wrong, but for testing's sake...
             for (int i = 0, len = enumValues.length; i < len; ++i) {
diff --git a/src/test/java/com/fasterxml/jackson/databind/introspect/TestNamingStrategyStd.java b/src/test/java/com/fasterxml/jackson/databind/introspect/TestNamingStrategyStd.java
index 344a067..14fd27a 100644
--- a/src/test/java/com/fasterxml/jackson/databind/introspect/TestNamingStrategyStd.java
+++ b/src/test/java/com/fasterxml/jackson/databind/introspect/TestNamingStrategyStd.java
@@ -115,7 +115,7 @@
     /**********************************************************

      */

 

-    public static List<Object[]> SNAKE_CASE_NAME_TRANSLATIONS = Arrays.asList(new Object[][] {

+    final static List<Object[]> SNAKE_CASE_NAME_TRANSLATIONS = Arrays.asList(new Object[][] {

                 {null, null},

                 {"", ""},

                 {"a", "a"},

@@ -268,31 +268,21 @@
      */

     public void testPascalCaseStandAlone()

     {

-        String translatedJavaName = PropertyNamingStrategy.UPPER_CAMEL_CASE.nameForField

-    	        (null, null, "userName");

-        assertEquals("UserName", translatedJavaName);

+        assertEquals("UserName", PropertyNamingStrategy.UPPER_CAMEL_CASE.nameForField(null, null, "userName"));

+        assertEquals("User", PropertyNamingStrategy.UPPER_CAMEL_CASE.nameForField(null, null, "User"));

+        assertEquals("User", PropertyNamingStrategy.UPPER_CAMEL_CASE.nameForField(null, null, "user"));

+        assertEquals("X", PropertyNamingStrategy.UPPER_CAMEL_CASE.nameForField(null, null, "x"));

 

-        translatedJavaName = PropertyNamingStrategy.UPPER_CAMEL_CASE.nameForField

-                (null, null, "User");

-        assertEquals("User", translatedJavaName);

-

-        translatedJavaName = PropertyNamingStrategy.UPPER_CAMEL_CASE.nameForField

-                (null, null, "user");

-        assertEquals("User", translatedJavaName);

-        translatedJavaName = PropertyNamingStrategy.UPPER_CAMEL_CASE.nameForField

-                (null, null, "x");

-        assertEquals("X", translatedJavaName);

+        assertEquals("BADPublicName", PropertyNamingStrategy.UPPER_CAMEL_CASE.nameForField(null, null, "bADPublicName"));

+        assertEquals("BADPublicName", PropertyNamingStrategy.UPPER_CAMEL_CASE.nameForGetterMethod(null, null, "bADPublicName"));

     }

 

-    /**

-     * For [databind#428]

-     */

-    public void testIssue428PascalWithOverrides() throws Exception {

-

+    // [databind#428]

+    public void testIssue428PascalWithOverrides() throws Exception

+    {

         String json = new ObjectMapper()

-                            .setPropertyNamingStrategy(PropertyNamingStrategy.UPPER_CAMEL_CASE)

-                            .writeValueAsString(new Bean428());

-        

+                .setPropertyNamingStrategy(PropertyNamingStrategy.UPPER_CAMEL_CASE)

+                .writeValueAsString(new Bean428());

         if (!json.contains(quote("fooBar"))) {

             fail("Should use name 'fooBar', does not: "+json);

         }

@@ -303,10 +293,8 @@
     /* Test methods for LOWER_CASE

     /**********************************************************

      */

-    

-    /**

-     * For [databind#461]

-     */

+

+    // For [databind#461]

     public void testSimpleLowerCase() throws Exception

     {

         final BoringBean input = new BoringBean();

diff --git a/src/test/java/com/fasterxml/jackson/databind/introspect/TransientTest.java b/src/test/java/com/fasterxml/jackson/databind/introspect/TransientTest.java
index 484c753..882c399 100644
--- a/src/test/java/com/fasterxml/jackson/databind/introspect/TransientTest.java
+++ b/src/test/java/com/fasterxml/jackson/databind/introspect/TransientTest.java
@@ -2,6 +2,7 @@
 
 import java.beans.Transient;
 
+import com.fasterxml.jackson.annotation.JsonProperty;
 import com.fasterxml.jackson.annotation.JsonPropertyOrder;
 import com.fasterxml.jackson.databind.*;
 
@@ -22,6 +23,11 @@
         public int getX() { return 42; }
     }
 
+    static class SimplePrunableTransient {
+        public int a = 1;
+        public transient int b = 2;
+    }
+    
     // for [databind#857]
     static class BeanTransient {
         @Transient
@@ -30,6 +36,15 @@
         public int getY() { return 4; }
     }
 
+    // for [databind#1184]
+    static class OverridableTransient {
+        @JsonProperty
+//        @JsonProperty("value") // should override transient here, to force inclusion
+        public transient int tValue;
+
+        public OverridableTransient(int v) { tValue = v; }
+    }
+
     /*
     /**********************************************************
     /* Unit tests
@@ -44,6 +59,8 @@
         // default handling: remove transient field but do not propagate
         assertEquals(aposToQuotes("{'x':42,'value':3}"),
                 MAPPER.writeValueAsString(new ClassyTransient()));
+        assertEquals(aposToQuotes("{'a':1}"),
+                MAPPER.writeValueAsString(new SimplePrunableTransient()));
 
         // but may change that
         ObjectMapper m = new ObjectMapper()
@@ -58,4 +75,11 @@
         assertEquals(aposToQuotes("{'y':4}"),
                 MAPPER.writeValueAsString(new BeanTransient()));
     }
+
+    // for [databind#1184]
+    public void testOverridingTransient() throws Exception
+    {
+        assertEquals(aposToQuotes("{'tValue':38}"),
+                MAPPER.writeValueAsString(new OverridableTransient(38)));
+    }
 }
diff --git a/src/test/java/com/fasterxml/jackson/databind/jsonschema/NewSchemaTest.java b/src/test/java/com/fasterxml/jackson/databind/jsonschema/NewSchemaTest.java
index 57cefec..ea31611 100644
--- a/src/test/java/com/fasterxml/jackson/databind/jsonschema/NewSchemaTest.java
+++ b/src/test/java/com/fasterxml/jackson/databind/jsonschema/NewSchemaTest.java
@@ -100,7 +100,8 @@
     public void testEnumWithJsonValue() throws Exception
     {
         final Set<String> values = new TreeSet<String>();
-        MAPPER.acceptJsonFormatVisitor(TestEnumWithJsonValue.class, new JsonFormatVisitorWrapper.Base() {
+        MAPPER.acceptJsonFormatVisitor(TestEnumWithJsonValue.class,
+                new JsonFormatVisitorWrapper.Base() {
             @Override
             public JsonStringFormatVisitor expectStringFormat(JavaType type) {
                 return new JsonStringFormatVisitor() {
diff --git a/src/test/java/com/fasterxml/jackson/databind/jsonschema/TestGenerateJsonSchema.java b/src/test/java/com/fasterxml/jackson/databind/jsonschema/TestGenerateJsonSchema.java
index ea086d6..7edfd4d 100644
--- a/src/test/java/com/fasterxml/jackson/databind/jsonschema/TestGenerateJsonSchema.java
+++ b/src/test/java/com/fasterxml/jackson/databind/jsonschema/TestGenerateJsonSchema.java
@@ -180,7 +180,7 @@
     	public void setObvious(String s) {obvious = s; }
     }
     
-    public static FilterProvider secretFilterProvider = new SimpleFilterProvider()
+    final static FilterProvider secretFilterProvider = new SimpleFilterProvider()
         .addFilter("filteredBean", SimpleBeanPropertyFilter.filterOutAllExcept(new String[]{"obvious"}));
 
     public void testGeneratingJsonSchemaWithFilters() throws Exception {
diff --git a/src/test/java/com/fasterxml/jackson/databind/jsontype/DefaultTypingWithPrimitivesTest.java b/src/test/java/com/fasterxml/jackson/databind/jsontype/DefaultTypingWithPrimitivesTest.java
new file mode 100644
index 0000000..707b33b
--- /dev/null
+++ b/src/test/java/com/fasterxml/jackson/databind/jsontype/DefaultTypingWithPrimitivesTest.java
@@ -0,0 +1,42 @@
+package com.fasterxml.jackson.databind.jsontype;
+
+import com.fasterxml.jackson.annotation.JsonTypeInfo;
+
+import com.fasterxml.jackson.databind.*;
+import com.fasterxml.jackson.databind.jsontype.impl.StdTypeResolverBuilder;
+
+import java.util.*;
+
+// [databind#1395]: prevent attempts at including type info for primitives
+public class DefaultTypingWithPrimitivesTest extends BaseMapTest
+{
+    static class Data {
+        public long key;
+    }
+
+    public void testDefaultTypingWithLong() throws Exception
+    {
+        Data data = new Data();
+        data.key = 1L;
+        Map<String, Object> mapData = new HashMap<String, Object>();
+        mapData.put("longInMap", 2L);
+        mapData.put("longAsField", data);
+
+        // Configure Jackson to preserve types
+        ObjectMapper mapper = new ObjectMapper();
+        StdTypeResolverBuilder resolver = new StdTypeResolverBuilder();
+        resolver.init(JsonTypeInfo.Id.CLASS, null);
+        resolver.inclusion(JsonTypeInfo.As.PROPERTY);
+        resolver.typeProperty("__t");
+        mapper.setDefaultTyping(resolver);
+        mapper.enable(SerializationFeature.INDENT_OUTPUT);
+
+        // Serialize
+        String json = mapper.writeValueAsString(mapData);
+
+        // Deserialize
+        Map<?,?> result = mapper.readValue(json, Map.class);
+        assertNotNull(result);
+        assertEquals(2, result.size());
+    }
+}
diff --git a/src/test/java/com/fasterxml/jackson/databind/jsontype/GenericTypeId1735Test.java b/src/test/java/com/fasterxml/jackson/databind/jsontype/GenericTypeId1735Test.java
new file mode 100644
index 0000000..673d4c8
--- /dev/null
+++ b/src/test/java/com/fasterxml/jackson/databind/jsontype/GenericTypeId1735Test.java
@@ -0,0 +1,64 @@
+package com.fasterxml.jackson.databind.jsontype;
+
+import com.fasterxml.jackson.annotation.JsonTypeInfo;
+
+import com.fasterxml.jackson.databind.*;
+
+// for [databind#1735]:
+public class GenericTypeId1735Test extends BaseMapTest
+{
+    static class Wrapper1735 {
+        @JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, property = "type")
+        public Payload1735 w;
+    }
+
+    static class Payload1735 {
+        public void setValue(String str) { }
+    }
+
+    static class Nefarious1735 {
+        public Nefarious1735() {
+            throw new Error("Never call this constructor");
+        }
+
+        public void setValue(String str) {
+            throw new Error("Never call this setter");
+        }
+    }
+
+    /*
+    /**********************************************************
+    /* Unit tests
+    /**********************************************************
+     */
+
+    private final ObjectMapper MAPPER = objectMapper();
+
+    private final static String NEF_CLASS = Nefarious1735.class.getName();
+    
+    // Existing checks should kick in fine
+    public void testSimpleTypeCheck1735() throws Exception
+    {
+        try {
+            MAPPER.readValue(aposToQuotes(
+"{'w':{'type':'"+NEF_CLASS+"'}}"),
+                    Wrapper1735.class);
+            fail("Should not pass");
+        } catch (JsonMappingException e) {
+            verifyException(e, "not subtype of");
+        }
+    }
+
+    // but this was not being verified early enough
+    public void testNestedTypeCheck1735() throws Exception
+    {
+        try {
+            MAPPER.readValue(aposToQuotes(
+"{'w':{'type':'java.util.HashMap<java.lang.String,java.lang.String>'}}"),
+                    Wrapper1735.class);
+            fail("Should not pass");
+        } catch (JsonMappingException e) {
+            verifyException(e, "not subtype of");
+        }
+    }
+}
diff --git a/src/test/java/com/fasterxml/jackson/databind/jsontype/TestCustomTypeIdResolver.java b/src/test/java/com/fasterxml/jackson/databind/jsontype/TestCustomTypeIdResolver.java
index 8fa9bd7..25ebfd5 100644
--- a/src/test/java/com/fasterxml/jackson/databind/jsontype/TestCustomTypeIdResolver.java
+++ b/src/test/java/com/fasterxml/jackson/databind/jsontype/TestCustomTypeIdResolver.java
@@ -5,7 +5,7 @@
 import com.fasterxml.jackson.annotation.*;
 import com.fasterxml.jackson.annotation.JsonTypeInfo.As;
 import com.fasterxml.jackson.annotation.JsonTypeInfo.Id;
-
+import com.fasterxml.jackson.core.type.TypeReference;
 import com.fasterxml.jackson.databind.*;
 import com.fasterxml.jackson.databind.annotation.JsonTypeIdResolver;
 import com.fasterxml.jackson.databind.jsontype.impl.TypeIdResolverBase;
@@ -102,7 +102,71 @@
             return "xxx";
         }
     }
-    
+
+    // for [databind#1270]
+    static class Top1270 {
+        @JsonTypeInfo(use = JsonTypeInfo.Id.NAME,
+                include = JsonTypeInfo.As.PROPERTY,
+                property = "type")
+        @JsonTypeIdResolver(Resolver1270.class)
+        public Base1270<?> b;
+    }
+
+    static class Base1270<O extends Poly1Base> {
+        public O options;
+        public String val;
+    }
+
+    static abstract class Poly1Base { }
+
+    static class Poly1 extends Poly1Base {
+        public String val;
+    }
+
+    static class Resolver1270 implements TypeIdResolver {
+        public Resolver1270() { }
+
+        @Override
+        public void init(JavaType baseType) { }
+     
+        @Override
+        public String idFromValue(Object value) {
+            if (value.getClass() == Base1270.class) {
+                return "poly1";
+            }
+            return null;
+        }
+
+        @Override
+        public String idFromValueAndType(Object value, Class<?> suggestedType) {
+            return idFromValue(value);
+        }
+
+        @Override
+        public String idFromBaseType() {
+            return null;
+        }
+
+        @Override
+        public JavaType typeFromId(DatabindContext context, String id) {
+            if ("poly1".equals(id)) {
+                return context.getTypeFactory()
+                        .constructType(new TypeReference<Base1270<Poly1>>() { });
+            }
+            return null;
+        }
+
+        @Override
+        public String getDescForKnownTypeIds() {
+            return null;
+        }
+
+        @Override
+        public JsonTypeInfo.Id getMechanism() {
+            return JsonTypeInfo.Id.CUSTOM;
+        }
+    }
+
     /*
     /**********************************************************
     /* Unit tests
@@ -110,8 +174,7 @@
      */
 
     private final ObjectMapper MAPPER = objectMapper();
-    
-    // for [JACKSON-359]
+
     public void testCustomTypeIdResolver() throws Exception
     {
         List<JavaType> types = new ArrayList<JavaType>();
@@ -143,4 +206,25 @@
         
         assertEquals(12, ((ExtBeanImpl) out.value).y);
     }
+
+    // for [databind#1270]
+    public void testPolymorphicTypeViaCustom() throws Exception {
+        Base1270<Poly1> req = new Base1270<Poly1>();
+        Poly1 o = new Poly1();
+        o.val = "optionValue";
+        req.options = o;
+        req.val = "some value";
+        Top1270 top = new Top1270();
+        top.b = req;
+        String json = MAPPER.writeValueAsString(top);
+        JsonNode tree = MAPPER.readTree(json);
+        assertNotNull(tree.get("b"));
+        assertNotNull(tree.get("b").get("options"));
+        assertNotNull(tree.get("b").get("options").get("val"));
+
+        // Can we reverse the process? I have some doubts
+        Top1270 itemRead = MAPPER.readValue(json, Top1270.class);
+        assertNotNull(itemRead);
+        assertNotNull(itemRead.b);
+    }
 }
diff --git a/src/test/java/com/fasterxml/jackson/databind/jsontype/TestDefaultForArrays.java b/src/test/java/com/fasterxml/jackson/databind/jsontype/TestDefaultForArrays.java
index f7ce743..154630d 100644
--- a/src/test/java/com/fasterxml/jackson/databind/jsontype/TestDefaultForArrays.java
+++ b/src/test/java/com/fasterxml/jackson/databind/jsontype/TestDefaultForArrays.java
@@ -1,5 +1,10 @@
 package com.fasterxml.jackson.databind.jsontype;
 
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
 import com.fasterxml.jackson.annotation.JsonTypeInfo;
 import com.fasterxml.jackson.databind.*;
 import com.fasterxml.jackson.databind.ObjectMapper.DefaultTyping;
@@ -66,6 +71,24 @@
         Object ob = result[0];
         assertTrue(ob instanceof JsonNode);
     }
+    
+    public void testNodeInEmptyArray() throws Exception {
+        Map<String, List<String>> outerMap = new HashMap<String, List<String>>();
+        outerMap.put("inner", new ArrayList<String>());
+        ObjectMapper m = new ObjectMapper().disable(SerializationFeature.WRITE_EMPTY_JSON_ARRAYS);
+        JsonNode tree = m.convertValue(outerMap, JsonNode.class);
+        
+        String json = m.writeValueAsString(tree);
+        assertEquals("{}", json);
+        
+        JsonNode node = new ObjectMapper().readTree("{\"a\":[]}");
+        
+        m.enableDefaultTyping(DefaultTyping.JAVA_LANG_OBJECT);
+        Object[] obs = new Object[] { node };
+        json = m.writeValueAsString(obs);
+        Object[] result = m.readValue(json, Object[].class);
+        assertEquals("{}", result[0].toString());
+    }
 
     // test for [JACKSON-845]
     public void testArraysOfArrays() throws Exception
diff --git a/src/test/java/com/fasterxml/jackson/databind/jsontype/TestDefaultWithCreators.java b/src/test/java/com/fasterxml/jackson/databind/jsontype/TestDefaultWithCreators.java
index 31f84b5..785a3b5 100644
--- a/src/test/java/com/fasterxml/jackson/databind/jsontype/TestDefaultWithCreators.java
+++ b/src/test/java/com/fasterxml/jackson/databind/jsontype/TestDefaultWithCreators.java
@@ -1,5 +1,7 @@
 package com.fasterxml.jackson.databind.jsontype;
 
+import org.junit.Assert;
+
 import com.fasterxml.jackson.annotation.*;
 
 import com.fasterxml.jackson.databind.BaseMapTest;
@@ -8,12 +10,6 @@
 public class TestDefaultWithCreators
     extends BaseMapTest
 {
-    /*
-    /**********************************************************
-    /* Helper types
-    /**********************************************************
-     */
-
     static abstract class Job
     {
         public long id;
@@ -36,7 +32,31 @@
         public String getUrl() { return url; }
         public int getCount() { return count; }
     }
+
+    // [databind#1385]
+    static class Bean1385Wrapper
+    {
+        public Object value;
+
+        protected Bean1385Wrapper() { }
+        public Bean1385Wrapper(Object v) { value = v; }
+    }
+
+    static class Bean1385
+    {
+        private byte[] raw;
     
+        @JsonCreator(mode=JsonCreator.Mode.DELEGATING)
+        public Bean1385(byte[] raw) {
+            this.raw = raw.clone();
+        }
+
+        @JsonValue
+        public byte[] getBytes() {
+            return raw;
+        }
+    }
+
     /*
     /**********************************************************
     /* Unit tests
@@ -58,4 +78,21 @@
         assertEquals("http://foo", o2.getUrl());
         assertEquals(3, o2.getCount());
     }
-}
+
+    // [databind#1385]
+    public void testWithCreatorAndJsonValue() throws Exception
+    {
+        final byte[] BYTES = new byte[] { 1, 2, 3, 4, 5 };
+        ObjectMapper mapper = new ObjectMapper();
+        mapper.enableDefaultTyping();
+        String json = mapper.writeValueAsString(new Bean1385Wrapper(
+                new Bean1385(BYTES)
+        ));
+        Bean1385Wrapper result = mapper.readValue(json, Bean1385Wrapper.class);
+        assertNotNull(result);
+        assertNotNull(result.value);
+        assertEquals(Bean1385.class, result.value.getClass());
+        Bean1385 b = (Bean1385) result.value;
+        Assert.assertArrayEquals(BYTES, b.raw);
+    }
+ }
diff --git a/src/test/java/com/fasterxml/jackson/databind/jsontype/TestGenericListSerialization.java b/src/test/java/com/fasterxml/jackson/databind/jsontype/TestGenericListSerialization.java
index dd096b4..7982ed2 100644
--- a/src/test/java/com/fasterxml/jackson/databind/jsontype/TestGenericListSerialization.java
+++ b/src/test/java/com/fasterxml/jackson/databind/jsontype/TestGenericListSerialization.java
@@ -63,7 +63,7 @@
         
         JSONResponse<List<Parent>> out = mapper.readValue(json, 0, json.length, rootType);
 
-        List<Parent> deserializedContent = (List<Parent>) out.getResult();
+        List<Parent> deserializedContent = out.getResult();
 
         assertEquals(2, deserializedContent.size());
         assertTrue(deserializedContent.get(0) instanceof Parent);
diff --git a/src/test/java/com/fasterxml/jackson/databind/jsontype/TestOverlappingTypeIdNames312.java b/src/test/java/com/fasterxml/jackson/databind/jsontype/TestOverlappingTypeIdNames.java
similarity index 96%
rename from src/test/java/com/fasterxml/jackson/databind/jsontype/TestOverlappingTypeIdNames312.java
rename to src/test/java/com/fasterxml/jackson/databind/jsontype/TestOverlappingTypeIdNames.java
index d922852..3ef352c 100644
--- a/src/test/java/com/fasterxml/jackson/databind/jsontype/TestOverlappingTypeIdNames312.java
+++ b/src/test/java/com/fasterxml/jackson/databind/jsontype/TestOverlappingTypeIdNames.java
@@ -3,7 +3,7 @@
 import com.fasterxml.jackson.annotation.*;
 import com.fasterxml.jackson.databind.*;
 
-public class TestOverlappingTypeIdNames312 extends BaseMapTest
+public class TestOverlappingTypeIdNames extends BaseMapTest
 {
     @JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "type")
     @JsonSubTypes({
diff --git a/src/test/java/com/fasterxml/jackson/databind/jsontype/TestPolymorphicWithDefaultImpl.java b/src/test/java/com/fasterxml/jackson/databind/jsontype/TestPolymorphicWithDefaultImpl.java
index 20d0ae7..439b7d6 100644
--- a/src/test/java/com/fasterxml/jackson/databind/jsontype/TestPolymorphicWithDefaultImpl.java
+++ b/src/test/java/com/fasterxml/jackson/databind/jsontype/TestPolymorphicWithDefaultImpl.java
@@ -3,10 +3,8 @@
 import java.util.*;
 
 import com.fasterxml.jackson.annotation.*;
-import com.fasterxml.jackson.databind.BaseMapTest;
-import com.fasterxml.jackson.databind.DeserializationFeature;
-import com.fasterxml.jackson.databind.ObjectMapper;
-import com.fasterxml.jackson.databind.ObjectReader;
+
+import com.fasterxml.jackson.databind.*;
 import com.fasterxml.jackson.databind.annotation.NoClass;
 
 /**
@@ -123,6 +121,24 @@
         public Event() {}
     }
 
+    @JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY,
+            property = "clazz")
+    abstract static class BaseClass { }    
+
+    static class BaseWrapper {
+        public BaseClass value;
+    }
+
+    // [databind#1533]
+    @JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY,
+            property = "type")
+    static class AsProperty {
+    }
+
+    static class AsPropertyWrapper {
+        public AsProperty value;
+    }
+
     /*
     /**********************************************************
     /* Unit tests, deserialization
@@ -230,6 +246,39 @@
         assertEquals("123", r3.application);
     }
 
+    public void testUnknownClassAsSubtype() throws Exception
+    {
+        ObjectMapper mapper = new ObjectMapper();
+        mapper.configure(DeserializationFeature.FAIL_ON_INVALID_SUBTYPE, false);
+        BaseWrapper w = mapper.readValue(aposToQuotes
+                ("{'value':{'clazz':'com.foobar.Nothing'}}'"),
+                BaseWrapper.class);
+        assertNotNull(w);
+        assertNull(w.value);
+    }
+
+    public void testWithoutEmptyStringAsNullObject1533() throws Exception
+    {
+        ObjectReader r = MAPPER.readerFor(AsPropertyWrapper.class)
+                .without(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT);
+        try {
+            r.readValue("{ \"value\": \"\" }");
+            fail("Expected " + JsonMappingException.class);
+        } catch (JsonMappingException e) {
+            verifyException(e, "missing property 'type'");
+            verifyException(e, "contain type id");
+        }
+    }
+
+    // [databind#1533]
+    public void testWithEmptyStringAsNullObject1533() throws Exception
+    {
+        ObjectReader r = MAPPER.readerFor(AsPropertyWrapper.class)
+                .with(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT);
+        AsPropertyWrapper wrapper = r.readValue("{ \"value\": \"\" }");
+        assertNull(wrapper.value);
+    }
+
     /*
     /**********************************************************
     /* Unit tests, serialization
diff --git a/src/test/java/com/fasterxml/jackson/databind/jsontype/TestSubtypes.java b/src/test/java/com/fasterxml/jackson/databind/jsontype/TestSubtypes.java
index 5aa2c4e..4450c04 100644
--- a/src/test/java/com/fasterxml/jackson/databind/jsontype/TestSubtypes.java
+++ b/src/test/java/com/fasterxml/jackson/databind/jsontype/TestSubtypes.java
@@ -147,7 +147,17 @@
             def = def0;
         }
     }
-    
+
+    // [databind#1311]
+    @JsonTypeInfo(property = "type", use = JsonTypeInfo.Id.NAME, defaultImpl = Factory1311ImplA.class)
+    interface Factory1311 { }
+
+    @JsonTypeName("implA")
+    static class Factory1311ImplA implements Factory1311 { }
+
+    @JsonTypeName("implB")
+    static class Factory1311ImplB implements Factory1311 { }
+
     /*
     /**********************************************************
     /* Unit tests
@@ -155,8 +165,7 @@
      */
 
     private final ObjectMapper MAPPER = new ObjectMapper();
-    
-    // JACKSON-510
+
     public void testPropertyWithSubtypes() throws Exception
     {
         ObjectMapper mapper = new ObjectMapper();
diff --git a/src/test/java/com/fasterxml/jackson/databind/jsontype/TypeRefinementForMapTest.java b/src/test/java/com/fasterxml/jackson/databind/jsontype/TypeRefinementForMapTest.java
index c810755..711c77c 100644
--- a/src/test/java/com/fasterxml/jackson/databind/jsontype/TypeRefinementForMapTest.java
+++ b/src/test/java/com/fasterxml/jackson/databind/jsontype/TypeRefinementForMapTest.java
@@ -54,10 +54,11 @@
     public static final class TestClass {
         @JsonProperty("mapProperty")
         @JsonSerialize(keyUsing = CompoundKeySerializer.class)
+        @JsonDeserialize(keyUsing = CompoundKeyDeserializer.class)
         private final Map<CompoundKey, String> mapProperty;
 
         @JsonCreator
-        private TestClass(@JsonDeserialize(keyUsing = CompoundKeyDeserializer.class) @JsonProperty("mapProperty") Map<CompoundKey, String> mapProperty) {
+        private TestClass(@JsonProperty("mapProperty") Map<CompoundKey, String> mapProperty) {
             this.mapProperty = mapProperty;
         }
     }
diff --git a/src/test/java/com/fasterxml/jackson/failing/FailingSubTypeUnknownClass1098Test.java b/src/test/java/com/fasterxml/jackson/databind/jsontype/UnknownSubClassTest.java
similarity index 86%
rename from src/test/java/com/fasterxml/jackson/failing/FailingSubTypeUnknownClass1098Test.java
rename to src/test/java/com/fasterxml/jackson/databind/jsontype/UnknownSubClassTest.java
index 9ec52a0..ba67098 100644
--- a/src/test/java/com/fasterxml/jackson/failing/FailingSubTypeUnknownClass1098Test.java
+++ b/src/test/java/com/fasterxml/jackson/databind/jsontype/UnknownSubClassTest.java
@@ -1,10 +1,10 @@
-package com.fasterxml.jackson.failing;
+package com.fasterxml.jackson.databind.jsontype;
 
 import com.fasterxml.jackson.annotation.JsonTypeInfo;
 
 import com.fasterxml.jackson.databind.*;
 
-public class FailingSubTypeUnknownClass1098Test extends BaseMapTest
+public class UnknownSubClassTest extends BaseMapTest
 {
     @JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY,
             property = "clazz")
diff --git a/src/test/java/com/fasterxml/jackson/databind/jsontype/ExternalTypeId198Test.java b/src/test/java/com/fasterxml/jackson/databind/jsontype/ext/ExternalTypeId198Test.java
similarity index 60%
rename from src/test/java/com/fasterxml/jackson/databind/jsontype/ExternalTypeId198Test.java
rename to src/test/java/com/fasterxml/jackson/databind/jsontype/ext/ExternalTypeId198Test.java
index effef58..c34793f 100644
--- a/src/test/java/com/fasterxml/jackson/databind/jsontype/ExternalTypeId198Test.java
+++ b/src/test/java/com/fasterxml/jackson/databind/jsontype/ext/ExternalTypeId198Test.java
@@ -1,4 +1,4 @@
-package com.fasterxml.jackson.databind.jsontype;
+package com.fasterxml.jackson.databind.jsontype.ext;
 
 import com.fasterxml.jackson.annotation.JsonCreator;
 import com.fasterxml.jackson.annotation.JsonSubTypes;
@@ -33,38 +33,38 @@
     }
 
     public static class Kick extends Attack {
-      @JsonCreator
-      public Kick(String side) {
-        super(side);
-      }
+        @JsonCreator
+        public Kick(String side) {
+            super(side);
+        }
     }
 
     public static class Punch extends Attack {
-      @JsonCreator
-      public Punch(String side) {
-        super(side);
-      }
+        @JsonCreator
+        public Punch(String side) {
+            super(side);
+        }
     }
 
     final ObjectMapper MAPPER = new ObjectMapper();
 
     public void testFails() throws Exception {
-      String json = "{ \"name\": \"foo\", \"attack\":\"right\" } }";
+        String json = "{ \"name\": \"foo\", \"attack\":\"right\" } }";
 
-      Character character = MAPPER.readValue(json, Character.class);
+        Character character = MAPPER.readValue(json, Character.class);
 
-      assertNotNull(character);
-      assertNotNull(character.attack);
-      assertEquals("foo", character.name);
+        assertNotNull(character);
+        assertNotNull(character.attack);
+        assertEquals("foo", character.name);
     }
 
     public void testWorks() throws Exception {
-      String json = "{ \"name\": \"foo\", \"preferredAttack\": \"KICK\", \"attack\":\"right\" } }";
+        String json = "{ \"name\": \"foo\", \"preferredAttack\": \"KICK\", \"attack\":\"right\" } }";
 
-      Character character = MAPPER.readValue(json, Character.class);
+        Character character = MAPPER.readValue(json, Character.class);
 
-      assertNotNull(character);
-      assertNotNull(character.attack);
-      assertEquals("foo", character.name);
+        assertNotNull(character);
+        assertNotNull(character.attack);
+        assertEquals("foo", character.name);
     }
 }
diff --git a/src/test/java/com/fasterxml/jackson/failing/ExternalTypeId999Test.java b/src/test/java/com/fasterxml/jackson/databind/jsontype/ext/ExternalTypeId999Test.java
similarity index 61%
rename from src/test/java/com/fasterxml/jackson/failing/ExternalTypeId999Test.java
rename to src/test/java/com/fasterxml/jackson/databind/jsontype/ext/ExternalTypeId999Test.java
index 1c7404f..a81f251 100644
--- a/src/test/java/com/fasterxml/jackson/failing/ExternalTypeId999Test.java
+++ b/src/test/java/com/fasterxml/jackson/databind/jsontype/ext/ExternalTypeId999Test.java
@@ -1,4 +1,4 @@
-package com.fasterxml.jackson.failing;
+package com.fasterxml.jackson.databind.jsontype.ext;
 
 import com.fasterxml.jackson.annotation.*;
 import com.fasterxml.jackson.core.type.TypeReference;
@@ -18,7 +18,8 @@
     {
         final String type;
 
-        @JsonTypeInfo(visible = true, use = JsonTypeInfo.Id.NAME,
+        @JsonTypeInfo(use = JsonTypeInfo.Id.NAME,
+                visible = true,
                 include = JsonTypeInfo.As.EXTERNAL_PROPERTY, property = "type")
         @JsonSubTypes({
                 @JsonSubTypes.Type(FooPayload.class),
@@ -29,24 +30,26 @@
         public Message(@JsonProperty("type") String type,
                 @JsonProperty("payload") P payload)
         {
-            if (payload == null) {
-                throw new RuntimeException("'payload' is null");
-            }
-            if (type == null) {
-                throw new RuntimeException("'type' is null");
-            }
             this.type = type;
             this.payload = payload;
         }
     }
 
+    private final ObjectMapper MAPPER = objectMapper();
 
     public void testExternalTypeId() throws Exception
     {
-        ObjectMapper objectMapper = new ObjectMapper();
-        Message<?> msg = objectMapper.readValue(
-                "{ \"type\": \"foo\", \"payload\": {} }",
-                new TypeReference<Message<FooPayload>>() { });
+        TypeReference<?> type = new TypeReference<Message<FooPayload>>() { };
+
+        Message<?> msg = MAPPER.readValue(aposToQuotes("{ 'type':'foo', 'payload': {} }"), type);
         assertNotNull(msg);
+        assertNotNull(msg.payload);
+        assertEquals("foo", msg.type);
+
+        // and then with different order
+        msg = MAPPER.readValue(aposToQuotes("{'payload': {}, 'type':'foo' }"), type);
+        assertNotNull(msg);
+        assertNotNull(msg.payload);
+        assertEquals("foo", msg.type);
     }
 }
diff --git a/src/test/java/com/fasterxml/jackson/databind/jsontype/TestExternalId.java b/src/test/java/com/fasterxml/jackson/databind/jsontype/ext/ExternalTypeIdTest.java
similarity index 96%
rename from src/test/java/com/fasterxml/jackson/databind/jsontype/TestExternalId.java
rename to src/test/java/com/fasterxml/jackson/databind/jsontype/ext/ExternalTypeIdTest.java
index 7bdcd09..8913f7a 100644
--- a/src/test/java/com/fasterxml/jackson/databind/jsontype/TestExternalId.java
+++ b/src/test/java/com/fasterxml/jackson/databind/jsontype/ext/ExternalTypeIdTest.java
@@ -1,4 +1,4 @@
-package com.fasterxml.jackson.databind.jsontype;
+package com.fasterxml.jackson.databind.jsontype.ext;
 
 import java.math.BigDecimal;
 import java.util.*;
@@ -12,7 +12,7 @@
 
 // Tests for External type id, one that exists at same level as typed Object,
 // that is, property is not within typed object but a member of its parent.
-public class TestExternalId extends BaseMapTest
+public class ExternalTypeIdTest extends BaseMapTest
 {
     static class ExternalBean
     {
@@ -473,22 +473,14 @@
         ExternalTypeWithNonPOJO input = new ExternalTypeWithNonPOJO(new AsValueThingy(12345L));
         String json = MAPPER.writeValueAsString(input);
         assertNotNull(json);
-        assertEquals("{\"value\":12345,\"type\":\"date\"}", json);
+        assertEquals("{\"value\":12345,\"type\":\"thingy\"}", json);
 
         // and get it back too:
         ExternalTypeWithNonPOJO result = MAPPER.readValue(json, ExternalTypeWithNonPOJO.class);
         assertNotNull(result);
         assertNotNull(result.value);
-        /* 13-Feb-2013, tatu: Urgh. I don't think this can work quite as intended...
-         *   since POJO type, and type of thing @JsonValue annotated method returns
-         *   are not related. Best we can do is thus this:
-         */
-        /*
         assertEquals(AsValueThingy.class, result.value.getClass());
         assertEquals(12345L, ((AsValueThingy) result.value).rawDate);
-        */
-        assertEquals(Date.class, result.value.getClass());
-        assertEquals(12345L, ((Date) result.value).getTime());
     }
 
     // for [databind#222]
diff --git a/src/test/java/com/fasterxml/jackson/databind/jsontype/ext/ExternalTypeIdTest1288.java b/src/test/java/com/fasterxml/jackson/databind/jsontype/ext/ExternalTypeIdTest1288.java
index 7681899..d756d40 100644
--- a/src/test/java/com/fasterxml/jackson/databind/jsontype/ext/ExternalTypeIdTest1288.java
+++ b/src/test/java/com/fasterxml/jackson/databind/jsontype/ext/ExternalTypeIdTest1288.java
@@ -504,12 +504,10 @@
                 + "\"csc\":666,\"address\":\"10 boulevard de Sebastopol\",\"zip_code\":\"75001\",\"city\":\"Paris\",\"province\":\"Ile-de-France\",\"country_code\":\"FR\",\"description\":\"John Doe personal credit card\"}}";
         final String asJson2 = "{\"form_of_payment\":\"INSTRUMENTED_CREDIT_CARD\",\"payment_details\":{\"payment_instrument_id\":\"00000000-0000-0000-0000-000000000000\", \"name\":\"Mr John Doe encrypted credit card\"}}";
         final ObjectMapper objectMapper = new ObjectMapper ().setPropertyNamingStrategy (PropertyNamingStrategy.SNAKE_CASE);
-//                .disable (DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
 
         ClassesWithoutBuilder.PaymentMean ob1 = objectMapper.readValue (asJson1, ClassesWithoutBuilder.PaymentMean.class);
         assertNotNull(ob1);
         ClassesWithBuilder.PaymentMean ob2 = objectMapper.readValue (asJson2, ClassesWithBuilder.PaymentMean.class);
         assertNotNull(ob2);
-
     }
 }
diff --git a/src/test/java/com/fasterxml/jackson/failing/TestTypeWithJsonValue466.java b/src/test/java/com/fasterxml/jackson/databind/jsontype/ext/JsonValueExtTypeIdTest.java
similarity index 95%
rename from src/test/java/com/fasterxml/jackson/failing/TestTypeWithJsonValue466.java
rename to src/test/java/com/fasterxml/jackson/databind/jsontype/ext/JsonValueExtTypeIdTest.java
index fa90f2a..b8d2542 100644
--- a/src/test/java/com/fasterxml/jackson/failing/TestTypeWithJsonValue466.java
+++ b/src/test/java/com/fasterxml/jackson/databind/jsontype/ext/JsonValueExtTypeIdTest.java
@@ -1,4 +1,4 @@
-package com.fasterxml.jackson.failing;
+package com.fasterxml.jackson.databind.jsontype.ext;
 
 import java.io.*;
 import java.math.BigDecimal;
@@ -8,7 +8,7 @@
 import com.fasterxml.jackson.databind.*;
 
 @SuppressWarnings("serial")
-public class TestTypeWithJsonValue466 extends BaseMapTest
+public class JsonValueExtTypeIdTest extends BaseMapTest
 {
     // The following is required for the testDecimalMetadata test case. That case fails.
     @JsonTypeName(value = "decimalValue")
diff --git a/src/test/java/com/fasterxml/jackson/databind/jsontype/ext/TestSubtypesExternalPropertyMissingProperty.java b/src/test/java/com/fasterxml/jackson/databind/jsontype/ext/TestSubtypesExternalPropertyMissingProperty.java
new file mode 100644
index 0000000..ac414b3
--- /dev/null
+++ b/src/test/java/com/fasterxml/jackson/databind/jsontype/ext/TestSubtypesExternalPropertyMissingProperty.java
@@ -0,0 +1,259 @@
+package com.fasterxml.jackson.databind.jsontype.ext;
+
+import com.fasterxml.jackson.annotation.*;
+import com.fasterxml.jackson.annotation.JsonSubTypes.Type;
+import com.fasterxml.jackson.annotation.JsonTypeInfo.As;
+import com.fasterxml.jackson.annotation.JsonTypeInfo.Id;
+
+import com.fasterxml.jackson.databind.*;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertSame;
+
+// for [databind#1341]
+public class TestSubtypesExternalPropertyMissingProperty
+{
+    @Rule
+    public ExpectedException thrown = ExpectedException.none();
+
+    /**
+     * Base class - external property for Fruit subclasses.
+     */
+    static class Box {
+        public String type;
+        @JsonTypeInfo(use = Id.NAME, include = As.EXTERNAL_PROPERTY, property = "type")
+        public Fruit fruit;
+
+        public Box() {
+        }
+
+        public Box(String type, Fruit fruit) {
+            this.type = type;
+            this.fruit = fruit;
+        }
+    }
+
+    /**
+     * Base class that requires the property to be present.
+     */
+    static class ReqBox {
+        public String type;
+        @JsonTypeInfo(use = Id.NAME, include = As.EXTERNAL_PROPERTY, property = "type")
+        @JsonProperty(required = true)
+        public Fruit fruit;
+
+        public ReqBox() {
+        }
+
+        public ReqBox(String type, Fruit fruit) {
+            this.type = type;
+            this.fruit = fruit;
+        }
+    }
+
+    @JsonSubTypes({
+            @Type(value = Apple.class, name = "apple"),
+            @Type(value = Orange.class, name = "orange")
+    })
+    static abstract class Fruit {
+        public String name;
+
+        public Fruit() {
+        }
+
+        protected Fruit(String n) {
+            name = n;
+        }
+    }
+
+    static class Apple extends Fruit {
+        public int seedCount;
+
+        public Apple() {
+        }
+
+        public Apple(String name, int b) {
+            super(name);
+            seedCount = b;
+        }
+    }
+
+    static class Orange extends Fruit {
+        public String color;
+
+        public Orange() {
+        }
+
+        public Orange(String name, String c) {
+            super(name);
+            color = c;
+        }
+    }
+
+    private final ObjectMapper MAPPER = new ObjectMapper();
+
+    /*
+    /**********************************************************
+    /* Mock data
+    /**********************************************************
+     */
+
+    private static final Orange orange = new Orange("Orange", "orange");
+    private static final Box orangeBox = new Box("orange", orange);
+    private static final String orangeBoxJson = "{\"type\":\"orange\",\"fruit\":{\"name\":\"Orange\",\"color\":\"orange\"}}";
+    private static final String orangeBoxNullJson = "{\"type\":\"orange\",\"fruit\":null}}";
+    private static final String orangeBoxEmptyJson = "{\"type\":\"orange\",\"fruit\":{}}}";
+    private static final String orangeBoxMissingJson = "{\"type\":\"orange\"}}";
+
+    private static final Apple apple = new Apple("Apple", 16);
+    private static Box appleBox = new Box("apple", apple);
+    private static final String appleBoxJson = "{\"type\":\"apple\",\"fruit\":{\"name\":\"Apple\",\"seedCount\":16}}";
+    private static final String appleBoxNullJson = "{\"type\":\"apple\",\"fruit\":null}";
+    private static final String appleBoxEmptyJson = "{\"type\":\"apple\",\"fruit\":{}}";
+    private static final String appleBoxMissingJson = "{\"type\":\"apple\"}";
+
+    /*
+    /**********************************************************
+    /* Unit tests
+    /**********************************************************
+     */
+
+    /**
+     * Deserialization tests for external type id property present
+     */
+    @Test
+    public void testDeserializationPresent() throws Exception {
+        MAPPER.disable(DeserializationFeature.FAIL_ON_MISSING_EXTERNAL_TYPE_ID_PROPERTY);
+        checkOrangeBox();
+        checkAppleBox();
+
+        MAPPER.enable(DeserializationFeature.FAIL_ON_MISSING_EXTERNAL_TYPE_ID_PROPERTY);
+        checkOrangeBox();
+        checkAppleBox();
+    }
+
+    /**
+     * Deserialization tests for external type id property null
+     */
+    @Test
+    public void testDeserializationNull() throws Exception {
+        MAPPER.disable(DeserializationFeature.FAIL_ON_MISSING_EXTERNAL_TYPE_ID_PROPERTY);
+        checkOrangeBoxNull(orangeBoxNullJson);
+        checkAppleBoxNull(appleBoxNullJson);
+
+        MAPPER.enable(DeserializationFeature.FAIL_ON_MISSING_EXTERNAL_TYPE_ID_PROPERTY);
+        checkOrangeBoxNull(orangeBoxNullJson);
+        checkAppleBoxNull(appleBoxNullJson);
+    }
+
+    /**
+     * Deserialization tests for external type id property empty
+     */
+    @Test
+    public void testDeserializationEmpty() throws Exception {
+        MAPPER.disable(DeserializationFeature.FAIL_ON_MISSING_EXTERNAL_TYPE_ID_PROPERTY);
+        checkOrangeBoxEmpty(orangeBoxEmptyJson);
+        checkAppleBoxEmpty(appleBoxEmptyJson);
+
+        MAPPER.enable(DeserializationFeature.FAIL_ON_MISSING_EXTERNAL_TYPE_ID_PROPERTY);
+        checkOrangeBoxEmpty(orangeBoxEmptyJson);
+        checkAppleBoxEmpty(appleBoxEmptyJson);
+    }
+
+    /**
+     * Deserialization tests for external type id property missing
+     */
+    @Test
+    public void testDeserializationMissing() throws Exception {
+        MAPPER.disable(DeserializationFeature.FAIL_ON_MISSING_EXTERNAL_TYPE_ID_PROPERTY);
+        checkOrangeBoxNull(orangeBoxMissingJson);
+        checkAppleBoxNull(appleBoxMissingJson);
+
+        MAPPER.enable(DeserializationFeature.FAIL_ON_MISSING_EXTERNAL_TYPE_ID_PROPERTY);
+        checkBoxJsonMappingException(orangeBoxMissingJson);
+        checkBoxJsonMappingException(appleBoxMissingJson);
+    }
+
+    /**
+     * Deserialization tests for external type id required property missing
+     */
+    @Test
+    public void testDeserializationMissingRequired() throws Exception {
+        MAPPER.disable(DeserializationFeature.FAIL_ON_MISSING_EXTERNAL_TYPE_ID_PROPERTY);
+        checkReqBoxJsonMappingException(orangeBoxMissingJson);
+        checkReqBoxJsonMappingException(appleBoxMissingJson);
+
+        MAPPER.enable(DeserializationFeature.FAIL_ON_MISSING_EXTERNAL_TYPE_ID_PROPERTY);
+        checkReqBoxJsonMappingException(orangeBoxMissingJson);
+        checkReqBoxJsonMappingException(appleBoxMissingJson);
+    }
+
+    private void checkOrangeBox() throws Exception {
+        Box deserOrangeBox = MAPPER.readValue(orangeBoxJson, Box.class);
+        assertEquals(orangeBox.type, deserOrangeBox.type);
+
+        Fruit deserOrange = deserOrangeBox.fruit;
+        assertSame(Orange.class, deserOrange.getClass());
+        assertEquals(orange.name, deserOrange.name);
+        assertEquals(orange.color, ((Orange) deserOrange).color);
+    }
+
+    private void checkAppleBox() throws Exception {
+        Box deserAppleBox = MAPPER.readValue(appleBoxJson, Box.class);
+        assertEquals(appleBox.type, deserAppleBox.type);
+
+        Fruit deserApple = deserAppleBox.fruit;
+        assertSame(Apple.class, deserApple.getClass());
+        assertEquals(apple.name, deserApple.name);
+        assertEquals(apple.seedCount, ((Apple) deserApple).seedCount);
+    }
+
+    private void checkOrangeBoxEmpty(String json) throws Exception {
+        Box deserOrangeBox = MAPPER.readValue(json, Box.class);
+        assertEquals(orangeBox.type, deserOrangeBox.type);
+
+        Fruit deserOrange = deserOrangeBox.fruit;
+        assertSame(Orange.class, deserOrange.getClass());
+        assertNull(deserOrange.name);
+        assertNull(((Orange) deserOrange).color);
+    }
+
+    private void checkAppleBoxEmpty(String json) throws Exception {
+        Box deserAppleBox = MAPPER.readValue(json, Box.class);
+        assertEquals(appleBox.type, deserAppleBox.type);
+
+        Fruit deserApple = deserAppleBox.fruit;
+        assertSame(Apple.class, deserApple.getClass());
+        assertNull(deserApple.name);
+        assertEquals(0, ((Apple) deserApple).seedCount);
+    }
+
+    private void checkOrangeBoxNull(String json) throws Exception {
+        Box deserOrangeBox = MAPPER.readValue(json, Box.class);
+        assertEquals(orangeBox.type, deserOrangeBox.type);
+        assertNull(deserOrangeBox.fruit);
+    }
+
+    private void checkAppleBoxNull(String json) throws Exception {
+        Box deserAppleBox = MAPPER.readValue(json, Box.class);
+        assertEquals(appleBox.type, deserAppleBox.type);
+        assertNull(deserAppleBox.fruit);
+    }
+
+    private void checkBoxJsonMappingException(String json) throws Exception {
+        thrown.expect(JsonMappingException.class);
+        thrown.expectMessage("Missing property 'fruit' for external type id 'type'");
+        MAPPER.readValue(json, Box.class);
+    }
+
+    private void checkReqBoxJsonMappingException(String json) throws Exception {
+        thrown.expect(JsonMappingException.class);
+        thrown.expectMessage("Missing property 'fruit' for external type id 'type'");
+        MAPPER.readValue(json, ReqBox.class);
+    }
+}    
diff --git a/src/test/java/com/fasterxml/jackson/databind/misc/AccessFixTest.java b/src/test/java/com/fasterxml/jackson/databind/misc/AccessFixTest.java
index 6e7eb98..64c4ca5 100644
--- a/src/test/java/com/fasterxml/jackson/databind/misc/AccessFixTest.java
+++ b/src/test/java/com/fasterxml/jackson/databind/misc/AccessFixTest.java
@@ -14,7 +14,7 @@
         @Override
         public void checkPermission(Permission perm) throws SecurityException {
             if ("suppressAccessChecks".equals(perm.getName())) {
-throw new SecurityException("Can not force permission: "+perm);
+                throw new SecurityException("Can not force permission: "+perm);
             }
         }
     }
@@ -24,18 +24,18 @@
     public void testCauseOfThrowableIgnoral() throws Exception
     {
         final SecurityManager origSecMan = System.getSecurityManager();
+        ObjectMapper mapper = new ObjectMapper();
+        mapper.disable(MapperFeature.OVERRIDE_PUBLIC_ACCESS_MODIFIERS);
         try {
             System.setSecurityManager(new CauseBlockingSecurityManager());
-            _testCauseOfThrowableIgnoral();
+            _testCauseOfThrowableIgnoral(mapper);
         } finally {
             System.setSecurityManager(origSecMan);
         }
     }
 
-    private void _testCauseOfThrowableIgnoral() throws Exception
+    private void _testCauseOfThrowableIgnoral(ObjectMapper mapper) throws Exception
     {
-        ObjectMapper mapper = new ObjectMapper();
-        mapper.disable(MapperFeature.OVERRIDE_PUBLIC_ACCESS_MODIFIERS);
         IOException e = mapper.readValue("{}", IOException.class);
         assertNotNull(e);
     }
diff --git a/src/test/java/com/fasterxml/jackson/databind/misc/CaseInsensitiveDeser.java b/src/test/java/com/fasterxml/jackson/databind/misc/CaseInsensitiveDeserTest.java
similarity index 62%
rename from src/test/java/com/fasterxml/jackson/databind/misc/CaseInsensitiveDeser.java
rename to src/test/java/com/fasterxml/jackson/databind/misc/CaseInsensitiveDeserTest.java
index 20a9fad..66b9554 100644
--- a/src/test/java/com/fasterxml/jackson/databind/misc/CaseInsensitiveDeser.java
+++ b/src/test/java/com/fasterxml/jackson/databind/misc/CaseInsensitiveDeserTest.java
@@ -1,32 +1,16 @@
 package com.fasterxml.jackson.databind.misc;
 
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonProperty;
 import com.fasterxml.jackson.core.JsonProcessingException;
 import com.fasterxml.jackson.databind.*;
 
-public class CaseInsensitiveDeser extends BaseMapTest
+public class CaseInsensitiveDeserTest extends BaseMapTest
 {
     // [databind#1036]
     static class BaseResponse {
         public int errorCode;
         public String debugMessage;
-
-        /*
-        public String getDebugMessage() {
-            return debugMessage;
-        }
-
-        public void setDebugMessage(String debugMessage) {
-            this.debugMessage = debugMessage;
-        }
-
-        public int getErrorCode() {
-            return errorCode;
-        }
-
-        public void setErrorCode(int errorCode) {
-            this.errorCode = errorCode;
-        }
-        */
     }
 
     static class Issue476Bean {
@@ -36,21 +20,37 @@
         public String name, value;
     }
 
+    // [databind#1438]
+    static class InsensitiveCreator
+    {
+        int v;
+
+        @JsonCreator
+        public InsensitiveCreator(@JsonProperty("value") int v0) {
+            v = v0;
+        }
+    }
+
     /*
     /********************************************************
     /* Test methods
     /********************************************************
      */
-    
-    // [databind#566]
+
+    private final ObjectMapper INSENSITIVE_MAPPER = new ObjectMapper();
+    {
+        INSENSITIVE_MAPPER.enable(MapperFeature.ACCEPT_CASE_INSENSITIVE_PROPERTIES);
+        
+    }
+
+// [databind#566]
     public void testCaseInsensitiveDeserialization() throws Exception
     {
-     final String JSON = "{\"Value1\" : {\"nAme\" : \"fruit\", \"vALUe\" : \"apple\"}, \"valUE2\" : {\"NAME\" : \"color\", \"value\" : \"red\"}}";
+        final String JSON = "{\"Value1\" : {\"nAme\" : \"fruit\", \"vALUe\" : \"apple\"}, \"valUE2\" : {\"NAME\" : \"color\", \"value\" : \"red\"}}";
         
         // first, verify default settings which do not accept improper case
         ObjectMapper mapper = new ObjectMapper();
         assertFalse(mapper.isEnabled(MapperFeature.ACCEPT_CASE_INSENSITIVE_PROPERTIES));
-        
         try {
             mapper.readValue(JSON, Issue476Bean.class);
             
@@ -61,9 +61,7 @@
         }
 
         // Definitely not OK to enable dynamically - the BeanPropertyMap (which is the consumer of this particular feature) gets cached.
-        mapper = new ObjectMapper();
-        mapper.configure(MapperFeature.ACCEPT_CASE_INSENSITIVE_PROPERTIES, true);
-        ObjectReader r = mapper.readerFor(Issue476Bean.class);
+        ObjectReader r = INSENSITIVE_MAPPER.readerFor(Issue476Bean.class);
         Issue476Bean result = r.readValue(JSON);
         assertEquals(result.value1.name, "fruit");
         assertEquals(result.value1.value, "apple");
@@ -75,10 +73,16 @@
         final String json = "{\"ErrorCode\":2,\"DebugMessage\":\"Signature not valid!\"}";
 //        final String json = "{\"errorCode\":2,\"debugMessage\":\"Signature not valid!\"}";
 
-        ObjectMapper mapper = new ObjectMapper();
-        mapper.enable(MapperFeature.ACCEPT_CASE_INSENSITIVE_PROPERTIES);
-        BaseResponse response = mapper.readValue(json, BaseResponse.class);
+        BaseResponse response = INSENSITIVE_MAPPER.readValue(json, BaseResponse.class);
         assertEquals(2, response.errorCode);
         assertEquals("Signature not valid!", response.debugMessage);
     }
+
+    // [databind#1438]
+    public void testCreatorWithInsensitive() throws Exception
+    {
+        final String json = aposToQuotes("{'VALUE':3}");
+        InsensitiveCreator bean = INSENSITIVE_MAPPER.readValue(json, InsensitiveCreator.class);
+        assertEquals(3, bean.v);
+    }
 }
diff --git a/src/test/java/com/fasterxml/jackson/databind/misc/TestJSONP.java b/src/test/java/com/fasterxml/jackson/databind/misc/TestJSONP.java
index 4aa7ef9..24249ff 100644
--- a/src/test/java/com/fasterxml/jackson/databind/misc/TestJSONP.java
+++ b/src/test/java/com/fasterxml/jackson/databind/misc/TestJSONP.java
@@ -1,8 +1,10 @@
 package com.fasterxml.jackson.databind.misc;
 
-import com.fasterxml.jackson.databind.*;
+import java.util.Arrays;
 
+import com.fasterxml.jackson.databind.*;
 import com.fasterxml.jackson.databind.util.JSONPObject;
+import com.fasterxml.jackson.databind.util.JSONWrappedObject;
 
 public class TestJSONP
     extends BaseMapTest
@@ -18,23 +20,23 @@
             this.b = b;
         }
     }
-    
+
+    private final ObjectMapper MAPPER = new ObjectMapper();
+
     public void testSimpleScalars() throws Exception
     {
-        ObjectMapper m = new ObjectMapper();
         assertEquals("callback(\"abc\")",
-                serializeAsString(m, new JSONPObject("callback", "abc")));
+                MAPPER.writeValueAsString(new JSONPObject("callback", "abc")));
         assertEquals("calc(123)",
-                serializeAsString(m, new JSONPObject("calc", Integer.valueOf(123))));
+                MAPPER.writeValueAsString(new JSONPObject("calc", Integer.valueOf(123))));
         assertEquals("dummy(null)",
-                serializeAsString(m, new JSONPObject("dummy", null)));
+                MAPPER.writeValueAsString(new JSONPObject("dummy", null)));
     }
 
     public void testSimpleBean() throws Exception
     {
-        ObjectMapper m = new ObjectMapper();
         assertEquals("xxx({\"a\":\"123\",\"b\":\"456\"})",
-                serializeAsString(m, new JSONPObject("xxx",
+                MAPPER.writeValueAsString(new JSONPObject("xxx",
                         new Impl("123", "456"))));
     }
     
@@ -44,10 +46,16 @@
      */
     public void testWithType() throws Exception
     {
-        ObjectMapper m = new ObjectMapper();
         Object ob = new Impl("abc", "def");
-        JavaType type = m.constructType(Base.class);
+        JavaType type = MAPPER.constructType(Base.class);
         assertEquals("do({\"a\":\"abc\"})",
-                serializeAsString(m, new JSONPObject("do", ob, type)));
+                MAPPER.writeValueAsString(new JSONPObject("do", ob, type)));
+    }
+
+    public void testGeneralWrapping() throws Exception
+    {
+        JSONWrappedObject input = new JSONWrappedObject("/*Foo*/", "\n// the end",
+                Arrays.asList());
+        assertEquals("/*Foo*/[]\n// the end", MAPPER.writeValueAsString(input));
     }
 }
diff --git a/src/test/java/com/fasterxml/jackson/databind/module/TestAbstractTypes.java b/src/test/java/com/fasterxml/jackson/databind/module/TestAbstractTypes.java
index 5d126c0..76402b0 100644
--- a/src/test/java/com/fasterxml/jackson/databind/module/TestAbstractTypes.java
+++ b/src/test/java/com/fasterxml/jackson/databind/module/TestAbstractTypes.java
@@ -9,12 +9,6 @@
 
 public class TestAbstractTypes extends BaseMapTest
 {
-    /*
-    /**********************************************************
-    /* Helper classes; simple beans and their handlers
-    /**********************************************************
-     */
-
     static class MyString implements CharSequence
     {
         protected String value;
@@ -34,10 +28,19 @@
         @Override
         public CharSequence subSequence(int arg0, int arg1) { return this; }
     }
-    
+
+    public interface Abstract {
+        public int getValue();
+    }
+
+    public static class AbstractImpl implements Abstract {
+        @Override
+        public int getValue() { return 3; }
+    }
+
     /*
     /**********************************************************
-    /* Unit tests
+    /* Test methods
     /**********************************************************
      */
 
@@ -103,5 +106,13 @@
         Object result = mapper.readValue(quote("abc"), CharSequence.class);
         assertEquals(MyString.class, result.getClass());
         assertEquals("abc", ((MyString) result).value);
+
+        // and ditto for POJOs
+        mod = new SimpleModule();
+        mod.addAbstractTypeMapping(Abstract.class, AbstractImpl.class);
+        mapper = new ObjectMapper()
+                .registerModule(mod);
+        Abstract a = mapper.readValue("{}", Abstract.class);
+        assertNotNull(a);
     }
 }
diff --git a/src/test/java/com/fasterxml/jackson/databind/module/TestCustomEnumKeyDeserializer.java b/src/test/java/com/fasterxml/jackson/databind/module/TestCustomEnumKeyDeserializer.java
index 1900a17..f99e320 100644
--- a/src/test/java/com/fasterxml/jackson/databind/module/TestCustomEnumKeyDeserializer.java
+++ b/src/test/java/com/fasterxml/jackson/databind/module/TestCustomEnumKeyDeserializer.java
@@ -6,12 +6,14 @@
 
 import org.junit.Test;
 
+import com.fasterxml.jackson.annotation.JsonTypeInfo;
 import com.fasterxml.jackson.core.*;
 import com.fasterxml.jackson.core.type.TypeReference;
 
 import com.fasterxml.jackson.databind.*;
 import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
 import com.fasterxml.jackson.databind.annotation.JsonSerialize;
+import com.fasterxml.jackson.databind.deser.BeanDeserializerModifier;
 import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
 import com.fasterxml.jackson.databind.exc.InvalidFormatException;
 import com.fasterxml.jackson.databind.node.ObjectNode;
@@ -71,7 +73,7 @@
             try {
                 return TestEnum.lookup(key);
             } catch (IllegalArgumentException e) {
-                throw ctxt.weirdKeyException(TestEnum.class, key, "Unknown code");
+                return ctxt.handleWeirdKey(TestEnum.class, key, "Unknown code");
             }
         }
     }
@@ -149,6 +151,17 @@
         }
     }
 
+    // for [databind#1441]
+
+    enum SuperTypeEnum {
+        FOO;
+    }
+
+    @JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "@type", defaultImpl = SuperType.class)
+    static class SuperType {
+        public Map<SuperTypeEnum, String> someMap;
+    }
+
     /*
     /**********************************************************
     /* Test methods
@@ -190,4 +203,79 @@
         String firstFieldName = inner.fieldNames().next();
         assertEquals("green", firstFieldName);
     }
+
+    // [databind#1441]
+    public void testCustomEnumKeySerializerWithPolymorphic() throws IOException
+    {
+        SimpleModule simpleModule = new SimpleModule();
+        simpleModule.addDeserializer(SuperTypeEnum.class, new JsonDeserializer<SuperTypeEnum>() {
+            @Override
+            public SuperTypeEnum deserialize(JsonParser p, DeserializationContext deserializationContext)
+                    throws IOException
+            {
+                return SuperTypeEnum.valueOf(p.getText());
+            }
+        });
+        ObjectMapper mapper = new ObjectMapper()
+                .registerModule(simpleModule);
+
+        SuperType superType = mapper.readValue("{\"someMap\": {\"FOO\": \"bar\"}}",
+                SuperType.class);
+        assertEquals("Deserialized someMap.FOO should equal bar", "bar",
+                superType.someMap.get(SuperTypeEnum.FOO));
+    }
+
+    // [databind#1445]
+    @SuppressWarnings({ "unchecked", "rawtypes" })
+    public void testCustomEnumValueAndKeyViaModifier() throws IOException
+    {
+        SimpleModule module = new SimpleModule();
+        module.setDeserializerModifier(new BeanDeserializerModifier() {        
+            @Override
+            public JsonDeserializer<Enum> modifyEnumDeserializer(DeserializationConfig config,
+                    final JavaType type, BeanDescription beanDesc,
+                    final JsonDeserializer<?> deserializer) {
+                return new JsonDeserializer<Enum>() {
+                    @Override
+                    public Enum deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
+                        Class<? extends Enum> rawClass = (Class<Enum<?>>) type.getRawClass();
+                        final String str = p.getValueAsString().toLowerCase();
+                        return KeyEnum.valueOf(rawClass, str);
+                    }
+                };
+            }
+
+            @Override
+            public KeyDeserializer modifyKeyDeserializer(DeserializationConfig config,
+                    final JavaType type, KeyDeserializer deserializer)
+            {
+                if (!type.isEnumType()) {
+                    return deserializer;
+                }
+                return new KeyDeserializer() {
+                    @Override
+                    public Object deserializeKey(String key, DeserializationContext ctxt)
+                            throws IOException
+                    {
+                        Class<? extends Enum> rawClass = (Class<Enum<?>>) type.getRawClass();
+                        return Enum.valueOf(rawClass, key.toLowerCase());
+                    }
+                };
+            }
+        });
+        ObjectMapper mapper = new ObjectMapper()
+                .registerModule(module);
+
+        // First, enum value as is
+        KeyEnum key = mapper.readValue(quote(KeyEnum.replacements.name().toUpperCase()),
+                KeyEnum.class);
+        assertSame(KeyEnum.replacements, key);
+
+        // and then as key
+        EnumMap<KeyEnum,String> map = mapper.readValue(
+                aposToQuotes("{'REPlaceMENTS':'foobar'}"),
+                new TypeReference<EnumMap<KeyEnum,String>>() { });
+        assertEquals(1, map.size());
+        assertSame(KeyEnum.replacements, map.keySet().iterator().next());
+    }
 }
diff --git a/src/test/java/com/fasterxml/jackson/databind/node/NotANumberConversionTest.java b/src/test/java/com/fasterxml/jackson/databind/node/NotANumberConversionTest.java
new file mode 100644
index 0000000..3fcb71d
--- /dev/null
+++ b/src/test/java/com/fasterxml/jackson/databind/node/NotANumberConversionTest.java
@@ -0,0 +1,41 @@
+package com.fasterxml.jackson.databind.node;
+
+import java.math.BigDecimal;
+
+import com.fasterxml.jackson.databind.*;
+
+public class NotANumberConversionTest extends BaseMapTest
+{
+    private final ObjectMapper m = new ObjectMapper();
+    {
+        m.enable(DeserializationFeature.USE_BIG_DECIMAL_FOR_FLOATS);
+    }
+
+    public void testBigDecimalWithNaN() throws Exception
+    {
+        JsonNode tree = m.valueToTree(new DoubleWrapper(Double.NaN));
+        assertNotNull(tree);
+        String json = m.writeValueAsString(tree);
+        assertNotNull(json);
+
+        tree = m.valueToTree(new DoubleWrapper(Double.NEGATIVE_INFINITY));
+        assertNotNull(tree);
+        json = m.writeValueAsString(tree);
+        assertNotNull(json);
+
+        tree = m.valueToTree(new DoubleWrapper(Double.POSITIVE_INFINITY));
+        assertNotNull(tree);
+        json = m.writeValueAsString(tree);
+        assertNotNull(json);
+    }
+
+    // for [databind#1315]: no accidental coercion to DoubleNode
+    public void testBigDecimalWithoutNaN() throws Exception
+    {
+        BigDecimal input = new BigDecimal(Double.MIN_VALUE).divide(new BigDecimal(10L));
+        JsonNode tree = m.readTree(input.toString());
+        assertTrue(tree.isBigDecimal());
+        BigDecimal output = tree.decimalValue();
+        assertEquals(input, output);
+    }
+}
diff --git a/src/test/java/com/fasterxml/jackson/databind/node/TestConversions.java b/src/test/java/com/fasterxml/jackson/databind/node/TestConversions.java
index b17dda3..354793a 100644
--- a/src/test/java/com/fasterxml/jackson/databind/node/TestConversions.java
+++ b/src/test/java/com/fasterxml/jackson/databind/node/TestConversions.java
@@ -8,6 +8,7 @@
 
 import org.junit.Assert;
 
+import com.fasterxml.jackson.annotation.JsonTypeInfo;
 import com.fasterxml.jackson.core.*;
 import com.fasterxml.jackson.databind.*;
 import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
@@ -69,7 +70,16 @@
 
         public Issue467TmpBean(int i) { x = i; }
     }
-    
+
+    static class Issue709Bean {
+        public byte[] data;
+    }
+
+    @JsonTypeInfo(use=JsonTypeInfo.Id.CLASS, include=JsonTypeInfo.As.PROPERTY, property="_class")
+    static class LongContainer1940 {
+        public Long longObj;
+    }
+
     /*
     /**********************************************************
     /* Unit tests
@@ -172,10 +182,6 @@
         }
     }
 
-    static class Issue709Bean {
-        public byte[] data;
-    }
-    
     /**
      * Simple test to verify that byte[] values can be handled properly when
      * converting, as long as there is metadata (from POJO definitions).
@@ -285,5 +291,12 @@
         assertTrue("Expected Object, got "+tree.getNodeType(), tree.isBoolean());
         assertEquals(EXP, MAPPER.writeValueAsString(tree));
     }
-}
 
+    // [databind#1940]: losing of precision due to coercion
+    public void testBufferedLongViaCoercion() throws Exception {
+        long EXP = 1519348261000L;
+        JsonNode tree = MAPPER.readTree("{\"longObj\": "+EXP+".0, \"_class\": \""+LongContainer1940.class.getName()+"\"}");
+        LongContainer1940 obj = MAPPER.treeToValue(tree, LongContainer1940.class);
+        assertEquals(Long.valueOf(EXP), obj.longObj);
+    }
+}
diff --git a/src/test/java/com/fasterxml/jackson/databind/node/TestEndOfInputHandling.java b/src/test/java/com/fasterxml/jackson/databind/node/TestEndOfInputHandling.java
new file mode 100644
index 0000000..a86baa1
--- /dev/null
+++ b/src/test/java/com/fasterxml/jackson/databind/node/TestEndOfInputHandling.java
@@ -0,0 +1,31 @@
+package com.fasterxml.jackson.databind.node;
+
+import java.io.IOException;
+
+import com.fasterxml.jackson.core.*;
+
+import com.fasterxml.jackson.databind.*;
+
+public class TestEndOfInputHandling extends BaseMapTest
+{
+  public void testErrorHandling() throws IOException {
+      ObjectMapper mapper = new ObjectMapper();
+
+      String json = "{\"A\":{\"B\":\n";
+      JsonParser parser = mapper.getFactory().createParser(json);
+      parser.setCodec(new ObjectMapper());
+      try {
+          parser.readValueAsTree();
+      } catch(JsonParseException e) {
+          verifyException(e, "Unexpected end-of-input");
+      }
+      parser.close();
+
+      try {
+          mapper.readTree(json);
+      }
+      catch(JsonParseException e) {
+          verifyException(e, "Unexpected end-of-input");
+      }
+  }
+}
diff --git a/src/test/java/com/fasterxml/jackson/databind/node/TestNumberNodes.java b/src/test/java/com/fasterxml/jackson/databind/node/TestNumberNodes.java
index f5b71c4..62610f0 100644
--- a/src/test/java/com/fasterxml/jackson/databind/node/TestNumberNodes.java
+++ b/src/test/java/com/fasterxml/jackson/databind/node/TestNumberNodes.java
@@ -196,11 +196,9 @@
 
     public void testDecimalNodeEqualsHashCode()
     {
-        /*
-         * We want DecimalNodes with equivalent _numeric_ values to be equal;
-         * this is not the case for BigDecimal where "1.0" and "1" are not
-         * equal!
-         */
+        // We want DecimalNodes with equivalent _numeric_ values to be equal;
+        // this is not the case for BigDecimal where "1.0" and "1" are not
+        // equal!
         BigDecimal b1 = BigDecimal.ONE;
         BigDecimal b2 = new BigDecimal("1.0");
         BigDecimal b3 = new BigDecimal("0.01e2");
@@ -236,8 +234,6 @@
         assertEquals(1L, n.longValue());
         assertEquals(BigInteger.ONE, n.bigIntegerValue());
         assertEquals("1", n.asText());
-        
-        // 1.6:
         assertNodeNumbers(n, 1, 1.0);
 
         BigInteger maxLong = BigInteger.valueOf(Long.MAX_VALUE);
@@ -284,7 +280,7 @@
         assertEquals("100", mapper.writeValueAsString(tree));
     }
 
-    // Related to [Issue#333]
+    // Related to [databind#333]
     public void testCanonicalNumbers() throws Exception
     {
         JsonNodeFactory f = new JsonNodeFactory();
diff --git a/src/test/java/com/fasterxml/jackson/databind/node/TestTreeDeserialization.java b/src/test/java/com/fasterxml/jackson/databind/node/TestTreeDeserialization.java
index 0c88cdc..5435b6d 100644
--- a/src/test/java/com/fasterxml/jackson/databind/node/TestTreeDeserialization.java
+++ b/src/test/java/com/fasterxml/jackson/databind/node/TestTreeDeserialization.java
@@ -20,6 +20,14 @@
         public void setNode(JsonNode n) { _node = n; }
     }
 
+    final static class CovarianceBean {
+        ObjectNode _object;
+        ArrayNode _array;
+
+        public void setObject(ObjectNode n) { _object = n; }
+        public void setArray(ArrayNode n) { _array = n; }
+    }
+
     /*
     /**********************************************************
     /* Unit tests
@@ -97,7 +105,7 @@
         assertNotNull(value);
     }
 
-    // Issue#186
+    // [databind#186]
     public void testNullHandling() throws Exception
     {
         // First, a stand-alone null
@@ -117,14 +125,6 @@
         assertTrue(n.isNull());
     }
 
-    final static class CovarianceBean {
-        ObjectNode _object;
-        ArrayNode _array;
-
-        public void setObject(ObjectNode n) { _object = n; }
-        public void setArray(ArrayNode n) { _array = n; }
-    }
-
     public void testNullHandlingCovariance() throws Exception
     {
         String JSON = "{\"object\" : null, \"array\" : null }";
diff --git a/src/test/java/com/fasterxml/jackson/databind/objectid/Objecid1083Test.java b/src/test/java/com/fasterxml/jackson/databind/objectid/Objecid1083Test.java
deleted file mode 100644
index 9bc5850..0000000
--- a/src/test/java/com/fasterxml/jackson/databind/objectid/Objecid1083Test.java
+++ /dev/null
@@ -1,43 +0,0 @@
-package com.fasterxml.jackson.databind.objectid;
-
-import java.util.*;
-
-import com.fasterxml.jackson.annotation.*;
-
-import com.fasterxml.jackson.databind.*;
-
-public class Objecid1083Test extends BaseMapTest
-{
-    public static class JsonRoot {
-        public final List<JsonSchema> schemas = new ArrayList<JsonSchema>();
-      }
-
-      @JsonTypeInfo(
-          use = JsonTypeInfo.Id.NAME,
-          property = "type",
-          defaultImpl = JsonMapSchema.class)
-      @JsonSubTypes({
-          @JsonSubTypes.Type(value = JsonMapSchema.class, name = "map"),
-          @JsonSubTypes.Type(value = JsonJdbcSchema.class, name = "jdbc") })
-      public static abstract class JsonSchema {
-        public String name;
-      }
-
-      static class JsonMapSchema extends JsonSchema { }
-
-      static class JsonJdbcSchema extends JsonSchema { }
-
-      /*
-      /*****************************************************
-      /* Unit tests, external id deserialization
-      /*****************************************************
-       */
-
-      public void testSimple() throws Exception {
-          final ObjectMapper mapper = new ObjectMapper();
-          final String json = aposToQuotes("{'schemas': [{\n"
-              + "  'name': 'FoodMart'\n"
-              + "}]}\n");
-          mapper.readValue(json, JsonRoot.class);
-      }
-}
diff --git a/src/test/java/com/fasterxml/jackson/databind/objectid/ObjectIdReordering1388Test.java b/src/test/java/com/fasterxml/jackson/databind/objectid/ObjectIdReordering1388Test.java
new file mode 100644
index 0000000..3555aeb
--- /dev/null
+++ b/src/test/java/com/fasterxml/jackson/databind/objectid/ObjectIdReordering1388Test.java
@@ -0,0 +1,92 @@
+package com.fasterxml.jackson.databind.objectid;
+
+import java.util.*;
+
+import com.fasterxml.jackson.annotation.*;
+import com.fasterxml.jackson.core.type.TypeReference;
+import com.fasterxml.jackson.databind.*;
+
+public class ObjectIdReordering1388Test extends BaseMapTest
+{
+    @JsonIdentityInfo(generator = ObjectIdGenerators.IntSequenceGenerator.class)
+    public static class NamedThing {
+        private final UUID id;
+        private final String name;
+
+        @JsonCreator
+        public NamedThing(@JsonProperty("id") UUID id, @JsonProperty("name") String name) {
+            this.id = id;
+            this.name = name;
+        }
+
+        public UUID getId() {
+            return id;
+        }
+
+        public String getName() {
+            return name;
+        }
+
+        @Override
+        public boolean equals(Object o) {
+            if (this == o) return true;
+            if (o == null || getClass() != o.getClass()) return false;
+            NamedThing that = (NamedThing) o;
+            return that.id.equals(id) && that.name.equals(name);
+        }
+
+        @Override
+        public int hashCode() {
+            return name.hashCode();
+        }
+    }
+
+
+    public void testDeserializationFinalClassJSOG() throws Exception
+    {
+        final ObjectMapper mapper = new ObjectMapper();
+        final UUID id = UUID.fromString("a59aa02c-fe3c-43f8-9b5a-5fe01878a818");
+        final NamedThing thing = new NamedThing(id, "Hello");
+
+        final TypeReference<?> namedThingListType = new TypeReference<List<NamedThing>>() { };
+
+        {
+            final String jsog = mapper.writeValueAsString(Arrays.asList(thing, thing, thing));
+            final List<NamedThing> list = mapper.readValue(jsog, namedThingListType);
+            _assertAllSame(list);
+            // this is the jsog representation of the list of 3 of the same item
+            assertTrue(jsog.equals("[{\"@id\":1,\"id\":\"a59aa02c-fe3c-43f8-9b5a-5fe01878a818\",\"name\":\"Hello\"},1,1]"));
+        }
+
+        // now move it around it have forward references
+        // this works
+        {
+            final String json = "[1,1,{\"@id\":1,\"id\":\"a59aa02c-fe3c-43f8-9b5a-5fe01878a818\",\"name\":\"Hello\"}]";
+            final List<NamedThing> forward = mapper.readValue(json, namedThingListType);
+            _assertAllSame(forward);
+        }
+
+        // next, move @id to between properties
+        {
+            final String json = aposToQuotes("[{'id':'a59aa02c-fe3c-43f8-9b5a-5fe01878a818','@id':1,'name':'Hello'}, 1, 1]");
+            final List<NamedThing> forward = mapper.readValue(json, namedThingListType);
+            _assertAllSame(forward);
+        }
+
+        // and last, move @id to be not the first key in the object
+        {
+            final String json = aposToQuotes("[{'id':'a59aa02c-fe3c-43f8-9b5a-5fe01878a818','name':'Hello','@id':1}, 1, 1]");
+            final List<NamedThing> forward = mapper.readValue(json, namedThingListType);
+            _assertAllSame(forward);
+        }
+    }
+
+    private void _assertAllSame(List<?> entries) {
+        Object first = entries.get(0);
+        for (int i = 0, end = entries.size(); i < end; ++i) {
+            if (first != entries.get(i)) {
+                fail("Mismatch: entry #"+i+" not same as #0");
+            }
+        }
+    }
+}
diff --git a/src/test/java/com/fasterxml/jackson/databind/objectid/ObjectWithCreator1261Test.java b/src/test/java/com/fasterxml/jackson/databind/objectid/ObjectWithCreator1261Test.java
new file mode 100644
index 0000000..e673d73
--- /dev/null
+++ b/src/test/java/com/fasterxml/jackson/databind/objectid/ObjectWithCreator1261Test.java
@@ -0,0 +1,107 @@
+package com.fasterxml.jackson.databind.objectid;
+
+import java.util.*;
+
+import com.fasterxml.jackson.annotation.*;
+import com.fasterxml.jackson.databind.*;
+
+public class ObjectWithCreator1261Test
+    extends BaseMapTest
+{
+    static class Answer
+    {
+       public SortedMap<String, Parent> parents;
+
+       public Answer() {
+           parents = new TreeMap<String, Parent>();
+       }
+    }
+
+    @JsonIdentityInfo(generator = ObjectIdGenerators.IntSequenceGenerator.class, property = "@id")
+    static class Parent
+    {
+       public Map<String, Child> children;
+
+       @JsonIdentityReference(alwaysAsId = true)
+       public Child favoriteChild;
+
+       public String name;
+
+       protected Parent() { }
+       
+       public Parent(String name, boolean ignored) {
+           children = new TreeMap<String, Child>();
+           this.name = name;
+       }
+    }
+
+    @JsonInclude(JsonInclude.Include.NON_NULL)
+    @JsonIdentityInfo(generator = ObjectIdGenerators.IntSequenceGenerator.class, property = "@id")
+    static class Child
+    {
+        public String name;
+
+        @JsonIdentityReference(alwaysAsId = true)
+        public Parent parent;
+
+        @JsonIdentityReference(alwaysAsId = true)
+        public List<Parent> parentAsList;
+
+        public String someNullProperty;
+
+        protected Child() { }
+        
+        @JsonCreator
+        public Child(@JsonProperty("name") String name,
+              @JsonProperty("someNullProperty") String someNullProperty) {
+            this.name = name;
+            this.someNullProperty = someNullProperty;
+        }
+
+        public Child(String n) {
+            name = n;
+        }
+    }
+
+    public void testObjectIds1261() throws Exception
+    {
+         ObjectMapper mapper = new ObjectMapper();
+         mapper.enable(SerializationFeature.INDENT_OUTPUT);
+         mapper.enable(MapperFeature.SORT_PROPERTIES_ALPHABETICALLY);
+
+         Answer initialAnswer = createInitialAnswer();
+         String initialAnswerString = mapper.writeValueAsString(initialAnswer);
+// System.out.println("Initial answer:\n"+initialAnswerString);
+         JsonNode tree = mapper.readTree(initialAnswerString);
+         Answer deserializedAnswer = mapper.readValue(initialAnswerString,
+               Answer.class);
+         String reserializedAnswerString = mapper
+               .writeValueAsString(deserializedAnswer);
+         JsonNode newTree = mapper.readTree(reserializedAnswerString);
+         if (!tree.equals(newTree)) {
+                  fail("Original and recovered Json are different. Recovered = \n"
+                        + reserializedAnswerString + "\n");
+         }
+   }
+
+   private Answer createInitialAnswer() {
+      Answer answer = new Answer();
+      String child1Name = "child1";
+      String child2Name = "child2";
+      String parent1Name = "parent1";
+      String parent2Name = "parent2";
+      Parent parent1 = new Parent(parent1Name, false);
+      answer.parents.put(parent1Name, parent1);
+      Child child1 = new Child(child1Name);
+      child1.parent = parent1;
+      child1.parentAsList = Collections.singletonList(parent1);
+      Child child2 = new Child(child2Name);
+      Parent parent2 = new Parent(parent2Name, false);
+      child2.parent = parent2;
+      child2.parentAsList = Collections.singletonList(parent2);
+      parent1.children.put(child1Name, child1);
+      parent1.children.put(child2Name, child2);
+      answer.parents.put(parent2Name, parent2);
+      return answer;
+   }
+}
diff --git a/src/test/java/com/fasterxml/jackson/databind/objectid/TestObjectId.java b/src/test/java/com/fasterxml/jackson/databind/objectid/TestObjectId.java
index f66de3e..a51776c 100644
--- a/src/test/java/com/fasterxml/jackson/databind/objectid/TestObjectId.java
+++ b/src/test/java/com/fasterxml/jackson/databind/objectid/TestObjectId.java
@@ -102,6 +102,22 @@
         public Foo next;
     }
 
+    // for [databind#1083]
+    @JsonTypeInfo(
+            use = JsonTypeInfo.Id.NAME,
+            property = "type",
+            defaultImpl = JsonMapSchema.class)
+      @JsonSubTypes({
+            @JsonSubTypes.Type(value = JsonMapSchema.class, name = "map"),
+            @JsonSubTypes.Type(value = JsonJdbcSchema.class, name = "jdbc") })
+      public static abstract class JsonSchema {
+          public String name;
+    }
+
+    static class JsonMapSchema extends JsonSchema { }
+
+    static class JsonJdbcSchema extends JsonSchema { }
+
     /*
     /**********************************************************
     /* Test methods
@@ -171,5 +187,16 @@
         Foo second = (Foo) first.next;
         assertNotNull(second.ref);
         assertSame(first, second.ref);
-    }    
+    }
+
+    public static class JsonRoot {
+        public final List<JsonSchema> schemas = new ArrayList<JsonSchema>();
+    }
+
+    public void testWithFieldsInBaseClass1083() throws Exception {
+          final String json = aposToQuotes("{'schemas': [{\n"
+              + "  'name': 'FoodMart'\n"
+              + "}]}\n");
+          MAPPER.readValue(json, JsonRoot.class);
+    }
 }
diff --git a/src/test/java/com/fasterxml/jackson/failing/TestObjectIdWithInjectables538.java b/src/test/java/com/fasterxml/jackson/databind/objectid/TestObjectIdWithInjectables538.java
similarity index 92%
rename from src/test/java/com/fasterxml/jackson/failing/TestObjectIdWithInjectables538.java
rename to src/test/java/com/fasterxml/jackson/databind/objectid/TestObjectIdWithInjectables538.java
index d2a552d..9f94257 100644
--- a/src/test/java/com/fasterxml/jackson/failing/TestObjectIdWithInjectables538.java
+++ b/src/test/java/com/fasterxml/jackson/databind/objectid/TestObjectIdWithInjectables538.java
@@ -1,4 +1,4 @@
-package com.fasterxml.jackson.failing;
+package com.fasterxml.jackson.databind.objectid;
 
 import com.fasterxml.jackson.annotation.*;
 
@@ -18,6 +18,7 @@
     public static class B {
         public A a;
 
+        @JsonCreator
         public B(@JacksonInject("i2") String injected) {
         }
     } 
@@ -50,8 +51,8 @@
             throw new IllegalStateException("Failed to deserialize from JSON '"+json+"'", e);
         }
         assertNotNull(output);
-
         assertNotNull(output.b);
+        assertSame(output, output.b.a);
     }
 }
 
diff --git a/src/test/java/com/fasterxml/jackson/databind/seq/ObjectReaderTest.java b/src/test/java/com/fasterxml/jackson/databind/seq/ObjectReaderTest.java
index 232af3d..f64d50b 100644
--- a/src/test/java/com/fasterxml/jackson/databind/seq/ObjectReaderTest.java
+++ b/src/test/java/com/fasterxml/jackson/databind/seq/ObjectReaderTest.java
@@ -1,14 +1,17 @@
 package com.fasterxml.jackson.databind.seq;
 
+import java.util.Collections;
+import java.util.List;
 import java.util.Map;
 
+import com.fasterxml.jackson.core.FormatSchema;
+import com.fasterxml.jackson.core.JsonFactory;
 import com.fasterxml.jackson.core.JsonParser;
+import com.fasterxml.jackson.core.JsonPointer;
 import com.fasterxml.jackson.core.JsonProcessingException;
-import com.fasterxml.jackson.databind.BaseMapTest;
-import com.fasterxml.jackson.databind.JsonNode;
-import com.fasterxml.jackson.databind.MappingIterator;
-import com.fasterxml.jackson.databind.ObjectMapper;
-import com.fasterxml.jackson.databind.ObjectReader;
+import com.fasterxml.jackson.databind.*;
+import com.fasterxml.jackson.databind.cfg.ContextAttributes;
+import com.fasterxml.jackson.databind.node.JsonNodeFactory;
 
 public class ObjectReaderTest extends BaseMapTest
 {
@@ -18,6 +21,16 @@
         public Map<String, Object> name;
     }
 
+    public void testSimpleViaParser() throws Exception
+    {
+        final String JSON = "[1]";
+        JsonParser p = MAPPER.getFactory().createParser(JSON);
+        Object ob = MAPPER.readerFor(Object.class)
+                .readValue(p);
+        p.close();
+        assertTrue(ob instanceof List<?>);
+    }
+
     public void testParserFeatures() throws Exception
     {
         final String JSON = "[ /* foo */ 7 ]";
@@ -62,7 +75,7 @@
     public void testPointerLoadingAsJsonNode() throws Exception {
         final String source = "{\"foo\":{\"bar\":{\"caller\":{\"name\":{\"value\":1234}}}}}";
 
-        ObjectReader reader = MAPPER.readerFor(POJO.class).at("/foo/bar/caller");
+        ObjectReader reader = MAPPER.readerFor(POJO.class).at(JsonPointer.compile("/foo/bar/caller"));
 
         JsonNode node = reader.readTree(source);
         assertTrue(node.has("name"));
@@ -105,4 +118,85 @@
         assertFalse(itr.hasNext());
         itr.close();
     }
+
+    public void testNodeHandling() throws Exception
+    {
+        JsonNodeFactory nodes = new JsonNodeFactory(true);
+        ObjectReader r = MAPPER.reader().with(nodes);
+        assertTrue(r.createArrayNode().isArray());
+        assertTrue(r.createObjectNode().isObject());
+    }
+
+    public void testSettings() throws Exception
+    {
+        ObjectReader r = MAPPER.reader();
+        assertSame(MAPPER.getFactory(), r.getFactory());
+
+        JsonFactory f = new JsonFactory();
+        r = r.with(f);
+        assertSame(f, r.getFactory());
+
+        assertNotNull(r.getTypeFactory());
+        assertNull(r.getInjectableValues());
+
+        r = r.withAttributes(Collections.emptyMap());
+        ContextAttributes attrs = r.getAttributes();
+        assertNotNull(attrs);
+        assertNull(attrs.getAttribute("abc"));
+
+        r = r.forType(MAPPER.constructType(String.class));
+        r = r.withRootName(PropertyName.construct("foo"));
+
+        r = r.withoutFeatures(DeserializationFeature.FAIL_ON_IGNORED_PROPERTIES,
+                DeserializationFeature.FAIL_ON_INVALID_SUBTYPE);
+        assertFalse(r.isEnabled(DeserializationFeature.FAIL_ON_IGNORED_PROPERTIES));
+        assertFalse(r.isEnabled(DeserializationFeature.FAIL_ON_INVALID_SUBTYPE));
+        r = r.withFeatures(DeserializationFeature.FAIL_ON_IGNORED_PROPERTIES,
+                DeserializationFeature.FAIL_ON_INVALID_SUBTYPE);
+        assertTrue(r.isEnabled(DeserializationFeature.FAIL_ON_IGNORED_PROPERTIES));
+        assertTrue(r.isEnabled(DeserializationFeature.FAIL_ON_INVALID_SUBTYPE));
+    }
+
+    public void testNoPrefetch() throws Exception
+    {
+        ObjectReader r = MAPPER.reader()
+                .without(DeserializationFeature.EAGER_DESERIALIZER_FETCH);
+        Number n = r.forType(Integer.class).readValue("123 ");
+        assertEquals(Integer.valueOf(123), n);
+    }
+
+    /*
+    /**********************************************************
+    /* Test methods, failures
+    /**********************************************************
+     */
+
+    public void testMissingType() throws Exception
+    {
+        ObjectReader r = MAPPER.reader();
+        try {
+            r.readValue("1");
+            fail("Should not pass");
+        } catch (JsonMappingException e) {
+            verifyException(e, "No value type configured");
+        }
+    }
+
+    public void testSchema() throws Exception
+    {
+        ObjectReader r = MAPPER.readerFor(String.class);
+        
+        // Ok to try to set `null` schema, always:
+        r = r.with((FormatSchema) null);
+
+        try {
+            // but not schema that doesn't match format (no schema exists for json)
+            r = r.with(new BogusSchema())
+                .readValue(quote("foo"));
+            
+            fail("Should not pass");
+        } catch (IllegalArgumentException e) {
+            verifyException(e, "Can not use FormatSchema");
+        }
+    }
 }
diff --git a/src/test/java/com/fasterxml/jackson/databind/seq/ObjectWriterTest.java b/src/test/java/com/fasterxml/jackson/databind/seq/ObjectWriterTest.java
index f3334c5..b4cc2a8 100644
--- a/src/test/java/com/fasterxml/jackson/databind/seq/ObjectWriterTest.java
+++ b/src/test/java/com/fasterxml/jackson/databind/seq/ObjectWriterTest.java
@@ -1,12 +1,15 @@
 package com.fasterxml.jackson.databind.seq;
 
+import java.io.ByteArrayOutputStream;
+import java.io.Closeable;
+import java.io.IOException;
 import java.util.*;
 
 import com.fasterxml.jackson.annotation.JsonTypeInfo;
 import com.fasterxml.jackson.annotation.JsonTypeName;
 
 import com.fasterxml.jackson.core.*;
-
+import com.fasterxml.jackson.core.io.SerializedString;
 import com.fasterxml.jackson.databind.*;
 import com.fasterxml.jackson.databind.node.ObjectNode;
 
@@ -17,6 +20,18 @@
 public class ObjectWriterTest
     extends BaseMapTest
 {
+    static class CloseableValue implements Closeable
+    {
+        public int x;
+
+        public boolean closed;
+        
+        @Override
+        public void close() throws IOException {
+            closed = true;
+        }
+    }
+
     final ObjectMapper MAPPER = new ObjectMapper();
 
     @JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "type")
@@ -36,13 +51,13 @@
         
         public ImplB(int v) { b = v; }
     }
-    
+
     /*
     /**********************************************************
-    /* Test methods
+    /* Test methods, normal operation
     /**********************************************************
      */
-    
+
     public void testPrettyPrinter() throws Exception
     {
         ObjectWriter writer = MAPPER.writer();
@@ -103,4 +118,84 @@
         json = writer.writeValueAsString(new ImplB(-5));
         assertEquals(aposToQuotes("{'type':'B','b':-5}"), json);
     }
+
+    public void testCanSerialize() throws Exception
+    {
+        assertTrue(MAPPER.writer().canSerialize(String.class));
+        assertTrue(MAPPER.writer().canSerialize(String.class, null));
+    }
+
+    public void testNoPrefetch() throws Exception
+    {
+        ObjectWriter w = MAPPER.writer()
+                .without(SerializationFeature.EAGER_SERIALIZER_FETCH);
+        ByteArrayOutputStream out = new ByteArrayOutputStream();
+        w.writeValue(out, Integer.valueOf(3));
+        out.close();
+        assertEquals("3", out.toString("UTF-8"));
+    }
+
+    public void testWithCloseCloseable() throws Exception
+    {
+        ObjectWriter w = MAPPER.writer()
+                .with(SerializationFeature.CLOSE_CLOSEABLE);
+        assertTrue(w.isEnabled(SerializationFeature.CLOSE_CLOSEABLE));
+        CloseableValue input = new CloseableValue();
+        assertFalse(input.closed);
+        byte[] json = w.writeValueAsBytes(input);
+        assertNotNull(json);
+        assertTrue(input.closed);
+        input.close();
+    }
+
+    public void testSettings() throws Exception
+    {
+        ObjectWriter w = MAPPER.writer();
+        assertFalse(w.isEnabled(MapperFeature.ACCEPT_CASE_INSENSITIVE_PROPERTIES));
+        assertFalse(w.isEnabled(JsonGenerator.Feature.STRICT_DUPLICATE_DETECTION));
+        assertSame(MAPPER.getFactory(), w.getFactory());
+        assertFalse(w.hasPrefetchedSerializer());
+        assertNotNull(w.getTypeFactory());
+
+        JsonFactory f = new JsonFactory();
+        w = w.with(f);
+        assertSame(f, w.getFactory());
+
+        w = w.withView(String.class);
+        w = w.withAttributes(Collections.emptyMap());
+        w = w.withAttribute("a", "b");
+        assertEquals("b", w.getAttributes().getAttribute("a"));
+        w = w.withoutAttribute("a");
+        assertNull(w.getAttributes().getAttribute("a"));
+        w = w.withRootValueSeparator(new SerializedString(","));
+    }
+
+    /*
+    /**********************************************************
+    /* Test methods, failures
+    /**********************************************************
+     */
+
+    public void testArgumentChecking() throws Exception
+    {
+        final ObjectWriter w = MAPPER.writer();
+        try {
+            w.acceptJsonFormatVisitor((JavaType) null, null);
+            fail("Should not pass");
+        } catch (IllegalArgumentException e) {
+            verifyException(e, "type must be provided");
+        }
+    }
+
+    public void testSchema() throws Exception
+    {
+        try {
+            MAPPER.writerFor(String.class)
+                .with(new BogusSchema())
+                .writeValueAsBytes("foo");
+            fail("Should not pass");
+        } catch (IllegalArgumentException e) {
+            verifyException(e, "Can not use FormatSchema");
+        }
+    }
 }
diff --git a/src/test/java/com/fasterxml/jackson/databind/seq/SequenceWriterTest.java b/src/test/java/com/fasterxml/jackson/databind/seq/SequenceWriterTest.java
index 301e94c..676383f 100644
--- a/src/test/java/com/fasterxml/jackson/databind/seq/SequenceWriterTest.java
+++ b/src/test/java/com/fasterxml/jackson/databind/seq/SequenceWriterTest.java
@@ -1,10 +1,12 @@
 package com.fasterxml.jackson.databind.seq;
 
 import java.io.StringWriter;
-import java.util.Arrays;
+import java.util.*;
 
 import com.fasterxml.jackson.annotation.JsonTypeInfo;
 import com.fasterxml.jackson.annotation.JsonTypeName;
+import com.fasterxml.jackson.core.JsonGenerator;
+import com.fasterxml.jackson.core.io.SerializedString;
 import com.fasterxml.jackson.databind.*;
 
 public class SequenceWriterTest extends BaseMapTest
@@ -40,7 +42,7 @@
         
         public ImplB(int v) { b = v; }
     }
-    
+
     /*
     /**********************************************************
     /* Test methods, simple writes
@@ -57,13 +59,25 @@
         SequenceWriter w = WRITER
                 .writeValues(strw);
         w.write(new Bean(13))
-        .write(new Bean(-6))
-        .writeAll(new Bean[] { new Bean(3), new Bean(1) })
-        .writeAll(Arrays.asList(new Bean(5), new Bean(7)))
+            .write(new Bean(-6))
+            .writeAll(new Bean[] { new Bean(3), new Bean(1) })
+            .writeAll(Arrays.asList(new Bean(5), new Bean(7)))
         ;
         w.close();
         assertEquals(aposToQuotes("{'a':13}\n{'a':-6}\n{'a':3}\n{'a':1}\n{'a':5}\n{'a':7}"),
                 strw.toString());
+
+        strw = new StringWriter();
+        JsonGenerator gen = WRITER.getFactory().createGenerator(strw);
+        w = WRITER
+                .withRootValueSeparator(new SerializedString("/"))
+                .writeValues(gen);
+        w.write(new Bean(1))
+            .write(new Bean(2));
+        w.close();
+        gen.close();
+        assertEquals(aposToQuotes("{'a':1}/{'a':2}"),
+                strw.toString());
     }
 
     public void testSimpleArray() throws Exception
@@ -71,11 +85,23 @@
         StringWriter strw = new StringWriter();
         SequenceWriter w = WRITER.writeValuesAsArray(strw);
         w.write(new Bean(1))
-        .write(new Bean(2))
-        .writeAll(new Bean[] { new Bean(-7), new Bean(2) });
+            .write(new Bean(2))
+            .writeAll(new Bean[] { new Bean(-7), new Bean(2) });
         w.close();
         assertEquals(aposToQuotes("[{'a':1},{'a':2},{'a':-7},{'a':2}]"),
                 strw.toString());
+
+        strw = new StringWriter();
+        JsonGenerator gen = WRITER.getFactory().createGenerator(strw);
+        w = WRITER.writeValuesAsArray(gen);
+        Collection<Bean> bean = Collections.singleton(new Bean(3));
+        w.write(new Bean(1))
+            .write(null)
+            .writeAll((Iterable<Bean>) bean);
+        w.close();
+        gen.close();
+        assertEquals(aposToQuotes("[{'a':1},null,{'a':3}]"),
+                strw.toString());
     }
 
     /*
diff --git a/src/test/java/com/fasterxml/jackson/databind/ser/DateSerializationTest.java b/src/test/java/com/fasterxml/jackson/databind/ser/DateSerializationTest.java
index 682da99..aff0b09 100644
--- a/src/test/java/com/fasterxml/jackson/databind/ser/DateSerializationTest.java
+++ b/src/test/java/com/fasterxml/jackson/databind/ser/DateSerializationTest.java
@@ -306,5 +306,13 @@
         json = mapper.writeValueAsString(new DateAsDefaultBeanWithTimezone(0L));
         assertEquals(aposToQuotes("{'date':'1970-01-01T01:00:00.000+0100'}"), json);
     }
-}
 
+    // [databind#1648]: contextual default format should be used
+    public void testFormatWithoutPattern() throws Exception
+    {
+        ObjectMapper mapper = new ObjectMapper();
+        mapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd'X'HH:mm:ss"));
+        String json = mapper.writeValueAsString(new DateAsDefaultBeanWithTimezone(0L));
+        assertEquals(aposToQuotes("{'date':'1970-01-01X01:00:00'}"), json);
+    }
+}
diff --git a/src/test/java/com/fasterxml/jackson/databind/ser/KeySerializers1679Test.java b/src/test/java/com/fasterxml/jackson/databind/ser/KeySerializers1679Test.java
new file mode 100644
index 0000000..ea7e600
--- /dev/null
+++ b/src/test/java/com/fasterxml/jackson/databind/ser/KeySerializers1679Test.java
@@ -0,0 +1,25 @@
+package com.fasterxml.jackson.databind.ser;
+
+import java.util.*;
+
+import com.fasterxml.jackson.databind.*;
+
+public class KeySerializers1679Test extends BaseMapTest
+{
+    /*
+    /**********************************************************
+    /* Unit tests
+    /**********************************************************
+     */
+
+    private final ObjectMapper MAPPER = new ObjectMapper();
+
+    // [databind#1679]
+    public void testRecursion1679() throws Exception
+    {
+        Map<Object, Object> objectMap = new HashMap<Object, Object>();
+        objectMap.put(new Object(), "foo");
+        String json = MAPPER.writeValueAsString(objectMap);
+        assertNotNull(json);
+    }
+}
diff --git a/src/test/java/com/fasterxml/jackson/databind/ser/NumberSerTest.java b/src/test/java/com/fasterxml/jackson/databind/ser/NumberSerTest.java
index c0870be..7d573d6 100644
--- a/src/test/java/com/fasterxml/jackson/databind/ser/NumberSerTest.java
+++ b/src/test/java/com/fasterxml/jackson/databind/ser/NumberSerTest.java
@@ -15,6 +15,12 @@
 {
     private final ObjectMapper MAPPER = objectMapper();
 
+    static class IntWrapper {
+        public int i;
+
+        public IntWrapper(int value) { i = value; }
+    }
+    
     static class IntAsString {
         @JsonFormat(shape=JsonFormat.Shape.STRING)
         @JsonProperty("value")
@@ -72,4 +78,13 @@
         assertEquals(aposToQuotes("{'value':'4'}"), MAPPER.writeValueAsString(new LongAsString()));
         assertEquals(aposToQuotes("{'value':'-0.5'}"), MAPPER.writeValueAsString(new DoubleAsString()));
     }
+
+    public void testConfigOverridesForNumbers() throws Exception
+    {
+        ObjectMapper mapper = new ObjectMapper();
+        mapper.configOverride(Integer.TYPE) // for `int`
+            .setFormat(JsonFormat.Value.forShape(JsonFormat.Shape.STRING));
+        assertEquals(aposToQuotes("{'i':'3'}"),
+                mapper.writeValueAsString(new IntWrapper(3)));
+    }
 }
diff --git a/src/test/java/com/fasterxml/jackson/databind/ser/TestFeatures.java b/src/test/java/com/fasterxml/jackson/databind/ser/SerializationFeaturesTest.java
similarity index 91%
rename from src/test/java/com/fasterxml/jackson/databind/ser/TestFeatures.java
rename to src/test/java/com/fasterxml/jackson/databind/ser/SerializationFeaturesTest.java
index 3a6e151..e408561 100644
--- a/src/test/java/com/fasterxml/jackson/databind/ser/TestFeatures.java
+++ b/src/test/java/com/fasterxml/jackson/databind/ser/SerializationFeaturesTest.java
@@ -3,25 +3,21 @@
 import java.io.*;
 import java.util.*;
 
-import com.fasterxml.jackson.core.JsonGenerator;
-import com.fasterxml.jackson.databind.*;
-import com.fasterxml.jackson.databind.introspect.BeanPropertyDefinition;
 import com.fasterxml.jackson.annotation.*;
 import com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility;
 
+import com.fasterxml.jackson.core.JsonGenerator;
+
+import com.fasterxml.jackson.databind.*;
+import com.fasterxml.jackson.databind.introspect.BeanPropertyDefinition;
+
 /**
- * Unit tests for checking whether JsonSerializerFactory.Feature
- * configuration works
+ * Unit tests for checking handling of some of {@link MapperFeature}s
+ * and {@link SerializationFeature}s for serialization.
  */
-public class TestFeatures
+public class SerializationFeaturesTest
     extends BaseMapTest
 {
-    /*
-    /**********************************************************
-    /* Helper classes
-    /**********************************************************
-     */
-
     /**
      * Class with one explicitly defined getter, one name-based
      * auto-detectable getter.
@@ -86,7 +82,19 @@
         
         public StringListBean(Collection<String> v) { values = v; }
     }
-    
+
+    static class TCls {
+        @JsonProperty("groupname")
+        private String groupname;
+
+        public void setName(String str) {
+            this.groupname = str;
+        }
+        public String getName() {
+            return groupname;
+        }
+    }
+
     /*
     /**********************************************************
     /* Test methods
@@ -193,49 +201,47 @@
         assertTrue(mapper.getSerializationConfig().isEnabled(SerializationFeature.FLUSH_AFTER_WRITE_VALUE));
         // default is to flush after writeValue()
         StringWriter sw = new StringWriter();
-        JsonGenerator jgen = mapper.getFactory().createGenerator(sw);
-        mapper.writeValue(jgen, Integer.valueOf(13));
+        JsonGenerator g = mapper.getFactory().createGenerator(sw);
+        mapper.writeValue(g, Integer.valueOf(13));
         assertEquals("13", sw.toString());
-        jgen.close();
+        g.close();
 
         // ditto with ObjectWriter
         sw = new StringWriter();
-        jgen = mapper.getFactory().createGenerator(sw);
+        g = mapper.getFactory().createGenerator(sw);
         ObjectWriter ow = mapper.writer();
-        ow.writeValue(jgen, Integer.valueOf(99));
+        ow.writeValue(g, Integer.valueOf(99));
         assertEquals("99", sw.toString());
-        jgen.close();
+        g.close();
     }
 
-    // Test for [JACKSON-401]
     public void testFlushingNotAutomatic() throws IOException
     {
         // but should not occur if configured otherwise
         ObjectMapper mapper = new ObjectMapper();
         mapper.configure(SerializationFeature.FLUSH_AFTER_WRITE_VALUE, false);
         StringWriter sw = new StringWriter();
-        JsonGenerator jgen = mapper.getFactory().createGenerator(sw);
+        JsonGenerator g = mapper.getFactory().createGenerator(sw);
 
-        mapper.writeValue(jgen, Integer.valueOf(13));
+        mapper.writeValue(g, Integer.valueOf(13));
         // no flushing now:
         assertEquals("", sw.toString());
         // except when actually flushing
-        jgen.flush();
+        g.flush();
         assertEquals("13", sw.toString());
-        jgen.close();
+        g.close();
         // Also, same should happen with ObjectWriter
         sw = new StringWriter();
-        jgen = mapper.getFactory().createGenerator(sw);
+        g = mapper.getFactory().createGenerator(sw);
         ObjectWriter ow = mapper.writer();
-        ow.writeValue(jgen, Integer.valueOf(99));
+        ow.writeValue(g, Integer.valueOf(99));
         assertEquals("", sw.toString());
         // except when actually flushing
-        jgen.flush();
+        g.flush();
         assertEquals("99", sw.toString());
-        jgen.close();
+        g.close();
     }
 
-    // Test for [JACKSON-805]
     public void testSingleElementCollections() throws IOException
     {
         final ObjectWriter writer = objectWriter().with(SerializationFeature.WRITE_SINGLE_ELEM_ARRAYS_UNWRAPPED);
@@ -265,19 +271,6 @@
         assertEquals("true", writer.writeValueAsString(new Boolean[] { Boolean.TRUE }));
         assertEquals("3", writer.writeValueAsString(new int[] { 3 }));
         assertEquals(quote("foo"), writer.writeValueAsString(new String[] { "foo" }));
-        
-    }
-
-    static class TCls {
-        @JsonProperty("groupname")
-        private String groupname;
-
-        public void setName(String str) {
-            this.groupname = str;
-        }
-        public String getName() {
-            return groupname;
-        }
     }
 
     public void testVisibilityFeatures() throws Exception
diff --git a/src/test/java/com/fasterxml/jackson/databind/ser/TestEnumSerialization.java b/src/test/java/com/fasterxml/jackson/databind/ser/TestEnumSerialization.java
index e13f3ea..d2120b9 100644
--- a/src/test/java/com/fasterxml/jackson/databind/ser/TestEnumSerialization.java
+++ b/src/test/java/com/fasterxml/jackson/databind/ser/TestEnumSerialization.java
@@ -4,7 +4,6 @@
 import java.util.*;
 
 import com.fasterxml.jackson.annotation.*;
-import com.fasterxml.jackson.annotation.JsonFormat.Shape;
 
 import com.fasterxml.jackson.core.*;
 import com.fasterxml.jackson.databind.*;
@@ -114,32 +113,6 @@
         protected String key;
         OK(String key) { this.key = key; }
     }
-    
-    // Types for [https://github.com/FasterXML/jackson-databind/issues/24]
-    // (Enums as JSON Objects)
-
-    @JsonFormat(shape=JsonFormat.Shape.OBJECT)
-    static enum PoNUM {
-        A("a1"), B("b2");
-
-        @JsonProperty
-        protected final String value;
-        
-        private PoNUM(String v) { value = v; }
-
-        public String getValue() { return value; }
-    }
-
-    static class PoNUMContainer {
-        @JsonFormat(shape=Shape.NUMBER)
-        public OK text = OK.V1;
-    }
-    
-    @JsonFormat(shape=JsonFormat.Shape.ARRAY) // alias for 'number', as of 2.5
-    static enum PoAsArray
-    {
-        A, B;
-    }
 
     @SuppressWarnings({ "rawtypes", "serial" })
     static class LowerCasingEnumSerializer extends StdSerializer<Enum>
@@ -152,19 +125,6 @@
         }
     }
 
-    // for [databind#572]
-    static class PoOverrideAsString
-    {
-        @JsonFormat(shape=Shape.STRING)
-        public PoNUM value = PoNUM.B;
-    }
-
-    static class PoOverrideAsNumber
-    {
-        @JsonFormat(shape=Shape.NUMBER)
-        public PoNUM value = PoNUM.B;
-    }
-
     static enum MyEnum594 {
         VALUE_WITH_A_REALLY_LONG_NAME_HERE("longValue");
 
@@ -321,11 +281,17 @@
         String json = MAPPER.writeValueAsString(bean);
         assertEquals("{\"map\":{\"B\":3}}", json);
 
-        ObjectMapper m2 = new ObjectMapper();
         // but can change
-        m2.enable(SerializationFeature.WRITE_ENUMS_USING_TO_STRING);
-        json = m2.writeValueAsString(bean);
+        json = MAPPER.writer()
+                .with(SerializationFeature.WRITE_ENUMS_USING_TO_STRING)
+                .writeValueAsString(bean);
         assertEquals("{\"map\":{\"b\":3}}", json);
+
+        // [databind#1570]
+        json = MAPPER.writer()
+                .with(SerializationFeature.WRITE_ENUMS_USING_INDEX)
+                .writeValueAsString(bean);
+        assertEquals(aposToQuotes("{'map':{'"+TestEnum.B.ordinal()+"':3}}"), json);
     }
 
     public void testAsIndex() throws Exception
@@ -348,22 +314,6 @@
         assertEquals(quote("V2"), MAPPER.writeValueAsString(NOT_OK2.V2));
     }
 
-    // Tests for [issue#24]
-
-    public void testEnumAsObjectValid() throws Exception {
-        assertEquals("{\"value\":\"a1\"}", MAPPER.writeValueAsString(PoNUM.A));
-    }
-
-    public void testEnumAsIndexViaAnnotations() throws Exception {
-        assertEquals("{\"text\":0}", MAPPER.writeValueAsString(new PoNUMContainer()));
-    }
-
-    // As of 2.5, use of Shape.ARRAY is legal alias for "write as number"
-    public void testEnumAsObjectBroken() throws Exception
-    {
-        assertEquals("0", MAPPER.writeValueAsString(PoAsArray.A));
-    }
-    
     // [Issue#227]
     public void testGenericEnumSerializer() throws Exception
     {
@@ -375,15 +325,6 @@
         assertEquals(quote("b"), m.writeValueAsString(TestEnum.B));
     }
 
-    // [databind#572]
-    public void testOverrideEnumAsString() throws Exception {
-        assertEquals("{\"value\":\"B\"}", MAPPER.writeValueAsString(new PoOverrideAsString()));
-    }
-
-    public void testOverrideEnumAsNumber() throws Exception {
-        assertEquals("{\"value\":1}", MAPPER.writeValueAsString(new PoOverrideAsNumber()));
-    }
-
     // [databind#594]
     public void testJsonValueForEnumMapKey() throws Exception {
         assertEquals(aposToQuotes("{'stuff':{'longValue':'foo'}}"),
@@ -412,7 +353,7 @@
         m.put(LC749Enum.A, "value");
         assertEquals("{\"A\":\"value\"}", w.writeValueAsString(m));
     }
-    
+
     public void testEnumMapSerEnableToString() throws Exception {
         final ObjectMapper mapper = new ObjectMapper();
         ObjectWriter w = mapper.writer().with(SerializationFeature.WRITE_ENUMS_USING_TO_STRING);
@@ -426,6 +367,13 @@
         assertEquals(quote("aleph"), MAPPER.writeValueAsString(EnumWithJsonProperty.A));
     }
 
+    // [databind#1535]
+    public void testEnumKeysWithJsonProperty() throws Exception {
+        Map<EnumWithJsonProperty,Integer> input = new HashMap<EnumWithJsonProperty,Integer>();
+        input.put(EnumWithJsonProperty.A, 13);
+        assertEquals(aposToQuotes("{'aleph':13}"), MAPPER.writeValueAsString(input));
+    }
+
     // [databind#1322]
     public void testEnumsWithJsonPropertyInSet() throws Exception
     {
diff --git a/src/test/java/com/fasterxml/jackson/databind/ser/TestExceptionSerialization.java b/src/test/java/com/fasterxml/jackson/databind/ser/TestExceptionSerialization.java
deleted file mode 100644
index f056ab2..0000000
--- a/src/test/java/com/fasterxml/jackson/databind/ser/TestExceptionSerialization.java
+++ /dev/null
@@ -1,42 +0,0 @@
-package com.fasterxml.jackson.databind.ser;
-
-import java.util.*;
-
-import com.fasterxml.jackson.databind.*;
-
-/**
- * Unit tests for verifying that simple exceptions can be serialized.
- */
-public class TestExceptionSerialization
-    extends BaseMapTest
-{
-    /*
-    /**********************************************************
-    /* Tests
-    /**********************************************************
-     */
-
-    public void testSimple() throws Exception
-    {
-        ObjectMapper mapper = new ObjectMapper();
-        String TEST = "test exception";
-        Map<String,Object> result = writeAndMap(mapper, new Exception(TEST));
-        // JDK 7 has introduced a new property 'suppressed' to Throwable
-        Object ob = result.get("suppressed");
-        if (ob != null) {
-            assertEquals(5, result.size());
-        } else {
-            assertEquals(4, result.size());
-        }
-
-        assertEquals(TEST, result.get("message"));
-        assertNull(result.get("cause"));
-        assertEquals(TEST, result.get("localizedMessage"));
-
-        // hmmh. what should we get for stack traces?
-        Object traces = result.get("stackTrace");
-        if (!(traces instanceof List<?>)) {
-            fail("Expected a List for exception member 'stackTrace', got: "+traces);
-        }
-    }
-}
diff --git a/src/test/java/com/fasterxml/jackson/databind/ser/TestJsonValue.java b/src/test/java/com/fasterxml/jackson/databind/ser/TestJsonValue.java
index fedf8d6..4b5b4d6 100644
--- a/src/test/java/com/fasterxml/jackson/databind/ser/TestJsonValue.java
+++ b/src/test/java/com/fasterxml/jackson/databind/ser/TestJsonValue.java
@@ -120,10 +120,11 @@
         External(Internal e) { i = e.value; }
     }
 
-    // [Issue#167]
+    // [databind#167]
     
     @JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "boingo")
-    @JsonSubTypes(value = {@JsonSubTypes.Type(name = "boopsy", value = AdditionInterfaceImpl.class) })
+    @JsonSubTypes(value = {@JsonSubTypes.Type(name = "boopsy", value = AdditionInterfaceImpl.class)
+    })
     static interface AdditionInterface
     {
         public int add(int in);
@@ -148,25 +149,6 @@
 	      return in + toAdd;
 	    }
     }
-	
-    public static class NegatingAdditionInterface implements AdditionInterface
-    {
-	    final AdditionInterface delegate;
-	
-	    public NegatingAdditionInterface(AdditionInterface delegate) {
-	        this.delegate = delegate;
-	    }
-	
-	    @Override
-	    public int add(int in) {
-	        return delegate.add(-in);
-	    }
-	
-	    @JsonValue
-	    public AdditionInterface getDelegate() {
-	        return delegate;
-	    }
-    }
 
     static class Bean838 {
         @JsonValue
@@ -258,13 +240,6 @@
 	    String json = MAPPER.writeValueAsString(adder);
 	    assertEquals("{\"boingo\":\"boopsy\",\"toAdd\":1}", json);
 	    assertEquals(2, MAPPER.readValue(json, AdditionInterface.class).add(1));
-	
-	    adder = new NegatingAdditionInterface(adder);
-	    assertEquals(0, adder.add(1));
-	    json = MAPPER.writeValueAsString(adder);
-
-	    assertEquals("{\"boingo\":\"boopsy\",\"toAdd\":1}", json);
-	    assertEquals(2, MAPPER.readValue(json, AdditionInterface.class).add(1));
     }
 
     public void testJsonValueWithCustomOverride() throws Exception
diff --git a/src/test/java/com/fasterxml/jackson/databind/ser/TestMapSerialization.java b/src/test/java/com/fasterxml/jackson/databind/ser/TestMapSerialization.java
index 2aa5ff0..a220237 100644
--- a/src/test/java/com/fasterxml/jackson/databind/ser/TestMapSerialization.java
+++ b/src/test/java/com/fasterxml/jackson/databind/ser/TestMapSerialization.java
@@ -3,6 +3,7 @@
 import java.io.*;
 import java.util.*;
 import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentSkipListMap;
 
 import com.fasterxml.jackson.annotation.*;
 import com.fasterxml.jackson.annotation.JsonTypeInfo.Id;
@@ -176,7 +177,7 @@
         assertEquals("{\"DEFAULT:a\":\"b\"}", m.writeValueAsString(map));
     }
 
-    // [JACKSON-636]: sort Map entries by key
+    // sort Map entries by key
     public void testOrderByKey() throws IOException
     {
         ObjectMapper m = new ObjectMapper();
@@ -187,7 +188,25 @@
         // by default, no (re)ordering:
         assertEquals("{\"b\":3,\"a\":6}", m.writeValueAsString(map));
         // but can be changed
-        assertEquals("{\"a\":6,\"b\":3}", m.writer(SerializationFeature.ORDER_MAP_ENTRIES_BY_KEYS).writeValueAsString(map));
+        ObjectWriter sortingW =  m.writer(SerializationFeature.ORDER_MAP_ENTRIES_BY_KEYS);
+        assertEquals("{\"a\":6,\"b\":3}", sortingW.writeValueAsString(map));
+    }
+
+    // related to [databind#1411]
+    public void testOrderByWithNulls() throws IOException
+    {
+        ObjectWriter sortingW = MAPPER.writer(SerializationFeature.ORDER_MAP_ENTRIES_BY_KEYS);
+        // 16-Oct-2016, tatu: but mind the null key, if any
+        Map<String,Integer> mapWithNullKey = new LinkedHashMap<String,Integer>();
+        mapWithNullKey.put(null, 1);
+        mapWithNullKey.put("b", 2);
+        // 16-Oct-2016, tatu: By default, null keys are not accepted...
+        try {
+            /*String json =*/ sortingW.writeValueAsString(mapWithNullKey);
+            //assertEquals(aposToQuotes("{'':1,'b':2}"), json);
+        } catch (JsonMappingException e) {
+            verifyException(e, "Null key for a Map not allowed");
+        }
     }
 
     // [Databind#335]
@@ -266,4 +285,29 @@
         String json = mapper.writeValueAsString(map);
         assertEquals("{\"@class\":\"java.util.HashMap\",\"NULL\":null}", json);
     }
+
+    // [databind#1513]
+    public void testConcurrentMaps() throws Exception
+    {
+        final ObjectWriter w = MAPPER.writer(SerializationFeature.ORDER_MAP_ENTRIES_BY_KEYS);
+
+        Map<String,String> input = new ConcurrentSkipListMap<String,String>();
+        input.put("x", "y");
+        input.put("a", "b");
+        String json = w.writeValueAsString(input);
+        assertEquals(aposToQuotes("{'a':'b','x':'y'}"), json);
+
+        input = new ConcurrentHashMap<String,String>();
+        input.put("x", "y");
+        input.put("a", "b");
+        json = w.writeValueAsString(input);
+        assertEquals(aposToQuotes("{'a':'b','x':'y'}"), json);
+
+        // One more: while not technically concurrent map at all, exhibits same issue
+        input = new Hashtable<String,String>();
+        input.put("x", "y");
+        input.put("a", "b");
+        json = w.writeValueAsString(input);
+        assertEquals(aposToQuotes("{'a':'b','x':'y'}"), json);
+    }
 }
diff --git a/src/test/java/com/fasterxml/jackson/databind/ser/TestRootType.java b/src/test/java/com/fasterxml/jackson/databind/ser/TestRootType.java
index 9665bad..0795bfe 100644
--- a/src/test/java/com/fasterxml/jackson/databind/ser/TestRootType.java
+++ b/src/test/java/com/fasterxml/jackson/databind/ser/TestRootType.java
@@ -140,9 +140,16 @@
         } catch (JsonProcessingException e) {
             verifyException(e, "Incompatible types");
         }
+
+        // and also with alternate output method
+        try {
+            w.writeValueAsBytes(bean);
+            fail("Should have failed due to incompatible type");
+        } catch (JsonProcessingException e) {
+            verifyException(e, "Incompatible types");
+        }
     }
-    
-    // [JACKSON-398]
+
     public void testJackson398() throws Exception
     {
         ObjectMapper mapper = objectMapper();
diff --git a/src/test/java/com/fasterxml/jackson/databind/struct/EmptyArrayAsNullTest.java b/src/test/java/com/fasterxml/jackson/databind/struct/EmptyArrayAsNullTest.java
new file mode 100644
index 0000000..5199545
--- /dev/null
+++ b/src/test/java/com/fasterxml/jackson/databind/struct/EmptyArrayAsNullTest.java
@@ -0,0 +1,156 @@
+package com.fasterxml.jackson.databind.struct;
+
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.EnumMap;
+import java.util.Map;
+import java.util.UUID;
+
+import com.fasterxml.jackson.core.type.TypeReference;
+import com.fasterxml.jackson.databind.*;
+
+/**
+ * Tests to verify implementation of [databind#540]; also for
+ * follow up work of:
+ *
+ * - [databind#994]
+ */
+public class EmptyArrayAsNullTest extends BaseMapTest
+{
+    private final ObjectMapper MAPPER = new ObjectMapper();
+    private final ObjectReader DEFAULT_READER = MAPPER.reader();
+    private final ObjectReader READER_WITH_ARRAYS = DEFAULT_READER
+            .with(DeserializationFeature.ACCEPT_EMPTY_ARRAY_AS_NULL_OBJECT);
+
+    static class Bean {
+        public String a = "foo";
+    }
+
+    final static String EMPTY_ARRAY = "  [\n]";
+
+    /*
+    /**********************************************************
+    /* Test methods, settings
+    /**********************************************************
+     */
+
+    public void testSettings() {
+        assertFalse(MAPPER.isEnabled(DeserializationFeature.ACCEPT_EMPTY_ARRAY_AS_NULL_OBJECT));
+        assertFalse(DEFAULT_READER.isEnabled(DeserializationFeature.ACCEPT_EMPTY_ARRAY_AS_NULL_OBJECT));
+        assertTrue(READER_WITH_ARRAYS.isEnabled(DeserializationFeature.ACCEPT_EMPTY_ARRAY_AS_NULL_OBJECT));
+    }
+
+    /*
+    /**********************************************************
+    /* Test methods, POJOs
+    /**********************************************************
+     */
+
+    // [databind#540]
+    public void testPOJOFromEmptyArray() throws Exception
+    {
+        // first, verify default settings which do not accept empty Array
+        try {
+            DEFAULT_READER.forType(Bean.class)
+                .readValue(EMPTY_ARRAY);
+            fail("Should not accept Empty Array for POJO by default");
+        } catch (JsonMappingException e) {
+            verifyException(e, "START_ARRAY token");
+            assertValidLocation(e.getLocation());
+        }
+
+        // should be ok to enable dynamically:
+        Bean result = READER_WITH_ARRAYS.forType(Bean.class)
+                .readValue(EMPTY_ARRAY);
+        assertNull(result);
+    }
+
+    /*
+    /**********************************************************
+    /* Test methods, Maps
+    /**********************************************************
+     */
+
+    public void testMapFromEmptyArray() throws Exception
+    {
+        // first, verify default settings which do not accept empty Array
+        try {
+            DEFAULT_READER.forType(Map.class)
+                .readValue(EMPTY_ARRAY);
+            fail("Should not accept Empty Array for Map by default");
+        } catch (JsonMappingException e) {
+            verifyException(e, "START_ARRAY token");
+        }
+        // should be ok to enable dynamically:
+        Map<?,?> result = READER_WITH_ARRAYS.forType(Map.class)
+                .readValue(EMPTY_ARRAY);
+        assertNull(result);
+    }
+
+    public void testEnumMapFromEmptyArray() throws Exception
+    {
+    
+        EnumMap<?,?> result2 = READER_WITH_ARRAYS.forType(new TypeReference<EnumMap<ABC,String>>() { })
+                .readValue(EMPTY_ARRAY);
+        assertNull(result2);
+    }
+
+    /*
+    /**********************************************************
+    /* Test methods, primitives/wrappers
+    /**********************************************************
+     */
+
+    public void testWrapperFromEmptyArray() throws Exception
+    {
+//        _testNullWrapper(Boolean.class);
+//        _testNullWrapper(Byte.class);
+        _testNullWrapper(Character.class);
+//        _testNullWrapper(Short.class);
+//        _testNullWrapper(Integer.class);
+//        _testNullWrapper(Long.class);
+//        _testNullWrapper(Float.class);
+//        _testNullWrapper(Double.class);
+    }
+
+    /*
+    /**********************************************************
+    /* Test methods, other
+    /**********************************************************
+     */
+
+    public void testNullStringFromEmptyArray() throws Exception {
+        _testNullWrapper(String.class);
+    }
+
+    public void testNullEnumFromEmptyArray() throws Exception {
+        _testNullWrapper(ABC.class);
+    }
+
+    public void testStdJdkTypesFromEmptyArray() throws Exception
+    {
+        _testNullWrapper(BigInteger.class);
+        _testNullWrapper(BigDecimal.class);
+
+        _testNullWrapper(UUID.class);
+
+        /*
+        _testNullWrapper(Date.class);
+        _testNullWrapper(Calendar.class);
+        */
+    }
+
+    /*
+    /**********************************************************
+    /* Helper methods
+    /**********************************************************
+     */
+    
+    private void _testNullWrapper(Class<?> cls) throws Exception
+    {
+        Object result = READER_WITH_ARRAYS.forType(cls).readValue(EMPTY_ARRAY);
+        assertNull(result);
+    }
+}
diff --git a/src/test/java/com/fasterxml/jackson/databind/struct/EnumFormatShapeTest.java b/src/test/java/com/fasterxml/jackson/databind/struct/EnumFormatShapeTest.java
new file mode 100644
index 0000000..8e7f13b
--- /dev/null
+++ b/src/test/java/com/fasterxml/jackson/databind/struct/EnumFormatShapeTest.java
@@ -0,0 +1,116 @@
+package com.fasterxml.jackson.databind.struct;
+
+import com.fasterxml.jackson.annotation.*;
+import com.fasterxml.jackson.annotation.JsonFormat.Shape;
+
+import com.fasterxml.jackson.databind.*;
+
+/**
+ * Unit tests for verifying serialization of simple basic non-structured
+ * types; primitives (and/or their wrappers), Strings.
+ */
+public class EnumFormatShapeTest
+    extends BaseMapTest
+{
+    @JsonFormat(shape=JsonFormat.Shape.OBJECT)
+    static enum PoNUM {
+        A("a1"), B("b2");
+
+        @JsonProperty
+        protected final String value;
+        
+        private PoNUM(String v) { value = v; }
+
+        public String getValue() { return value; }
+    }
+
+    static enum OK {
+        V1("v1");
+        protected String key;
+        OK(String key) { this.key = key; }
+    }
+
+    static class PoNUMContainer {
+        @JsonFormat(shape=Shape.NUMBER)
+        public OK text = OK.V1;
+    }
+    
+    @JsonFormat(shape=JsonFormat.Shape.ARRAY) // alias for 'number', as of 2.5
+    static enum PoAsArray
+    {
+        A, B;
+    }
+
+    // for [databind#572]
+    static class PoOverrideAsString
+    {
+        @JsonFormat(shape=Shape.STRING)
+        public PoNUM value = PoNUM.B;
+    }
+
+    static class PoOverrideAsNumber
+    {
+        @JsonFormat(shape=Shape.NUMBER)
+        public PoNUM value = PoNUM.B;
+    }
+
+    // for [databind#1543]
+    @JsonFormat(shape = JsonFormat.Shape.NUMBER_INT)
+    enum Color {
+        RED,
+        YELLOW,
+        GREEN
+    }
+
+    static class ColorWrapper {
+        public final Color color;
+
+        ColorWrapper(Color color) {
+            this.color = color;
+        }
+    }
+
+    /*
+    /**********************************************************
+    /* Tests
+    /**********************************************************
+     */
+
+    private final ObjectMapper MAPPER = new ObjectMapper();
+
+    // Tests for JsonFormat.shape
+
+    public void testEnumAsObjectValid() throws Exception {
+        assertEquals("{\"value\":\"a1\"}", MAPPER.writeValueAsString(PoNUM.A));
+    }
+
+    public void testEnumAsIndexViaAnnotations() throws Exception {
+        assertEquals("{\"text\":0}", MAPPER.writeValueAsString(new PoNUMContainer()));
+    }
+
+    // As of 2.5, use of Shape.ARRAY is legal alias for "write as number"
+    public void testEnumAsObjectBroken() throws Exception
+    {
+        assertEquals("0", MAPPER.writeValueAsString(PoAsArray.A));
+    }
+
+    // [databind#572]
+    public void testOverrideEnumAsString() throws Exception {
+        assertEquals("{\"value\":\"B\"}", MAPPER.writeValueAsString(new PoOverrideAsString()));
+    }
+
+    public void testOverrideEnumAsNumber() throws Exception {
+        assertEquals("{\"value\":1}", MAPPER.writeValueAsString(new PoOverrideAsNumber()));
+    }
+
+    // for [databind#1543]
+    public void testEnumValueAsNumber() throws Exception {
+        assertEquals(String.valueOf(Color.GREEN.ordinal()),
+                MAPPER.writeValueAsString(Color.GREEN));
+    }
+
+    public void testEnumPropertyAsNumber() throws Exception {
+        assertEquals(String.format(aposToQuotes("{'color':%s}"), Color.GREEN.ordinal()),
+                MAPPER.writeValueAsString(new ColorWrapper(Color.GREEN)));
+    }
+}
diff --git a/src/test/java/com/fasterxml/jackson/databind/struct/FormatFeaturesTest.java b/src/test/java/com/fasterxml/jackson/databind/struct/FormatFeaturesTest.java
index 3c3f642..87d5922 100644
--- a/src/test/java/com/fasterxml/jackson/databind/struct/FormatFeaturesTest.java
+++ b/src/test/java/com/fasterxml/jackson/databind/struct/FormatFeaturesTest.java
@@ -26,7 +26,7 @@
 
         public boolean[] bools = new boolean[] { true };
     }
-    
+
     @JsonPropertyOrder( { "strings", "ints", "bools", "enums" })
     static class WrapWriteWithCollections
     {
@@ -47,16 +47,23 @@
         public String[] values;
     }
 
+    static class StringArrayNotAnnoted {
+        public String[] values;
+
+        protected StringArrayNotAnnoted() { }
+        public StringArrayNotAnnoted(String ... v) { values = v; }
+    }
+    
     static class IntArrayWrapper {
         @JsonFormat(with = JsonFormat.Feature.ACCEPT_SINGLE_VALUE_AS_ARRAY)
         public int[] values;
     }
+
     static class LongArrayWrapper {
         @JsonFormat(with = JsonFormat.Feature.ACCEPT_SINGLE_VALUE_AS_ARRAY)
         public long[] values;
     }
 
-    
     static class StringListWrapper {
         @JsonFormat(with = JsonFormat.Feature.ACCEPT_SINGLE_VALUE_AS_ARRAY)
         public List<String> values;
@@ -82,6 +89,24 @@
         public String Name;
     }
 
+    static class CaseInsensitiveRoleWrapper
+    {
+        @JsonFormat(with={ JsonFormat.Feature.ACCEPT_CASE_INSENSITIVE_PROPERTIES })
+        public Role role;
+    }
+
+    static class SortedKeysMap {
+        @JsonFormat(with = JsonFormat.Feature.WRITE_SORTED_MAP_ENTRIES)
+        public Map<String,Integer> values = new LinkedHashMap<>();
+
+        protected SortedKeysMap() { }
+
+        public SortedKeysMap put(String key, int value) {
+            values.put(key, value);
+            return this;
+        }
+    }
+
     /*
     /**********************************************************
     /* Test methods, writing with single-element unwrapping
@@ -105,6 +130,13 @@
         assertEquals(aposToQuotes("{'strings':'a','ints':[1],'bools':[true]}"),
                 MAPPER.writer().without(SerializationFeature.WRITE_SINGLE_ELEM_ARRAYS_UNWRAPPED)
                 .writeValueAsString(new WrapWriteWithArrays()));
+
+        // And then without SerializationFeature but with config override:
+        ObjectMapper mapper = new ObjectMapper();
+        mapper.configOverride(String[].class).setFormat(JsonFormat.Value.empty()
+                .withFeature(JsonFormat.Feature.WRITE_SINGLE_ELEM_ARRAYS_UNWRAPPED));
+        assertEquals(aposToQuotes("{'values':'a'}"),
+                mapper.writeValueAsString(new StringArrayNotAnnoted("a")));
     }
 
     public void testWithCollectionTypes() throws Exception
@@ -137,6 +169,15 @@
         assertNotNull(result.values);
         assertEquals(1, result.values.length);
         assertEquals("first", result.values[0]);
+
+        // and then without annotation, but with global override
+        ObjectMapper mapper = new ObjectMapper();
+        mapper.configOverride(String[].class).setFormat(JsonFormat.Value.empty()
+                .withFeature(JsonFormat.Feature.ACCEPT_SINGLE_VALUE_AS_ARRAY));
+        StringArrayNotAnnoted result2 = mapper.readValue(json, StringArrayNotAnnoted.class);
+        assertNotNull(result2.values);
+        assertEquals(1, result2.values.length);
+        assertEquals("first", result2.values[0]);
     }
 
     public void testSingleIntArrayRead() throws Exception {
@@ -185,10 +226,29 @@
     }
 
     public void testSingleEnumSetRead() throws Exception {
-        String json = aposToQuotes("{ 'values': 'B' }");
-        EnumSetWrapper result = MAPPER.readValue(json, EnumSetWrapper.class);
+        EnumSetWrapper result = MAPPER.readValue(aposToQuotes("{ 'values': 'B' }"),
+                EnumSetWrapper.class);
         assertNotNull(result.values);
         assertEquals(1, result.values.size());
         assertEquals(ABC.B, result.values.iterator().next());
     }
+
+    // [databind#1232]: allow per-property case-insensitivity
+    public void testCaseInsensitive() throws Exception {
+        CaseInsensitiveRoleWrapper w = MAPPER.readValue
+                (aposToQuotes("{'role':{'id':'12','name':'Foo'}}"),
+                        CaseInsensitiveRoleWrapper.class);
+        assertNotNull(w);
+        assertEquals("12", w.role.ID);
+        assertEquals("Foo", w.role.Name);
+    }
+
+    // [databind#1232]: allow forcing sorting on Map keys
+    public void testOrderedMaps() throws Exception {
+        SortedKeysMap map = new SortedKeysMap()
+            .put("b", 2)
+            .put("a", 1);
+        assertEquals(aposToQuotes("{'values':{'a':1,'b':2}}"),
+                MAPPER.writeValueAsString(map));
+    }
 }
diff --git a/src/test/java/com/fasterxml/jackson/databind/struct/SingleValueAsArrayTest.java b/src/test/java/com/fasterxml/jackson/databind/struct/SingleValueAsArrayTest.java
new file mode 100644
index 0000000..1903b2e
--- /dev/null
+++ b/src/test/java/com/fasterxml/jackson/databind/struct/SingleValueAsArrayTest.java
@@ -0,0 +1,86 @@
+package com.fasterxml.jackson.databind.struct;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+import com.fasterxml.jackson.core.type.TypeReference;
+
+import com.fasterxml.jackson.databind.*;
+
+public class SingleValueAsArrayTest extends BaseMapTest
+{
+    private static final String JSON = "[{\"message\":\"messageHere\"}]";
+
+    static class Bean1421A
+    {
+        List<Messages> bs = Collections.emptyList();
+
+        @JsonCreator
+        Bean1421A(final List<Messages> bs)
+        {
+            this.bs = bs;
+        }
+    }
+
+    static class Messages
+    {
+        List<MessageWrapper> cs = Collections.emptyList();
+
+        @JsonCreator
+        Messages(final List<MessageWrapper> cs)
+        {
+            this.cs = cs;
+        }
+    }
+
+    static class MessageWrapper
+    {
+        String message;
+
+        @JsonCreator
+        MessageWrapper(@JsonProperty("message") String message)
+        {
+            this.message = message;
+        }
+    }
+
+    static class Bean1421B<T> {
+        T value;
+
+        @JsonCreator
+        public Bean1421B(T value) {
+            this.value = value;
+        }
+    }
+
+    /*
+    /**********************************************************
+    /* Unit tests
+    /**********************************************************
+     */
+    
+    private final ObjectMapper MAPPER = new ObjectMapper();
+    {
+        MAPPER.enable(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY);
+    }
+
+    public void testSuccessfulDeserializationOfObjectWithChainedArrayCreators() throws IOException
+    {
+        MAPPER.readValue(JSON, Bean1421A.class);
+    }
+
+    public void testWithSingleString() throws Exception {
+        ObjectMapper objectMapper = new ObjectMapper();
+        objectMapper.enable(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY);
+        Bean1421B<List<String>> a = objectMapper.readValue(quote("test2"),
+                new TypeReference<Bean1421B<List<String>>>() {});
+        List<String> expected = new ArrayList<>();
+        expected.add("test2");
+        assertEquals(expected, a.value);
+    }
+}
diff --git a/src/test/java/com/fasterxml/jackson/databind/struct/TestBackRefsWithPolymorphic.java b/src/test/java/com/fasterxml/jackson/databind/struct/TestBackRefsWithPolymorphic.java
index 6e631b7..33f3eca 100644
--- a/src/test/java/com/fasterxml/jackson/databind/struct/TestBackRefsWithPolymorphic.java
+++ b/src/test/java/com/fasterxml/jackson/databind/struct/TestBackRefsWithPolymorphic.java
@@ -12,33 +12,6 @@
 // Unit test for [JACKSON-890]
 public class TestBackRefsWithPolymorphic extends BaseMapTest
 {
-    private final String CLASS_NAME = getClass().getName();
-
-    // NOTE: order is arbitrary, test is fragile... has to work for now
-    private final String JSON =
-        "{\"@class\":\""+CLASS_NAME+"$PropertySheetImpl\",\"id\":0,\"properties\":{\"p1name\":{\"@class\":"
-            +"\"" +CLASS_NAME+ "$StringPropertyImpl\",\"id\":0,\"name\":\"p1name\",\"value\":\"p1value\"},"
-            +"\"p2name\":{\"@class\":\""+CLASS_NAME+"$StringPropertyImpl\",\"id\":0,"
-            +"\"name\":\"p2name\",\"value\":\"p2value\"}}}";
-
-    private final ObjectMapper MAPPER = new ObjectMapper();
-
-    public void testDeserialize() throws IOException
-    {
-        PropertySheet input = MAPPER.readValue(JSON, PropertySheet.class);
-        assertEquals(JSON, MAPPER.writeValueAsString(input));
-    }
-
-    public void testSerialize() throws IOException
-    {
-        PropertySheet sheet = new PropertySheetImpl();
-
-        sheet.addProperty(new StringPropertyImpl("p1name", "p1value"));
-        sheet.addProperty(new StringPropertyImpl("p2name", "p2value"));
-        String actual = MAPPER.writeValueAsString(sheet);
-        assertEquals(JSON, actual);
-    }
-
     @JsonPropertyOrder(alphabetic=true)
     interface Entity
     {
@@ -217,4 +190,36 @@
     }
 
     static class YetAnotherClass extends StringPropertyImpl { }
+
+    /*
+    /**********************************************************
+    /* Test methods
+    /**********************************************************
+     */
+
+    private final String CLASS_NAME = getClass().getName();
+    // NOTE: order is arbitrary, test is fragile... has to work for now
+    private final String JSON =
+        "{\"@class\":\""+CLASS_NAME+"$PropertySheetImpl\",\"id\":0,\"properties\":{\"p1name\":{\"@class\":"
+            +"\"" +CLASS_NAME+ "$StringPropertyImpl\",\"id\":0,\"name\":\"p1name\",\"value\":\"p1value\"},"
+            +"\"p2name\":{\"@class\":\""+CLASS_NAME+"$StringPropertyImpl\",\"id\":0,"
+            +"\"name\":\"p2name\",\"value\":\"p2value\"}}}";
+    
+    private final ObjectMapper MAPPER = new ObjectMapper();
+
+    public void testDeserialize() throws IOException
+    {
+        PropertySheet input = MAPPER.readValue(JSON, PropertySheet.class);
+        assertEquals(JSON, MAPPER.writeValueAsString(input));
+    }
+
+    public void testSerialize() throws IOException
+    {
+        PropertySheet sheet = new PropertySheetImpl();
+
+        sheet.addProperty(new StringPropertyImpl("p1name", "p1value"));
+        sheet.addProperty(new StringPropertyImpl("p2name", "p2value"));
+        String actual = MAPPER.writeValueAsString(sheet);
+        assertEquals(JSON, actual);
+    }
 }
diff --git a/src/test/java/com/fasterxml/jackson/databind/struct/TestFormatForCollections.java b/src/test/java/com/fasterxml/jackson/databind/struct/TestFormatForCollections.java
index 344f7e4..bd308b3 100644
--- a/src/test/java/com/fasterxml/jackson/databind/struct/TestFormatForCollections.java
+++ b/src/test/java/com/fasterxml/jackson/databind/struct/TestFormatForCollections.java
@@ -10,7 +10,7 @@
 
 public class TestFormatForCollections extends BaseMapTest
 {
-    // [issue#40]: Allow serialization 'as POJO' (resulting in JSON Object) 
+    // [databind#40]: Allow serialization 'as POJO' (resulting in JSON Object) 
     @JsonPropertyOrder({ "size", "value" })
     @JsonFormat(shape=Shape.OBJECT)
     @JsonIgnoreProperties({ "empty" }) // from 'isEmpty()'
diff --git a/src/test/java/com/fasterxml/jackson/databind/struct/TestPOJOAsArray.java b/src/test/java/com/fasterxml/jackson/databind/struct/TestPOJOAsArray.java
index 81cfa35..7e8f091 100644
--- a/src/test/java/com/fasterxml/jackson/databind/struct/TestPOJOAsArray.java
+++ b/src/test/java/com/fasterxml/jackson/databind/struct/TestPOJOAsArray.java
@@ -12,27 +12,38 @@
 
 public class TestPOJOAsArray extends BaseMapTest
 {
-    static class Pojo
+    static class PojoAsArrayWrapper
     {
         @JsonFormat(shape=JsonFormat.Shape.ARRAY)
-        public PojoValue value;
+        public PojoAsArray value;
 
-        public Pojo() { }
-        public Pojo(String name, int x, int y, boolean c) {
-            value = new PojoValue(name, x, y, c);
+        public PojoAsArrayWrapper() { }
+        public PojoAsArrayWrapper(String name, int x, int y, boolean c) {
+            value = new PojoAsArray(name, x, y, c);
         }
     }
 
+    @JsonPropertyOrder(alphabetic=true)
+    static class NonAnnotatedXY {
+        public int x, y;
+
+        public NonAnnotatedXY() { }
+        public NonAnnotatedXY(int x0, int y0) {
+            x = x0;
+            y = y0;
+        }
+    }
+    
     // note: must be serialized/deserialized alphabetically; fields NOT declared in that order
     @JsonPropertyOrder(alphabetic=true)
-    static class PojoValue
+    static class PojoAsArray
     {
         public int x, y;
         public String name;
         public boolean complete;
 
-        public PojoValue() { }
-        public PojoValue(String name, int x, int y, boolean c) {
+        public PojoAsArray() { }
+        public PojoAsArray(String name, int x, int y, boolean c) {
             this.name = name;
             this.x = x;
             this.y = y;
@@ -77,7 +88,6 @@
         public int y = 2;
     }
 
-    // for [JACKSON-805]
     @JsonFormat(shape=Shape.ARRAY)
     static class SingleBean {
         public String name = "foo";
@@ -115,7 +125,6 @@
         }
     }
 
-
     /*
     /*****************************************************
     /* Basic tests
@@ -130,7 +139,7 @@
     public void testReadSimplePropertyValue() throws Exception
     {
         String json = "{\"value\":[true,\"Foobar\",42,13]}";
-        Pojo p = MAPPER.readValue(json, Pojo.class);
+        PojoAsArrayWrapper p = MAPPER.readValue(json, PojoAsArrayWrapper.class);
         assertNotNull(p.value);
         assertTrue(p.value.complete);
         assertEquals("Foobar", p.value.name);
@@ -156,7 +165,7 @@
      */
     public void testWriteSimplePropertyValue() throws Exception
     {
-        String json = MAPPER.writeValueAsString(new Pojo("Foobar", 42, 13, true));
+        String json = MAPPER.writeValueAsString(new PojoAsArrayWrapper("Foobar", 42, 13, true));
         // will have wrapper POJO, then POJO-as-array..
         assertEquals("{\"value\":[true,\"Foobar\",42,13]}", json);
     }
@@ -215,6 +224,8 @@
         ObjectMapper mapper2 = new ObjectMapper();
         mapper2.setAnnotationIntrospector(new ForceArraysIntrospector());
         assertEquals("[[1,2]]", mapper2.writeValueAsString(new A()));
+
+        // and allow reading back, too
     }
 
     public void testWithMaps() throws Exception
@@ -237,4 +248,18 @@
         assertEquals(2, value._a);
         assertEquals(1, value._b);
     }
+
+    public void testWithConfigOverrides() throws Exception
+    {
+        ObjectMapper mapper = new ObjectMapper();
+        mapper.configOverride(NonAnnotatedXY.class)
+            .setFormat(JsonFormat.Value.forShape(JsonFormat.Shape.ARRAY));
+        String json = mapper.writeValueAsString(new NonAnnotatedXY(2, 3));
+        assertEquals("[2,3]", json);
+
+        // also, read it back
+        NonAnnotatedXY result = mapper.readValue(json, NonAnnotatedXY.class);
+        assertNotNull(result);
+        assertEquals(3, result.y);
+    }
 }
diff --git a/src/test/java/com/fasterxml/jackson/databind/struct/TestUnwrapped.java b/src/test/java/com/fasterxml/jackson/databind/struct/TestUnwrapped.java
index 59ac4e0..dd373f6 100644
--- a/src/test/java/com/fasterxml/jackson/databind/struct/TestUnwrapped.java
+++ b/src/test/java/com/fasterxml/jackson/databind/struct/TestUnwrapped.java
@@ -97,6 +97,20 @@
         private Inner inner;
     }
 
+    // [databind#1493]: case-insensitive handling
+    static class Person {
+        @JsonUnwrapped(prefix = "businessAddress.")
+        public Address businessAddress;
+    }
+
+    static class Address {
+        public String street;
+        public String addon;
+        public String zip;
+        public String town;    
+        public String country;
+    }
+
     /*
     /**********************************************************
     /* Tests, serialization
@@ -192,45 +206,13 @@
         assertTrue(actual.contains("Zebra"));
         assertFalse(actual.contains("inner"));
     }
-    
-    // 22-Apr-2013, tatu: Commented out as it can't be simply fixed; requires implementing
-    //    deep-update/merge. But leaving here to help with that effort, if/when it proceeds.
 
-    /*
-    // [databind#211]: Actually just variant of #160
-
-    static class Issue211Bean {
-        public String test1;
-
-        public String test2;
-        @JsonUnwrapped
-        public Issue211Unwrapped unwrapped;
-    }
-
-    static class Issue211Unwrapped {
-        public String test3;
-        public String test4;
-    }
-
-    public void testIssue211() throws Exception
+    // [databind#1493]: case-insensitive handling
+    public void testCaseInsensitiveUnwrap() throws Exception
     {
-         Issue211Bean bean = new Issue211Bean();
-         bean.test1 = "Field 1";
-         bean.test2 = "Field 2";
-         Issue211Unwrapped tJackson2 = new Issue211Unwrapped();
-         tJackson2.test3 = "Field 3";
-         tJackson2.test4 = "Field 4";
-         bean.unwrapped = tJackson2;
- 
-         final String JSON = "{\"test1\": \"Field 1 merged\", \"test3\": \"Field 3 merged\"}";
-         ObjectMapper o = new ObjectMapper();
-         Issue211Bean result = o.readerForUpdating(bean).withType(Issue211Bean.class).readValue(JSON);
-         assertSame(bean, result);
-         assertEquals("Field 1 merged", result.test1);
-         assertEquals("Field 2", result.test2);
-         assertNotNull(result.unwrapped);
-         assertEquals("Field 3 merged", result.unwrapped.test3);
-         assertEquals("Field 4", result.unwrapped.test4);
+        ObjectMapper mapper = new ObjectMapper();
+        mapper.enable(MapperFeature.ACCEPT_CASE_INSENSITIVE_PROPERTIES);
+        Person p = mapper.readValue("{ }", Person.class);
+        assertNotNull(p);
     }
-    */
 }
diff --git a/src/test/java/com/fasterxml/jackson/databind/type/NestedTypes1604Test.java b/src/test/java/com/fasterxml/jackson/databind/type/NestedTypes1604Test.java
new file mode 100644
index 0000000..753f017
--- /dev/null
+++ b/src/test/java/com/fasterxml/jackson/databind/type/NestedTypes1604Test.java
@@ -0,0 +1,130 @@
+package com.fasterxml.jackson.databind.type;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import com.fasterxml.jackson.databind.*;
+
+// for [databind#1604]
+public class NestedTypes1604Test extends BaseMapTest
+{
+    public static class Data<T> {
+        private T data;
+
+        public Data(T data) {
+             this.data = data;
+        }
+
+        public T getData() {
+             return data;
+        }
+
+        public static <T> Data<List<T>> of(List<T> data) {
+             return new DataList<>(data);
+        }
+
+        public static <T> Data<List<T>> ofRefined(List<T> data) {
+            return new RefinedDataList<>(data);
+        }
+
+        public static <T> Data<List<T>> ofSneaky(List<T> data) {
+            return new SneakyDataList<String,T>(data);
+        }
+    }
+
+    public static class DataList<T> extends Data<List<T>> {
+        public DataList(List<T> data) {
+            super(data);
+        }
+    }
+
+    // And then add one level between types
+    public static class RefinedDataList<T> extends DataList<T> {
+        public RefinedDataList(List<T> data) {
+            super(data);
+        }
+    }
+
+    // And/or add another type parameter that is not relevant (less common
+    // but potential concern)
+    public static class SneakyDataList<BOGUS,T> extends Data<List<T>> {
+        public SneakyDataList(List<T> data) {
+            super(data);
+        }
+    }
+
+    public static class Inner {
+        private int index;
+
+        public Inner(int index) {
+             this.index = index;
+        }
+
+        public int getIndex() {
+             return index;
+        }
+    }
+
+    public static class BadOuter {
+        private Data<List<Inner>> inner;
+
+        public BadOuter(Data<List<Inner>> inner) {
+            this.inner = inner;
+        }
+
+        public Data<List<Inner>> getInner() {
+            return inner;
+        }
+    }
+
+    public static class GoodOuter {
+        private DataList<Inner> inner;
+
+        public GoodOuter(DataList<Inner> inner) {
+            this.inner = inner;
+        }
+
+        public DataList<Inner> getInner() {
+            return inner;
+        }
+    }
+
+    private final ObjectMapper objectMapper = new ObjectMapper();
+    
+    public void testIssue1604Simple() throws Exception
+    {
+        List<Inner> inners = new ArrayList<>();
+        for (int i = 0; i < 2; i++) {
+            inners.add(new Inner(i));
+        }
+        BadOuter badOuter = new BadOuter(Data.of(inners));
+//        GoodOuter goodOuter = new GoodOuter(new DataList<>(inners));
+//        String json = objectMapper.writeValueAsString(goodOuter);
+
+        // 11-Oct-2017, tatu: Fails with exception wrt type specialization
+        String json = objectMapper.writeValueAsString(badOuter);
+        assertNotNull(json);
+   }
+
+    public void testIssue1604Subtype() throws Exception
+    {
+        List<Inner> inners = new ArrayList<>();
+        for (int i = 0; i < 2; i++) {
+            inners.add(new Inner(i));
+        }
+        BadOuter badOuter = new BadOuter(Data.ofRefined(inners));
+        String json = objectMapper.writeValueAsString(badOuter);
+        assertNotNull(json);
+   }
+
+    public void testIssue1604Sneaky() throws Exception
+    {
+        List<Inner> inners = new ArrayList<>();
+        for (int i = 0; i < 2; i++) {
+            inners.add(new Inner(i));
+        }
+        BadOuter badOuter = new BadOuter(Data.ofSneaky(inners));
+        String json = objectMapper.writeValueAsString(badOuter);
+        assertNotNull(json);
+   }
+}
diff --git a/src/test/java/com/fasterxml/jackson/databind/type/RecursiveType1658Test.java b/src/test/java/com/fasterxml/jackson/databind/type/RecursiveType1658Test.java
new file mode 100644
index 0000000..c211cd9
--- /dev/null
+++ b/src/test/java/com/fasterxml/jackson/databind/type/RecursiveType1658Test.java
@@ -0,0 +1,45 @@
+package com.fasterxml.jackson.databind.type;
+
+import java.util.*;
+
+import com.fasterxml.jackson.annotation.JsonTypeInfo;
+import com.fasterxml.jackson.databind.*;
+import com.fasterxml.jackson.databind.jsontype.TypeResolverBuilder;
+import com.fasterxml.jackson.databind.jsontype.impl.StdTypeResolverBuilder;
+
+public class RecursiveType1658Test extends BaseMapTest
+{
+    @SuppressWarnings("serial")
+    static class Tree<T> extends HashMap<T, Tree<T>> // implements Serializable
+    {
+        public Tree() { }
+
+        public Tree(List<T> children) {
+            this();
+            for (final T t : children) {
+                this.put(t, new Tree<T>());
+            }
+        }
+
+        public List<Tree<T>> getLeafTrees() {
+            return null;
+        }
+    }
+
+    public void testRecursive1658() throws Exception
+    {
+        Tree<String> t = new Tree<String>(Arrays.asList("hello", "world"));
+        ObjectMapper mapper = new ObjectMapper();
+
+        final TypeResolverBuilder<?> typer = new StdTypeResolverBuilder()
+                .init(JsonTypeInfo.Id.CLASS, null)
+                .inclusion(JsonTypeInfo.As.PROPERTY);
+        mapper.setDefaultTyping(typer);
+
+        String res = mapper.writeValueAsString(t);
+
+        Tree<?> tRead = mapper.readValue(res, Tree.class);
+
+        assertNotNull(tRead);
+    }
+}
diff --git a/src/test/java/com/fasterxml/jackson/databind/type/RecursiveTypeTest.java b/src/test/java/com/fasterxml/jackson/databind/type/RecursiveTypeTest.java
index 57115cf..f0643af 100644
--- a/src/test/java/com/fasterxml/jackson/databind/type/RecursiveTypeTest.java
+++ b/src/test/java/com/fasterxml/jackson/databind/type/RecursiveTypeTest.java
@@ -13,6 +13,15 @@
  // for [databind#938]
     public static interface Ability<T> { }
 
+    // for [databind#1647]
+    static interface IFace<T> {}
+
+    // for [databind#1647]
+    static class Base implements IFace<Sub> { }
+
+    // for [databind#1647]
+    static class Sub extends Base { }
+
     public static final class ImmutablePair<L, R> implements Map.Entry<L, R>, Ability<ImmutablePair<L, R>> {
         public final L key;
         public final R value;
@@ -93,4 +102,14 @@
             fail("Description should contain 'recursive type', did not: "+desc);
         }
     }
+
+    // for [databind#1647]
+    public void testSuperClassWithReferencedJavaType() {
+        TypeFactory tf = objectMapper().getTypeFactory();
+        tf.constructType(Base.class); // must be constructed before sub to set the cache correctly
+        JavaType subType = tf.constructType(Sub.class);
+        // baseTypeFromSub should be a ResolvedRecursiveType in this test
+        JavaType baseTypeFromSub = subType.getSuperClass();
+        assertNotNull(baseTypeFromSub.getSuperClass());
+    }
 }
diff --git a/src/test/java/com/fasterxml/jackson/databind/type/TestJavaType.java b/src/test/java/com/fasterxml/jackson/databind/type/TestJavaType.java
index c773e83..91be3f7 100644
--- a/src/test/java/com/fasterxml/jackson/databind/type/TestJavaType.java
+++ b/src/test/java/com/fasterxml/jackson/databind/type/TestJavaType.java
@@ -36,6 +36,9 @@
         public Map<String,String> getMap();
     }
 
+    @SuppressWarnings("serial")
+    static class AtomicStringReference extends AtomicReference<String> { }
+    
     /*
     /**********************************************************
     /* Test methods
@@ -75,8 +78,11 @@
         assertFalse(baseType.isEnumType());
         assertFalse(baseType.isInterface());
         assertFalse(baseType.isPrimitive());
+        assertFalse(baseType.isReferenceType());
+        assertFalse(baseType.hasContentType());
 
         assertNull(baseType.getContentType());
+        assertNull(baseType.getKeyType());
         assertNull(baseType.getValueHandler());
     }
 
@@ -86,8 +92,12 @@
         JavaType arrayT = ArrayType.construct(tf.constructType(String.class), null);
         assertNotNull(arrayT);
         assertTrue(arrayT.isContainerType());
+        assertFalse(arrayT.isReferenceType());
+        assertTrue(arrayT.hasContentType());
 
         assertNotNull(arrayT.toString());
+        assertNotNull(arrayT.getContentType());
+        assertNull(arrayT.getKeyType());
 
         assertTrue(arrayT.equals(arrayT));
         assertFalse(arrayT.equals(null));
@@ -97,6 +107,23 @@
         assertFalse(arrayT.equals(ArrayType.construct(tf.constructType(Integer.class), null)));
     }
 
+    public void testMapType()
+    {
+        TypeFactory tf = TypeFactory.defaultInstance();
+        JavaType mapT = tf.constructType(HashMap.class);
+        assertTrue(mapT.isContainerType());
+        assertFalse(mapT.isReferenceType());
+        assertTrue(mapT.hasContentType());
+
+        assertNotNull(mapT.toString());
+        assertNotNull(mapT.getContentType());
+        assertNotNull(mapT.getKeyType());
+
+        assertTrue(mapT.equals(mapT));
+        assertFalse(mapT.equals(null));
+        assertFalse(mapT.equals("xyz"));
+    }
+    
     public void testEnumType()
     {
         TypeFactory tf = TypeFactory.defaultInstance();
@@ -147,4 +174,27 @@
         t  = tf.constructType(m.getGenericReturnType());
         assertEquals("Ljava/util/concurrent/atomic/AtomicReference<Ljava/lang/String;>;", t.getGenericSignature());
     }
+
+    public void testAnchorTypeForRefTypes() throws Exception
+    {
+        TypeFactory tf = TypeFactory.defaultInstance();
+        JavaType t  = tf.constructType(AtomicStringReference.class);
+        assertTrue(t.isReferenceType());
+        assertTrue(t.hasContentType());
+        ReferenceType rt = (ReferenceType) t;
+        assertFalse(rt.isAnchorType());
+        assertEquals(AtomicReference.class, rt.getAnchorType().getRawClass());
+    }
+
+    // for [databind#1290]
+    public void testObjectToReferenceSpecialization() throws Exception
+    {
+        TypeFactory tf = TypeFactory.defaultInstance();
+        JavaType base = tf.constructType(Object.class);
+        assertTrue(base.isJavaLangObject());
+
+        JavaType sub = tf.constructSpecializedType(base, AtomicReference.class);
+        assertEquals(AtomicReference.class, sub.getRawClass());
+        assertTrue(sub.isReferenceType());
+    }
 }
diff --git a/src/test/java/com/fasterxml/jackson/databind/type/TestTypeBindings.java b/src/test/java/com/fasterxml/jackson/databind/type/TestTypeBindings.java
index f2b9e4a..7af37e8 100644
--- a/src/test/java/com/fasterxml/jackson/databind/type/TestTypeBindings.java
+++ b/src/test/java/com/fasterxml/jackson/databind/type/TestTypeBindings.java
@@ -29,14 +29,17 @@
             }
         }
     }
-    
+
+    // for [databind#76]
+    @SuppressWarnings("serial")
+    static class HashTree<K, V> extends HashMap<K, HashTree<K, V>> { }
+
     /*
     /**********************************************************
     /* Test methods
     /**********************************************************
      */
 
-    // [JACKSON-677]
     public void testInnerType() throws Exception
     {
         TypeFactory tf = TypeFactory.defaultInstance();
@@ -49,4 +52,12 @@
         JavaType vt2 = valueType.getContentType();
         assertEquals(Object.class, vt2.getRawClass());
     }
+
+    // for [databind#76]
+    public void testRecursiveType()
+    {
+        TypeFactory tf = TypeFactory.defaultInstance();
+        JavaType type = tf.constructType(HashTree.class);
+        assertNotNull(type);
+    }
 }
diff --git a/src/test/java/com/fasterxml/jackson/databind/type/TestTypeFactory.java b/src/test/java/com/fasterxml/jackson/databind/type/TestTypeFactory.java
index e5183a0..ab0ff60 100644
--- a/src/test/java/com/fasterxml/jackson/databind/type/TestTypeFactory.java
+++ b/src/test/java/com/fasterxml/jackson/databind/type/TestTypeFactory.java
@@ -70,7 +70,11 @@
 
     static class CollectionLike<E> { }
     static class MapLike<K,V> { }
-    
+
+    static class Wrapper1297<T> {
+        public T content;
+    }
+
     /*
     /**********************************************************
     /* Unit tests
@@ -227,7 +231,42 @@
         assertEquals("java.util.EnumMap<com.fasterxml.jackson.databind.type.TestTypeFactory$EnumForCanonical,java.lang.String>",
                 can);
         assertEquals(t, tf.constructFromCanonical(can));
-        
+
+        // [databind#2109]: also ReferenceTypes
+        t = tf.constructType(new TypeReference<AtomicReference<Long>>() { });
+        can = t.toCanonical();
+        assertEquals("java.util.concurrent.atomic.AtomicReference<java.lang.Long>",
+                can);
+        assertEquals(t, tf.constructFromCanonical(can));
+
+        // [databind#1941]: allow "raw" types too
+        t = tf.constructFromCanonical("java.util.List");
+        assertEquals(List.class, t.getRawClass());
+        assertEquals(CollectionType.class, t.getClass());
+        // 01-Mar-2018, tatu: not 100% should we expect type parameters here...
+        //    But currently we do NOT get any
+        /*
+        assertEquals(1, t.containedTypeCount());
+        assertEquals(Object.class, t.containedType(0).getRawClass());
+        */
+        assertEquals(Object.class, t.getContentType().getRawClass());
+        can = t.toCanonical();
+        assertEquals("java.util.List<java.lang.Object>", can);
+        assertEquals(t, tf.constructFromCanonical(can));
+    }
+
+    // [databind#1768]
+    @SuppressWarnings("serial")
+    public void testCanonicalWithSpaces()
+    {
+        TypeFactory tf = TypeFactory.defaultInstance();
+        Object objects = new TreeMap<Object, Object>() { }; // to get subtype
+        String reflectTypeName = objects.getClass().getGenericSuperclass().toString();
+        JavaType t1 = tf.constructType(objects.getClass().getGenericSuperclass());
+        // This will throw an Exception if you don't remove all white spaces from the String.
+        JavaType t2 = tf.constructFromCanonical(reflectTypeName);
+        assertNotNull(t2);
+        assertEquals(t2, t1);
     }
 
     /*
@@ -276,15 +315,9 @@
         assertEquals(Long.class, subtype.getContentType().getRawClass());
 
         // but with refinement, should have non-null super class
-        // 20-Oct-2015, tatu: For now refinement does not faithfully replicate the
-        //    structure, it only retains most important information. Here it means
-        //    that actually existing super-classes are skipped, and only original
-        //    type is linked as expected
-        /*
         JavaType superType = subtype.getSuperClass();
         assertNotNull(superType);
         assertEquals(AbstractList.class, superType.getRawClass());
-        */
     }
 
     /*
@@ -355,7 +388,6 @@
         //    that actually existing super-classes are skipped, and only original
         //    type is linked as expected
 
-        /*
         JavaType superType = subtype.getSuperClass();
         assertNotNull(superType);
         assertEquals(HashMap.class, superType.getRawClass());
@@ -363,7 +395,6 @@
         assertEquals(String.class, superType.getKeyType().getRawClass());
         assertEquals(List.class, superType.getContentType().getRawClass());
         assertEquals(Integer.class, superType.getContentType().getContentType().getRawClass());
-        */
     }
 
     public void testMapTypesRaw()
@@ -565,5 +596,14 @@
         tf.clearCache();
         assertEquals(0, tf._typeCache.size());
     }
+
+    // for [databind#1297]
+    public void testRawMapType()
+    {
+        TypeFactory tf = TypeFactory.defaultInstance().withModifier(null); // to get a new copy
+
+        JavaType type = tf.constructParametricType(Wrapper1297.class, Map.class);
+        assertNotNull(type);
+        assertEquals(Wrapper1297.class, type.getRawClass());
+    }
 }
-        
\ No newline at end of file
diff --git a/src/test/java/com/fasterxml/jackson/databind/type/TestTypeFactory1604.java b/src/test/java/com/fasterxml/jackson/databind/type/TestTypeFactory1604.java
new file mode 100644
index 0000000..6bfec7c
--- /dev/null
+++ b/src/test/java/com/fasterxml/jackson/databind/type/TestTypeFactory1604.java
@@ -0,0 +1,118 @@
+package com.fasterxml.jackson.databind.type;
+
+import java.util.*;
+
+import com.fasterxml.jackson.core.type.TypeReference;
+import com.fasterxml.jackson.databind.BaseMapTest;
+import com.fasterxml.jackson.databind.JavaType;
+import com.fasterxml.jackson.databind.type.TypeFactory;
+
+// for [databind#1604]
+public class TestTypeFactory1604 extends BaseMapTest
+{
+    static class Data1604<T> { }
+
+    static class DataList1604<T> extends Data1604<List<T>> { }
+
+    static class RefinedDataList1604<T> extends DataList1604<T> { }
+
+    public static class SneakyDataList1604<BOGUS,T> extends Data1604<List<T>> { }
+
+    static class TwoParam1604<KEY,VALUE> { }
+
+    static class SneakyTwoParam1604<V,K> extends TwoParam1604<K,List<V>> { }
+
+    public void testCustomTypesRefinedSimple()
+    {
+        TypeFactory tf = newTypeFactory();
+        JavaType base = tf.constructType(new TypeReference<Data1604<List<Long>>>() { });
+        assertEquals(Data1604.class, base.getRawClass());
+        assertEquals(1, base.containedTypeCount());
+        assertEquals(List.class, base.containedType(0).getRawClass());
+
+        JavaType subtype = tf.constructSpecializedType(base, DataList1604.class);
+        assertEquals(DataList1604.class, subtype.getRawClass());
+        assertEquals(1, subtype.containedTypeCount());
+        JavaType paramType = subtype.containedType(0);
+        assertEquals(Long.class, paramType.getRawClass());
+    }
+
+    public void testCustomTypesRefinedNested()
+    {
+        TypeFactory tf = newTypeFactory();
+        JavaType base = tf.constructType(new TypeReference<Data1604<List<Long>>>() { });
+        assertEquals(Data1604.class, base.getRawClass());
+
+        JavaType subtype = tf.constructSpecializedType(base, RefinedDataList1604.class);
+        assertEquals(RefinedDataList1604.class, subtype.getRawClass());
+        assertEquals(DataList1604.class, subtype.getSuperClass().getRawClass());
+
+        assertEquals(1, subtype.containedTypeCount());
+        JavaType paramType = subtype.containedType(0);
+        assertEquals(Long.class, paramType.getRawClass());
+    }
+
+    public void testCustomTypesRefinedSneaky()
+    {
+        TypeFactory tf = newTypeFactory();
+        JavaType base = tf.constructType(new TypeReference<Data1604<List<Long>>>() { });
+        assertEquals(Data1604.class, base.getRawClass());
+
+        JavaType subtype = tf.constructSpecializedType(base, SneakyDataList1604.class);
+        assertEquals(SneakyDataList1604.class, subtype.getRawClass());
+        assertEquals(2, subtype.containedTypeCount());
+        assertEquals(Long.class, subtype.containedType(1).getRawClass());
+        // first one, "bogus", has to be essentially "unknown"
+        assertEquals(Object.class, subtype.containedType(0).getRawClass());
+
+        // and have correct parent too
+        assertEquals(Data1604.class, subtype.getSuperClass().getRawClass());
+    }
+
+    public void testTwoParamSneakyCustom()
+    {
+        TypeFactory tf = newTypeFactory();
+        JavaType type = tf.constructType(new TypeReference<TwoParam1604<String,List<Long>>>() { });
+        assertEquals(TwoParam1604.class, type.getRawClass());
+        assertEquals(String.class, type.containedType(0).getRawClass());
+        JavaType ct = type.containedType(1);
+        assertEquals(List.class, ct.getRawClass());
+        assertEquals(Long.class, ct.getContentType().getRawClass());
+
+        JavaType subtype = tf.constructSpecializedType(type, SneakyTwoParam1604.class);
+        assertEquals(SneakyTwoParam1604.class, subtype.getRawClass());
+        assertEquals(TwoParam1604.class, subtype.getSuperClass().getRawClass());
+        assertEquals(2, subtype.containedTypeCount());
+
+        // should properly resolve type parameters despite sneaky switching, including "unwounding"
+        // `List` wrapper
+        JavaType first = subtype.containedType(0);
+        assertEquals(Long.class, first.getRawClass());
+        JavaType second = subtype.containedType(1);
+        assertEquals(String.class, second.getRawClass());
+    }
+
+    // Also: let's not allow mismatching binding
+    public void testErrorForMismatch()
+    {
+        TypeFactory tf = newTypeFactory();
+        
+        // NOTE: plain `String` NOT `List<String>`
+        JavaType base = tf.constructType(new TypeReference<Data1604<String>>() { });
+
+        try {
+            tf.constructSpecializedType(base, DataList1604.class);
+            fail("Should not pass");
+        } catch (IllegalArgumentException e) {
+            verifyException(e, "Failed to specialize");
+            verifyException(e, "Data1604");
+            verifyException(e, "DataList1604");
+        }
+    }
+    
+    /*
+    static class TwoParam1604<KEY,VALUE> { }
+
+    static class SneakyTwoParam1604<V,K> extends TwoParam1604<K,List<V>> { }
+     */
+}
diff --git a/src/test/java/com/fasterxml/jackson/databind/type/TestTypeFactoryWithRecursiveTypes.java b/src/test/java/com/fasterxml/jackson/databind/type/TestTypeFactoryWithRecursiveTypes.java
new file mode 100644
index 0000000..50c5249
--- /dev/null
+++ b/src/test/java/com/fasterxml/jackson/databind/type/TestTypeFactoryWithRecursiveTypes.java
@@ -0,0 +1,32 @@
+package com.fasterxml.jackson.databind.type;
+
+import java.io.IOException;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.databind.BaseMapTest;
+import com.fasterxml.jackson.databind.type.TypeFactory;
+
+
+// https://github.com/FasterXML/jackson-databind/issues/1647
+public class TestTypeFactoryWithRecursiveTypes extends BaseMapTest {
+
+    static interface IFace<T> {
+    }
+
+    static class Base implements IFace<Sub> {
+        @JsonProperty int base = 1;
+    }
+
+    static class Sub extends Base {
+        @JsonProperty int sub = 2;
+    }
+
+    public void testBasePropertiesIncludedWhenSerializingSubWhenSubTypeLoadedAfterBaseType() throws IOException {
+        TypeFactory tf = TypeFactory.defaultInstance();
+        tf.constructType(Base.class);
+        tf.constructType(Sub.class);
+        Sub sub = new Sub();
+        String serialized = objectMapper().writeValueAsString(sub);
+        assertEquals("{\"base\":1,\"sub\":2}", serialized);
+    }
+}
diff --git a/src/test/java/com/fasterxml/jackson/databind/util/JSONPObjectTest.java b/src/test/java/com/fasterxml/jackson/databind/util/JSONPObjectTest.java
new file mode 100644
index 0000000..032f40b
--- /dev/null
+++ b/src/test/java/com/fasterxml/jackson/databind/util/JSONPObjectTest.java
@@ -0,0 +1,37 @@
+package com.fasterxml.jackson.databind.util;
+
+import java.io.IOException;
+
+import com.fasterxml.jackson.databind.BaseMapTest;
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+public class JSONPObjectTest extends BaseMapTest {
+
+  private final String CALLBACK = "callback";
+  private final ObjectMapper MAPPER = new ObjectMapper();
+
+  /**
+   * Unit tests for checking that JSONP breaking characters U+2028 and U+2029 are escaped when creating a {@link JSONPObject}.
+   */
+
+  public void testU2028Escaped() throws IOException {
+    String containsU2028 = String.format("This string contains %c char", '\u2028');
+    JSONPObject jsonpObject = new JSONPObject(CALLBACK, containsU2028);
+    String valueAsString = MAPPER.writeValueAsString(jsonpObject);
+    assertFalse(valueAsString.contains("\u2028"));
+  }
+
+  public void testU2029Escaped() throws IOException {
+    String containsU2029 = String.format("This string contains %c char", '\u2029');
+    JSONPObject jsonpObject = new JSONPObject(CALLBACK, containsU2029);
+    String valueAsString = MAPPER.writeValueAsString(jsonpObject);
+    assertFalse(valueAsString.contains("\u2029"));
+  }
+
+  public void testU2030NotEscaped() throws IOException {
+    String containsU2030 = String.format("This string contains %c char", '\u2030');
+    JSONPObject jsonpObject = new JSONPObject(CALLBACK, containsU2030);
+    String valueAsString = MAPPER.writeValueAsString(jsonpObject);
+    assertTrue(valueAsString.contains("\u2030"));
+  }
+}
diff --git a/src/test/java/com/fasterxml/jackson/databind/util/TestTokenBuffer.java b/src/test/java/com/fasterxml/jackson/databind/util/TestTokenBuffer.java
index 4e14bbf..477301e 100644
--- a/src/test/java/com/fasterxml/jackson/databind/util/TestTokenBuffer.java
+++ b/src/test/java/com/fasterxml/jackson/databind/util/TestTokenBuffer.java
@@ -26,31 +26,46 @@
         TokenBuffer buf = new TokenBuffer(null, false); // no ObjectCodec
 
         // First, with empty buffer
-        JsonParser jp = buf.asParser();
-        assertNull(jp.getCurrentToken());
-        assertNull(jp.nextToken());
-        jp.close();
+        JsonParser p = buf.asParser();
+        assertNull(p.getCurrentToken());
+        assertNull(p.nextToken());
+        p.close();
 
         // Then with simple text
         buf.writeString("abc");
 
         // First, simple text
-        jp = buf.asParser();
-        assertNull(jp.getCurrentToken());
-        assertToken(JsonToken.VALUE_STRING, jp.nextToken());
-        assertEquals("abc", jp.getText());
-        assertNull(jp.nextToken());
-        jp.close();
+        p = buf.asParser();
+        assertNull(p.getCurrentToken());
+        assertToken(JsonToken.VALUE_STRING, p.nextToken());
+        assertEquals("abc", p.getText());
+        assertNull(p.nextToken());
+        p.close();
 
         // Then, let's append at root level
         buf.writeNumber(13);
-        jp = buf.asParser();
-        assertNull(jp.getCurrentToken());
-        assertToken(JsonToken.VALUE_STRING, jp.nextToken());
-        assertToken(JsonToken.VALUE_NUMBER_INT, jp.nextToken());
-        assertEquals(13, jp.getIntValue());
-        assertNull(jp.nextToken());
-        jp.close();
+        p = buf.asParser();
+        assertNull(p.getCurrentToken());
+        assertToken(JsonToken.VALUE_STRING, p.nextToken());
+        assertToken(JsonToken.VALUE_NUMBER_INT, p.nextToken());
+        assertEquals(13, p.getIntValue());
+        assertNull(p.nextToken());
+        p.close();
+        buf.close();
+    }
+
+    public void testParentContext() throws IOException
+    {
+        TokenBuffer buf = new TokenBuffer(null, false); // no ObjectCodec
+        buf.writeStartObject();
+        buf.writeFieldName("b");
+        buf.writeStartObject();
+        buf.writeFieldName("c");
+        //This assertion succeeds as expected
+        assertEquals("b", buf.getOutputContext().getParent().getCurrentName());
+        buf.writeString("cval");
+        buf.writeEndObject();
+        buf.writeEndObject();
         buf.close();
     }
 
@@ -65,15 +80,15 @@
         buf.writeEndArray();
         assertTrue(buf.getOutputContext().inRoot());
 
-        JsonParser jp = buf.asParser();
-        assertNull(jp.getCurrentToken());
-        assertTrue(jp.getParsingContext().inRoot());
-        assertToken(JsonToken.START_ARRAY, jp.nextToken());
-        assertTrue(jp.getParsingContext().inArray());
-        assertToken(JsonToken.END_ARRAY, jp.nextToken());
-        assertTrue(jp.getParsingContext().inRoot());
-        assertNull(jp.nextToken());
-        jp.close();
+        JsonParser p = buf.asParser();
+        assertNull(p.getCurrentToken());
+        assertTrue(p.getParsingContext().inRoot());
+        assertToken(JsonToken.START_ARRAY, p.nextToken());
+        assertTrue(p.getParsingContext().inArray());
+        assertToken(JsonToken.END_ARRAY, p.nextToken());
+        assertTrue(p.getParsingContext().inRoot());
+        assertNull(p.nextToken());
+        p.close();
         buf.close();
 
         // Then one with simple contents
@@ -82,14 +97,14 @@
         buf.writeBoolean(true);
         buf.writeNull();
         buf.writeEndArray();
-        jp = buf.asParser();
-        assertToken(JsonToken.START_ARRAY, jp.nextToken());
-        assertToken(JsonToken.VALUE_TRUE, jp.nextToken());
-        assertTrue(jp.getBooleanValue());
-        assertToken(JsonToken.VALUE_NULL, jp.nextToken());
-        assertToken(JsonToken.END_ARRAY, jp.nextToken());
-        assertNull(jp.nextToken());
-        jp.close();
+        p = buf.asParser();
+        assertToken(JsonToken.START_ARRAY, p.nextToken());
+        assertToken(JsonToken.VALUE_TRUE, p.nextToken());
+        assertTrue(p.getBooleanValue());
+        assertToken(JsonToken.VALUE_NULL, p.nextToken());
+        assertToken(JsonToken.END_ARRAY, p.nextToken());
+        assertNull(p.nextToken());
+        p.close();
         buf.close();
 
         // And finally, with array-in-array
@@ -99,19 +114,19 @@
         buf.writeBinary(new byte[3]);
         buf.writeEndArray();
         buf.writeEndArray();
-        jp = buf.asParser();
-        assertToken(JsonToken.START_ARRAY, jp.nextToken());
-        assertToken(JsonToken.START_ARRAY, jp.nextToken());
+        p = buf.asParser();
+        assertToken(JsonToken.START_ARRAY, p.nextToken());
+        assertToken(JsonToken.START_ARRAY, p.nextToken());
         // TokenBuffer exposes it as embedded object...
-        assertToken(JsonToken.VALUE_EMBEDDED_OBJECT, jp.nextToken());
-        Object ob = jp.getEmbeddedObject();
+        assertToken(JsonToken.VALUE_EMBEDDED_OBJECT, p.nextToken());
+        Object ob = p.getEmbeddedObject();
         assertNotNull(ob);
         assertTrue(ob instanceof byte[]);
         assertEquals(3, ((byte[]) ob).length);
-        assertToken(JsonToken.END_ARRAY, jp.nextToken());
-        assertToken(JsonToken.END_ARRAY, jp.nextToken());
-        assertNull(jp.nextToken());
-        jp.close();
+        assertToken(JsonToken.END_ARRAY, p.nextToken());
+        assertToken(JsonToken.END_ARRAY, p.nextToken());
+        assertNull(p.nextToken());
+        p.close();
         buf.close();
     }
     
@@ -126,15 +141,15 @@
         buf.writeEndObject();
         assertTrue(buf.getOutputContext().inRoot());
 
-        JsonParser jp = buf.asParser();
-        assertNull(jp.getCurrentToken());
-        assertTrue(jp.getParsingContext().inRoot());
-        assertToken(JsonToken.START_OBJECT, jp.nextToken());
-        assertTrue(jp.getParsingContext().inObject());
-        assertToken(JsonToken.END_OBJECT, jp.nextToken());
-        assertTrue(jp.getParsingContext().inRoot());
-        assertNull(jp.nextToken());
-        jp.close();
+        JsonParser p = buf.asParser();
+        assertNull(p.getCurrentToken());
+        assertTrue(p.getParsingContext().inRoot());
+        assertToken(JsonToken.START_OBJECT, p.nextToken());
+        assertTrue(p.getParsingContext().inObject());
+        assertToken(JsonToken.END_OBJECT, p.nextToken());
+        assertTrue(p.getParsingContext().inRoot());
+        assertNull(p.nextToken());
+        p.close();
         buf.close();
 
         // Then one with simple contents
@@ -143,25 +158,25 @@
         buf.writeNumberField("num", 1.25);
         buf.writeEndObject();
 
-        jp = buf.asParser();
-        assertNull(jp.getCurrentToken());
-        assertToken(JsonToken.START_OBJECT, jp.nextToken());
-        assertNull(jp.getCurrentName());
-        assertToken(JsonToken.FIELD_NAME, jp.nextToken());
-        assertEquals("num", jp.getCurrentName());
+        p = buf.asParser();
+        assertNull(p.getCurrentToken());
+        assertToken(JsonToken.START_OBJECT, p.nextToken());
+        assertNull(p.getCurrentName());
+        assertToken(JsonToken.FIELD_NAME, p.nextToken());
+        assertEquals("num", p.getCurrentName());
         // and override should also work:
-        jp.overrideCurrentName("bah");
-        assertEquals("bah", jp.getCurrentName());
+        p.overrideCurrentName("bah");
+        assertEquals("bah", p.getCurrentName());
         
-        assertToken(JsonToken.VALUE_NUMBER_FLOAT, jp.nextToken());
-        assertEquals(1.25, jp.getDoubleValue());
+        assertToken(JsonToken.VALUE_NUMBER_FLOAT, p.nextToken());
+        assertEquals(1.25, p.getDoubleValue());
         // should still have access to (overridden) name
-        assertEquals("bah", jp.getCurrentName());
-        assertToken(JsonToken.END_OBJECT, jp.nextToken());
+        assertEquals("bah", p.getCurrentName());
+        assertToken(JsonToken.END_OBJECT, p.nextToken());
         // but not any more
-        assertNull(jp.getCurrentName());
-        assertNull(jp.nextToken());
-        jp.close();
+        assertNull(p.getCurrentName());
+        assertNull(p.nextToken());
+        p.close();
         buf.close();
     }
 
@@ -172,10 +187,10 @@
     public void testWithJSONSampleDoc() throws Exception
     {
         // First, copy events from known good source (StringReader)
-        JsonParser jp = createParserUsingReader(SAMPLE_DOC_JSON_SPEC);
+        JsonParser p = createParserUsingReader(SAMPLE_DOC_JSON_SPEC);
         TokenBuffer tb = new TokenBuffer(null, false);
-        while (jp.nextToken() != null) {
-            tb.copyCurrentEvent(jp);
+        while (p.nextToken() != null) {
+            tb.copyCurrentEvent(p);
         }
 
         // And then request verification; first structure only:
@@ -184,7 +199,7 @@
         // then content check too:
         verifyJsonSpecSampleDoc(tb.asParser(), true);
         tb.close();
-        jp.close();
+        p.close();
     }
 
     public void testAppend() throws IOException
@@ -202,17 +217,17 @@
         buf1.append(buf2);
         
         // and verify that we got it all...
-        JsonParser jp = buf1.asParser();
-        assertToken(JsonToken.START_OBJECT, jp.nextToken());
-        assertToken(JsonToken.FIELD_NAME, jp.nextToken());
-        assertEquals("a", jp.getCurrentName());
-        assertToken(JsonToken.VALUE_TRUE, jp.nextToken());
-        assertToken(JsonToken.FIELD_NAME, jp.nextToken());
-        assertEquals("b", jp.getCurrentName());
-        assertToken(JsonToken.VALUE_NUMBER_INT, jp.nextToken());
-        assertEquals(13, jp.getIntValue());
-        assertToken(JsonToken.END_OBJECT, jp.nextToken());
-        jp.close();
+        JsonParser p = buf1.asParser();
+        assertToken(JsonToken.START_OBJECT, p.nextToken());
+        assertToken(JsonToken.FIELD_NAME, p.nextToken());
+        assertEquals("a", p.getCurrentName());
+        assertToken(JsonToken.VALUE_TRUE, p.nextToken());
+        assertToken(JsonToken.FIELD_NAME, p.nextToken());
+        assertEquals("b", p.getCurrentName());
+        assertToken(JsonToken.VALUE_NUMBER_INT, p.nextToken());
+        assertEquals(13, p.getIntValue());
+        assertToken(JsonToken.END_OBJECT, p.nextToken());
+        p.close();
         buf1.close();
         buf2.close();
     }
@@ -239,11 +254,11 @@
             assertEquals(uuid.toString(), out.toString());
 
             // second part: As per [databind#362], should NOT use binary with TokenBuffer
-            JsonParser jp = buf.asParser();
-            assertEquals(JsonToken.VALUE_STRING, jp.nextToken());
-            String str = jp.getText();
+            JsonParser p = buf.asParser();
+            assertEquals(JsonToken.VALUE_STRING, p.nextToken());
+            String str = p.getText();
             assertEquals(value, str);
-            jp.close();
+            p.close();
         }
     }
 
@@ -325,7 +340,7 @@
         } else if (ctxt2 == null) {
             fail("Context 2 null, context 1 not null: "+ctxt1);
         }
-        if (!ctxt1.getTypeDesc().equals(ctxt2.getTypeDesc())) {
+        if (!ctxt1.toString().equals(ctxt2.toString())) {
             fail("Different output context: token-buffer's = "+ctxt1+", json-generator's: "+ctxt2);
         }
 
@@ -344,6 +359,29 @@
         _verifyOutputContext(ctxt1.getParent(), ctxt2.getParent());
     }
 
+    // [databind#1253]
+    public void testParentSiblingContext() throws IOException
+    {
+        TokenBuffer buf = new TokenBuffer(null, false); // no ObjectCodec
+
+        // {"a":{},"b":{"c":"cval"}}
+        
+        buf.writeStartObject();
+        buf.writeFieldName("a");
+        buf.writeStartObject();
+        buf.writeEndObject();
+
+        buf.writeFieldName("b");
+        buf.writeStartObject();
+        buf.writeFieldName("c");
+        //This assertion fails (because of 'a')
+        assertEquals("b", buf.getOutputContext().getParent().getCurrentName());
+        buf.writeString("cval");
+        buf.writeEndObject();
+        buf.writeEndObject();
+        buf.close();
+    }
+
     /*
     /**********************************************************
     /* Tests to verify interaction of TokenBuffer and JsonParserSequence
@@ -356,12 +394,12 @@
         TokenBuffer buf = new TokenBuffer(null, false);
         buf.writeStartArray();
         buf.writeString("test");
-        JsonParser jp = createParserUsingReader("[ true, null ]");
+        JsonParser p = createParserUsingReader("[ true, null ]");
         
-        JsonParserSequence seq = JsonParserSequence.createFlattened(buf.asParser(), jp);
+        JsonParserSequence seq = JsonParserSequence.createFlattened(false, buf.asParser(), p);
         assertEquals(2, seq.containedParsersCount());
 
-        assertFalse(jp.isClosed());
+        assertFalse(p.isClosed());
         
         assertFalse(seq.hasCurrentToken());
         assertNull(seq.getCurrentToken());
@@ -389,8 +427,8 @@
         assertNull(seq.nextToken());
 
         // also: original parsers should be closed
-        assertTrue(jp.isClosed());
-        jp.close();
+        assertTrue(p.isClosed());
+        p.close();
         buf.close();
         seq.close();
     }
@@ -411,11 +449,11 @@
         TokenBuffer buf4 = new TokenBuffer(null, false);
         buf4.writeEndArray();
 
-        JsonParserSequence seq1 = JsonParserSequence.createFlattened(buf1.asParser(), buf2.asParser());
+        JsonParserSequence seq1 = JsonParserSequence.createFlattened(false, buf1.asParser(), buf2.asParser());
         assertEquals(2, seq1.containedParsersCount());
-        JsonParserSequence seq2 = JsonParserSequence.createFlattened(buf3.asParser(), buf4.asParser());
+        JsonParserSequence seq2 = JsonParserSequence.createFlattened(false, buf3.asParser(), buf4.asParser());
         assertEquals(2, seq2.containedParsersCount());
-        JsonParserSequence combo = JsonParserSequence.createFlattened(seq1, seq2);
+        JsonParserSequence combo = JsonParserSequence.createFlattened(false, seq1, seq2);
         // should flatten it to have 4 underlying parsers
         assertEquals(4, combo.containedParsersCount());
 
diff --git a/src/test/java/com/fasterxml/jackson/databind/views/TestViewSerialization.java b/src/test/java/com/fasterxml/jackson/databind/views/TestViewSerialization.java
index 8c17034..564eb41 100644
--- a/src/test/java/com/fasterxml/jackson/databind/views/TestViewSerialization.java
+++ b/src/test/java/com/fasterxml/jackson/databind/views/TestViewSerialization.java
@@ -159,7 +159,7 @@
      */
     public void testImplicitAutoDetection() throws Exception
     {
-    	assertEquals("{\"a\":1}", serializeAsString(new ImplicitBean()));
+        assertEquals("{\"a\":1}", objectMapper().writeValueAsString(new ImplicitBean()));
     }
 
     public void testVisibility() throws Exception
diff --git a/src/test/java/com/fasterxml/jackson/failing/AnySetter1035Test.java b/src/test/java/com/fasterxml/jackson/failing/AnySetter1035Test.java
index 48fce29..451cab3 100644
--- a/src/test/java/com/fasterxml/jackson/failing/AnySetter1035Test.java
+++ b/src/test/java/com/fasterxml/jackson/failing/AnySetter1035Test.java
@@ -6,6 +6,10 @@
 
 import com.fasterxml.jackson.databind.*;
 
+/**
+ * Test for [databind#1035], wherein key type of a `Map` not used with `@JsonAnySetter`
+ * (value type is).
+ */
 public class AnySetter1035Test extends BaseMapTest
 {
     static class MyGeneric<T>
@@ -63,7 +67,9 @@
         Map<Integer, Integer> integerGenericMap = new HashMap<Integer, Integer>();
         integerGenericMap.put(111, 6);
 
-        MyWrapper deserialized = mapper.readValue("{\"myStringGeneric\":{\"staticallyMappedProperty\":\"Test\",\"testStringKey\":5},\"myIntegerGeneric\":{\"staticallyMappedProperty\":\"Test2\",\"111\":6}}", MyWrapper.class);
+        MyWrapper deserialized = mapper.readValue(aposToQuotes(
+                "{'myStringGeneric':{'staticallyMappedProperty':'Test','testStringKey':5},'myIntegerGeneric':{'staticallyMappedProperty':'Test2','111':6}}"
+                ), MyWrapper.class);
         MyGeneric<String> stringGeneric = deserialized.getMyStringGeneric();
         MyGeneric<Integer> integerGeneric = deserialized.getMyIntegerGeneric();
 
diff --git a/src/test/java/com/fasterxml/jackson/failing/BackReference1516Test.java b/src/test/java/com/fasterxml/jackson/failing/BackReference1516Test.java
new file mode 100644
index 0000000..95c4de7
--- /dev/null
+++ b/src/test/java/com/fasterxml/jackson/failing/BackReference1516Test.java
@@ -0,0 +1,93 @@
+package com.fasterxml.jackson.failing;
+
+import java.beans.ConstructorProperties;
+
+import com.fasterxml.jackson.annotation.*;
+
+import com.fasterxml.jackson.databind.BaseMapTest;
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+public class BackReference1516Test extends BaseMapTest
+{
+    static class ParentWithCreator {
+        String id, name;
+
+        @JsonManagedReference
+        ChildObject1 child;
+
+        @ConstructorProperties({ "id", "name", "child" })
+        public ParentWithCreator(String id, String name,
+                ChildObject1 child) {
+            this.id = id;
+            this.name = name;
+            this.child = child;
+        }
+    }
+
+    static class ChildObject1
+    {
+        public String id, name;
+
+        @JsonBackReference
+        public ParentWithCreator parent;
+
+        @ConstructorProperties({ "id", "name", "parent" })
+        public ChildObject1(String id, String name,
+                ParentWithCreator parent) {
+            this.id = id;
+            this.name = name;
+            this.parent = parent;
+        }
+    }
+    
+    static class ParentWithoutCreator {
+        public String id, name;
+
+        @JsonManagedReference
+        public ChildObject2 child;
+    }
+
+    static class ChildObject2
+    {
+        public String id, name;
+
+        @JsonBackReference
+        public ParentWithoutCreator parent;
+
+        @ConstructorProperties({ "id", "name", "parent" })
+        public ChildObject2(String id, String name,
+                ParentWithoutCreator parent) {
+            this.id = id;
+            this.name = name;
+            this.parent = parent;
+        }
+    }
+    
+    /*
+    /**********************************************************
+    /* Unit tests
+    /**********************************************************
+     */
+
+    private final ObjectMapper MAPPER = new ObjectMapper();
+
+    private final String PARENT_CHILD_JSON = aposToQuotes(
+"{ 'id': 'abc',\n"+
+"  'name': 'Bob',\n"+
+"  'child': { 'id': 'def', 'title':'Bert' }\n"+
+"}");
+    
+    public void testWithParentCreator() throws Exception
+    {
+        ParentWithCreator result = MAPPER.readValue(PARENT_CHILD_JSON,
+                ParentWithCreator.class);
+        assertNotNull(result);
+    }
+
+    public void testWithParentNoCreator() throws Exception
+    {
+        ParentWithoutCreator result = MAPPER.readValue(PARENT_CHILD_JSON,
+                ParentWithoutCreator.class);
+        assertNotNull(result);
+    }
+}
diff --git a/src/test/java/com/fasterxml/jackson/failing/BuilderWithIgnored1214Test.java b/src/test/java/com/fasterxml/jackson/failing/BuilderWithIgnored1214Test.java
new file mode 100644
index 0000000..54c6d6a
--- /dev/null
+++ b/src/test/java/com/fasterxml/jackson/failing/BuilderWithIgnored1214Test.java
@@ -0,0 +1,49 @@
+package com.fasterxml.jackson.failing;
+
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+import com.fasterxml.jackson.databind.*;
+import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
+
+public class BuilderWithIgnored1214Test extends BaseMapTest
+{
+    @JsonDeserialize(builder = TestObject1214.Builder.class)
+    @JsonIgnoreProperties(ignoreUnknown = true)
+    static class TestObject1214 {
+        final String property1;
+
+        private TestObject1214(Builder builder) {
+            property1 = builder.property1;
+        }
+
+        public static Builder builder() {
+            return new Builder();
+        }
+
+        public String getProperty1() {
+            return property1;
+        }
+
+        static class Builder {
+
+            private String property1;
+
+            public Builder withProperty1(String p1) {
+                property1 = p1;
+                return this;
+            }
+
+            public TestObject1214 build() {
+                return new TestObject1214(this);
+            }
+        }
+    }
+
+    public void testUnknown1214() throws Exception
+    {
+        ObjectMapper mapper = new ObjectMapper();
+        TestObject1214 value = mapper.readValue(aposToQuotes
+                ("{'property1':'a', 'property2':'b'}"),
+                TestObject1214.class);
+        assertEquals("a", value.property1);
+    }
+}
diff --git a/src/test/java/com/fasterxml/jackson/failing/CollectionType1415Test.java b/src/test/java/com/fasterxml/jackson/failing/CollectionType1415Test.java
new file mode 100644
index 0000000..dcf8718
--- /dev/null
+++ b/src/test/java/com/fasterxml/jackson/failing/CollectionType1415Test.java
@@ -0,0 +1,61 @@
+package com.fasterxml.jackson.failing;
+
+import java.util.*;
+
+import com.fasterxml.jackson.databind.BaseMapTest;
+import com.fasterxml.jackson.databind.JavaType;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.type.CollectionType;
+import com.fasterxml.jackson.databind.type.MapType;
+
+// for [databind#1415]
+public class CollectionType1415Test extends BaseMapTest
+{
+    static abstract class LongList implements List<Long> { }
+
+    static abstract class StringLongMap implements Map<String,Long> { }
+
+    /*
+    /**********************************************************
+    /* Unit tests
+    /**********************************************************
+     */
+
+    private final ObjectMapper MAPPER = new ObjectMapper();
+
+    public void testExplicitCollectionType() throws Exception
+    {
+        JavaType t = MAPPER.getTypeFactory()
+                .constructCollectionType(LongList.class, Long.class);
+        assertEquals(LongList.class, t.getRawClass());
+        assertEquals(Long.class, t.getContentType().getRawClass());
+    }
+
+    public void testImplicitCollectionType() throws Exception
+    {
+        JavaType t = MAPPER.getTypeFactory()
+                .constructParametricType(List.class, Long.class);
+        assertEquals(CollectionType.class, t.getClass());
+        assertEquals(List.class, t.getRawClass());
+        assertEquals(Long.class, t.getContentType().getRawClass());
+    }
+
+    public void testExplicitMapType() throws Exception
+    {
+        JavaType t = MAPPER.getTypeFactory()
+                .constructMapType(StringLongMap.class,
+                        String.class, Long.class);
+        assertEquals(StringLongMap.class, t.getRawClass());
+        assertEquals(String.class, t.getKeyType().getRawClass());
+        assertEquals(Long.class, t.getContentType().getRawClass());
+    }
+
+    public void testImplicitMapType() throws Exception
+    {
+        JavaType t = MAPPER.getTypeFactory()
+                .constructParametricType(Map.class, Long.class, Boolean.class);
+        assertEquals(MapType.class, t.getClass());
+        assertEquals(Long.class, t.getKeyType().getRawClass());
+        assertEquals(Boolean.class, t.getContentType().getRawClass());
+    }
+}
diff --git a/src/test/java/com/fasterxml/jackson/failing/CreatorProperties1401Test.java b/src/test/java/com/fasterxml/jackson/failing/CreatorProperties1401Test.java
new file mode 100644
index 0000000..7671519
--- /dev/null
+++ b/src/test/java/com/fasterxml/jackson/failing/CreatorProperties1401Test.java
@@ -0,0 +1,43 @@
+package com.fasterxml.jackson.failing;
+
+import com.fasterxml.jackson.annotation.*;
+
+import com.fasterxml.jackson.databind.*;
+
+// for [databind#1401]: should allow "Any Setter" to back up otherwise problematic
+// Creator properties?
+public class CreatorProperties1401Test extends BaseMapTest
+{
+    // for [databind#1401]
+    static class NoSetter1401 {
+        int _a;
+
+        @JsonCreator
+        public NoSetter1401(@JsonProperty("a") int a) {
+            _a = a;
+        }
+
+        @JsonAnySetter
+        public void any(String key, Object value) { }
+    }
+
+    /*
+    /**********************************************************
+    /* Test methods
+    /**********************************************************
+     */
+
+    private final ObjectMapper MAPPER = new ObjectMapper();
+
+    // [databind#1401]
+    public void testCreatorNoSetter() throws Exception
+    {
+        NoSetter1401 b = MAPPER.readValue(aposToQuotes("{'a':1,'b':2}"),
+                NoSetter1401.class);
+        assertEquals(1, b._a);
+
+        NoSetter1401 b2 = MAPPER.readerForUpdating(new NoSetter1401(1))
+                .readValue(aposToQuotes("{'a':1}"));
+        assertEquals(1, b2._a);
+    }
+}
diff --git a/src/test/java/com/fasterxml/jackson/failing/CustomAnnotationIntrospector1756Test.java b/src/test/java/com/fasterxml/jackson/failing/CustomAnnotationIntrospector1756Test.java
new file mode 100644
index 0000000..80e6438
--- /dev/null
+++ b/src/test/java/com/fasterxml/jackson/failing/CustomAnnotationIntrospector1756Test.java
@@ -0,0 +1,118 @@
+package com.fasterxml.jackson.failing;
+
+import java.io.IOException;
+import java.lang.annotation.*;
+
+import com.fasterxml.jackson.annotation.*;
+import com.fasterxml.jackson.core.JsonParser;
+import com.fasterxml.jackson.databind.*;
+import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
+import com.fasterxml.jackson.databind.introspect.*;
+import com.fasterxml.jackson.databind.module.SimpleModule;
+
+@SuppressWarnings("serial")
+public class CustomAnnotationIntrospector1756Test extends BaseMapTest
+{
+    @Target({ElementType.PARAMETER, ElementType.METHOD})
+    @Retention(RetentionPolicy.RUNTIME)
+    @interface Field1756 {
+
+      String value() default "";
+    }
+
+    public interface Foobar
+    {
+      @JsonIgnore // Comment out this annotation or ...
+      String foo();
+
+      @JsonDeserialize(using = CustomStringDeserializer.class) // ... this annotation to unbreak deserialization.
+      String bar();
+    }
+
+    /**
+     * Custom String deserializer.
+     */
+    private static class CustomStringDeserializer extends JsonDeserializer<String> {
+
+      @Override
+      public String deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
+        return p.getText();
+      }
+    }
+
+    /**
+     * A concrete implementation.
+     */
+    public static class FoobarImpl implements Foobar {
+
+      private final String foo;
+      private final String bar;
+
+      public FoobarImpl(@Field1756("foo") String foo,
+              @Field1756("bar") String bar) {
+        this.foo = foo;
+        this.bar = bar;
+      }
+
+      @Override
+      public String foo() {
+        return foo;
+      }
+
+      @Override
+      public String bar() {
+        return bar;
+      }
+    }
+
+    /**
+     * Instructs jackson that {@link Foobar#foo()}, {@link Foobar#bar()} and the {@code foo} and {@code bar} constructor
+     * arguments map to the {@code foo} and {@code bar} properties.
+     */
+    public static class FoobarAnnotationIntrospector extends NopAnnotationIntrospector {
+
+      @Override
+      public String findImplicitPropertyName(final AnnotatedMember member) {
+        // Constructor parameter
+        if (member instanceof AnnotatedParameter) {
+          final Field1756 field = member.getAnnotation(Field1756.class);
+          if (field == null) {
+            return null;
+          }
+          return field.value();
+        }
+        // Getter
+        if (member instanceof AnnotatedMethod) {
+          return member.getName();
+        }
+        return null;
+      }
+
+      @Override
+      public boolean hasCreatorAnnotation(Annotated a) {
+        final AnnotatedConstructor ctor = (AnnotatedConstructor) a;
+        return (ctor.getParameterCount() > 0)
+                && (ctor.getParameter(0).getAnnotation(Field1756.class) != null);
+      }
+    }
+
+    public static class Issue1756Module extends SimpleModule {
+        @Override
+        public void setupModule(final SetupContext context) {
+            super.setupModule(context);
+            context.appendAnnotationIntrospector(new FoobarAnnotationIntrospector());
+        }
+    }
+
+    public void testIssue1756() throws Exception
+    {
+        Issue1756Module m = new Issue1756Module();
+        m.addAbstractTypeMapping(Foobar.class, FoobarImpl.class);
+        final ObjectMapper mapper = new ObjectMapper()
+            .registerModule(m);
+
+        final Foobar foobar = mapper.readValue(aposToQuotes("{'bar':'bar', 'foo':'foo'}"),
+                Foobar.class);
+        assertNotNull(foobar);
+    }
+}
diff --git a/src/test/java/com/fasterxml/jackson/failing/EnumAsExternalPropertyId1328Test.java b/src/test/java/com/fasterxml/jackson/failing/EnumAsExternalPropertyId1328Test.java
new file mode 100644
index 0000000..e0510dd
--- /dev/null
+++ b/src/test/java/com/fasterxml/jackson/failing/EnumAsExternalPropertyId1328Test.java
@@ -0,0 +1,54 @@
+package com.fasterxml.jackson.failing;
+
+import com.fasterxml.jackson.annotation.*;
+
+import com.fasterxml.jackson.databind.*;
+
+// Test for [databind#1328]; does not actually reproduce the issue at this point.
+public class EnumAsExternalPropertyId1328Test extends BaseMapTest
+{
+    static class Bean1328 {
+        public Type1328 type;
+
+        @JsonTypeInfo(property = "type", include = JsonTypeInfo.As.EXTERNAL_PROPERTY, use = JsonTypeInfo.Id.NAME,
+                visible=true)
+        @JsonSubTypes({
+                  @JsonSubTypes.Type(value = A.class,name = "A"),
+                  @JsonSubTypes.Type(value = B.class,name = "B")
+        })
+        public Interface1328 obj;
+    }
+
+    static interface Interface1328 { }
+
+    enum Type1328 {
+        A, B;
+    }
+
+   static class A implements Interface1328 {
+       public int a;
+   }
+
+   static class B implements Interface1328 {
+       public int b;
+   }
+
+   /*
+    /**********************************************************
+    /* Test methods
+    /**********************************************************
+     */
+
+    private final ObjectMapper MAPPER = new ObjectMapper();
+
+    public void testExternalTypeIdAsEnum() throws Exception
+    {
+        final String JSON = aposToQuotes("{ 'type':'A', 'obj': { 'a' : 4 } }'");
+        Bean1328 result = MAPPER.readValue(JSON, Bean1328.class);
+        assertNotNull(result.obj);
+        assertSame(A.class, result.obj.getClass());
+        assertEquals(4, ((A) result.obj).a);
+
+        assertSame(Type1328.A, result.type);
+    }
+}
diff --git a/src/test/java/com/fasterxml/jackson/failing/EnumCreatorTest929.java b/src/test/java/com/fasterxml/jackson/failing/EnumCreatorTest929.java
deleted file mode 100644
index 783a5e8..0000000
--- a/src/test/java/com/fasterxml/jackson/failing/EnumCreatorTest929.java
+++ /dev/null
@@ -1,29 +0,0 @@
-package com.fasterxml.jackson.failing;
-
-import com.fasterxml.jackson.annotation.JsonCreator;
-import com.fasterxml.jackson.annotation.JsonProperty;
-import com.fasterxml.jackson.databind.*;
-
-public class EnumCreatorTest929 extends BaseMapTest
-{
-    static enum MyEnum
-    {
-        A, B, C;
-        
-        @JsonCreator(mode = JsonCreator.Mode.PROPERTIES)
-        static MyEnum forValues(@JsonProperty("id") int intProp,
-                @JsonProperty("name") String name)
-        {
-            return MyEnum.valueOf(name);
-        }
-    }
-    
-    private final ObjectMapper MAPPER = new ObjectMapper();
-
-    // for [databind#929]
-    public void testMultiArgEnumCreator() throws Exception
-    {
-        MyEnum v = MAPPER.readValue("{\"id\":3,\"name\":\"B\"}", MyEnum.class);
-        assertEquals(MyEnum.B, v);
-    }
-}
diff --git a/src/test/java/com/fasterxml/jackson/failing/ExternalId96Test.java b/src/test/java/com/fasterxml/jackson/failing/ExternalTypeId96Test.java
similarity index 97%
rename from src/test/java/com/fasterxml/jackson/failing/ExternalId96Test.java
rename to src/test/java/com/fasterxml/jackson/failing/ExternalTypeId96Test.java
index 0d19357..0e6fd53 100644
--- a/src/test/java/com/fasterxml/jackson/failing/ExternalId96Test.java
+++ b/src/test/java/com/fasterxml/jackson/failing/ExternalTypeId96Test.java
@@ -9,7 +9,7 @@
 
 // Tests for External type id, one that exists at same level as typed Object,
 // that is, property is not within typed object but a member of its parent.
-public class ExternalId96Test extends BaseMapTest
+public class ExternalTypeId96Test extends BaseMapTest
 {
     // for [databind#96]
     static class ExternalBeanWithDefault
diff --git a/src/test/java/com/fasterxml/jackson/failing/IgnorePropertyOnDeser1217Test.java b/src/test/java/com/fasterxml/jackson/failing/IgnorePropertyOnDeser1217Test.java
deleted file mode 100644
index 7df823e..0000000
--- a/src/test/java/com/fasterxml/jackson/failing/IgnorePropertyOnDeser1217Test.java
+++ /dev/null
@@ -1,44 +0,0 @@
-package com.fasterxml.jackson.failing;
-
-import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
-import com.fasterxml.jackson.databind.BaseMapTest;
-import com.fasterxml.jackson.databind.ObjectMapper;
-
-public class IgnorePropertyOnDeser1217Test extends BaseMapTest
-{
-    static class IgnoreObject {
-        public int x = 1;
-        public int y = 2;
-    }
-
-    final static class TestIgnoreObject {
-        @JsonIgnoreProperties({ "x" })
-        public IgnoreObject obj;
-
-        @JsonIgnoreProperties({ "y" })
-        public IgnoreObject obj2;
-    }
-
-    private final ObjectMapper MAPPER = new ObjectMapper();
-    
-    public void testIgnoreOnProperty() throws Exception
-    {
-        TestIgnoreObject result = MAPPER.readValue(
-                aposToQuotes("{'obj':{'x': 10, 'y': 20}, 'obj2':{'x': 10, 'y': 20}}"),
-                TestIgnoreObject.class);
-        assertEquals(20, result.obj.y);
-        assertEquals(10, result.obj2.x);
-
-        assertEquals(1, result.obj.x);
-        assertEquals(2, result.obj2.y);
-        
-        TestIgnoreObject result1 = MAPPER.readValue(
-                  aposToQuotes("{'obj':{'x': 20, 'y': 30}, 'obj2':{'x': 20, 'y': 40}}"),
-                  TestIgnoreObject.class);
-        assertEquals(1, result1.obj.x);
-        assertEquals(30, result1.obj.y);
-       
-        assertEquals(20, result1.obj2.x);
-        assertEquals(2, result1.obj2.y);
-    }
-}
diff --git a/src/test/java/com/fasterxml/jackson/failing/IgnoredCreatorProperty1572Test.java b/src/test/java/com/fasterxml/jackson/failing/IgnoredCreatorProperty1572Test.java
new file mode 100644
index 0000000..e3ed8b9
--- /dev/null
+++ b/src/test/java/com/fasterxml/jackson/failing/IgnoredCreatorProperty1572Test.java
@@ -0,0 +1,73 @@
+package com.fasterxml.jackson.failing;
+
+import com.fasterxml.jackson.annotation.*;
+
+import com.fasterxml.jackson.databind.BaseMapTest;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.introspect.*;
+
+public class IgnoredCreatorProperty1572Test extends BaseMapTest
+{
+    static class InnerTest
+    {
+        public String str;
+        public String otherStr;
+    }
+
+    static class OuterTest
+    {
+        InnerTest innerTest;
+
+        @JsonIgnore
+        String otherOtherStr;
+        
+        @JsonCreator
+        public OuterTest(/*@JsonProperty("innerTest")*/ InnerTest inner,
+                /*@JsonProperty("otherOtherStr")*/ String otherStr) {
+            this.innerTest = inner;
+        }
+    }
+
+    static class ImplicitNames extends JacksonAnnotationIntrospector
+    {
+        private static final long serialVersionUID = 1L;
+
+        @Override
+        public String findImplicitPropertyName(AnnotatedMember member) {
+            if (member instanceof AnnotatedParameter) {
+                // A placeholder for legitimate property name detection
+                // such as what the JDK8 module provides
+                AnnotatedParameter param = (AnnotatedParameter) member;
+                switch (param.getIndex()) {
+                case 0:
+                    return "innerTest";
+                case 1:
+                    return "otherOtherStr";
+                default:
+                }
+            }
+            return null;
+        }
+    }
+
+    /*
+    /********************************************************
+    /* Test methods
+    /********************************************************
+     */
+
+    // [databind#1572]
+    public void testIgnoredCtorParam() throws Exception
+    {
+        final ObjectMapper mapper = new ObjectMapper();
+        mapper.setAnnotationIntrospector(new ImplicitNames());
+        String JSON = aposToQuotes("{'innerTest': {\n"
+                +"'str':'str',\n"
+                +"'otherStr': 'otherStr'\n"
+                +"}}\n");
+        OuterTest result = mapper.readValue(JSON, OuterTest.class);
+        assertNotNull(result);
+        assertNotNull(result.innerTest);
+        assertEquals("otherStr", result.innerTest.otherStr);
+    }
+}
diff --git a/src/test/java/com/fasterxml/jackson/failing/InnerClassCreator1502Test.java b/src/test/java/com/fasterxml/jackson/failing/InnerClassCreator1502Test.java
deleted file mode 100644
index 47a299b..0000000
--- a/src/test/java/com/fasterxml/jackson/failing/InnerClassCreator1502Test.java
+++ /dev/null
@@ -1,75 +0,0 @@
-package com.fasterxml.jackson.failing;
-
-import com.fasterxml.jackson.annotation.JsonCreator;
-import com.fasterxml.jackson.annotation.JsonProperty;
-import com.fasterxml.jackson.databind.*;
-
-// for [databind#1502], [databind#1503]
-public class InnerClassCreator1502Test extends BaseMapTest
-{
-    static class Something1501 {
-        public InnerSomething a;
-
-        // important: must name the parameter (param names module, or explicit)
-        @JsonCreator
-        public Something1501(@JsonProperty("a") InnerSomething a) { this.a = a; }
-
-        public Something1501(boolean bogus) { a = new InnerSomething(); }
-
-        class InnerSomething {
-            @JsonCreator
-            public InnerSomething() { }
-        }
-    }
-
-    static class Something1502 {
-        @JsonProperty
-        public InnerSomething1502 a;
-
-        @JsonCreator
-        public Something1502(InnerSomething1502 a) {}
-
-        class InnerSomething1502 {
-            @JsonCreator
-            public InnerSomething1502() {}
-        }
-    }    
-
-    static class Broken1503 {
-        public InnerClass1503 innerClass;
-
-        class InnerClass1503 {
-            public Generic<?> generic;
-            public InnerClass1503(@JsonProperty("generic") Generic<?> generic) {}
-        }
-
-        static class Generic<T> {
-            public int ignored;
-        }
-    }
-
-    private final ObjectMapper MAPPER = new ObjectMapper();
-    {
-        MAPPER.disable(SerializationFeature.FAIL_ON_EMPTY_BEANS);
-    }
-
-    // Used to trigger `ArrayIndexOutOfBoundsException` for missing creator property index
-    public void testIssue1501() throws Exception
-    {
-        String ser = MAPPER.writeValueAsString(new Something1501(false));
-        MAPPER.readValue(ser, Something1501.class);
-    }    
-
-    public void testIssue1502() throws Exception
-    {
-        String ser = MAPPER.writeValueAsString(new Something1502(null));
-//System.err.println("DEBUG: ser == "+ser);
-        MAPPER.readValue(ser, Something1502.class);
-    }
-
-    public void testIssue1503() throws Exception
-    {
-        String ser = MAPPER.writeValueAsString(new Broken1503());
-        MAPPER.readValue(ser, Broken1503.class);
-    }
-}
diff --git a/src/test/java/com/fasterxml/jackson/failing/ObjectIdWithInjectable639Test.java b/src/test/java/com/fasterxml/jackson/failing/ObjectIdWithInjectable639Test.java
new file mode 100644
index 0000000..30dfcf3
--- /dev/null
+++ b/src/test/java/com/fasterxml/jackson/failing/ObjectIdWithInjectable639Test.java
@@ -0,0 +1,45 @@
+package com.fasterxml.jackson.failing;
+
+import com.fasterxml.jackson.annotation.*;
+import com.fasterxml.jackson.databind.*;
+
+public class ObjectIdWithInjectable639Test extends BaseMapTest
+{
+    // for [databind#639]
+    @JsonIdentityInfo(generator = ObjectIdGenerators.IntSequenceGenerator.class)
+    public static final class Parent2 {
+        @JsonProperty
+        public Child2 child;
+
+        @JsonCreator
+        public Parent2(@JacksonInject("context") String context) {
+        }
+    }
+
+    @JsonIdentityInfo(generator = ObjectIdGenerators.IntSequenceGenerator.class)
+    public static final class Child2 {
+        @JsonProperty
+        private final Parent2 parent;
+
+        @JsonCreator
+        public Child2(@JsonProperty("parent") Parent2 parent) {
+            this.parent = parent;
+        }
+    }
+
+    // for [databind#639]
+    public void testObjectIdWithInjectable() throws Exception
+    {
+        ObjectMapper mapper = new ObjectMapper()
+                .setInjectableValues(new InjectableValues.Std().
+                        addValue("context", "Stuff"));
+        Parent2 parent2 = new Parent2("foo");
+        Child2 child2 = new Child2(parent2);
+        parent2.child = child2;
+
+        String json2 = mapper.writeValueAsString(parent2);
+        parent2 = mapper.readValue(json2, Parent2.class);
+        assertNotNull(parent2);
+        assertNotNull(parent2.child);
+    }
+}
diff --git a/src/test/java/com/fasterxml/jackson/failing/PolymorphicWithObjectId1551Test.java b/src/test/java/com/fasterxml/jackson/failing/PolymorphicWithObjectId1551Test.java
new file mode 100644
index 0000000..6944644
--- /dev/null
+++ b/src/test/java/com/fasterxml/jackson/failing/PolymorphicWithObjectId1551Test.java
@@ -0,0 +1,53 @@
+package com.fasterxml.jackson.failing;
+
+import com.fasterxml.jackson.annotation.JsonIdentityInfo;
+import com.fasterxml.jackson.annotation.JsonIdentityReference;
+import com.fasterxml.jackson.annotation.JsonTypeInfo;
+import com.fasterxml.jackson.annotation.ObjectIdGenerators;
+import com.fasterxml.jackson.databind.*;
+
+public class PolymorphicWithObjectId1551Test extends BaseMapTest
+{
+    @JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY,
+            property = "@class")
+    static abstract class Vehicle {
+        public String vehicleId;
+    }
+
+    static class Car extends Vehicle {
+        public int numberOfDoors;
+    }
+
+    static class VehicleOwnerViaProp {
+        @JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "vehicleId")
+        @JsonIdentityReference(alwaysAsId = false)
+        public Vehicle ownedVehicle;
+    }
+
+    public void testWithAbstractUsingProp() throws Exception {
+        Car c = new Car();
+        c.vehicleId = "123";
+        c.numberOfDoors = 2;
+        // both owners own the same vehicle (car sharing ;-))
+        VehicleOwnerViaProp v1 = new VehicleOwnerViaProp();
+        v1.ownedVehicle = c;
+        VehicleOwnerViaProp v2 = new VehicleOwnerViaProp();
+        v2.ownedVehicle = c;
+
+        ObjectMapper objectMapper = new ObjectMapper();
+        String serialized = objectMapper.writer()
+                .writeValueAsString(new VehicleOwnerViaProp[] { v1, v2 });
+
+        // 02-May-2017, tatu: Not possible to support as of Jackson 2.8 at least, so:
+
+        try {
+            /*VehicleOwnerViaProp[] deserialized = */
+            objectMapper.readValue(serialized, VehicleOwnerViaProp[].class);
+            fail("Should not pass");
+        } catch (JsonMappingException e) {
+            verifyException(e, "Invalid Object Id definition for abstract type");
+        }
+//        assertEquals(2, deserialized.length);
+//        assertSame(deserialized[0].ownedVehicle, deserialized[1].ownedVehicle);
+    }
+}
diff --git a/src/test/java/com/fasterxml/jackson/failing/SkipInjectableIntrospection962Test.java b/src/test/java/com/fasterxml/jackson/failing/SkipInjectableIntrospection962Test.java
new file mode 100644
index 0000000..cb37a5c
--- /dev/null
+++ b/src/test/java/com/fasterxml/jackson/failing/SkipInjectableIntrospection962Test.java
@@ -0,0 +1,55 @@
+package com.fasterxml.jackson.failing;
+
+import com.fasterxml.jackson.annotation.JacksonInject;
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.databind.*;
+
+public class SkipInjectableIntrospection962Test extends BaseMapTest
+{
+    static class InjectMe
+    {
+        private String a;
+
+        public InjectMe(boolean dummy) { }
+
+        public void setA(Integer a) {
+            this.a = a.toString();
+        }
+
+        public void setA(InjectMe a) {
+            this.a = String.valueOf(a);
+        }
+        
+        public String getA() {
+            return a;
+        }
+    }
+
+    static class Injectee
+    {
+        private String b;
+
+        @JsonCreator
+        public Injectee(@JacksonInject InjectMe injectMe, @JsonProperty("b") String b) {
+            this.b = b;
+        }
+
+        public String getB() {
+            return b;
+        }
+    }
+
+    // 14-Jun-2016, tatu: For some odd reason, this test sometimes fails, other times not...
+    //    possibly related to unstable ordering of properties?
+    public void testInjected() throws Exception
+    {
+        InjectMe im = new InjectMe(true);
+        ObjectMapper mapper = new ObjectMapper()
+            .setInjectableValues(new InjectableValues.Std().addValue(InjectMe.class, im));
+        String test = "{\"b\":\"bbb\"}";
+
+        Injectee actual = mapper.readValue(test, Injectee.class);
+        assertEquals("bbb", actual.getB());
+    }
+}
diff --git a/src/test/java/com/fasterxml/jackson/failing/TestDefaultForUtilCollections1868.java b/src/test/java/com/fasterxml/jackson/failing/TestDefaultForUtilCollections1868.java
new file mode 100644
index 0000000..4dc9cd1
--- /dev/null
+++ b/src/test/java/com/fasterxml/jackson/failing/TestDefaultForUtilCollections1868.java
@@ -0,0 +1,100 @@
+package com.fasterxml.jackson.failing;
+
+import java.util.*;
+
+import com.fasterxml.jackson.annotation.JsonTypeInfo;
+import com.fasterxml.jackson.databind.BaseMapTest;
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+// Unit tests for [databind#1868], related
+public class TestDefaultForUtilCollections1868 extends BaseMapTest
+{
+   private final ObjectMapper DEFAULT_MAPPER = new ObjectMapper();
+   {
+       DEFAULT_MAPPER.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY);
+   }
+
+   /*
+   /**********************************************************
+   /* Unit tests, "empty" types
+   /**********************************************************
+    */
+
+   public void testEmptyList() throws Exception {
+       _verifyCollection(Collections.emptyList());
+   }
+
+   public void testEmptySet() throws Exception {
+       _verifyCollection(Collections.emptySet());
+   }
+
+   public void testEmptyMap() throws Exception {
+       _verifyMap(Collections.emptyMap());
+   }
+
+   /*
+   /**********************************************************
+   /* Unit tests, "singleton" types
+   /**********************************************************
+    */
+
+   public void testSingletonList() throws Exception {
+       _verifyCollection(Collections.singletonList(Arrays.asList("TheOne")));
+   }
+
+   public void testSingletonSet() throws Exception {
+       _verifyCollection(Collections.singleton(Arrays.asList("TheOne")));
+   }
+
+   public void testSingletonMap() throws Exception {
+       _verifyMap(Collections.singletonMap("foo", "bar"));
+   }
+
+   /*
+   /**********************************************************
+   /* Unit tests, "unmodifiable" types
+   /**********************************************************
+    */
+
+   public void testUnmodifiableList() throws Exception {
+       _verifyCollection(Collections.unmodifiableList(Arrays.asList("first", "second")));
+   }
+
+   public void testUnmodifiableSet() throws Exception
+   {
+       Set<String> input = new LinkedHashSet<>(Arrays.asList("first", "second"));
+       _verifyCollection(Collections.unmodifiableSet(input));
+   }
+
+   public void testUnmodifiableMap() throws Exception
+   {
+       Map<String,String> input = new LinkedHashMap<>();
+       input.put("a", "b");
+       input.put("c", "d");
+       _verifyMap(Collections.unmodifiableMap(input));
+   }
+
+   /*
+   /**********************************************************
+   /* Helper methods
+   /**********************************************************
+    */
+
+   protected void _verifyCollection(Collection<?> exp) throws Exception
+   {
+       String json = DEFAULT_MAPPER.writeValueAsString(exp);
+       Collection<?> act = DEFAULT_MAPPER.readValue(json, Collection.class);
+       
+       assertEquals(exp, act);
+       assertEquals(exp.getClass(), act.getClass());
+   }
+
+   protected void _verifyMap(Map<?,?> exp) throws Exception
+   {
+       String json = DEFAULT_MAPPER.writeValueAsString(exp);
+       Map<?,?> act = DEFAULT_MAPPER.readValue(json, Map.class);
+
+       assertEquals(exp, act);
+       assertEquals(exp.getClass(), act.getClass());
+   }
+}
diff --git a/src/test/java/com/fasterxml/jackson/failing/TestMultipleExternalIds291.java b/src/test/java/com/fasterxml/jackson/failing/TestMultipleExternalIds291.java
index 7b942d8..75ef0c2 100644
--- a/src/test/java/com/fasterxml/jackson/failing/TestMultipleExternalIds291.java
+++ b/src/test/java/com/fasterxml/jackson/failing/TestMultipleExternalIds291.java
@@ -50,7 +50,7 @@
     /**********************************************************
      */
 
-    // [Issue#291]
+    // [databind#291]
     public void testMultiple() throws Exception
     {
         final ObjectMapper mapper = objectMapper();
diff --git a/src/test/java/com/fasterxml/jackson/failing/TestObjectIdWithInjectables639.java b/src/test/java/com/fasterxml/jackson/failing/TestObjectIdWithInjectables639.java
new file mode 100644
index 0000000..3d85f2c
--- /dev/null
+++ b/src/test/java/com/fasterxml/jackson/failing/TestObjectIdWithInjectables639.java
@@ -0,0 +1,85 @@
+package com.fasterxml.jackson.failing;
+
+import com.fasterxml.jackson.annotation.*;
+import com.fasterxml.jackson.databind.*;
+
+// This is probably impossible to handle, in general case, since
+// there is a cycle for Parent2/Child2... unless special handling
+// could be made to ensure that 
+public class TestObjectIdWithInjectables639 extends BaseMapTest
+{
+        public static final class Context { }
+
+        @JsonIdentityInfo(generator = ObjectIdGenerators.IntSequenceGenerator.class)
+        public static final class Parent1 {
+            public Child1 child;
+
+            public Parent1() { }
+        }
+
+        @JsonIdentityInfo(generator = ObjectIdGenerators.IntSequenceGenerator.class)
+        public static final class Child1 {
+
+            @JsonProperty
+            private final Parent1 parent;
+
+            @JsonCreator
+            public Child1(@JsonProperty("parent") Parent1 parent) {
+                this.parent = parent;
+            }
+        }
+        
+        @JsonIdentityInfo(generator = ObjectIdGenerators.IntSequenceGenerator.class)
+        public static final class Parent2 {
+
+            protected final Context context;
+
+            public Child2 child;
+
+            @JsonCreator
+            public Parent2(@JacksonInject Context context) {
+                this.context = context;
+            }
+        }
+
+        @JsonIdentityInfo(generator = ObjectIdGenerators.IntSequenceGenerator.class)
+        public static final class Child2 {
+
+            protected final Context context;
+
+            @JsonProperty
+            protected Parent2 parent;
+
+            @JsonCreator
+            public Child2(@JacksonInject Context context,
+                    @JsonProperty("parent") Parent2 parent) {
+                this.context = context;
+                this.parent = parent;
+            }
+        }
+
+        public void testObjectIdWithInjectables() throws Exception
+        {
+            ObjectMapper mapper = new ObjectMapper();
+            Context context = new Context();
+            InjectableValues iv = new InjectableValues.Std().
+                    addValue(Context.class, context);
+            mapper.setInjectableValues(iv);
+
+            Parent1 parent1 = new Parent1();
+            Child1 child1 = new Child1(parent1);
+            parent1.child = child1;
+
+            Parent2 parent2 = new Parent2(context);
+            Child2 child2 = new Child2(context, parent2);
+            parent2.child = child2;
+
+            String json = mapper.writeValueAsString(parent1);
+            parent1 = mapper.readValue(json, Parent1.class);
+//            System.out.println("This works: " + json);
+
+            json = mapper.writeValueAsString(parent2);
+//System.out.println("This fails: " + json);
+            parent2 = mapper.readValue(json, Parent2.class);
+        }
+}
diff --git a/src/test/java/com/fasterxml/jackson/failing/TestObjectIdWithUnwrapping1298.java b/src/test/java/com/fasterxml/jackson/failing/TestObjectIdWithUnwrapping1298.java
new file mode 100644
index 0000000..8c4b97b
--- /dev/null
+++ b/src/test/java/com/fasterxml/jackson/failing/TestObjectIdWithUnwrapping1298.java
@@ -0,0 +1,83 @@
+package com.fasterxml.jackson.failing;
+
+import java.io.StringWriter;
+import java.util.ArrayList;
+import java.util.List;
+
+import com.fasterxml.jackson.annotation.*;
+import com.fasterxml.jackson.core.JsonGenerator;
+import com.fasterxml.jackson.databind.BaseMapTest;
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+// Test case for https://github.com/FasterXML/jackson-databind/issues/1298
+public class TestObjectIdWithUnwrapping1298 extends BaseMapTest
+{
+    private static Long nextId = 1L;
+
+    public static final class ListOfParents{
+        public List<Parent> parents = new ArrayList<>();
+
+        public void addParent( Parent parent) { parents.add(parent);}
+    }
+
+    @JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id", scope = Parent.class)
+    public static final class Parent {
+        public Long id;
+
+        @JsonUnwrapped
+        public Child child;
+        public Parent() { this.id = nextId++;}
+    }
+
+    @JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id", scope = Child.class)
+    public static final class Child
+    {
+        public Long id;
+
+        public final String name;
+
+        public Child(@JsonProperty("name") String name) {
+            this.name = name;
+            this.id = TestObjectIdWithUnwrapping1298.nextId++;
+        }
+    }
+
+    public void testObjectIdWithRepeatedChild() throws Exception
+    {
+        ObjectMapper mapper = new ObjectMapper();
+        mapper.disable(JsonGenerator.Feature.AUTO_CLOSE_JSON_CONTENT);
+
+        // Equivalent to Spring _embedded for Bean w/ List property
+        ListOfParents parents = new ListOfParents();
+
+        //Bean with Relationship
+        Parent parent1 = new Parent();
+        Child child1 = new Child("Child1");
+        parent1.child = child1;
+        parents.addParent(parent1);
+
+        // serialize parent1 and parent2
+        String json = mapper
+//                .writerWithDefaultPrettyPrinter()
+                .writeValueAsString(parents);
+        System.out.println("This works: " + json);
+
+        // Add parent3 to create ObjectId reference
+        // Bean w/ repeated relationship from parent1, should generate ObjectId
+        Parent parent3 = new Parent();
+        parent3.child = child1;
+        parents.addParent(parent3);
+        StringWriter sw = new StringWriter();
+
+        try {
+            mapper
+//                .writerWithDefaultPrettyPrinter()
+                .writeValue(sw, parents);
+        } catch (Exception e) {
+            System.out.println("Failed output so far: " + sw);
+            throw e;
+        }
+
+        System.out.println("Also works: " + sw);
+    }
+}
diff --git a/src/test/java/com/fasterxml/jackson/failing/TestSubtypes1311.java b/src/test/java/com/fasterxml/jackson/failing/TestSubtypes1311.java
new file mode 100644
index 0000000..b3cfbc9
--- /dev/null
+++ b/src/test/java/com/fasterxml/jackson/failing/TestSubtypes1311.java
@@ -0,0 +1,38 @@
+package com.fasterxml.jackson.failing;
+
+import com.fasterxml.jackson.annotation.JsonTypeInfo;
+import com.fasterxml.jackson.annotation.JsonTypeName;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+// Not sure if this is valid, but for what it's worth, shows
+// the thing wrt [databind#1311]. May be removed if we can't find
+// improvements.
+public class TestSubtypes1311 extends com.fasterxml.jackson.databind.BaseMapTest
+{
+    // [databind#1311]
+    @JsonTypeInfo(property = "type", use = JsonTypeInfo.Id.NAME, defaultImpl = Factory1311ImplA.class)
+    interface Factory1311 { }
+
+    @JsonTypeName("implA")
+    static class Factory1311ImplA implements Factory1311 { }
+
+    @JsonTypeName("implB")
+    static class Factory1311ImplB implements Factory1311 { }
+
+    /*
+    /**********************************************************
+    /* Unit tests
+    /**********************************************************
+     */
+    
+    // [databind#1311]
+    public void testSubtypeAssignmentCheck() throws Exception
+    {
+        ObjectMapper mapper = new ObjectMapper();
+        mapper.registerSubtypes(Factory1311ImplA.class, Factory1311ImplB.class);
+        Factory1311ImplB result = mapper.readValue("{\"type\":\"implB\"}", Factory1311ImplB.class);
+        assertNotNull(result);
+        assertEquals(Factory1311ImplB.class, result.getClass());
+    }
+}
diff --git a/src/test/java/com/fasterxml/jackson/failing/TestUnknownProperty426.java b/src/test/java/com/fasterxml/jackson/failing/TestUnknownProperty426.java
index acb1806..48a9ff2 100644
--- a/src/test/java/com/fasterxml/jackson/failing/TestUnknownProperty426.java
+++ b/src/test/java/com/fasterxml/jackson/failing/TestUnknownProperty426.java
@@ -15,7 +15,7 @@
         public String firstName;
         Integer userId; 
 
-        void setUserId(CharSequence id) {
+        public void setUserId(CharSequence id) {
             // 21-Dec-2015, tatu: With a fix in 2.7, use of String would not
             //   trigger the problem, so use CharSequence...
             setUserId(new Integer(id.toString()));
diff --git a/src/test/java/perf/ManualReadWithTypeResolution.java b/src/test/java/perf/ManualReadWithTypeResolution.java
new file mode 100644
index 0000000..3f3f358
--- /dev/null
+++ b/src/test/java/perf/ManualReadWithTypeResolution.java
@@ -0,0 +1,156 @@
+package perf;
+
+import java.io.*;
+import java.util.*;
+
+import com.fasterxml.jackson.core.type.TypeReference;
+import com.fasterxml.jackson.databind.*;
+
+/**
+ * Variant that uses hard-coded input but compares cost of generic type
+ * resolution to that of passing raw (type-erased) Class.
+ *
+ * @since 2.8
+ */
+public class ManualReadWithTypeResolution
+{
+    private final String _desc1, _desc2;
+    private final byte[] _input;
+    private final Class<?> _inputType;
+    private final TypeReference<?> _inputTypeRef;
+
+    private final ObjectMapper _mapper;
+    private final int REPS;
+
+    protected int hash;
+    // wait for 3 seconds
+    protected long startMeasure = System.currentTimeMillis() + 3000L;
+    protected int roundsDone = 0;
+    private double[] timeMsecs;
+
+    public static void main(String[] args) throws Exception {
+        new ManualReadWithTypeResolution().doTest();
+    }
+
+    private ManualReadWithTypeResolution() throws IOException {
+        _desc1 = "Raw type";
+        _desc2 = "Generic type";
+        _mapper = new ObjectMapper();
+
+        _input = "[\"value\",\"123\"]".getBytes("UTF-8");
+        _inputType = List.class;
+        _inputTypeRef = new TypeReference<List<String>>() { };
+
+        /*
+        _input = "{\"id\":124}".getBytes("UTF-8");
+        _inputType = Map.class;
+        _inputTypeRef = new TypeReference<Map<String,Object>>() { };
+        */
+        
+        REPS = (int) ((double) (15 * 1000 * 1000) / (double) _input.length);
+    }
+
+    // When comparing to simple streaming parsing, uncomment:
+
+    private void doTest() throws Exception
+    {
+
+        System.out.printf("Read %d bytes to bind; will do %d repetitions\n",
+                _input.length, REPS);
+        System.out.print("Warming up");
+
+        int i = 0;
+        final int TYPES = 2;
+
+
+        timeMsecs = new double[TYPES];
+
+        while (true) {
+            Thread.sleep(100L);
+            final int type = (i++ % TYPES);
+
+            String msg;
+            double msesc;
+            
+            switch (type) {
+            case 0:
+                msesc = testDeser(REPS, _input, _mapper, _inputType);
+                msg = _desc1;
+                break;
+            case 1:
+                msesc = testDeser(REPS, _input, _mapper, _inputTypeRef);
+                msg = _desc2;
+                break;
+            default:
+                throw new Error();
+            }
+            updateStats(type, (i % 17) == 0, msg, msesc);
+        }
+    }
+
+    protected final double testDeser(int reps, byte[] json, ObjectMapper mapper, Class<?> type)
+            throws IOException
+    {
+        long start = System.nanoTime();
+        Object result = null;
+        while (--reps >= 0) {
+            result = mapper.readValue(json, type);
+        }
+        hash = result.hashCode();
+        return _msecsFromNanos(System.nanoTime() - start);
+    }
+
+    protected final double testDeser(int reps, byte[] json, ObjectMapper mapper, TypeReference<?> type)
+            throws IOException
+    {
+        long start = System.nanoTime();
+        Object result = null;
+        while (--reps >= 0) {
+            result = mapper.readValue(json, type);
+        }
+        hash = result.hashCode();
+        return _msecsFromNanos(System.nanoTime() - start);
+    }
+    
+    private void updateStats(int type, boolean doGc, String msg, double msecs)
+        throws Exception
+    {
+        final boolean lf = (type == (timeMsecs.length - 1));
+
+        if (startMeasure == 0L) { // skip first N seconds
+            timeMsecs[type] += msecs;
+        } else {
+            if (lf) {
+                if (System.currentTimeMillis() >= startMeasure) {
+                    startMeasure = 0L;
+                    System.out.println(" complete!");
+                } else {
+                    System.out.print(".");
+                }
+            }
+            return;
+        }
+
+        System.out.printf("Test '%s' [hash: 0x%s] -> %.1f msecs\n", msg, Integer.toHexString(hash), msecs);
+        if (lf) {
+            ++roundsDone;
+            if ((roundsDone % 3) == 0 ) {
+                double den = (double) roundsDone;
+                System.out.printf("Averages after %d rounds (%s/%s): %.1f / %.1f msecs\n",
+                        (int) den, _desc1, _desc2,
+                        timeMsecs[0] / den, timeMsecs[1] / den);
+            }
+            System.out.println();
+        }
+        if (doGc) {
+            System.out.println("[GC]");
+            Thread.sleep(100L);
+            System.gc();
+            Thread.sleep(100L);
+        }
+    }
+
+    protected final double _msecsFromNanos(long nanos) {
+        return (nanos / 1000000.0);
+    }
+}