Merge branch '2.4'

Conflicts:
	pom.xml
diff --git a/.travis.yml b/.travis.yml
index c134ca9..9f83625 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,5 +1,6 @@
 language: java
 jdk:
+  - oraclejdk7
   - openjdk6
 
 # Below this line is configuration for deploying to the Sonatype OSS repo
@@ -11,6 +12,7 @@
 branches:
   only:
     - master
+    - "2.4"
     - "2.3"
 
 env:
diff --git a/README.md b/README.md
index 64bc22e..35e439f 100644
--- a/README.md
+++ b/README.md
@@ -27,7 +27,7 @@
 </dependency>
 ```
 
-Since package also depends on `jackson-core` and `jackson-databind` packages, you will need to download these if not using Maven; and you may also want to add them as Maven dependency to ensure that compatible versions are used.
+Since package also depends on `jackson-core` and `jackson-annotations` packages, you will need to download these if not using Maven; and you may also want to add them as Maven dependency to ensure that compatible versions are used.
 If so, also add:
 
 ```xml
@@ -376,7 +376,7 @@
 
 # Further reading
 
-* [Documentation](https://github.com/FasterXML/jackson-databind/wiki/Documentation)
+* [Documentation](https://github.com/FasterXML/jackson-databind/wiki)
 
 Related:
 
diff --git a/pom.xml b/pom.xml
index 0aa11a1..7533273 100644
--- a/pom.xml
+++ b/pom.xml
@@ -5,12 +5,12 @@
   <parent>
     <groupId>com.fasterxml.jackson</groupId>
     <artifactId>jackson-parent</artifactId>
-    <version>2.4</version>
+    <version>2.5-rc1</version>
   </parent>
 
   <groupId>com.fasterxml.jackson.core</groupId>
   <artifactId>jackson-databind</artifactId>
-  <version>2.4.4-SNAPSHOT</version>
+  <version>2.5.0-SNAPSHOT</version>
   <name>jackson-databind</name>
   <packaging>bundle</packaging>
   <description>General data-binding functionality for Jackson: works on core streaming API</description>
@@ -69,12 +69,12 @@
     <dependency>
       <groupId>com.fasterxml.jackson.core</groupId>
       <artifactId>jackson-annotations</artifactId>
-      <version>2.4.0</version>
+      <version>2.5.0-SNAPSHOT</version>
     </dependency>
     <dependency>
       <groupId>com.fasterxml.jackson.core</groupId>
       <artifactId>jackson-core</artifactId>
-      <version>2.4.4-SNAPSHOT</version>
+      <version>2.5.0-SNAPSHOT</version>
     </dependency>
 
     <!-- and for testing we need a few libraries
@@ -102,15 +102,10 @@
 
   <build>
      <plugins>
-       <plugin> <!-- parent uses 2.4.2 -->
-         <groupId>org.apache.maven.plugins</groupId>
-          <artifactId>maven-release-plugin</artifactId>
-          <version>2.5</version>
-       </plugin>
-     <plugin>
+      <plugin>
         <groupId>org.apache.maven.plugins</groupId>
+        <version>${version.plugin.surefire}</version>
         <artifactId>maven-surefire-plugin</artifactId>
-        <version>${surefire.version}</version>
         <configuration>
           <excludes>
             <exclude>com/fasterxml/jackson/failing/*.java</exclude>
@@ -121,12 +116,12 @@
       <plugin>
         <groupId>org.apache.maven.plugins</groupId>
         <artifactId>maven-javadoc-plugin</artifactId>
-        <version>${javadoc.version}</version>
+        <version>${version.plugin.javadoc}</version>
         <configuration>
           <links>
             <link>http://docs.oracle.com/javase/6/docs/api/</link>
-            <link>http://fasterxml.github.com/jackson-annotations/javadoc/2.4/</link>
-            <link>http://fasterxml.github.com/jackson-core/javadoc/2.4/</link>
+            <link>http://fasterxml.github.com/jackson-annotations/javadoc/2.5/</link>
+            <link>http://fasterxml.github.com/jackson-core/javadoc/2.5/</link>
           </links>
         </configuration>
       </plugin>
diff --git a/release-notes/CREDITS b/release-notes/CREDITS
index c161eee..a52f66b 100644
--- a/release-notes/CREDITS
+++ b/release-notes/CREDITS
@@ -146,8 +146,20 @@
 
 Ian Barfield: (tea-dragon@github)
   * Reported #580: delegate deserializers choke on a (single) abstract/polymorphic parameter
-    (2.4.4)
+   (2.4.4)
 
 Eugene Lukash
   * Reported #592: Wrong `TokenBuffer` delegate deserialization using `@JsonCreator`
-    (2.4.4)
+   (2.4.4)
+
+Lovro Pandžić (lpandzic@github)
+  * Reported #421: @JsonCreator not used in case of multiple creators with parameter names
+   (2.5.0)
+
+Adam Stroud (adstro@github)
+  * Contributed	#576: Add fluent API for adding mixins
+   (2.5.0)
+
+David Fleeman (fleebytes@github)
+  * Contributed #528 implementation: Add support for `JsonType.As.EXISTING_PROPERTY`
+   (2.5.0)
diff --git a/release-notes/VERSION b/release-notes/VERSION
index 0cdb8fc..b7f0526 100644
--- a/release-notes/VERSION
+++ b/release-notes/VERSION
@@ -4,6 +4,41 @@
 === Releases ===
 ------------------------------------------------------------------------
 
+2.5.0 (not yet released)
+
+#113: Problem deserializing polymorphic types with @JsonCreator
+#408: External type id does not allow use of 'visible=true'
+#421: @JsonCreator not used in case of multiple creators with parameter names
+ (reported by Lovro P, lpandzic@github)
+#521: Keep bundle annotations, prevent problems with recursive annotation types
+ (reported by tea-dragon@github)
+#527: Add support for `@JsonInclude(contents=Include.NON_NULL)` (and others) for Maps
+#528: Add support for `JsonType.As.EXISTING_PROPERTY`
+ (reported by heapifyman@github; implemented by fleebytes@github)
+#539: Problem with post-procesing of "empty bean" serializer; was not calling
+  'BeanSerializerModifier.modifySerializer()` for empty beans
+ (reported by Fabien R, fabienrenaud@github)
+#540: Support deserializing `[]` as null or empty collection when the java type is a not an object
+ (requested by Fabien R, fabienrenaud@github)
+#543: Problem resolving self-referential recursive types
+ (reported by ahgittin@github)
+#550: Minor optimization: prune introspection of "well-known" JDK types
+#552: Improved handling for ISO-8601 (date) format
+ (contributed by Jerome G, geronimo-iia@github)
+#559: Add `getDateFormat()`, `getPropertyNamingStrategy()` in `ObjectMapper`
+#560: @JsonCreator to deserialize BigInteger to Enum
+ (requested by gisupp@github)
+#565: Add support for handling `Map.Entry`
+#571: Add support in ObjectMapper for custom `ObjectReader`, `ObjectWriter` (sub-classes)
+#572: Override default serialization of Enums
+ (requested by herau@github)
+#576: Add fluent API for adding mixins
+ (contributed by Adam S, adstro@github)
+- Allow use of `Shape.ARRAY` for Enums, as an alias to 'use index'
+- Start using `JsonGenerator.writeStartArray(int)` to help data formats
+  that benefit from knowing number of elements in arrays (and would otherwise
+  need to buffer values to know length)
+
 2.4.4 (not yet released)
 
 (jackson-core)#158: Setter confusion on assignable types
@@ -37,10 +72,12 @@
 - Fixed a problem with `acceptJsonFormatVisitor` with Collection/array types that
   are marked with `@JsonValue`; could cause NPE in JSON Schema generator module.
 
+<<<<<<< HEAD
+2.4.2 (14-Aug-2014)
+=======
 2.4.2 (13-Aug-2014)
+>>>>>>> 2.4
 
-#506: Index is never set for Collection and Array in InvalidFormatException.Reference
- (reported by Fabrice D, fabdouglas@github)
 #515: Mixin annotations lost when using a mixin class hierarchy with non-mixin interfaces
  (reported by 'stevebread@github')
 - Fixed a problem related to [jackson-dataformat-smile#19].
@@ -58,6 +95,9 @@
 
 #491: Temporary work-around for issue #490 (full fix for 2.5 needs to be
   in `jackson-annotations`)
+#506: Index is never set for Collection and Array in InvalidFormatException.Reference
+ (reported by Fabrice D, fabdouglas@github)
+- Fixed a problem related to [jackson-dataformat-smile#19].
 
 2.4.1 (17-Jun-2014)
 
diff --git a/src/main/java/com/fasterxml/jackson/databind/AnnotationIntrospector.java b/src/main/java/com/fasterxml/jackson/databind/AnnotationIntrospector.java
index 70b32d4..b793afb 100644
--- a/src/main/java/com/fasterxml/jackson/databind/AnnotationIntrospector.java
+++ b/src/main/java/com/fasterxml/jackson/databind/AnnotationIntrospector.java
@@ -5,10 +5,8 @@
 
 import com.fasterxml.jackson.annotation.JsonFormat;
 import com.fasterxml.jackson.annotation.JsonInclude;
-
 import com.fasterxml.jackson.core.Version;
 import com.fasterxml.jackson.core.Versioned;
-
 import com.fasterxml.jackson.databind.JsonDeserializer;
 import com.fasterxml.jackson.databind.JsonSerializer;
 import com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder;
@@ -571,7 +569,12 @@
      * field) defines which Bean/Map properties are to be included in
      * serialization.
      * If no annotation is found, method should return given second
-     * argument; otherwise value indicated by the annotation
+     * argument; otherwise value indicated by the annotation.
+     *<p>
+     * Note that meaning of inclusion value depends on whether it is for
+     * a Class or property (field/method/constructor): in former case,
+     * it is the default for all properties; in latter case it is specific
+     * override for annotated property.
      *
      * @return Enumerated value indicating which properties to include
      *   in serialization
@@ -581,6 +584,16 @@
     }
 
     /**
+     * Method for checking whether content (entries) of a {@link java.util.Map} property
+     * are to be included during serialization or not.
+     * 
+     * @since 2.5
+     */
+    public JsonInclude.Include findSerializationInclusionForContent(Annotated a, JsonInclude.Include defValue) {
+        return defValue;
+    }
+
+    /**
      * Method for accessing annotated type definition that a
      * method/field can have, to be used as the type for serialization
      * instead of the runtime type.
@@ -1006,4 +1019,47 @@
     public boolean hasCreatorAnnotation(Annotated a) {
         return false;
     }
+
+    /*
+    /**********************************************************
+    /* Overridable methods: may be used as low-level extension
+    /* points.
+    /**********************************************************
+     */
+
+    /**
+     * Method that should be used by sub-classes for ALL
+     * annotation access;
+     * overridable so 
+     * that sub-classes may, if they choose to, mangle actual access to
+     * block access ("hide" annotations) or perhaps change it.
+     *<p>
+     * Default implementation is simply:
+     *<code>
+     *  return annotated.getAnnotation(annoClass);
+     *</code>
+     * 
+     * @since 2.5
+     */
+    protected <A extends Annotation> A _findAnnotation(Annotated annotated,
+            Class<A> annoClass) {
+        return annotated.getAnnotation(annoClass);
+    }
+
+    /**
+     * Method that should be used by sub-classes for ALL
+     * annotation existence access;
+     * overridable so  that sub-classes may, if they choose to, mangle actual access to
+     * block access ("hide" annotations) or perhaps change value seen.
+     *<p>
+     * Default implementation is simply:
+     *<code>
+     *  return annotated.hasAnnotation(annoClass);
+     *</code>
+     * 
+     * @since 2.5
+     */
+    protected boolean _hasAnnotation(Annotated annotated, Class<? extends Annotation> annoClass) {
+        return annotated.hasAnnotation(annoClass);
+    }
 }
diff --git a/src/main/java/com/fasterxml/jackson/databind/BeanDescription.java b/src/main/java/com/fasterxml/jackson/databind/BeanDescription.java
index 393300b..27998f0 100644
--- a/src/main/java/com/fasterxml/jackson/databind/BeanDescription.java
+++ b/src/main/java/com/fasterxml/jackson/databind/BeanDescription.java
@@ -187,6 +187,11 @@
     public abstract JsonInclude.Include findSerializationInclusion(JsonInclude.Include defValue);
 
     /**
+     * @since 2.5
+     */
+    public abstract JsonInclude.Include findSerializationInclusionForContent(JsonInclude.Include defValue);
+    
+    /**
      * Method for checking what is the expected format for POJO, as
      * defined by defaults and possible annotations.
      * Note that this may be further refined by per-property annotations.
diff --git a/src/main/java/com/fasterxml/jackson/databind/DeserializationFeature.java b/src/main/java/com/fasterxml/jackson/databind/DeserializationFeature.java
index 0808671..d36a890 100644
--- a/src/main/java/com/fasterxml/jackson/databind/DeserializationFeature.java
+++ b/src/main/java/com/fasterxml/jackson/databind/DeserializationFeature.java
@@ -243,12 +243,27 @@
      * If disabled, standard POJOs can only be bound from JSON null or
      * JSON Object (standard meaning that no custom deserializers or
      * constructors are defined; both of which can add support for other
-     * kinds of JSON values); if enable, empty JSON String can be taken
+     * kinds of JSON values); if enabled, empty JSON String can be taken
      * to be equivalent of JSON null.
      *<p>
      * Feature is disabled by default.
      */
     ACCEPT_EMPTY_STRING_AS_NULL_OBJECT(false),
+
+    /**
+     * Feature that can be enabled to allow empty JSON Array
+     * value (that is, <code>[ ]</code>) to be bound to POJOs as null.
+     * If disabled, standard POJOs can only be bound from JSON null or
+     * JSON Object (standard meaning that no custom deserializers or
+     * constructors are defined; both of which can add support for other
+     * kinds of JSON values); if enabled, empty JSON Array will be taken
+     * to be equivalent of JSON null.
+     *<p>
+     * Feature is disabled by default.
+     * 
+     * @since 2.5
+     */
+    ACCEPT_EMPTY_ARRAY_AS_NULL_OBJECT(false),
     
     /**
      * Feature that allows unknown Enum values to be parsed as null values. 
diff --git a/src/main/java/com/fasterxml/jackson/databind/JavaType.java b/src/main/java/com/fasterxml/jackson/databind/JavaType.java
index 3b93479..110d3c3 100644
--- a/src/main/java/com/fasterxml/jackson/databind/JavaType.java
+++ b/src/main/java/com/fasterxml/jackson/databind/JavaType.java
@@ -3,6 +3,7 @@
 import java.lang.reflect.Modifier;
 
 import com.fasterxml.jackson.core.type.ResolvedType;
+import com.fasterxml.jackson.databind.type.TypeFactory;
 
 /**
  * Base class for type token classes used both to contain information
@@ -319,10 +320,40 @@
 
     @Override
     public JavaType containedType(int index) { return null; }
-
+       
     @Override
     public String containedTypeName(int index) { return null; }
 
+    @Override
+    public abstract Class<?> getParameterSource();
+    
+    /*
+    /**********************************************************
+    /* Extended API beyond ResolvedType
+    /**********************************************************
+     */
+    
+    // NOTE: not defined in Resolved type
+    /**
+     * Convenience method that is functionally same as:
+     *<code>
+     * JavaType t = containedType(index);
+     * if (t == null) {
+     *    t = TypeFactory.unknownType();
+     * }
+     *</code>
+     * and typically used to eliminate need for null checks for common case
+     * where we just want to check if containedType is available first; and
+     * if not, use "unknown type" (which translates to <code>java.lang.Object</code>
+     * basically).
+     *
+     * @since 2.5
+     */
+    public JavaType containedTypeOrUnknown(int index) {
+        JavaType t = containedType(index);
+        return (t == null)  ? TypeFactory.unknownType() : t;
+    }
+
     /*
     /**********************************************************
     /* Semi-public API, accessing handlers
diff --git a/src/main/java/com/fasterxml/jackson/databind/MapperFeature.java b/src/main/java/com/fasterxml/jackson/databind/MapperFeature.java
index 7753c88..6a19b10 100644
--- a/src/main/java/com/fasterxml/jackson/databind/MapperFeature.java
+++ b/src/main/java/com/fasterxml/jackson/databind/MapperFeature.java
@@ -182,6 +182,8 @@
      * explicitly annotated for such use.
      *<p>
      * Feature is enabled by default, for backwards compatibility reasons.
+     * 
+     * @since 2.2
      */
     ALLOW_FINAL_FIELDS_AS_MUTATORS(true),
     
diff --git a/src/main/java/com/fasterxml/jackson/databind/MappingIterator.java b/src/main/java/com/fasterxml/jackson/databind/MappingIterator.java
index 04e8077..ff3f394 100644
--- a/src/main/java/com/fasterxml/jackson/databind/MappingIterator.java
+++ b/src/main/java/com/fasterxml/jackson/databind/MappingIterator.java
@@ -48,8 +48,7 @@
      */
     @Deprecated
     protected MappingIterator(JavaType type, JsonParser jp, DeserializationContext ctxt,
-            JsonDeserializer<?> deser)
-    {
+            JsonDeserializer<?> deser) {
         this(type, jp, ctxt, deser, true, null);
     }
 
@@ -107,12 +106,12 @@
         try {
             return hasNextValue();
         } catch (JsonMappingException e) {
-            throw new RuntimeJsonMappingException(e.getMessage(), e);
+            return _handleMappingException(e);
         } catch (IOException e) {
-            throw new RuntimeException(e.getMessage(), e);
+            return _handleIOException(e);
         }
     }
-
+    
     @Override
     public T next()
     {
@@ -132,7 +131,7 @@
     
     @Override
     public void close() throws IOException{
-        if(_parser != null) {
+        if (_parser != null) {
             _parser.close();
         }
     }
@@ -176,11 +175,11 @@
         // caller should always call 'hasNext[Value]' first; but let's ensure:
         if (!_hasNextChecked) {
             if (!hasNextValue()) {
-                throw new NoSuchElementException();
+                return _throwNoSuchElement();
             }
         }
         if (_parser == null) {
-            throw new NoSuchElementException();
+            return _throwNoSuchElement();
         }
         _hasNextChecked = false;
         T result;
@@ -198,7 +197,7 @@
 
     /**
      * Convenience method for reading all entries accessible via
-     * this iterator
+     * this iterator; resulting container will be a {@link java.util.ArrayList}.
      * 
      * @return List of entries read
      * 
@@ -216,13 +215,27 @@
      * 
      * @since 2.2
      */
-    public List<T> readAll(List<T> resultList) throws IOException
+    public <L extends List<? super T>> L readAll(L resultList) throws IOException
     {
         while (hasNextValue()) {
-    		    resultList.add(nextValue());
+            resultList.add(nextValue());
         }
         return resultList;
     }
+
+    /**
+     * Convenience method for reading all entries accessible via
+     * this iterator
+     * 
+     * @since 2.5
+     */
+    public <C extends Collection<? super T>> C readAll(C results) throws IOException
+    {
+        while (hasNextValue()) {
+            results.add(nextValue());
+        }
+        return results;
+    }
     
     /*
     /**********************************************************
@@ -263,4 +276,22 @@
     public JsonLocation getCurrentLocation() {
         return _parser.getCurrentLocation();
     }
+
+    /*
+    /**********************************************************
+    /* Helper methods
+    /**********************************************************
+     */
+
+    protected <R> R _throwNoSuchElement() {
+        throw new NoSuchElementException();
+    }
+    
+    protected <R> R _handleMappingException(JsonMappingException e) {
+        throw new RuntimeJsonMappingException(e.getMessage(), e);
+    }
+
+    protected <R> R _handleIOException(IOException e) {
+        throw new RuntimeException(e.getMessage(), e);
+    }
 }
diff --git a/src/main/java/com/fasterxml/jackson/databind/ObjectMapper.java b/src/main/java/com/fasterxml/jackson/databind/ObjectMapper.java
index 76e8d62..51e6af0 100644
--- a/src/main/java/com/fasterxml/jackson/databind/ObjectMapper.java
+++ b/src/main/java/com/fasterxml/jackson/databind/ObjectMapper.java
@@ -198,11 +198,6 @@
     // Quick little shortcut, to avoid having to use global TypeFactory instance...
     private final static JavaType JSON_NODE_TYPE = SimpleType.constructUnsafe(JsonNode.class);
 
-    /* !!! 03-Apr-2009, tatu: Should try to avoid direct reference... but not
-     *   sure what'd be simple and elegant way. So until then:
-     */
-    protected final static ClassIntrospector DEFAULT_INTROSPECTOR = BasicClassIntrospector.instance;
-
     // 16-May-2009, tatu: Ditto ^^^
     protected final static AnnotationIntrospector DEFAULT_ANNOTATION_INTROSPECTOR = new JacksonAnnotationIntrospector();
 
@@ -214,8 +209,10 @@
      * Base settings contain defaults used for all {@link ObjectMapper}
      * instances.
      */
-    protected final static BaseSettings DEFAULT_BASE = new BaseSettings(DEFAULT_INTROSPECTOR,
-            DEFAULT_ANNOTATION_INTROSPECTOR, STD_VISIBILITY_CHECKER, null, TypeFactory.defaultInstance(),
+    protected final static BaseSettings DEFAULT_BASE = new BaseSettings(
+            null, // can not share global ClassIntrospector any more (2.5+)
+            DEFAULT_ANNOTATION_INTROSPECTOR,
+            STD_VISIBILITY_CHECKER, null, TypeFactory.defaultInstance(),
             null, StdDateFormat.instance, null,
             Locale.getDefault(),
 //            TimeZone.getDefault()
@@ -339,7 +336,7 @@
 
     /**
      * We will use a separate main-level Map for keeping track
-     * of root-level deserializers. This is where most succesful
+     * of root-level deserializers. This is where most successful
      * cache lookups get resolved.
      * Map will contain resolvers for all kinds of types, including
      * container types: this is different from the component cache
@@ -374,8 +371,7 @@
      * Java Beans (based on method names and Jackson-specific annotations),
      * but does not support JAXB annotations.
      */
-    public ObjectMapper()
-    {
+    public ObjectMapper() {
         this(null, null, null);
     }
 
@@ -384,8 +380,7 @@
      * for constructing necessary {@link JsonParser}s and/or
      * {@link JsonGenerator}s.
      */
-    public ObjectMapper(JsonFactory jf)
-    {
+    public ObjectMapper(JsonFactory jf) {
         this(jf, null, null);
     }
 
@@ -448,9 +443,11 @@
 
         HashMap<ClassKey,Class<?>> mixins = new HashMap<ClassKey,Class<?>>();
         _mixInAnnotations = mixins;
-        _serializationConfig = new SerializationConfig(DEFAULT_BASE,
+
+        BaseSettings base = DEFAULT_BASE.withClassIntrospector(defaultClassIntrospector());
+        _serializationConfig = new SerializationConfig(base,
                     _subtypeResolver, mixins);
-        _deserializationConfig = new DeserializationConfig(DEFAULT_BASE,
+        _deserializationConfig = new DeserializationConfig(base,
                     _subtypeResolver, mixins);
 
         // Some overrides we may need
@@ -468,6 +465,22 @@
     }
 
     /**
+     * Overridable helper method used to construct default {@link ClassIntrospector}
+     * to use.
+     * 
+     * @since 2.5
+     */
+    protected ClassIntrospector defaultClassIntrospector() {
+        return new BasicClassIntrospector();
+    }
+    
+    /*
+    /**********************************************************
+    /* Methods sub-classes MUST override
+    /**********************************************************
+     */
+    
+    /**
      * Method for creating a new {@link ObjectMapper} instance that
      * has same initial configuration as this instance. Note that this
      * also requires making a copy of the underlying {@link JsonFactory}
@@ -482,15 +495,13 @@
      * 
      * @since 2.1
      */
-    public ObjectMapper copy()
-    {
+    public ObjectMapper copy() {
         _checkInvalidCopy(ObjectMapper.class);
         return new ObjectMapper(this);
     }
 
     /**
      * @since 2.1
-     * @param exp
      */
     protected void _checkInvalidCopy(Class<?> exp)
     {
@@ -499,7 +510,60 @@
                     +" (version: "+version()+") does not override copy(); it has to");
         }
     }
+
+    /**
+     * Factory method sub-classes must override, to produce {@link ObjectReader}
+     * instances of proper sub-type
+     * 
+     * @since 2.5
+     */
+    protected ObjectReader _newReader(DeserializationConfig config) {
+        return new ObjectReader(this, config);
+    }
+
+    /**
+     * Factory method sub-classes must override, to produce {@link ObjectReader}
+     * instances of proper sub-type
+     * 
+     * @since 2.5
+     */
+    protected ObjectReader _newReader(DeserializationConfig config,
+            JavaType valueType, Object valueToUpdate,
+            FormatSchema schema, InjectableValues injectableValues) {
+        return new ObjectReader(this, config, valueType, valueToUpdate, schema, injectableValues);
+    }
+
+    /**
+     * Factory method sub-classes must override, to produce {@link ObjectWriter}
+     * instances of proper sub-type
+     * 
+     * @since 2.5
+     */
+    protected ObjectWriter _newWriter(SerializationConfig config) {
+        return new ObjectWriter(this, config);
+    }
+
+    /**
+     * Factory method sub-classes must override, to produce {@link ObjectWriter}
+     * instances of proper sub-type
+     * 
+     * @since 2.5
+     */
+    protected ObjectWriter _newWriter(SerializationConfig config, FormatSchema schema) {
+        return new ObjectWriter(this, config, schema);
+    }
     
+    /**
+     * Factory method sub-classes must override, to produce {@link ObjectWriter}
+     * instances of proper sub-type
+     * 
+     * @since 2.5
+     */
+    protected ObjectWriter _newWriter(SerializationConfig config,
+            JavaType rootType, PrettyPrinter pp) {
+        return new ObjectWriter(this, config, rootType, pp);
+    }
+
     /*
     /**********************************************************
     /* Versioned impl
@@ -514,7 +578,7 @@
     public Version version() {
         return com.fasterxml.jackson.databind.cfg.PackageVersion.VERSION;
     }
-    
+
     /*
     /**********************************************************
     /* Module registration, discovery
@@ -874,7 +938,7 @@
     /* Configuration: mix-in annotations
     /**********************************************************
      */
-    
+
     /**
      * Method to use for defining mix-in annotations to use for augmenting
      * annotations that processable (serializable / deserializable)
@@ -886,8 +950,10 @@
      * Annotations from source classes (and their supertypes)
      * will <b>override</b>
      * annotations that target classes (and their super-types) have.
+     *
+     * @since 2.5
      */
-    public final void setMixInAnnotations(Map<Class<?>, Class<?>> sourceMixins)
+    public ObjectMapper setMixIns(Map<Class<?>, Class<?>> sourceMixins)
     {
         _mixInAnnotations.clear();
         if (sourceMixins != null && sourceMixins.size() > 0) {
@@ -895,6 +961,7 @@
                 _mixInAnnotations.put(new ClassKey(en.getKey()), en.getValue());
             }
         }
+        return this;
     }
 
     /**
@@ -906,35 +973,39 @@
      * @param target Class (or interface) whose annotations to effectively override
      * @param mixinSource Class (or interface) whose annotations are to
      *   be "added" to target's annotations, overriding as necessary
-     */
-    public final void addMixInAnnotations(Class<?> target, Class<?> mixinSource)
-    {
-        _mixInAnnotations.put(new ClassKey(target), mixinSource);
-    }
-
-    /**
-     * Method to use for adding mix-in annotations to use for augmenting
-     * specified class or interface. All annotations from
-     * <code>mixinSource</code> are taken to override annotations
-     * that <code>target</code> (or its supertypes) has.
      *
-     * @param target Class (or interface) whose annotations to effectively override
-     * @param mixinSource Class (or interface) whose annotations are to
-     *   be "added" to target's annotations, overriding as necessary
+     * @since 2.5
      */
-    public final ObjectMapper addMixIn(Class<?> target, Class<?> mixinSource)
+    public ObjectMapper addMixIn(Class<?> target, Class<?> mixinSource)
     {
         _mixInAnnotations.put(new ClassKey(target), mixinSource);
         return this;
     }
 
-    public final Class<?> findMixInClassFor(Class<?> cls) {
+    public Class<?> findMixInClassFor(Class<?> cls) {
         return (_mixInAnnotations == null) ? null : _mixInAnnotations.get(new ClassKey(cls));
     }
 
-    public final int mixInCount() {
+    public int mixInCount() {
         return (_mixInAnnotations == null) ? 0 : _mixInAnnotations.size();
     }
+
+
+    /**
+     * @deprecated Since 2.5: replaced by a fluent form of the method; {@link #setMixIns}.
+     */
+    @Deprecated
+    public void setMixInAnnotations(Map<Class<?>, Class<?>> sourceMixins) {
+        setMixIns(sourceMixins);
+    }
+
+    /**
+     * @deprecated Since 2.5: replaced by a fluent form of the method; {@link #addMixIn(Class, Class)}.
+     */
+    @Deprecated
+    public final void addMixInAnnotations(Class<?> target, Class<?> mixinSource) {
+        addMixIn(target, mixinSource);
+    }
     
     /*
     /**********************************************************
@@ -1051,6 +1122,14 @@
     }
 
     /**
+     * @since 2.5
+     */
+    public PropertyNamingStrategy getPropertyNamingStrategy() {
+        // arbitrary choice but let's do:
+        return _serializationConfig.getPropertyNamingStrategy();
+    }
+    
+    /**
      * Method for setting defalt POJO property inclusion strategy for serialization.
      */
     public ObjectMapper setSerializationInclusion(JsonInclude.Include incl) {
@@ -1088,12 +1167,23 @@
      * Method for enabling automatic inclusion of type information, needed
      * for proper deserialization of polymorphic types (unless types
      * have been annotated with {@link com.fasterxml.jackson.annotation.JsonTypeInfo}).
+     *<P>
+     * NOTE: use of <code>JsonTypeInfo.As#EXTERNAL_PROPERTY</code> <b>NOT SUPPORTED</b>;
+     * and attempts of do so will throw an {@link IllegalArgumentException} to make
+     * this limitation explicit.
      * 
      * @param applicability Defines kinds of types for which additional type information
      *    is added; see {@link DefaultTyping} for more information.
      */
     public ObjectMapper enableDefaultTyping(DefaultTyping applicability, JsonTypeInfo.As includeAs)
     {
+        /* 18-Sep-2014, tatu: Let's add explicit check to ensure no one tries to
+         *   use "As.EXTERNAL_PROPERTY", since that will not work (with 2.5+)
+         */
+        if (includeAs == JsonTypeInfo.As.EXTERNAL_PROPERTY) {
+            throw new IllegalArgumentException("Can not use includeAs of "+includeAs);
+        }
+        
         TypeResolverBuilder<?> typer = new DefaultTypeResolverBuilder(applicability);
         // we'll always use full class name, when using defaulting
         typer = typer.init(JsonTypeInfo.Id.CLASS, null);
@@ -1353,6 +1443,14 @@
     }
 
     /**
+     * @since 2.5
+     */
+    public DateFormat getDateFormat() {
+        // arbitrary choice but let's do:
+        return _serializationConfig.getDateFormat();
+    }
+    
+    /**
      * Method for configuring {@link HandlerInstantiator} to use for creating
      * instances of handlers (such as serializers, deserializers, type and type
      * id resolvers), given a class.
@@ -1968,8 +2066,7 @@
      * @param n Root node of the tree that resulting parser will read from
      */
     @Override
-    public JsonParser treeAsTokens(TreeNode n)
-    {
+    public JsonParser treeAsTokens(TreeNode n) {
         return new TreeTraversingParser((JsonNode) n, this);
     }
 
@@ -2051,7 +2148,8 @@
      *<p>
      * NOTE: since this method does NOT throw exceptions, but internal
      * processing may, caller usually has little information as to why
-     * serialization would fail.
+     * serialization would fail. If you want access to internal {@link Exception},
+     * call {@link #canSerialize(Class, AtomicReference)} instead.
      *
      * @return True if mapper can find a serializer for instances of
      *  given class (potentially serializable), false otherwise (not
@@ -2075,8 +2173,15 @@
     /**
      * Method that can be called to check whether mapper thinks
      * it could deserialize an Object of given type.
-     * Check is done
-     * by checking whether a deserializer can be found for the type.
+     * Check is done by checking whether a registered deserializer can
+     * be found or built for the type; if not (either by no mapping being
+     * found, or through an <code>Exception</code> being thrown, false
+     * is returned.
+     *<p>
+     * <b>NOTE</b>: in case an exception is thrown during course of trying
+     * co construct matching deserializer, it will be effectively swallowed.
+     * If you want access to that exception, call
+     * {@link #canDeserialize(JavaType, AtomicReference)} instead.
      *
      * @return True if mapper can find a serializer for instances of
      *  given class (potentially serializable), false otherwise (not
@@ -2381,8 +2486,9 @@
      * Convenience method for constructing {@link ObjectWriter}
      * with default settings.
      */
-    public ObjectWriter writer() {
-        return new ObjectWriter(this, getSerializationConfig());
+    @SuppressWarnings("unchecked")
+    public <W extends ObjectWriter> W writer() {
+        return (W) _newWriter(getSerializationConfig());
     }
 
     /**
@@ -2390,8 +2496,9 @@
      * specified feature enabled (compared to settings that this
      * mapper instance has).
      */
-    public ObjectWriter writer(SerializationFeature feature) {
-        return new ObjectWriter(this, getSerializationConfig().with(feature));
+    @SuppressWarnings("unchecked")
+    public <W extends ObjectWriter> W writer(SerializationFeature feature) {
+        return (W) _newWriter(getSerializationConfig().with(feature));
     }
 
     /**
@@ -2399,9 +2506,10 @@
      * specified features enabled (compared to settings that this
      * mapper instance has).
      */
-    public ObjectWriter writer(SerializationFeature first,
+    @SuppressWarnings("unchecked")
+    public <W extends ObjectWriter> W writer(SerializationFeature first,
             SerializationFeature... other) {
-        return new ObjectWriter(this, getSerializationConfig().with(first, other));
+        return (W) _newWriter(getSerializationConfig().with(first, other));
     }
     
     /**
@@ -2409,16 +2517,18 @@
      * serialize objects using specified {@link DateFormat}; or, if
      * null passed, using timestamp (64-bit number.
      */
-    public ObjectWriter writer(DateFormat df) {
-        return new ObjectWriter(this, getSerializationConfig().with(df));
+    @SuppressWarnings("unchecked")
+    public <W extends ObjectWriter> W writer(DateFormat df) {
+        return (W) _newWriter(getSerializationConfig().with(df));
     }
     
     /**
      * Factory method for constructing {@link ObjectWriter} that will
      * serialize objects using specified JSON View (filter).
      */
-    public ObjectWriter writerWithView(Class<?> serializationView) {
-        return new ObjectWriter(this, getSerializationConfig().withView(serializationView));
+    @SuppressWarnings("unchecked")
+    public <W extends ObjectWriter> W writerWithView(Class<?> serializationView) {
+        return (W) _newWriter(getSerializationConfig().withView(serializationView));
     }
     
     /**
@@ -2427,8 +2537,9 @@
      * runtime type of value. Type must be a super-type of runtime
      * type.
      */
-    public ObjectWriter writerWithType(Class<?> rootType) {
-        return new ObjectWriter(this, getSerializationConfig(),
+    @SuppressWarnings("unchecked")
+    public <W extends ObjectWriter> W writerWithType(Class<?> rootType) {
+        return (W) _newWriter(getSerializationConfig(),
                 // 15-Mar-2013, tatu: Important! Indicate that static typing is needed:
                 ((rootType == null) ? null :_typeFactory.constructType(rootType)),
                 /*PrettyPrinter*/null);
@@ -2439,8 +2550,9 @@
      * serialize objects using specified root type, instead of actual
      * runtime type of value. Type must be a super-type of runtime type.
      */
-    public ObjectWriter writerWithType(TypeReference<?> rootType) {
-        return new ObjectWriter(this, getSerializationConfig(),
+    @SuppressWarnings("unchecked")
+    public <W extends ObjectWriter> W writerWithType(TypeReference<?> rootType) {
+        return (W) _newWriter(getSerializationConfig(),
                 // 15-Mar-2013, tatu: Important! Indicate that static typing is needed:
                 ((rootType == null) ? null : _typeFactory.constructType(rootType)),
                 /*PrettyPrinter*/null);
@@ -2451,8 +2563,9 @@
      * serialize objects using specified root type, instead of actual
      * runtime type of value. Type must be a super-type of runtime type.
      */
-    public ObjectWriter writerWithType(JavaType rootType) {
-        return new ObjectWriter(this, getSerializationConfig(), rootType, /*PrettyPrinter*/null);
+    @SuppressWarnings("unchecked")
+    public <W extends ObjectWriter> W writerWithType(JavaType rootType) {
+        return (W) _newWriter(getSerializationConfig(), rootType, /*PrettyPrinter*/null);
     }
     
     /**
@@ -2460,19 +2573,21 @@
      * serialize objects using specified pretty printer for indentation
      * (or if null, no pretty printer)
      */
-    public ObjectWriter writer(PrettyPrinter pp) {
+    @SuppressWarnings("unchecked")
+    public <W extends ObjectWriter> W writer(PrettyPrinter pp) {
         if (pp == null) { // need to use a marker to indicate explicit disabling of pp
             pp = ObjectWriter.NULL_PRETTY_PRINTER;
         }
-        return new ObjectWriter(this, getSerializationConfig(), /*root type*/ null, pp);
+        return (W) _newWriter(getSerializationConfig(), /*root type*/ null, pp);
     }
     
     /**
      * Factory method for constructing {@link ObjectWriter} that will
      * serialize objects using the default pretty printer for indentation
      */
-    public ObjectWriter writerWithDefaultPrettyPrinter() {
-        return new ObjectWriter(this, getSerializationConfig(),
+    @SuppressWarnings("unchecked")
+    public <W extends ObjectWriter> W writerWithDefaultPrettyPrinter() {
+        return (W) _newWriter(getSerializationConfig(),
                 /*root type*/ null, _defaultPrettyPrinter());
     }
     
@@ -2480,9 +2595,9 @@
      * Factory method for constructing {@link ObjectWriter} that will
      * serialize objects using specified filter provider.
      */
-    public ObjectWriter writer(FilterProvider filterProvider) {
-        return new ObjectWriter(this,
-                getSerializationConfig().withFilters(filterProvider));
+    @SuppressWarnings("unchecked")
+    public <W extends ObjectWriter> W writer(FilterProvider filterProvider) {
+        return (W) _newWriter(getSerializationConfig().withFilters(filterProvider));
     }
     
     /**
@@ -2492,9 +2607,10 @@
      * 
      * @param schema Schema to pass to generator
      */
-    public ObjectWriter writer(FormatSchema schema) {
+    @SuppressWarnings("unchecked")
+    public <W extends ObjectWriter> W writer(FormatSchema schema) {
         _verifySchemaType(schema);
-        return new ObjectWriter(this, getSerializationConfig(), schema);
+        return (W) _newWriter(getSerializationConfig(), schema);
     }
 
     /**
@@ -2503,8 +2619,9 @@
      * 
      * @since 2.1
      */
-    public ObjectWriter writer(Base64Variant defaultBase64) {
-        return new ObjectWriter(this, getSerializationConfig().with(defaultBase64));
+    @SuppressWarnings("unchecked")
+    public <W extends ObjectWriter> W writer(Base64Variant defaultBase64) {
+        return (W) _newWriter(getSerializationConfig().with(defaultBase64));
     }
 
     /**
@@ -2513,8 +2630,9 @@
      * 
      * @since 2.3
      */
-    public ObjectWriter writer(CharacterEscapes escapes) {
-        return writer().with(escapes);
+    @SuppressWarnings("unchecked")
+    public <W extends ObjectWriter> W writer(CharacterEscapes escapes) {
+        return (W) _newWriter(getSerializationConfig()).with(escapes);
     }
 
     /**
@@ -2523,8 +2641,9 @@
      * 
      * @since 2.3
      */
-    public ObjectWriter writer(ContextAttributes attrs) {
-        return new ObjectWriter(this, getSerializationConfig().with(attrs));
+    @SuppressWarnings("unchecked")
+    public <W extends ObjectWriter> W writer(ContextAttributes attrs) {
+        return (W) _newWriter(getSerializationConfig().with(attrs));
     }
     
     /*
@@ -2539,9 +2658,9 @@
      * default settings. Note that the resulting instance is NOT usable as is,
      * without defining expected value type.
      */
-    public ObjectReader reader() {
-        return new ObjectReader(this, getDeserializationConfig())
-            .with(_injectableValues);
+    @SuppressWarnings("unchecked")
+    public <T extends ObjectReader> T reader() {
+        return (T) _newReader(getDeserializationConfig()).with(_injectableValues);
     }
 
     /**
@@ -2551,8 +2670,9 @@
      * Note that the resulting instance is NOT usable as is,
      * without defining expected value type.
      */
-    public ObjectReader reader(DeserializationFeature feature) {
-        return new ObjectReader(this, getDeserializationConfig().with(feature));
+    @SuppressWarnings("unchecked")
+    public <T extends ObjectReader> T reader(DeserializationFeature feature) {
+        return (T) _newReader(getDeserializationConfig().with(feature));
     }
 
     /**
@@ -2562,9 +2682,10 @@
      * Note that the resulting instance is NOT usable as is,
      * without defining expected value type.
      */
-    public ObjectReader reader(DeserializationFeature first,
+    @SuppressWarnings("unchecked")
+    public <T extends ObjectReader> T reader(DeserializationFeature first,
             DeserializationFeature... other) {
-        return new ObjectReader(this, getDeserializationConfig().with(first, other));
+        return (T) _newReader(getDeserializationConfig().with(first, other));
     }
     
     /**
@@ -2577,10 +2698,10 @@
      * Runtime type of value object is used for locating deserializer,
      * unless overridden by other factory methods of {@link ObjectReader}
      */
-    public ObjectReader readerForUpdating(Object valueToUpdate)
-    {
+    @SuppressWarnings("unchecked")
+    public <T extends ObjectReader> T readerForUpdating(Object valueToUpdate) {
         JavaType t = _typeFactory.constructType(valueToUpdate.getClass());
-        return new ObjectReader(this, getDeserializationConfig(), t, valueToUpdate,
+        return (T) _newReader(getDeserializationConfig(), t, valueToUpdate,
                 null, _injectableValues);
     }
 
@@ -2588,9 +2709,9 @@
      * Factory method for constructing {@link ObjectReader} that will
      * read or update instances of specified type
      */
-    public ObjectReader reader(JavaType type)
-    {
-        return new ObjectReader(this, getDeserializationConfig(), type, null,
+    @SuppressWarnings("unchecked")
+    public <T extends ObjectReader> T reader(JavaType type) {
+        return (T) _newReader(getDeserializationConfig(), type, null,
                 null, _injectableValues);
     }
 
@@ -2598,27 +2719,29 @@
      * Factory method for constructing {@link ObjectReader} that will
      * read or update instances of specified type
      */
-    public ObjectReader reader(Class<?> type)
-    {
-        return reader(_typeFactory.constructType(type));
+    @SuppressWarnings("unchecked")
+    public <T extends ObjectReader> T reader(Class<?> type) {
+        return (T) _newReader(getDeserializationConfig(), _typeFactory.constructType(type), null,
+                null, _injectableValues);
     }
 
     /**
      * Factory method for constructing {@link ObjectReader} that will
      * read or update instances of specified type
      */
-    public ObjectReader reader(TypeReference<?> type)
-    {
-        return reader(_typeFactory.constructType(type));
+    @SuppressWarnings("unchecked")
+    public <T extends ObjectReader> T reader(TypeReference<?> type) {
+        return (T)_newReader(getDeserializationConfig(), _typeFactory.constructType(type), null,
+                null, _injectableValues);
     }
 
     /**
      * Factory method for constructing {@link ObjectReader} that will
      * use specified {@link JsonNodeFactory} for constructing JSON trees.
      */
-    public ObjectReader reader(JsonNodeFactory f)
-    {
-        return new ObjectReader(this, getDeserializationConfig()).with(f);
+    @SuppressWarnings("unchecked")
+    public <T extends ObjectReader> T reader(JsonNodeFactory f) {
+        return (T) _newReader(getDeserializationConfig()).with(f);
     }
 
     /**
@@ -2628,9 +2751,10 @@
      * 
      * @param schema Schema to pass to parser
      */
-    public ObjectReader reader(FormatSchema schema) {
+    @SuppressWarnings("unchecked")
+    public <T extends ObjectReader> T reader(FormatSchema schema) {
         _verifySchemaType(schema);
-        return new ObjectReader(this, getDeserializationConfig(), null, null,
+        return (T)_newReader(getDeserializationConfig(), null, null,
                 schema, _injectableValues);
     }
 
@@ -2640,8 +2764,9 @@
      * 
      * @param injectableValues Injectable values to use
      */
-    public ObjectReader reader(InjectableValues injectableValues) {
-        return new ObjectReader(this, getDeserializationConfig(), null, null,
+    @SuppressWarnings("unchecked")
+    public <T extends ObjectReader> T reader(InjectableValues injectableValues) {
+        return (T)_newReader(getDeserializationConfig(), null, null,
                 null, injectableValues);
     }
 
@@ -2649,8 +2774,9 @@
      * Factory method for constructing {@link ObjectReader} that will
      * deserialize objects using specified JSON View (filter).
      */
-    public ObjectReader readerWithView(Class<?> view) {
-        return new ObjectReader(this, getDeserializationConfig().withView(view));
+    @SuppressWarnings("unchecked")
+    public <T extends ObjectReader> T readerWithView(Class<?> view) {
+        return (T) _newReader(getDeserializationConfig().withView(view));
     }
 
     /**
@@ -2659,8 +2785,9 @@
      * 
      * @since 2.1
      */
-    public ObjectReader reader(Base64Variant defaultBase64) {
-        return new ObjectReader(this, getDeserializationConfig().with(defaultBase64));
+    @SuppressWarnings("unchecked")
+    public <T extends ObjectReader> T reader(Base64Variant defaultBase64) {
+        return (T) _newReader(getDeserializationConfig().with(defaultBase64));
     }
 
     /**
@@ -2669,16 +2796,17 @@
      * 
      * @since 2.3
      */
-    public ObjectReader reader(ContextAttributes attrs) {
-        return new ObjectReader(this, getDeserializationConfig().with(attrs));
+    @SuppressWarnings("unchecked")
+    public <T extends ObjectReader> T reader(ContextAttributes attrs) {
+        return (T) _newReader(getDeserializationConfig().with(attrs));
     }
-    
+
     /*
     /**********************************************************
     /* Extended Public API: convenience type conversion
     /**********************************************************
      */
-   
+
     /**
      * Convenience method for doing two-step conversion from given value, into
      * instance of given value type. This is functionality equivalent to first
@@ -2991,7 +3119,7 @@
             }
         }
     }
-    
+
     /*
     /**********************************************************
     /* Internal methods for deserialization, overridable
diff --git a/src/main/java/com/fasterxml/jackson/databind/ObjectReader.java b/src/main/java/com/fasterxml/jackson/databind/ObjectReader.java
index a73d4b7..024a6cd 100644
--- a/src/main/java/com/fasterxml/jackson/databind/ObjectReader.java
+++ b/src/main/java/com/fasterxml/jackson/databind/ObjectReader.java
@@ -156,8 +156,7 @@
     /**
      * Constructor used by {@link ObjectMapper} for initial instantiation
      */
-    protected ObjectReader(ObjectMapper mapper, DeserializationConfig config)
-    {
+    protected ObjectReader(ObjectMapper mapper, DeserializationConfig config) {
         this(mapper, config, null, null, null, null);
     }
 
@@ -234,7 +233,7 @@
         _unwrapRoot = config.useRootWrapping();
         _dataFormatReaders = base._dataFormatReaders;
     }
-
+    
     protected ObjectReader(ObjectReader base, JsonFactory f)
     {
         // may need to override ordering, based on data format capabilities
@@ -266,6 +265,104 @@
 
     /*
     /**********************************************************
+    /* Methods sub-classes MUST override, used for constructing
+    /* reader instances, (re)configuring parser instances
+    /**********************************************************
+     */
+
+    /**
+     * Overridable factory method called by various "withXxx()" methods
+     * 
+     * @since 2.5
+     */
+    protected ObjectReader _new(ObjectReader base, JsonFactory f) {
+        return new ObjectReader(base, f);
+    }
+
+    /**
+     * Overridable factory method called by various "withXxx()" methods
+     * 
+     * @since 2.5
+     */
+    protected ObjectReader _new(ObjectReader base, DeserializationConfig config) {
+        return new ObjectReader(base, config);
+    }
+
+    /**
+     * Overridable factory method called by various "withXxx()" methods
+     * 
+     * @since 2.5
+     */
+    protected ObjectReader _new(ObjectReader base, DeserializationConfig config,
+            JavaType valueType, JsonDeserializer<Object> rootDeser, Object valueToUpdate,
+            FormatSchema schema, InjectableValues injectableValues,
+            DataFormatReaders dataFormatReaders) {
+        return new ObjectReader(base, config, valueType, rootDeser,  valueToUpdate,
+                 schema,  injectableValues, dataFormatReaders);
+    }
+
+    /**
+     * Factory method used to create {@link MappingIterator} instances;
+     * either default, or custom subtype.
+     * 
+     * @since 2.5
+     */
+    protected <T> MappingIterator<T> _newIterator(JavaType valueType,
+            JsonParser parser, DeserializationContext ctxt,
+            JsonDeserializer<?> deser, boolean parserManaged, Object valueToUpdate)
+    {
+            return new MappingIterator<T>(valueType, parser, ctxt,
+                    deser, parserManaged, valueToUpdate);
+    }
+
+    /*
+    /**********************************************************
+    /* Methods sub-classes may choose to override, if customized
+    /* initialization is needed.
+    /**********************************************************
+     */
+
+    /**
+     * NOTE: changed from static to non-static in 2.5; unfortunate but
+     * necessary change to support overridability
+     */
+    protected JsonToken _initForReading(JsonParser p) throws IOException
+    {
+        if (_schema != null) {
+            p.setSchema(_schema);
+        }
+        /* First: must point to a token; if not pointing to one, advance.
+         * This occurs before first read from JsonParser, as well as
+         * after clearing of current token.
+         */
+        JsonToken t = p.getCurrentToken();
+        if (t == null) { // and then we must get something...
+            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");
+            }
+        }
+        return t;
+    }
+
+    /**
+     * Alternative to {@link #_initForReading(JsonParser)} 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
+     */
+    protected void _initForMultiRead(JsonParser p) throws IOException {
+        if (_schema != null) {
+            p.setSchema(_schema);
+        }
+    }
+    
+    /*
+    /**********************************************************
     /* Life-cycle, fluent factory methods
     /**********************************************************
      */
@@ -280,7 +377,7 @@
      */
     public ObjectReader with(DeserializationFeature feature) {
         return _with(_config.with(feature));
-    }    
+    }
 
     /**
      * Method for constructing a new reader instance that is configured
@@ -299,22 +396,21 @@
     public ObjectReader withFeatures(DeserializationFeature... features) {
         return _with(_config.withFeatures(features));
     }    
-    
+
     /**
      * Method for constructing a new reader instance that is configured
      * with specified feature disabled.
      */
     public ObjectReader without(DeserializationFeature feature) {
         return _with(_config.without(feature)); 
-    }    
+    }
 
     /**
      * Method for constructing a new reader instance that is configured
      * with specified features disabled.
      */
     public ObjectReader without(DeserializationFeature first,
-            DeserializationFeature... other)
-    {
+            DeserializationFeature... other) {
         return _with(_config.without(first, other));
     }    
 
@@ -338,7 +434,7 @@
         if (_injectableValues == injectableValues) {
             return this;
         }
-        return new ObjectReader(this, _config,
+        return _new(this, _config,
                 _valueType, _rootDeserializer, _valueToUpdate,
                 _schema, injectableValues, _dataFormatReaders);
     }
@@ -370,7 +466,7 @@
         if (f == _parserFactory) {
             return this;
         }
-        ObjectReader r = new ObjectReader(this, f);
+        ObjectReader r = _new(this, f);
         // Also, try re-linking, if possible...
         if (f.getCodec() == null) {
             f.setCodec(r);
@@ -405,7 +501,7 @@
             return this;
         }
         _verifySchemaType(schema);
-        return new ObjectReader(this, _config, _valueType, _rootDeserializer, _valueToUpdate,
+        return _new(this, _config, _valueType, _rootDeserializer, _valueToUpdate,
                 schema, _injectableValues, _dataFormatReaders);
     }
 
@@ -427,7 +523,7 @@
         if (det != null) {
             det = det.withType(valueType);
         }
-        return new ObjectReader(this, _config, valueType, rootDeser,
+        return _new(this, _config, valueType, rootDeser,
                 _valueToUpdate, _schema, _injectableValues, det);
     }    
 
@@ -489,7 +585,7 @@
         } else {
             t = _valueType;
         }
-        return new ObjectReader(this, _config, t, _rootDeserializer, value,
+        return _new(this, _config, t, _rootDeserializer, value,
                 _schema, _injectableValues, _dataFormatReaders);
     }
 
@@ -542,8 +638,7 @@
      * 
      * @since 2.1
      */
-    public ObjectReader withFormatDetection(ObjectReader... readers)
-    {
+    public ObjectReader withFormatDetection(ObjectReader... readers) {
         return withFormatDetection(new DataFormatReaders(readers));
     }
 
@@ -562,9 +657,8 @@
      * 
      * @since 2.1
      */
-    public ObjectReader withFormatDetection(DataFormatReaders readers)
-    {
-        return new ObjectReader(this, _config, _valueType, _rootDeserializer, _valueToUpdate,
+    public ObjectReader withFormatDetection(DataFormatReaders readers) {
+        return _new(this, _config, _valueType, _rootDeserializer, _valueToUpdate,
                 _schema, _injectableValues, readers);
     }
 
@@ -572,32 +666,45 @@
      * @since 2.3
      */
     public ObjectReader with(ContextAttributes attrs) {
-        DeserializationConfig newConfig = _config.with(attrs);
-        return (newConfig == _config) ? this :  new ObjectReader(this, newConfig);
+        return _with(_config.with(attrs));
     }
 
     /**
      * @since 2.3
      */
     public ObjectReader withAttributes(Map<Object,Object> attrs) {
-        DeserializationConfig newConfig = _config.withAttributes(attrs);
-        return (newConfig == _config) ? this :  new ObjectReader(this, newConfig);
+        return _with(_config.withAttributes(attrs));
     }
 
     /**
      * @since 2.3
      */
     public ObjectReader withAttribute(Object key, Object value) {
-        DeserializationConfig newConfig = _config.withAttribute(key, value);
-        return (newConfig == _config) ? this :  new ObjectReader(this, newConfig);
+        return _with( _config.withAttribute(key, value));
     }
 
     /**
      * @since 2.3
      */
     public ObjectReader withoutAttribute(Object key) {
-        DeserializationConfig newConfig = _config.withoutAttribute(key);
-        return (newConfig == _config) ? this :  new ObjectReader(this, newConfig);
+        return _with(_config.withoutAttribute(key));
+    }
+
+    /*
+    /**********************************************************
+    /* Overridable factory methods that sub-classes MUST override
+    /**********************************************************
+     */
+    
+    protected ObjectReader _with(DeserializationConfig newConfig) {
+        if (newConfig == _config) {
+            return this;
+        }
+        ObjectReader r = _new(this, newConfig);
+        if (_dataFormatReaders != null) {
+            r  = r.withFormatDetection(_dataFormatReaders.with(newConfig));
+        }
+        return r;
     }
     
     /*
@@ -818,24 +925,25 @@
     public JsonParser treeAsTokens(TreeNode n) {
         return new TreeTraversingParser((JsonNode) n, this);
     }
-     /**
-      * Convenience method that binds content read using given parser, using
-      * configuration of this reader, except that content is bound as
-      * JSON tree instead of configured root value type.
-      *<p>
-      * Note: if an object was specified with {@link #withValueToUpdate}, it
-      * will be ignored.
-      *<p>
-      * NOTE: this method never tries to auto-detect format, since actual
-      * (data-format specific) parser is given.
-      */
-     @SuppressWarnings("unchecked")
-     @Override
-     public <T extends TreeNode> T readTree(JsonParser jp)
-         throws IOException, JsonProcessingException
-     {
-         return (T) _bindAsTree(jp);
-     }
+
+    /**
+     * Convenience method that binds content read using given parser, using
+     * configuration of this reader, except that content is bound as
+     * JSON tree instead of configured root value type.
+     *<p>
+     * Note: if an object was specified with {@link #withValueToUpdate}, it
+     * will be ignored.
+     *<p>
+     * NOTE: this method never tries to auto-detect format, since actual
+     * (data-format specific) parser is given.
+     */
+    @SuppressWarnings("unchecked")
+    @Override
+    public <T extends TreeNode> T readTree(JsonParser jp)
+            throws IOException, JsonProcessingException
+    {
+        return (T) _bindAsTree(jp);
+    }
      
     @Override
     public void writeTree(JsonGenerator jgen, TreeNode rootNode) {
@@ -1047,7 +1155,7 @@
     {
         DeserializationContext ctxt = createDeserializationContext(jp, _config);
         // false -> do not close as caller gave parser instance
-        return new MappingIterator<T>(_valueType, jp, ctxt,
+        return _newIterator(_valueType, jp, ctxt,
                 _findRootDeserializer(ctxt, _valueType),
                 false, _valueToUpdate);
     }
@@ -1091,13 +1199,11 @@
         if (_dataFormatReaders != null) {
             _reportUndetectableSource(src);
         }
-        JsonParser jp = _parserFactory.createParser(src);
-        if (_schema != null) {
-            jp.setSchema(_schema);
-        }
-        jp.nextToken();
-        DeserializationContext ctxt = createDeserializationContext(jp, _config);
-        return new MappingIterator<T>(_valueType, jp, ctxt,
+        JsonParser p = _parserFactory.createParser(src);
+        _initForMultiRead(p);
+        p.nextToken();
+        DeserializationContext ctxt = createDeserializationContext(p, _config);
+        return _newIterator(_valueType, p, ctxt,
                 _findRootDeserializer(ctxt, _valueType), true, _valueToUpdate);
     }
     
@@ -1113,13 +1219,11 @@
         if (_dataFormatReaders != null) {
             _reportUndetectableSource(json);
         }
-        JsonParser jp = _parserFactory.createParser(json);
-        if (_schema != null) {
-            jp.setSchema(_schema);
-        }
-        jp.nextToken();
-        DeserializationContext ctxt = createDeserializationContext(jp, _config);
-        return new MappingIterator<T>(_valueType, jp, ctxt,
+        JsonParser p = _parserFactory.createParser(json);
+        _initForMultiRead(p);
+        p.nextToken();
+        DeserializationContext ctxt = createDeserializationContext(p, _config);
+        return _newIterator(_valueType, p, ctxt,
                 _findRootDeserializer(ctxt, _valueType), true, _valueToUpdate);
     }
 
@@ -1178,8 +1282,7 @@
      */
 
     @Override
-    public <T> T treeToValue(TreeNode n, Class<T> valueType)
-        throws JsonProcessingException
+    public <T> T treeToValue(TreeNode n, Class<T> valueType) throws JsonProcessingException
     {
         try {
             return readValue(treeAsTokens(n), valueType);
@@ -1191,8 +1294,7 @@
     }    
     
     @Override
-    public void writeValue(JsonGenerator jgen, Object value) throws IOException, JsonProcessingException
-    {
+    public void writeValue(JsonGenerator jgen, Object value) throws IOException, JsonProcessingException {
         throw new UnsupportedOperationException("Not implemented for ObjectReader");
     }
 
@@ -1205,8 +1307,7 @@
     /**
      * Actual implementation of value reading+binding operation.
      */
-    protected Object _bind(JsonParser jp, Object valueToUpdate)
-        throws IOException, JsonParseException, JsonMappingException
+    protected Object _bind(JsonParser jp, Object valueToUpdate) 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)
@@ -1241,12 +1342,8 @@
         return result;
     }
     
-    protected Object _bindAndClose(JsonParser jp, Object valueToUpdate)
-        throws IOException, JsonParseException, JsonMappingException
+    protected Object _bindAndClose(JsonParser jp, Object valueToUpdate) throws IOException
     {
-        if (_schema != null) {
-            jp.setSchema(_schema);
-        }
         try {
             Object result;
             JsonToken t = _initForReading(jp);
@@ -1281,8 +1378,17 @@
         }
     }
 
-    protected JsonNode _bindAsTree(JsonParser jp)
-        throws IOException, JsonParseException, JsonMappingException
+    protected JsonNode _bindAndCloseAsTree(JsonParser jp) throws IOException {
+        try {
+            return _bindAsTree(jp);
+        } finally {
+            try {
+                jp.close();
+            } catch (IOException ioe) { }
+        }
+    }
+    
+    protected JsonNode _bindAsTree(JsonParser jp) throws IOException
     {
         JsonNode result;
         JsonToken t = _initForReading(jp);
@@ -1302,58 +1408,62 @@
         return result;
     }
     
-    protected JsonNode _bindAndCloseAsTree(JsonParser jp)
-        throws IOException, JsonParseException, JsonMappingException
-    {
-        if (_schema != null) {
-            jp.setSchema(_schema);
-        }
-        try {
-            return _bindAsTree(jp);
-        } finally {
-            try {
-                jp.close();
-            } catch (IOException ioe) { }
-        }
-    }
-    
     /**
      * @since 2.1
      */
-    protected <T> MappingIterator<T> _bindAndReadValues(JsonParser p,
-            Object valueToUpdate)
-        throws IOException, JsonProcessingException
+    protected <T> MappingIterator<T> _bindAndReadValues(JsonParser p, Object valueToUpdate) throws IOException
     {
-        if (_schema != null) {
-            p.setSchema(_schema);
-        }
+        _initForMultiRead(p);
         p.nextToken();
         DeserializationContext ctxt = createDeserializationContext(p, _config);
-        return new MappingIterator<T>(_valueType, p, ctxt, 
-                _findRootDeserializer(ctxt, _valueType),
-                true, _valueToUpdate);
-    }
-    
-    protected static JsonToken _initForReading(JsonParser jp)
-        throws IOException, JsonParseException, JsonMappingException
-    {
-        /* First: must point to a token; if not pointing to one, advance.
-         * This occurs before first read from JsonParser, as well as
-         * after clearing of current token.
-         */
-        JsonToken t = jp.getCurrentToken();
-        if (t == null) { // and then we must get something...
-            t = jp.nextToken();
-            if (t == null) {
-                /* [JACKSON-546] Throw mapping exception, since it's failure to map,
-                 *   not an actual parsing problem
-                 */
-                throw JsonMappingException.from(jp, "No content to map due to end-of-input");
-            }
-        }
-        return t;
+        return _newIterator(_valueType, p, ctxt, 
+                _findRootDeserializer(ctxt, _valueType), true, _valueToUpdate);
     }
 
+    protected Object _unwrapAndDeserialize(JsonParser jp, DeserializationContext ctxt,
+            JavaType rootType, JsonDeserializer<Object> deser) throws IOException
+    {
+        String expName = _config.getRootName();
+        if (expName == null) {
+            PropertyName pname = _rootNames.findRootName(rootType, _config);
+            expName = pname.getSimpleName();
+        }
+        if (jp.getCurrentToken() != JsonToken.START_OBJECT) {
+            throw JsonMappingException.from(jp, "Current token not START_OBJECT (needed to unwrap root name '"
+                    +expName+"'), but "+jp.getCurrentToken());
+        }
+        if (jp.nextToken() != JsonToken.FIELD_NAME) {
+            throw JsonMappingException.from(jp, "Current token not FIELD_NAME (to contain expected root name '"
+                    +expName+"'), but "+jp.getCurrentToken());
+        }
+        String actualName = jp.getCurrentName();
+        if (!expName.equals(actualName)) {
+            throw JsonMappingException.from(jp, "Root name '"+actualName+"' does not match expected ('"
+                    +expName+"') for type "+rootType);
+        }
+        // ok, then move to value itself....
+        jp.nextToken();
+        Object result;
+        if (_valueToUpdate == null) {
+            result = deser.deserialize(jp, ctxt);
+        } else {
+            deser.deserialize(jp, ctxt, _valueToUpdate);
+            result = _valueToUpdate;                    
+        }
+        // and last, verify that we now get matching END_OBJECT
+        if (jp.nextToken() != JsonToken.END_OBJECT) {
+            throw JsonMappingException.from(jp, "Current token not END_OBJECT (to match wrapper object with root name '"
+                    +expName+"'), but "+jp.getCurrentToken());
+        }
+        return result;
+    }
+
+    /*
+    /**********************************************************
+    /* Helper methods, locating deserializers etc
+    /**********************************************************
+     */
+    
     /**
      * Method called to locate deserializer for the passed root-level value.
      */
@@ -1389,8 +1499,7 @@
      * by configuration. Method also is NOT to throw an exception if
      * access fails.
      */
-    protected JsonDeserializer<Object> _prefetchRootDeserializer(
-            DeserializationConfig config, JavaType valueType)
+    protected JsonDeserializer<Object> _prefetchRootDeserializer(DeserializationConfig config, JavaType valueType)
     {
         if (valueType == null || !_config.isEnabled(DeserializationFeature.EAGER_DESERIALIZER_FETCH)) {
             return null;
@@ -1413,45 +1522,6 @@
         }
         return deser;
     }
-    
-    protected Object _unwrapAndDeserialize(JsonParser jp, DeserializationContext ctxt,
-            JavaType rootType, JsonDeserializer<Object> deser)
-        throws IOException, JsonParseException, JsonMappingException
-    {
-        String expName = _config.getRootName();
-        if (expName == null) {
-            PropertyName pname = _rootNames.findRootName(rootType, _config);
-            expName = pname.getSimpleName();
-        }
-        if (jp.getCurrentToken() != JsonToken.START_OBJECT) {
-            throw JsonMappingException.from(jp, "Current token not START_OBJECT (needed to unwrap root name '"
-                    +expName+"'), but "+jp.getCurrentToken());
-        }
-        if (jp.nextToken() != JsonToken.FIELD_NAME) {
-            throw JsonMappingException.from(jp, "Current token not FIELD_NAME (to contain expected root name '"
-                    +expName+"'), but "+jp.getCurrentToken());
-        }
-        String actualName = jp.getCurrentName();
-        if (!expName.equals(actualName)) {
-            throw JsonMappingException.from(jp, "Root name '"+actualName+"' does not match expected ('"
-                    +expName+"') for type "+rootType);
-        }
-        // ok, then move to value itself....
-        jp.nextToken();
-        Object result;
-        if (_valueToUpdate == null) {
-            result = deser.deserialize(jp, ctxt);
-        } else {
-            deser.deserialize(jp, ctxt, _valueToUpdate);
-            result = _valueToUpdate;                    
-        }
-        // and last, verify that we now get matching END_OBJECT
-        if (jp.nextToken() != JsonToken.END_OBJECT) {
-            throw JsonMappingException.from(jp, "Current token not END_OBJECT (to match wrapper object with root name '"
-                    +expName+"'), but "+jp.getCurrentToken());
-        }
-        return result;
-    }
 
     /*
     /**********************************************************
@@ -1556,17 +1626,6 @@
         // 04-Jan-2010, tatu: we do actually need the provider too... (for polymorphic deser)
         return _context.createInstance(cfg, jp, _injectableValues);
     }
-    
-    protected ObjectReader _with(DeserializationConfig newConfig) {
-        if (newConfig == _config) {
-            return this;
-        }
-        if (_dataFormatReaders != null) {
-            return new ObjectReader(this, newConfig)
-                .withFormatDetection(_dataFormatReaders.with(newConfig));
-        }
-        return new ObjectReader(this, newConfig);
-    }
 
     protected void _reportUndetectableSource(Object src) throws JsonProcessingException
     {
diff --git a/src/main/java/com/fasterxml/jackson/databind/SerializerProvider.java b/src/main/java/com/fasterxml/jackson/databind/SerializerProvider.java
index c433836..b820b5d 100644
--- a/src/main/java/com/fasterxml/jackson/databind/SerializerProvider.java
+++ b/src/main/java/com/fasterxml/jackson/databind/SerializerProvider.java
@@ -37,9 +37,6 @@
 public abstract class SerializerProvider
     extends DatabindContext
 {
-    @Deprecated // since 2.3, not used by anything it seems
-    protected final static JavaType TYPE_OBJECT = TypeFactory.defaultInstance().uncheckedSimpleType(Object.class);
-
     /**
      * Setting for determining whether mappings for "unknown classes" should be
      * cached for faster resolution. Usually this isn't needed, but maybe it
@@ -459,8 +456,7 @@
      *   finding any serializer
      */
     @SuppressWarnings("unchecked")
-    public JsonSerializer<Object> findValueSerializer(Class<?> valueType,
-            BeanProperty property)
+    public JsonSerializer<Object> findValueSerializer(Class<?> valueType, BeanProperty property)
         throws JsonMappingException
     {
         // Fast lookup from local lookup thingy works?
@@ -474,11 +470,7 @@
                 if (ser == null) {
                     // If neither, must create
                     ser = _createAndCacheUntypedSerializer(valueType);
-                    // Not found? Must use the unknown type serializer
-                    /* Couldn't create? Need to return the fallback serializer, which
-                     * most likely will report an error: but one question is whether
-                     * we should cache it?
-                     */
+                    // Not found? Must use the unknown type serializer, which will report error later on
                     if (ser == null) {
                         ser = getUnknownTypeSerializer(valueType);
                         // Should this be added to lookups?
@@ -508,22 +500,14 @@
     public JsonSerializer<Object> findValueSerializer(JavaType valueType, BeanProperty property)
         throws JsonMappingException
     {
-        // Fast lookup from local lookup thingy works?
+        // (see comments from above method)
         JsonSerializer<Object> ser = _knownSerializers.untypedValueSerializer(valueType);
         if (ser == null) {
-            // If not, maybe shared map already has it?
             ser = _serializerCache.untypedValueSerializer(valueType);
             if (ser == null) {
-                // If neither, must create
                 ser = _createAndCacheUntypedSerializer(valueType);
-                // Not found? Must use the unknown type serializer
-                /* Couldn't create? Need to return the fallback serializer, which
-                 * most likely will report an error: but one question is whether
-                 * we should cache it?
-                 */
                 if (ser == null) {
                     ser = getUnknownTypeSerializer(valueType.getRawClass());
-                    // Should this be added to lookups?
                     if (CACHE_UNKNOWN_MAPPINGS) {
                         _serializerCache.addAndResolveNonTypedSerializer(valueType, ser, this);
                     }
@@ -535,6 +519,62 @@
     }
 
     /**
+     * Method variant used when we do NOT want contextualization to happen; it will need
+     * to be handled at a later point, but caller wants to be able to do that
+     * as needed; sometimes to avoid infinite loops
+     * 
+     * @since 2.5
+     */
+    public JsonSerializer<Object> findValueSerializer(Class<?> valueType) throws JsonMappingException
+    {
+        // (see comments from above method)
+        JsonSerializer<Object> ser = _knownSerializers.untypedValueSerializer(valueType);
+        if (ser == null) {
+            ser = _serializerCache.untypedValueSerializer(valueType);
+            if (ser == null) {
+                ser = _serializerCache.untypedValueSerializer(_config.constructType(valueType));
+                if (ser == null) {
+                    ser = _createAndCacheUntypedSerializer(valueType);
+                    if (ser == null) {
+                        ser = getUnknownTypeSerializer(valueType);
+                        if (CACHE_UNKNOWN_MAPPINGS) {
+                            _serializerCache.addAndResolveNonTypedSerializer(valueType, ser, this);
+                        }
+                    }
+                }
+            }
+        }
+        return ser;
+    }
+
+    /**
+     * Method variant used when we do NOT want contextualization to happen; it will need
+     * to be handled at a later point, but caller wants to be able to do that
+     * as needed; sometimes to avoid infinite loops
+     * 
+     * @since 2.5
+     */
+    public JsonSerializer<Object> findValueSerializer(JavaType valueType)
+        throws JsonMappingException
+    {
+        // (see comments from above method)
+        JsonSerializer<Object> ser = _knownSerializers.untypedValueSerializer(valueType);
+        if (ser == null) {
+            ser = _serializerCache.untypedValueSerializer(valueType);
+            if (ser == null) {
+                ser = _createAndCacheUntypedSerializer(valueType);
+                if (ser == null) {
+                    ser = getUnknownTypeSerializer(valueType.getRawClass());
+                    if (CACHE_UNKNOWN_MAPPINGS) {
+                        _serializerCache.addAndResolveNonTypedSerializer(valueType, ser, this);
+                    }
+                }
+            }
+        }
+        return ser;
+    }
+    
+    /**
      * Similar to {@link #findValueSerializer(JavaType, BeanProperty)}, but used
      * when finding "primary" property value serializer (one directly handling
      * value of the property). Difference has to do with contextual resolution,
@@ -779,6 +819,17 @@
         return _unknownTypeSerializer;
     }
 
+    /**
+     * Helper method called to see if given serializer is considered to be
+     * something returned by {@link #getUnknownTypeSerializer}, that is, something
+     * for which no regular serializer was found or constructed.
+     * 
+     * @since 2.5
+     */
+    public boolean isUnknownTypeSerializer(JsonSerializer<?> ser) {
+        return (ser == _unknownTypeSerializer) || (ser == null);
+    }
+    
     /*
     /**********************************************************
     /* Methods for creating instances based on annotations
@@ -807,19 +858,6 @@
      */
 
     /**
-     * @deprecated Since 2.3 (and to be removed from 2.4); use
-     *   {@link #handlePrimaryContextualization} or {@link #handleSecondaryContextualization}
-     *   instead
-     */
-    @Deprecated
-    public JsonSerializer<?> handleContextualization(JsonSerializer<?> ser,
-            BeanProperty property)
-        throws JsonMappingException
-    {
-        return handleSecondaryContextualization(ser, property);
-    }
-    
-    /**
      * Method called for primary property serializers (ones
      * directly created to serialize values of a POJO property),
      * to handle details of resolving
@@ -1034,19 +1072,26 @@
      * @return Serializer if one can be found, null if not.
      */
     protected JsonSerializer<Object> _findExplicitUntypedSerializer(Class<?> runtimeType)
-		throws JsonMappingException
+        throws JsonMappingException
     {        
         // Fast lookup from local lookup thingy works?
         JsonSerializer<Object> ser = _knownSerializers.untypedValueSerializer(runtimeType);
-        if (ser != null) {
-            return ser;
+        if (ser == null) {
+            // If not, maybe shared map already has it?
+            ser = _serializerCache.untypedValueSerializer(runtimeType);
+            if (ser == null) {
+                ser = _createAndCacheUntypedSerializer(runtimeType);
+                /* 18-Sep-2014, tatu: This is unfortunate patch over related change
+                 *    that pushes creation of "unknown type" serializer deeper down
+                 *    in BeanSerializerFactory; as a result, we need to "undo" creation
+                 *    here.
+                 */
+                if (isUnknownTypeSerializer(ser)) {
+                    return null;
+                }
+            }
         }
-        // If not, maybe shared map already has it?
-        ser = _serializerCache.untypedValueSerializer(runtimeType);
-        if (ser != null) {
-            return ser;
-        }
-        return _createAndCacheUntypedSerializer(runtimeType);
+        return ser;
     }
 
     /*
diff --git a/src/main/java/com/fasterxml/jackson/databind/annotation/JsonNaming.java b/src/main/java/com/fasterxml/jackson/databind/annotation/JsonNaming.java
index c5fb85c..7b94610 100644
--- a/src/main/java/com/fasterxml/jackson/databind/annotation/JsonNaming.java
+++ b/src/main/java/com/fasterxml/jackson/databind/annotation/JsonNaming.java
@@ -15,5 +15,11 @@
 @com.fasterxml.jackson.annotation.JacksonAnnotation
 public @interface JsonNaming
 {
-    public Class<? extends PropertyNamingStrategy> value();
+    /**
+     * @return Type of {@link PropertyNamingStrategy} to use, if any; default value of
+     *    <code>PropertyNamingStrategy.class</code> means "no strategy specified"
+     *    (and may also be used for overriding to remove otherwise applicable
+     *    naming strategy)
+     */
+    public Class<? extends PropertyNamingStrategy> value() default PropertyNamingStrategy.class;
 }
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 b31ccb1..555b3ad 100644
--- a/src/main/java/com/fasterxml/jackson/databind/deser/AbstractDeserializer.java
+++ b/src/main/java/com/fasterxml/jackson/databind/deser/AbstractDeserializer.java
@@ -65,8 +65,7 @@
      * 
      * @since 2.3
      */
-    public static AbstractDeserializer constructForNonPOJO(BeanDescription beanDesc)
-    {
+    public static AbstractDeserializer constructForNonPOJO(BeanDescription beanDesc) {
         return new AbstractDeserializer(beanDesc);
     }
     
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 b4e305d..efbb895 100644
--- a/src/main/java/com/fasterxml/jackson/databind/deser/BasicDeserializerFactory.java
+++ b/src/main/java/com/fasterxml/jackson/databind/deser/BasicDeserializerFactory.java
@@ -3,6 +3,7 @@
 import java.lang.reflect.Method;
 import java.util.*;
 import java.util.concurrent.*;
+import java.util.concurrent.atomic.AtomicReference;
 
 import com.fasterxml.jackson.core.JsonLocation;
 import com.fasterxml.jackson.databind.*;
@@ -10,6 +11,7 @@
 import com.fasterxml.jackson.databind.cfg.HandlerInstantiator;
 import com.fasterxml.jackson.databind.deser.impl.CreatorCollector;
 import com.fasterxml.jackson.databind.deser.std.*;
+import com.fasterxml.jackson.databind.ext.OptionalHandlerFactory;
 import com.fasterxml.jackson.databind.introspect.*;
 import com.fasterxml.jackson.databind.jsontype.NamedType;
 import com.fasterxml.jackson.databind.jsontype.TypeDeserializer;
@@ -39,6 +41,7 @@
     private final static Class<?> CLASS_STRING = String.class;
     private final static Class<?> CLASS_CHAR_BUFFER = CharSequence.class;
     private final static Class<?> CLASS_ITERABLE = Iterable.class;
+    private final static Class<?> CLASS_MAP_ENTRY = Map.Entry.class;
 
     /**
      * We need a placeholder for creator properties that don't have name
@@ -316,17 +319,55 @@
         VisibilityChecker<?> vchecker = config.getDefaultVisibilityChecker();
         vchecker = intr.findAutoDetectVisibility(beanDesc.getClassInfo(), vchecker);
 
+        /* 24-Sep-2014, tatu: Tricky part first; need to merge resolved property information
+         *  (which has creator parameters sprinkled around) with actual creator
+         *  declarations (which are needed to access creator annotation, amongst other things).
+         *  Easiest to combine that info first, then pass it to remaining processing.
+         */
+        Map<AnnotatedWithParams,BeanPropertyDefinition[]> creatorDefs = _findCreatorsFromProperties(ctxt,
+                beanDesc);
+        
         /* Important: first add factory methods; then constructors, so
          * latter can override former!
          */
-        _addDeserializerFactoryMethods(ctxt, beanDesc, vchecker, intr, creators);
+        _addDeserializerFactoryMethods(ctxt, beanDesc, vchecker, intr, creators, creatorDefs);
         // constructors only usable on concrete types:
         if (beanDesc.getType().isConcrete()) {
-            _addDeserializerConstructors(ctxt, beanDesc, vchecker, intr, creators);
+            _addDeserializerConstructors(ctxt, beanDesc, vchecker, intr, creators, creatorDefs);
         }
         return creators.constructValueInstantiator(config);
     }
 
+    protected Map<AnnotatedWithParams,BeanPropertyDefinition[]> _findCreatorsFromProperties(DeserializationContext ctxt,
+            BeanDescription beanDesc) throws JsonMappingException
+    {
+        Map<AnnotatedWithParams,BeanPropertyDefinition[]> result = Collections.emptyMap();
+        for (BeanPropertyDefinition propDef : beanDesc.findProperties()) {
+            Iterator<AnnotatedParameter> it = propDef.getConstructorParameters();
+            while (it.hasNext()) {
+                AnnotatedParameter param = it.next();
+                AnnotatedWithParams owner = param.getOwner();
+                BeanPropertyDefinition[] defs = result.get(owner);
+                final int index = param.getIndex();
+                
+                if (defs == null) {
+                    if (result.isEmpty()) {
+                        result = new LinkedHashMap<AnnotatedWithParams,BeanPropertyDefinition[]>();
+                    }
+                    defs = new BeanPropertyDefinition[owner.getParameterCount()];
+                    result.put(owner, defs);
+                } else {
+                    if (defs[index] != null) {
+                        throw new IllegalStateException("Conflict: parameter #"+index+" of "+owner
+                                +" bound to more than one property; "+defs[index]+" vs "+propDef);
+                    }
+                }
+                defs[index] = propDef;
+            }
+        }
+        return result;
+    }
+    
     public ValueInstantiator _valueInstantiatorInstance(DeserializationConfig config,
             Annotated annotated, Object instDef)
         throws JsonMappingException
@@ -363,104 +404,108 @@
         return (ValueInstantiator) ClassUtil.createInstance(instClass,
                 config.canOverrideAccessModifiers());
     }
+
+    @Deprecated // since 2.5.0, removed from 2.6.0
+    protected void _addDeserializerConstructors(DeserializationContext ctxt, BeanDescription beanDesc, VisibilityChecker<?> vchecker,
+            AnnotationIntrospector intr, CreatorCollector creators)
+        throws JsonMappingException
+    {
+        _addDeserializerConstructors(ctxt, beanDesc, vchecker, intr, creators,
+                Collections.<AnnotatedWithParams,BeanPropertyDefinition[]>emptyMap());
+    }
     
     protected void _addDeserializerConstructors
         (DeserializationContext ctxt, BeanDescription beanDesc, VisibilityChecker<?> vchecker,
-         AnnotationIntrospector intr, CreatorCollector creators)
+         AnnotationIntrospector intr, CreatorCollector creators,
+         Map<AnnotatedWithParams,BeanPropertyDefinition[]> creatorParams)
         throws JsonMappingException
     {
-        /* First things first: the "default constructor" (zero-arg
-         * constructor; whether implicit or explicit) is NOT included
-         * in list of constructors, so needs to be handled separately.
-         */
+        // First things first: the "default constructor" (zero-arg
+        // constructor; whether implicit or explicit) is NOT included
+        // in list of constructors, so needs to be handled separately.
         AnnotatedConstructor defaultCtor = beanDesc.findDefaultConstructor();
         if (defaultCtor != null) {
             if (!creators.hasDefaultCreator() || intr.hasCreatorAnnotation(defaultCtor)) {
                 creators.setDefaultCreator(defaultCtor);
             }
         }
-
-        PropertyName[] ctorPropNames = null;
-        AnnotatedConstructor propertyCtor = null;
-        for (BeanPropertyDefinition propDef : beanDesc.findProperties()) {
-            if (propDef.getConstructorParameter() != null) {
-                AnnotatedParameter param = propDef.getConstructorParameter();
-                AnnotatedWithParams owner = param.getOwner();
-                if (owner instanceof AnnotatedConstructor) {
-                    if (propertyCtor == null) {
-                        propertyCtor = (AnnotatedConstructor) owner;
-                        ctorPropNames = new PropertyName[propertyCtor.getParameterCount()];
-                    }
-                    ctorPropNames[param.getIndex()] = propDef.getFullName();
-                }
-            }
-        }
-
         for (AnnotatedConstructor ctor : beanDesc.getConstructors()) {
-            int argCount = ctor.getParameterCount();
-            boolean isCreator = intr.hasCreatorAnnotation(ctor) || ctor == propertyCtor;
-            boolean isVisible =  vchecker.isCreatorVisible(ctor);
-            // some single-arg constructors (String, number) are auto-detected
+            final boolean isCreator = intr.hasCreatorAnnotation(ctor);
+            BeanPropertyDefinition[] propDefs = creatorParams.get(ctor);
+            final int argCount = ctor.getParameterCount();
+
+            // some single-arg factory methods (String, number) are auto-detected
             if (argCount == 1) {
-                PropertyName name = (ctor == propertyCtor) ? ctorPropNames[0] : null;
-                _handleSingleArgumentConstructor(ctxt, beanDesc, vchecker, intr, creators,
-                        ctor, isCreator, isVisible, name);
-                continue;
-            }
-            if (!isCreator && !isVisible) {
+                BeanPropertyDefinition propDef = (propDefs == null) ? null : propDefs[0];
+                boolean hasExplicitName = (propDef != null) && propDef.isExplicitlyNamed();
+                Object injectId = intr.findInjectableValueId(ctor.getParameter(0));
+
+                if (hasExplicitName || (injectId != null)) {
+                    CreatorProperty[] properties = new CreatorProperty[1];
+                    PropertyName name = (propDef == null) ? null : propDef.getFullName();
+                    properties[0] = constructCreatorProperty(ctxt, beanDesc, name, 0, ctor.getParameter(0), injectId);
+                    creators.addPropertyCreator(ctor, properties);
+                } else {
+                    /*boolean added = */ _handleSingleArgumentConstructor(ctxt, beanDesc, vchecker, intr, creators,
+                            ctor, isCreator,
+                            vchecker.isCreatorVisible(ctor));
+                }
+                // regardless, fully handled
                 continue;
             }
 
-            // [JACKSON-541] improved handling a bit so:
-            // 2 or more args; all params must have name annotations
-            // ... or @JacksonInject (or equivalent)
-            /* [JACKSON-711] One more possibility; can have 1 or more injectables, and
-             * exactly one non-annotated parameter: if so, it's still delegating.
-             */
-            AnnotatedParameter nonAnnotatedParam = null;
-            int namedCount = 0;
-            int injectCount = 0;
+            // 2 or more args; all params must have names or be injectable
+            AnnotatedParameter nonAnnotatedParam = null;            
             CreatorProperty[] properties = new CreatorProperty[argCount];
+            int explicitNameCount = 0;
+            int implicitNameCount = 0;
+            int injectCount = 0;            
             for (int i = 0; i < argCount; ++i) {
-                AnnotatedParameter param = ctor.getParameter(i);
-                PropertyName name = null;
-                if (ctor == propertyCtor) {
-                    name = ctorPropNames[i];
-                }
-                if (name == null) {
-                    name = _findParamName(param, intr);
-                }
+                final AnnotatedParameter param = ctor.getParameter(i);
+                BeanPropertyDefinition propDef = (propDefs == null) ? null : propDefs[i];
                 Object injectId = intr.findInjectableValueId(param);
-                if (name != null && name.hasSimpleName()) {
-                    ++namedCount;
+                final PropertyName name = (propDef == null) ? null : propDef.getFullName();
+                if (propDef != null && propDef.isExplicitlyNamed()) {
+                    ++explicitNameCount;
                     properties[i] = constructCreatorProperty(ctxt, beanDesc, name, i, param, injectId);
-                } else if (injectId != null) { // injectable
+                    continue;
+                }
+                if (injectId != null) {
                     ++injectCount;
                     properties[i] = constructCreatorProperty(ctxt, beanDesc, name, i, param, injectId);
-                } else {
-                    NameTransformer unwrapper = intr.findUnwrappingNameTransformer(param);
-                    if (unwrapper != null) { // [Issue#265]: allow unwrapped properties
-                        properties[i] = constructCreatorProperty(ctxt, beanDesc,
-                                UNWRAPPED_CREATOR_PARAM_NAME, i, param, null);
-                        ++namedCount;
-                    } else {
-                        if (nonAnnotatedParam == null) {
-                            nonAnnotatedParam = param;
-                        }
+                    continue;
+                }
+                NameTransformer unwrapper = intr.findUnwrappingNameTransformer(param);
+                if (unwrapper != null) {
+                    properties[i] = constructCreatorProperty(ctxt, beanDesc, UNWRAPPED_CREATOR_PARAM_NAME, i, param, null);
+                    ++explicitNameCount;
+                    continue;
+                }
+                // One more thing: implicit names are ok iff ctor has creator annotation
+                if (isCreator) {
+                    if (name != null && !name.isEmpty()) {
+                        ++implicitNameCount;
+                        properties[i] = constructCreatorProperty(ctxt, beanDesc, name, i, param, injectId);
+                        continue;
                     }
                 }
+                if (nonAnnotatedParam == null) {
+                    nonAnnotatedParam = param;
+                }
             }
 
+            final int namedCount = explicitNameCount + implicitNameCount;
             // Ok: if named or injectable, we have more work to do
-            if (isCreator || namedCount > 0 || injectCount > 0) {
+            if (isCreator || explicitNameCount > 0 || injectCount > 0) {
                 // simple case; everything covered:
                 if ((namedCount + injectCount) == argCount) {
                     creators.addPropertyCreator(ctor, properties);
-                } else if ((namedCount == 0) && ((injectCount + 1) == argCount)) {
+                } else if ((explicitNameCount == 0) && ((injectCount + 1) == argCount)) {
                     // [712] secondary: all but one injectable, one un-annotated (un-named)
                     creators.addDelegatingCreator(ctor, properties);
-                } else { // otherwise, record the incomplete parameter for later error messaging.
-                    creators.addIncompeteParameter(nonAnnotatedParam);
+                } else { // otherwise, epic fail
+                    throw new IllegalArgumentException("Argument #"+nonAnnotatedParam.getIndex()
+                            +" of constructor "+ctor+" has no property name annotation; must have name when multiple-parameter constructor annotated as Creator");
                 }
             }
         }
@@ -469,25 +514,9 @@
     protected boolean _handleSingleArgumentConstructor(DeserializationContext ctxt,
             BeanDescription beanDesc, VisibilityChecker<?> vchecker,
             AnnotationIntrospector intr, CreatorCollector creators,
-            AnnotatedConstructor ctor, boolean isCreator, boolean isVisible,
-            PropertyName name)
+            AnnotatedConstructor ctor, boolean isCreator, boolean isVisible)
         throws JsonMappingException
     {
-        // note: if we do have parameter name, it'll be "property constructor":
-        AnnotatedParameter param = ctor.getParameter(0);
-        if (name == null) {
-            name = _findParamName(param, intr);
-        }
-        Object injectId = intr.findInjectableValueId(param);
-    
-        if ((injectId != null) || (name != null && name.hasSimpleName())) { // property-based
-            // We know there's a name and it's only 1 parameter.
-            CreatorProperty[] properties = new CreatorProperty[1];
-            properties[0] = constructCreatorProperty(ctxt, beanDesc, name, 0, param, injectId);
-            creators.addPropertyCreator(ctor, properties);
-            return true;
-        }
-    
         // otherwise either 'simple' number, String, or general delegate:
         Class<?> type = ctor.getRawParameterType(0);
         if (type == String.class) {
@@ -528,15 +557,25 @@
         return false;
     }
 
+    @Deprecated // since 2.5, remove from 2.6
+    protected void _addDeserializerFactoryMethods(DeserializationContext ctxt, BeanDescription beanDesc, VisibilityChecker<?> vchecker,
+            AnnotationIntrospector intr, CreatorCollector creators)
+        throws JsonMappingException
+    {
+        _addDeserializerFactoryMethods(ctxt, beanDesc, vchecker, intr, creators,
+                Collections.<AnnotatedWithParams,BeanPropertyDefinition[]>emptyMap());
+    }
+
     protected void _addDeserializerFactoryMethods
         (DeserializationContext ctxt, BeanDescription beanDesc, VisibilityChecker<?> vchecker,
-         AnnotationIntrospector intr, CreatorCollector creators)
+         AnnotationIntrospector intr, CreatorCollector creators,
+         Map<AnnotatedWithParams,BeanPropertyDefinition[]> creatorParams)
         throws JsonMappingException
     {
         final DeserializationConfig config = ctxt.getConfig();
         for (AnnotatedMethod factory : beanDesc.getFactoryMethods()) {
-            boolean isCreator = intr.hasCreatorAnnotation(factory);
-            int argCount = factory.getParameterCount();
+            final boolean isCreator = intr.hasCreatorAnnotation(factory);
+            final int argCount = factory.getParameterCount();
             // zero-arg methods must be annotated; if so, are "default creators" [JACKSON-850]
             if (argCount == 0) {
                 if (isCreator) {
@@ -544,60 +583,87 @@
                 }
                 continue;
             }
+
+            final BeanPropertyDefinition[] propDefs = creatorParams.get(factory);
             // some single-arg factory methods (String, number) are auto-detected
             if (argCount == 1) {
-                AnnotatedParameter param = factory.getParameter(0);
-                PropertyName pn = _findParamName(param, intr);
-                String name = (pn == null) ? null : pn.getSimpleName();
-                Object injectId = intr.findInjectableValueId(param);
-
-                if ((injectId == null) && (name == null || name.length() == 0)) { // not property based
-                    _handleSingleArgumentFactory(config, beanDesc, vchecker, intr, creators,
+                BeanPropertyDefinition propDef = (propDefs == null) ? null : propDefs[0];
+                boolean hasExplicitName = (propDef != null) && propDef.isExplicitlyNamed();
+                final Object injectId = intr.findInjectableValueId(factory.getParameter(0));
+                if ((injectId == null) && !hasExplicitName) { // not property based
+                    /*boolean added=*/ _handleSingleArgumentFactory(config, beanDesc, vchecker, intr, creators,
                             factory, isCreator);
                     // otherwise just ignored
                     continue;
                 }
                 // fall through if there's name
             } else {
-                // more than 2 args, must be @JsonCreator
-                if (!intr.hasCreatorAnnotation(factory)) {
+                // more than 2 args, must have @JsonCreator
+                if (!isCreator) {
                     continue;
                 }
             }
             // 1 or more args; all params must have name annotations
             AnnotatedParameter nonAnnotatedParam = null;            
             CreatorProperty[] properties = new CreatorProperty[argCount];
-            int namedCount = 0;
-            int injectCount = 0;            
+            int implicitNameCount = 0;
+            int explicitNameCount = 0;
+            int injectCount = 0;
+            
             for (int i = 0; i < argCount; ++i) {
-                AnnotatedParameter param = factory.getParameter(i);
-                PropertyName name = _findParamName(param, intr);
+                final AnnotatedParameter param = factory.getParameter(i);
+                BeanPropertyDefinition propDef = (propDefs == null) ? null : propDefs[i];
                 Object injectId = intr.findInjectableValueId(param);
-                if (name != null && name.hasSimpleName()) {
-                    ++namedCount;
+                final PropertyName name = (propDef == null) ? null : propDef.getFullName();
+
+                if (propDef != null && propDef.isExplicitlyNamed()) {
+                    ++explicitNameCount;
                     properties[i] = constructCreatorProperty(ctxt, beanDesc, name, i, param, injectId);
-                } else if (injectId != null) {
+                    continue;
+                }
+                if (injectId != null) {
                     ++injectCount;
                     properties[i] = constructCreatorProperty(ctxt, beanDesc, name, i, param, injectId);
-                } else {
-                    NameTransformer unwrapper = intr.findUnwrappingNameTransformer(param);
-                    if (unwrapper != null) {
-                        properties[i] = constructCreatorProperty(ctxt, beanDesc, UNWRAPPED_CREATOR_PARAM_NAME, i, param, null);
-                        ++namedCount;
-                    } else {
-                        if (nonAnnotatedParam == null) {
-                            nonAnnotatedParam = param;
-                        }
+                    continue;
+                }
+                NameTransformer unwrapper = intr.findUnwrappingNameTransformer(param);
+                if (unwrapper != null) {
+                    properties[i] = constructCreatorProperty(ctxt, beanDesc, UNWRAPPED_CREATOR_PARAM_NAME, i, param, null);
+                    ++implicitNameCount;
+                    continue;
+                }
+                // One more thing: implicit names are ok iff ctor has creator annotation
+                if (isCreator) {
+                    if (name != null && !name.isEmpty()) {
+                        ++implicitNameCount;
+                        properties[i] = constructCreatorProperty(ctxt, beanDesc, name, i, param, injectId);
+                        continue;
                     }
                 }
+                /* 25-Sep-2014, tatu: Actually, we may end up "losing" naming due to higher-priority constructor
+                 *  (see TestCreators#testConstructorCreator() test). And just to avoid running into that problem,
+                 *  let's add one more work around
+                 */
+                /*
+                PropertyName name2 = _findExplicitParamName(param, intr);
+                if (name2 != null && !name2.isEmpty()) {
+                    // Hmmh. Ok, fine. So what are we to do with it... ?
+                    // For now... skip. May need to revisit this, should this become problematic
+                    continue main_loop;
+                }
+                */
+                if (nonAnnotatedParam == null) {
+                    nonAnnotatedParam = param;
+                }
             }
-
+            final int namedCount = explicitNameCount + implicitNameCount;
+            
             // Ok: if named or injectable, we have more work to do
-            if (isCreator || namedCount > 0 || injectCount > 0) {
+            if (isCreator || explicitNameCount > 0 || injectCount > 0) {
                 // simple case; everything covered:
                 if ((namedCount + injectCount) == argCount) {
                     creators.addPropertyCreator(factory, properties);
-                } else if ((namedCount == 0) && ((injectCount + 1) == argCount)) {
+                } else if ((explicitNameCount == 0) && ((injectCount + 1) == argCount)) {
                     // [712] secondary: all but one injectable, one un-annotated (un-named)
                     creators.addDelegatingCreator(factory, properties);
                 } else { // otherwise, epic fail
@@ -646,7 +712,7 @@
             }
             return true;
         }
-        if (intr.hasCreatorAnnotation(factory)) {
+        if (isCreator) {
             creators.addDelegatingCreator(factory, null);
             return true;
         }
@@ -708,7 +774,7 @@
         }
         return prop;
     }
-
+    
     protected PropertyName _findParamName(AnnotatedParameter param, AnnotationIntrospector intr)
     {
         if (param != null && intr != null) {
@@ -726,6 +792,32 @@
         }
         return null;
     }
+
+    protected PropertyName _findExplicitParamName(AnnotatedParameter param, AnnotationIntrospector intr)
+    {
+        if (param != null && intr != null) {
+            return intr.findNameForDeserialization(param);
+        }
+        return null;
+    }
+
+    protected PropertyName _findImplicitParamName(AnnotatedParameter param, AnnotationIntrospector intr)
+    {
+        String str = intr.findImplicitPropertyName(param);
+        if (str != null && !str.isEmpty()) {
+            return new PropertyName(str);
+        }
+        return null;
+    }
+    
+    protected boolean _hasExplicitParamName(AnnotatedParameter param, AnnotationIntrospector intr)
+    {
+        if (param != null && intr != null) {
+            PropertyName n = intr.findNameForDeserialization(param);
+            return (n != null) && n.hasSimpleName();
+        }
+        return false;
+    }
     
     /*
     /**********************************************************
@@ -743,7 +835,7 @@
         
         // Very first thing: is deserializer hard-coded for elements?
         JsonDeserializer<Object> contentDeser = elemType.getValueHandler();
-        // Then optional type info (1.5): if type has been resolved, we may already know type deserializer:
+        // Then optional type info: if type has been resolved, we may already know type deserializer:
         TypeDeserializer elemTypeDeser = elemType.getTypeHandler();
         // but if not, may still be possible to find:
         if (elemTypeDeser == null) {
@@ -772,21 +864,6 @@
         return deser;
     }
 
-    protected JsonDeserializer<?> _findCustomArrayDeserializer(ArrayType type,
-            DeserializationConfig config, BeanDescription beanDesc,
-            TypeDeserializer elementTypeDeserializer, JsonDeserializer<?> elementDeserializer)
-        throws JsonMappingException
-    {
-        for (Deserializers d  : _factoryConfig.deserializers()) {
-            JsonDeserializer<?> deser = d.findArrayDeserializer(type, config,
-                    beanDesc, elementTypeDeserializer, elementDeserializer);
-            if (deser != null) {
-                return deser;
-            }
-        }
-        return null;
-    }
-    
     /*
     /**********************************************************
     /* JsonDeserializerFactory impl: Collection(-like) deserializers
@@ -882,21 +959,6 @@
         }
         return (CollectionType) config.constructSpecializedType(type, collectionClass);
     }
-
-    protected JsonDeserializer<?> _findCustomCollectionDeserializer(CollectionType type,
-            DeserializationConfig config, BeanDescription beanDesc,
-            TypeDeserializer elementTypeDeserializer, JsonDeserializer<?> elementDeserializer)
-        throws JsonMappingException
-    {
-        for (Deserializers d  : _factoryConfig.deserializers()) {
-            JsonDeserializer<?> deser = d.findCollectionDeserializer(type, config, beanDesc,
-                    elementTypeDeserializer, elementDeserializer);
-            if (deser != null) {
-                return deser;
-            }
-        }
-        return null;
-    }
     
     // Copied almost verbatim from "createCollectionDeserializer" -- should try to share more code
     @Override
@@ -928,27 +990,12 @@
         return deser;
     }
 
-    protected JsonDeserializer<?> _findCustomCollectionLikeDeserializer(CollectionLikeType type,
-            DeserializationConfig config, BeanDescription beanDesc,
-            TypeDeserializer elementTypeDeserializer, JsonDeserializer<?> elementDeserializer)
-        throws JsonMappingException
-    {
-        for (Deserializers d  : _factoryConfig.deserializers()) {
-            JsonDeserializer<?> deser = d.findCollectionLikeDeserializer(type, config, beanDesc,
-                    elementTypeDeserializer, elementDeserializer);
-            if (deser != null) {
-                return deser;
-            }
-        }
-        return null;
-    }
-
     /*
     /**********************************************************
     /* JsonDeserializerFactory impl: Map(-like) deserializers
     /**********************************************************
      */
-    
+
     @Override
     public JsonDeserializer<?> createMapDeserializer(DeserializationContext ctxt,
             MapType type, BeanDescription beanDesc)
@@ -1071,38 +1118,6 @@
         return deser;
     }
 
-    protected JsonDeserializer<?> _findCustomMapDeserializer(MapType type,
-            DeserializationConfig config, BeanDescription beanDesc,
-            KeyDeserializer keyDeserializer,
-            TypeDeserializer elementTypeDeserializer, JsonDeserializer<?> elementDeserializer)
-        throws JsonMappingException
-    {
-        for (Deserializers d  : _factoryConfig.deserializers()) {
-            JsonDeserializer<?> deser = d.findMapDeserializer(type, config, beanDesc,
-                    keyDeserializer, elementTypeDeserializer, elementDeserializer);
-            if (deser != null) {
-                return deser;
-            }
-        }
-        return null;
-    }
-
-    protected JsonDeserializer<?> _findCustomMapLikeDeserializer(MapLikeType type,
-            DeserializationConfig config, BeanDescription beanDesc,
-            KeyDeserializer keyDeserializer,
-            TypeDeserializer elementTypeDeserializer, JsonDeserializer<?> elementDeserializer)
-        throws JsonMappingException
-    {
-        for (Deserializers d  : _factoryConfig.deserializers()) {
-            JsonDeserializer<?> deser = d.findMapLikeDeserializer(type, config, beanDesc,
-                    keyDeserializer, elementTypeDeserializer, elementDeserializer);
-            if (deser != null) {
-                return deser;
-            }
-        }
-        return null;
-    }
-    
     /*
     /**********************************************************
     /* JsonDeserializerFactory impl: Enum deserializers
@@ -1152,19 +1167,6 @@
         }
         return deser;
     }
-
-    protected JsonDeserializer<?> _findCustomEnumDeserializer(Class<?> type,
-            DeserializationConfig config, BeanDescription beanDesc)
-        throws JsonMappingException
-    {
-        for (Deserializers d  : _factoryConfig.deserializers()) {
-            JsonDeserializer<?> deser = d.findEnumDeserializer(type, config, beanDesc);
-            if (deser != null) {
-                return deser;
-            }
-        }
-        return null;
-    }
     
     /*
     /**********************************************************
@@ -1187,19 +1189,6 @@
         }
         return JsonNodeDeserializer.getDeserializer(nodeClass);
     }
-
-    protected JsonDeserializer<?> _findCustomTreeNodeDeserializer(Class<? extends JsonNode> type,
-            DeserializationConfig config, BeanDescription beanDesc)
-        throws JsonMappingException
-    {
-        for (Deserializers d  : _factoryConfig.deserializers()) {
-            JsonDeserializer<?> deser = d.findTreeNodeDeserializer(type, config, beanDesc);
-            if (deser != null) {
-                return deser;
-            }
-        }
-        return null;
-    }
     
     /*
     /**********************************************************
@@ -1240,6 +1229,18 @@
         return b.buildTypeDeserializer(config, baseType, subtypes);
     }
 
+    /**
+     * Overridable method called after checking all other types.
+     * 
+     * @since 2.2
+     */
+    protected JsonDeserializer<?> findOptionalStdDeserializer(DeserializationContext ctxt,
+            JavaType type, BeanDescription beanDesc)
+        throws JsonMappingException
+    {
+        return OptionalHandlerFactory.instance.findDeserializer(type, ctxt.getConfig(), beanDesc);
+    }
+    
     /*
     /**********************************************************
     /* JsonDeserializerFactory impl (partial): key deserializers
@@ -1410,11 +1411,31 @@
         if (rawType == CLASS_ITERABLE) {
             // [Issue#199]: Can and should 'upgrade' to a Collection type:
             TypeFactory tf = ctxt.getTypeFactory();
-            JavaType elemType = (type.containedTypeCount() > 0) ? type.containedType(0) : TypeFactory.unknownType();
+            JavaType[] tps = tf.findTypeParameters(type, CLASS_ITERABLE);
+            JavaType elemType = (tps == null || tps.length != 1) ? TypeFactory.unknownType() : tps[0];
             CollectionType ct = tf.constructCollectionType(Collection.class, elemType);
             // Should we re-introspect beanDesc? For now let's not...
             return createCollectionDeserializer(ctxt, ct, beanDesc);
         }
+        if (rawType == CLASS_MAP_ENTRY) {
+            final DeserializationConfig config = ctxt.getConfig();
+            TypeFactory tf = ctxt.getTypeFactory();
+            JavaType[] tps = tf.findTypeParameters(type, CLASS_MAP_ENTRY);
+            JavaType kt, vt;
+            if (tps == null || tps.length != 2) {
+                kt = vt = TypeFactory.unknownType();
+            } else {
+                kt = tps[0];
+                vt = tps[1];
+            }
+            TypeDeserializer vts = (TypeDeserializer) vt.getTypeHandler();
+            if (vts == null) {
+                vts = findTypeDeserializer(config, vt);
+            }
+            JsonDeserializer<Object> valueDeser = vt.getValueHandler();
+            KeyDeserializer keyDes = (KeyDeserializer) kt.getValueHandler();
+            return new MapEntryDeserializer(type, keyDes, valueDeser, vts);
+        }
         String clsName = rawType.getName();
         if (rawType.isPrimitive() || clsName.startsWith("java.")) {
             // Primitives/wrappers, other Numbers:
@@ -1430,11 +1451,153 @@
         if (rawType == TokenBuffer.class) {
             return new TokenBufferDeserializer();
         }
+        if (AtomicReference.class.isAssignableFrom(rawType)) {
+            // Must find parameterization
+            TypeFactory tf = ctxt.getTypeFactory();
+            JavaType[] params = tf.findTypeParameters(type, AtomicReference.class);
+            JavaType referencedType;
+            if (params == null || params.length < 1) { // untyped (raw)
+                referencedType = TypeFactory.unknownType();
+            } else {
+                referencedType = params[0];
+            }
+            TypeDeserializer vts = findTypeDeserializer(ctxt.getConfig(), referencedType);
+            BeanDescription refdDesc = ctxt.getConfig().introspectClassAnnotations(referencedType);
+            JsonDeserializer<?> deser = findDeserializerFromAnnotation(ctxt, refdDesc.getClassInfo());
+            return new AtomicReferenceDeserializer(referencedType, vts, deser);
+        }
+        JsonDeserializer<?> deser = findOptionalStdDeserializer(ctxt, type, beanDesc);
+        if (deser != null) {
+            return deser;
+        }
         return JdkDeserializers.find(rawType, clsName);
     }
 
     /*
     /**********************************************************
+    /* Helper methods, finding custom deserializers
+    /**********************************************************
+     */
+
+    protected JsonDeserializer<?> _findCustomArrayDeserializer(ArrayType type,
+            DeserializationConfig config, BeanDescription beanDesc,
+            TypeDeserializer elementTypeDeserializer, JsonDeserializer<?> elementDeserializer)
+        throws JsonMappingException
+    {
+        for (Deserializers d  : _factoryConfig.deserializers()) {
+            JsonDeserializer<?> deser = d.findArrayDeserializer(type, config,
+                    beanDesc, elementTypeDeserializer, elementDeserializer);
+            if (deser != null) {
+                return deser;
+            }
+        }
+        return null;
+    }
+
+    @SuppressWarnings("unchecked")
+    protected JsonDeserializer<Object> _findCustomBeanDeserializer(JavaType type,
+            DeserializationConfig config, BeanDescription beanDesc)
+        throws JsonMappingException
+    {
+        for (Deserializers d  : _factoryConfig.deserializers()) {
+            JsonDeserializer<?> deser = d.findBeanDeserializer(type, config, beanDesc);
+            if (deser != null) {
+                return (JsonDeserializer<Object>) deser;
+            }
+        }
+        return null;
+    }
+
+    protected JsonDeserializer<?> _findCustomCollectionDeserializer(CollectionType type,
+            DeserializationConfig config, BeanDescription beanDesc,
+            TypeDeserializer elementTypeDeserializer, JsonDeserializer<?> elementDeserializer)
+        throws JsonMappingException
+    {
+        for (Deserializers d  : _factoryConfig.deserializers()) {
+            JsonDeserializer<?> deser = d.findCollectionDeserializer(type, config, beanDesc,
+                    elementTypeDeserializer, elementDeserializer);
+            if (deser != null) {
+                return deser;
+            }
+        }
+        return null;
+    }
+    
+    protected JsonDeserializer<?> _findCustomCollectionLikeDeserializer(CollectionLikeType type,
+            DeserializationConfig config, BeanDescription beanDesc,
+            TypeDeserializer elementTypeDeserializer, JsonDeserializer<?> elementDeserializer)
+        throws JsonMappingException
+    {
+        for (Deserializers d  : _factoryConfig.deserializers()) {
+            JsonDeserializer<?> deser = d.findCollectionLikeDeserializer(type, config, beanDesc,
+                    elementTypeDeserializer, elementDeserializer);
+            if (deser != null) {
+                return deser;
+            }
+        }
+        return null;
+    }
+
+    protected JsonDeserializer<?> _findCustomEnumDeserializer(Class<?> type,
+            DeserializationConfig config, BeanDescription beanDesc)
+        throws JsonMappingException
+    {
+        for (Deserializers d  : _factoryConfig.deserializers()) {
+            JsonDeserializer<?> deser = d.findEnumDeserializer(type, config, beanDesc);
+            if (deser != null) {
+                return deser;
+            }
+        }
+        return null;
+    }
+    
+    protected JsonDeserializer<?> _findCustomMapDeserializer(MapType type,
+            DeserializationConfig config, BeanDescription beanDesc,
+            KeyDeserializer keyDeserializer,
+            TypeDeserializer elementTypeDeserializer, JsonDeserializer<?> elementDeserializer)
+        throws JsonMappingException
+    {
+        for (Deserializers d  : _factoryConfig.deserializers()) {
+            JsonDeserializer<?> deser = d.findMapDeserializer(type, config, beanDesc,
+                    keyDeserializer, elementTypeDeserializer, elementDeserializer);
+            if (deser != null) {
+                return deser;
+            }
+        }
+        return null;
+    }
+
+    protected JsonDeserializer<?> _findCustomMapLikeDeserializer(MapLikeType type,
+            DeserializationConfig config, BeanDescription beanDesc,
+            KeyDeserializer keyDeserializer,
+            TypeDeserializer elementTypeDeserializer, JsonDeserializer<?> elementDeserializer)
+        throws JsonMappingException
+    {
+        for (Deserializers d  : _factoryConfig.deserializers()) {
+            JsonDeserializer<?> deser = d.findMapLikeDeserializer(type, config, beanDesc,
+                    keyDeserializer, elementTypeDeserializer, elementDeserializer);
+            if (deser != null) {
+                return deser;
+            }
+        }
+        return null;
+    }
+
+    protected JsonDeserializer<?> _findCustomTreeNodeDeserializer(Class<? extends JsonNode> type,
+            DeserializationConfig config, BeanDescription beanDesc)
+        throws JsonMappingException
+    {
+        for (Deserializers d  : _factoryConfig.deserializers()) {
+            JsonDeserializer<?> deser = d.findTreeNodeDeserializer(type, config, beanDesc);
+            if (deser != null) {
+                return deser;
+            }
+        }
+        return null;
+    }
+    
+    /*
+    /**********************************************************
     /* Helper methods, value/content/key type introspection
     /**********************************************************
      */
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 0d9af65..555134b 100644
--- a/src/main/java/com/fasterxml/jackson/databind/deser/BeanDeserializer.java
+++ b/src/main/java/com/fasterxml/jackson/databind/deser/BeanDeserializer.java
@@ -326,7 +326,7 @@
     @SuppressWarnings("resource")
     protected Object _deserializeUsingPropertyBased(final JsonParser jp, final DeserializationContext ctxt)
         throws IOException, JsonProcessingException
-    { 
+    {
         final PropertyBasedCreator creator = _propertyBasedCreator;
         PropertyValueBuffer buffer = creator.startBuilding(jp, ctxt, _objectIdReader);
         
@@ -391,7 +391,7 @@
             unknown.writeFieldName(propName);
             unknown.copyCurrentStructure(jp);
         }
-
+        
         // We hit END_OBJECT, so:
         Object bean;
         try {
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 ac65574..62cc3e1 100644
--- a/src/main/java/com/fasterxml/jackson/databind/deser/BeanDeserializerBase.java
+++ b/src/main/java/com/fasterxml/jackson/databind/deser/BeanDeserializerBase.java
@@ -29,7 +29,7 @@
     implements ContextualDeserializer, ResolvableDeserializer,
         java.io.Serializable // since 2.1
 {
-    private static final long serialVersionUID = 2960120955735322578L;
+    private static final long serialVersionUID = 1;
 
     protected final static PropertyName TEMP_PROPERTY_NAME = new PropertyName("#temporary-name");
 
@@ -111,7 +111,7 @@
      * to use have been successfully resolved.
      */
     final protected BeanPropertyMap _beanProperties;
-    
+
     /**
      * List of {@link ValueInjector}s, if any injectable values are
      * expected by the bean; otherwise null.
@@ -119,7 +119,7 @@
      * and fields, but not ones passed through constructor parameters.
      */
     final protected ValueInjector[] _injectables;
-    
+
     /**
      * Fallback setter used for handling any properties that are not
      * mapped to regular setters. If setter is not null, it will be
@@ -238,8 +238,7 @@
                 ;
     }
 
-    protected BeanDeserializerBase(BeanDeserializerBase src)
-    {
+    protected BeanDeserializerBase(BeanDeserializerBase src) {
         this(src, src._ignoreAllUnknown);
     }
 
@@ -517,6 +516,7 @@
             }
             JsonDeserializer<Object> dd = findDeserializer(ctxt, delegateType, property);
             if (td != null) {
+                td = td.forProperty(property);
                 dd = new TypeWrappedDeserializer(td, dd);
             }
             _delegateDeserializer = dd;
@@ -1031,8 +1031,7 @@
      * buffering in some cases, but usually just a simple lookup to ensure
      * that ordering is correct.
      */
-    protected Object deserializeWithObjectId(JsonParser jp, DeserializationContext ctxt) throws IOException
-    {
+    protected Object deserializeWithObjectId(JsonParser jp, DeserializationContext ctxt) throws IOException {
         return deserializeFromObject(jp, ctxt);
     }
     
@@ -1200,15 +1199,24 @@
                 wrapInstantiationProblem(e, ctxt);
             }
         } else if (ctxt.isEnabled(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS)) {
-            jp.nextToken();
+            JsonToken t = jp.nextToken();
+            if (t == JsonToken.END_ARRAY && ctxt.isEnabled(DeserializationFeature.ACCEPT_EMPTY_ARRAY_AS_NULL_OBJECT)) {
+                return null;
+            }
             final Object 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 '" + _valueClass.getName() + "' value but there was more than a single value in the array");
             }
             return value;
+        } else if (ctxt.isEnabled(DeserializationFeature.ACCEPT_EMPTY_ARRAY_AS_NULL_OBJECT)) {
+            JsonToken t = jp.nextToken();
+            if (t == JsonToken.END_ARRAY) {
+                return null;
+            }
+            throw ctxt.mappingException(handledType(), JsonToken.START_ARRAY);
         }
-        throw ctxt.mappingException(getBeanClass());
+        throw ctxt.mappingException(handledType());
     }
 
     public Object deserializeFromEmbedded(JsonParser jp, DeserializationContext ctxt) throws IOException
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 24c0ca0..c2e6f72 100644
--- a/src/main/java/com/fasterxml/jackson/databind/deser/BeanDeserializerBuilder.java
+++ b/src/main/java/com/fasterxml/jackson/databind/deser/BeanDeserializerBuilder.java
@@ -180,14 +180,6 @@
         //   For now, won't add, since it is inferred, not explicit...
     }
 
-    @Deprecated // since 2.3
-    public void addInjectable(String propName, JavaType propType,
-            Annotations contextAnnotations, AnnotatedMember member,
-            Object valueId)
-    {
-        addInjectable(new PropertyName(propName), propType, contextAnnotations, member, valueId);
-    }
-    
     public void addInjectable(PropertyName propName, JavaType propType,
             Annotations contextAnnotations, AnnotatedMember member,
             Object valueId)
@@ -269,41 +261,17 @@
         return _properties.values().iterator();
     }
 
-    /**
-     * @since 2.3
-     */
     public SettableBeanProperty findProperty(PropertyName propertyName) {
         return _properties.get(propertyName.getSimpleName());
     }
 
-    @Deprecated // since 2.3
-    public SettableBeanProperty findProperty(String propertyName) {
-        return _properties.get(propertyName);
-    }
-
-    /**
-     * @since 2.3
-     */
     public boolean hasProperty(PropertyName propertyName) {
         return findProperty(propertyName) != null;
     }
-    
-    @Deprecated // since 2.3
-    public boolean hasProperty(String propertyName) {
-        return findProperty(propertyName) != null;
-    }
 
-    /**
-     * @since 2.3
-     */
     public SettableBeanProperty removeProperty(PropertyName name) {
         return _properties.remove(name.getSimpleName());
     }
-    
-    @Deprecated // since 2.3
-    public SettableBeanProperty removeProperty(String name) {
-        return _properties.remove(name);
-    }
 
     public SettableAnyProperty getAnySetter() {
         return _anySetter;
@@ -384,8 +352,7 @@
      * 
      * @since 2.0
      */
-    public AbstractDeserializer buildAbstract()
-    {
+    public AbstractDeserializer buildAbstract() {
         return new AbstractDeserializer(this, _beanDesc, _backRefProperties);
     }
     
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 a10cc45..2c20c1e 100644
--- a/src/main/java/com/fasterxml/jackson/databind/deser/BeanDeserializerFactory.java
+++ b/src/main/java/com/fasterxml/jackson/databind/deser/BeanDeserializerFactory.java
@@ -2,21 +2,18 @@
 
 import java.lang.reflect.Type;
 import java.util.*;
-import java.util.concurrent.atomic.AtomicReference;
 
 import com.fasterxml.jackson.annotation.ObjectIdGenerator;
 import com.fasterxml.jackson.annotation.ObjectIdGenerators;
 import com.fasterxml.jackson.annotation.ObjectIdResolver;
+
 import com.fasterxml.jackson.databind.*;
 import com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder;
 import com.fasterxml.jackson.databind.cfg.DeserializerFactoryConfig;
 import com.fasterxml.jackson.databind.deser.impl.*;
-import com.fasterxml.jackson.databind.deser.std.AtomicReferenceDeserializer;
 import com.fasterxml.jackson.databind.deser.std.ThrowableDeserializer;
-import com.fasterxml.jackson.databind.ext.OptionalHandlerFactory;
 import com.fasterxml.jackson.databind.introspect.*;
 import com.fasterxml.jackson.databind.jsontype.TypeDeserializer;
-import com.fasterxml.jackson.databind.type.TypeFactory;
 import com.fasterxml.jackson.databind.util.ArrayBuilders;
 import com.fasterxml.jackson.databind.util.ClassUtil;
 import com.fasterxml.jackson.databind.util.SimpleBeanPropertyDefinition;
@@ -89,28 +86,6 @@
     
     /*
     /**********************************************************
-    /* Overrides for super-class methods used for finding
-    /* custom deserializers
-    /**********************************************************
-     */
-
-    // Note: NOT overriding, superclass has no matching method
-    @SuppressWarnings("unchecked")
-    protected JsonDeserializer<Object> _findCustomBeanDeserializer(JavaType type,
-            DeserializationConfig config, BeanDescription beanDesc)
-        throws JsonMappingException
-    {
-        for (Deserializers d  : _factoryConfig.deserializers()) {
-            JsonDeserializer<?> deser = d.findBeanDeserializer(type, config, beanDesc);
-            if (deser != null) {
-                return (JsonDeserializer<Object>) deser;
-            }
-        }
-        return null;
-    }
-    
-    /*
-    /**********************************************************
     /* DeserializerFactory API implementation
     /**********************************************************
      */
@@ -191,40 +166,15 @@
         // note: we do NOT check for custom deserializers here, caller has already
         // done that
         JsonDeserializer<?> deser = findDefaultDeserializer(ctxt, type, beanDesc);
+        // Also: better ensure these are post-processable?
         if (deser != null) {
-            return deser;
-        }
-        
-        Class<?> cls = type.getRawClass();
-        // [JACKSON-283]: AtomicReference is a rather special type...
-        if (AtomicReference.class.isAssignableFrom(cls)) {
-            // Must find parameterization
-            TypeFactory tf = ctxt.getTypeFactory();
-            JavaType[] params = tf.findTypeParameters(type, AtomicReference.class);
-            JavaType referencedType;
-            if (params == null || params.length < 1) { // untyped (raw)
-                referencedType = TypeFactory.unknownType();
-            } else {
-                referencedType = params[0];
+            if (_factoryConfig.hasDeserializerModifiers()) {
+                for (BeanDeserializerModifier mod : _factoryConfig.deserializerModifiers()) {
+                    deser = mod.modifyDeserializer(ctxt.getConfig(), beanDesc, deser);
+                }
             }
-            TypeDeserializer valueTypeDeser = findTypeDeserializer(ctxt.getConfig(), referencedType);
-            BeanDescription refdDesc = ctxt.getConfig().introspectClassAnnotations(referencedType);
-            deser = findDeserializerFromAnnotation(ctxt, refdDesc.getClassInfo());
-            return new AtomicReferenceDeserializer(referencedType, valueTypeDeser, deser);
         }
-        return findOptionalStdDeserializer(ctxt, type, beanDesc);
-    }
-
-    /**
-     * Overridable method called after checking all other types.
-     * 
-     * @since 2.2
-     */
-    protected JsonDeserializer<?> findOptionalStdDeserializer(DeserializationContext ctxt,
-            JavaType type, BeanDescription beanDesc)
-        throws JsonMappingException
-    {
-        return OptionalHandlerFactory.instance.findDeserializer(type, ctxt.getConfig(), beanDesc);
+        return deser;
     }
     
     protected JavaType materializeAbstractType(DeserializationContext ctxt,
@@ -487,6 +437,7 @@
     {
         final SettableBeanProperty[] creatorProps =
                 builder.getValueInstantiator().getFromObjectArguments(ctxt.getConfig());
+        final boolean isConcrete = !beanDesc.getType().isAbstract();
         
         // Things specified as "ok to ignore"? [JACKSON-77]
         AnnotationIntrospector intr = ctxt.getAnnotationIntrospector();
@@ -508,7 +459,7 @@
         if (anySetter != null) {
             builder.setAnySetter(constructAnySetter(ctxt, beanDesc, anySetter));
         }
-        // NOTE: we do NOT add @JsonIgnore'd properties into blocked ones if there's any setter
+        // 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) {
             Collection<String> ignored2 = beanDesc.getIgnoredPropertyNames();
@@ -559,7 +510,9 @@
                     prop = constructSetterlessProperty(ctxt, beanDesc, propDef);
                 }
             }
-            if (propDef.hasConstructorParameter()) {
+            // 25-Sep-2014, tatu: No point in finding constructor parameters for abstract types
+            //   (since they are never used anyway)
+            if (isConcrete && propDef.hasConstructorParameter()) {
                 /* [JACKSON-700] 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.
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 6bc7579..ef11980 100644
--- a/src/main/java/com/fasterxml/jackson/databind/deser/DefaultDeserializationContext.java
+++ b/src/main/java/com/fasterxml/jackson/databind/deser/DefaultDeserializationContext.java
@@ -82,6 +82,7 @@
     public ReadableObjectId findObjectId(Object id, ObjectIdGenerator<?> gen, ObjectIdResolver resolverType)
     {
         final ObjectIdGenerator.IdKey key = gen.key(id);
+
         if (_objectIds == null) {
             _objectIds = new LinkedHashMap<ObjectIdGenerator.IdKey,ReadableObjectId>();
         } else {
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 bfe5efe..840641e 100644
--- a/src/main/java/com/fasterxml/jackson/databind/deser/SettableAnyProperty.java
+++ b/src/main/java/com/fasterxml/jackson/databind/deser/SettableAnyProperty.java
@@ -1,7 +1,6 @@
 package com.fasterxml.jackson.databind.deser;
 
 import java.io.IOException;
-import java.lang.reflect.*;
 
 import com.fasterxml.jackson.core.*;
 import com.fasterxml.jackson.databind.*;
@@ -27,14 +26,11 @@
      * information. Retained to allow contextualization of any properties.
      */
     protected final BeanProperty _property;
-    
+
     /**
-     * Physical JDK object used for assigning properties.
-     *<p>
-     * NOTE: must be marked transient since it is not serializable,
-     * in case these are to be serialized
+     * Annotated variant is needed for JDK serialization only
      */
-    protected final transient Method _setter;
+    final protected AnnotatedMethod _setter;
 
     protected final JavaType _type;
 
@@ -48,30 +44,12 @@
     /**********************************************************
      */
 
-    @Deprecated // since 2.3
     public SettableAnyProperty(BeanProperty property, AnnotatedMethod setter, JavaType type,
-            JsonDeserializer<Object> valueDeser) {
-        this(property, setter, type, valueDeser, null);
-    }
-
-    public SettableAnyProperty(BeanProperty property, AnnotatedMethod setter, JavaType type,
-            JsonDeserializer<Object> valueDeser, TypeDeserializer typeDeser)
-    {
-        this(property, setter.getAnnotated(), type, valueDeser, typeDeser);
-    }
-    
-    @Deprecated // since 2.3
-    public SettableAnyProperty(BeanProperty property, Method rawSetter, JavaType type,
-            JsonDeserializer<Object> valueDeser) {
-        this(property, rawSetter, type, valueDeser, null);
-    }
-    
-    public SettableAnyProperty(BeanProperty property, Method rawSetter, JavaType type,
             JsonDeserializer<Object> valueDeser, TypeDeserializer typeDeser)
     {
         _property = property;
+        _setter = setter;
         _type = type;
-        _setter = rawSetter;
         _valueDeserializer = valueDeser;
         _valueTypeDeserializer = typeDeser;
     }
@@ -80,6 +58,18 @@
         return new SettableAnyProperty(_property, _setter, _type,
                 deser, _valueTypeDeserializer);
     }
+
+    /**
+     * Constructor used for JDK Serialization when reading persisted object
+     */
+    protected SettableAnyProperty(SettableAnyProperty src)
+    {
+        _property = src._property;
+        _setter = src._setter;
+        _type = src._type;
+        _valueDeserializer = src._valueDeserializer;
+        _valueTypeDeserializer = src._valueTypeDeserializer;
+    }
     
     /*
     /**********************************************************
@@ -87,13 +77,16 @@
     /**********************************************************
      */
 
-    // TODO (2.3): handle restoring of reference to any-setter method
-    
-/*
+    /**
+     * Need to define this to verify that we retain actual Method reference
+     */
     Object readResolve() {
-        return new SettableAnyProperty(this, _annotated.getAnnotated());
+        // sanity check...
+        if (_setter == null || _setter.getAnnotated() == null) {
+            throw new IllegalArgumentException("Missing method (broken JDK (de)serialization?)");
+        }
+        return this;
     }
-    */
     
     /*
     /**********************************************************
@@ -148,7 +141,8 @@
     public void set(Object instance, String propName, Object value) throws IOException
     {
         try {
-            _setter.invoke(instance, propName, value);
+            // note: can not use 'setValue()' due to taking 2 args
+            _setter.getAnnotated().invoke(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 7b4ee60..be9879f 100644
--- a/src/main/java/com/fasterxml/jackson/databind/deser/SettableBeanProperty.java
+++ b/src/main/java/com/fasterxml/jackson/databind/deser/SettableBeanProperty.java
@@ -145,14 +145,6 @@
                 contextAnnotations, propDef.getMetadata());
     }
 
-    @Deprecated // since 2.2
-    protected SettableBeanProperty(String propName, JavaType type, PropertyName wrapper,
-            TypeDeserializer typeDeser, Annotations contextAnnotations)
-    {
-        this(new PropertyName(propName), type, wrapper, typeDeser, contextAnnotations,
-                PropertyMetadata.STD_OPTIONAL);
-    }
-
     @Deprecated // since 2.3
     protected SettableBeanProperty(String propName, JavaType type, PropertyName wrapper,
             TypeDeserializer typeDeser, Annotations contextAnnotations,
@@ -509,7 +501,7 @@
      * @since 2.0
      */
     public abstract Object setAndReturn(Object instance, Object value)
-            throws IOException;
+        throws IOException;
     
     /**
      * This method is needed by some specialized bean deserializers,
@@ -524,8 +516,7 @@
      * this method should also not be called directly unless you really know
      * what you are doing (and probably not even then).
      */
-    public final Object deserialize(JsonParser jp, DeserializationContext ctxt)
-        throws IOException, JsonProcessingException
+    public final Object deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
     {
         JsonToken t = jp.getCurrentToken();
         
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 e47934e..5dd3d6c 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
@@ -55,7 +55,7 @@
      */
     public boolean handleTypePropertyValue(JsonParser jp, DeserializationContext ctxt,
             String propName, Object bean)
-        throws IOException, JsonProcessingException
+        throws IOException
     {
         Integer I = _nameToPropertyIndex.get(propName);
         if (I == null) {
@@ -89,8 +89,7 @@
      * @return True, if the given property was properly handled
      */
     public boolean handlePropertyValue(JsonParser jp, DeserializationContext ctxt,
-            String propName, Object bean)
-        throws IOException, JsonProcessingException
+            String propName, Object bean) throws IOException
     {
         Integer I = _nameToPropertyIndex.get(propName);
         if (I == null) {
@@ -125,7 +124,7 @@
     
     @SuppressWarnings("resource")
     public Object complete(JsonParser jp, DeserializationContext ctxt, Object bean)
-        throws IOException, JsonProcessingException
+        throws IOException
     {
         for (int i = 0, len = _properties.length; i < len; ++i) {
             String typeId = _typeIds[i];
@@ -170,7 +169,7 @@
      */
     public Object complete(JsonParser jp, DeserializationContext ctxt,
             PropertyValueBuffer buffer, PropertyBasedCreator creator)
-        throws IOException, JsonProcessingException
+        throws IOException
     {
         // first things first: deserialize all data buffered:
         final int len = _properties.length;
@@ -214,8 +213,7 @@
 
     @SuppressWarnings("resource")
     protected final Object _deserialize(JsonParser jp, DeserializationContext ctxt,
-            int index, String typeId)
-        throws IOException, JsonProcessingException
+            int index, String typeId) throws IOException
     {
         TokenBuffer merged = new TokenBuffer(jp);
         merged.writeStartArray();
@@ -233,8 +231,7 @@
 
     @SuppressWarnings("resource")
     protected final void _deserializeAndSet(JsonParser jp, DeserializationContext ctxt,
-            Object bean, int index, String typeId)
-        throws IOException, JsonProcessingException
+            Object bean, int index, String typeId) throws IOException
     {
         /* Ok: time to mix type id, value; and we will actually use "wrapper-array"
          * style to ensure we can handle all kinds of JSON constructs.
@@ -246,7 +243,6 @@
         p2.nextToken();
         merged.copyCurrentStructure(p2);
         merged.writeEndArray();
-        
         // needs to point to START_OBJECT (or whatever first token is)
         p2 = merged.asParser(jp);
         p2.nextToken();
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 e6e24ce..dbdea50 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
@@ -58,13 +58,13 @@
     /**
      * Constructor used for JDK Serialization when reading persisted object
      */
-    protected FieldProperty(FieldProperty src, Field f)
+    protected FieldProperty(FieldProperty src)
     {
         super(src);
         _annotated = src._annotated;
+        Field f = _annotated.getAnnotated();
         if (f == null) {
-            throw new IllegalArgumentException("No Field passed for property '"+src.getName()
-                    +"' (class "+src.getDeclaringClass().getName()+")");
+            throw new IllegalArgumentException("Missing field (broken JDK (de)serialization?)");
         }
         _field = f;
     }
@@ -144,6 +144,6 @@
      */
 
     Object readResolve() {
-        return new FieldProperty(this, _annotated.getAnnotated());
+        return new FieldProperty(this);
     }
 }
\ No newline at end of file
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 8e5c243..76616ab 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
@@ -4,14 +4,10 @@
 import java.lang.annotation.Annotation;
 import java.lang.reflect.Constructor;
 
-import com.fasterxml.jackson.core.JsonParser;
-import com.fasterxml.jackson.core.JsonProcessingException;
-import com.fasterxml.jackson.core.JsonToken;
-import com.fasterxml.jackson.databind.DeserializationContext;
-import com.fasterxml.jackson.databind.JsonDeserializer;
-import com.fasterxml.jackson.databind.PropertyName;
+import com.fasterxml.jackson.core.*;
+import com.fasterxml.jackson.databind.*;
 import com.fasterxml.jackson.databind.deser.SettableBeanProperty;
-import com.fasterxml.jackson.databind.introspect.AnnotatedMember;
+import com.fasterxml.jackson.databind.introspect.*;
 import com.fasterxml.jackson.databind.util.ClassUtil;
 
 /**
@@ -31,10 +27,17 @@
     protected final SettableBeanProperty _delegate;
 
     /**
-     * Single-arg constructor we use for value instantiation.
+     * Constructor used when deserializing this property.
+     * Transient since there is no need to persist; only needed during
+     * construction of objects.
      */
-    protected final Constructor<?> _creator;
+    final protected transient Constructor<?> _creator;
     
+    /**
+     * Serializable version of single-arg constructor we use for value instantiation.
+     */
+    protected AnnotatedConstructor _annotated;
+
     public InnerClassProperty(SettableBeanProperty delegate,
             Constructor<?> ctor)
     {
@@ -43,6 +46,21 @@
         _creator = ctor;
     }
 
+    /**
+     * Constructor used with JDK Serialization; needed to handle transient
+     * Constructor, wrap/unwrap in/out-of Annotated variant.
+     */
+    protected InnerClassProperty(InnerClassProperty src, AnnotatedConstructor ann)
+    {
+        super(src);
+        _delegate = src._delegate;
+        _annotated = ann;
+        _creator = (_annotated == null) ? null : _annotated.getAnnotated();
+        if (_creator == null) {
+            throw new IllegalArgumentException("Missing constructor (broken JDK (de)serialization?)");
+        }
+    }
+    
     protected InnerClassProperty(InnerClassProperty src, JsonDeserializer<?> deser)
     {
         super(src, deser);
@@ -82,9 +100,8 @@
      */
 
     @Override
-    public void deserializeAndSet(JsonParser jp, DeserializationContext ctxt,
-            Object bean)
-        throws IOException, JsonProcessingException
+    public void deserializeAndSet(JsonParser jp, DeserializationContext ctxt, Object bean)
+        throws IOException
     {
         JsonToken t = jp.getCurrentToken();
         Object value;
@@ -107,21 +124,37 @@
     @Override
     public Object deserializeSetAndReturn(JsonParser jp,
     		DeserializationContext ctxt, Object instance)
-        throws IOException, JsonProcessingException
+        throws IOException
     {
         return setAndReturn(instance, deserialize(jp, ctxt));
     }
     
     @Override
-    public final void set(Object instance, Object value) throws IOException
-    {
+    public final void set(Object instance, Object value) throws IOException {
         _delegate.set(instance, value);
     }
 
     @Override
-    public Object setAndReturn(Object instance, Object value)
-            throws IOException
-    {
-    	return _delegate.setAndReturn(instance, value);
+    public Object setAndReturn(Object instance, Object value) throws IOException {
+        return _delegate.setAndReturn(instance, value);
+    }
+
+    /*
+    /**********************************************************
+    /* JDK serialization handling
+    /**********************************************************
+     */
+
+    // When reading things back, 
+    Object readResolve() {
+        return new InnerClassProperty(this, _annotated);
+    }
+
+    Object writeReplace() {
+        // need to construct a fake instance to support serialization
+        if (_annotated != null) {
+            return this;
+        }
+        return new InnerClassProperty(this, new AnnotatedConstructor(_creator, null, null));
     }
 }
\ No newline at end of file
diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/impl/ObjectIdReader.java b/src/main/java/com/fasterxml/jackson/databind/deser/impl/ObjectIdReader.java
index 16dcc4c..bad83ba 100644
--- a/src/main/java/com/fasterxml/jackson/databind/deser/impl/ObjectIdReader.java
+++ b/src/main/java/com/fasterxml/jackson/databind/deser/impl/ObjectIdReader.java
@@ -5,8 +5,9 @@
 import com.fasterxml.jackson.annotation.ObjectIdGenerator;
 import com.fasterxml.jackson.annotation.ObjectIdResolver;
 import com.fasterxml.jackson.annotation.SimpleObjectIdResolver;
+
 import com.fasterxml.jackson.core.JsonParser;
-import com.fasterxml.jackson.core.JsonProcessingException;
+
 import com.fasterxml.jackson.databind.*;
 import com.fasterxml.jackson.databind.deser.SettableBeanProperty;
 
@@ -29,9 +30,6 @@
      */
     public final ObjectIdGenerator<?> generator;
 
-    /**
-     * 
-     */
     public final ObjectIdResolver resolver;
 
     /**
@@ -66,13 +64,6 @@
         this(t,propName, gen, deser, idProp, new SimpleObjectIdResolver());
     }
 
-    @Deprecated // since 2.3
-    protected ObjectIdReader(JavaType t, String propName, ObjectIdGenerator<?> gen,
-            JsonDeserializer<?> deser, SettableBeanProperty idProp)
-    {
-        this(t, new PropertyName(propName), gen, deser, idProp);
-    }
-
     /**
      * Factory method called by {@link com.fasterxml.jackson.databind.ser.std.BeanSerializerBase}
      * with the initial information based on standard settings for the type
@@ -92,14 +83,6 @@
     {
         return construct(idType, propName, generator, deser, idProp, new SimpleObjectIdResolver());
     }
-    
-    @Deprecated // since 2.3
-    public static ObjectIdReader construct(JavaType idType, String propName,
-            ObjectIdGenerator<?> generator, JsonDeserializer<?> deser,
-            SettableBeanProperty idProp)
-    {
-        return construct(idType, new PropertyName(propName), generator, deser, idProp);
-    }
 
     /*
     /**********************************************************
@@ -121,9 +104,7 @@
      * 
      * @since 2.3
      */
-    public Object readObjectReference(JsonParser jp, DeserializationContext ctxt)
-        throws IOException, JsonProcessingException
-    {
+    public Object readObjectReference(JsonParser jp, DeserializationContext ctxt) throws IOException {
         return _deserializer.deserialize(jp, ctxt);
     }
 }
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 3dcec66..ac04b96 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
@@ -4,11 +4,7 @@
 import java.lang.annotation.Annotation;
 
 import com.fasterxml.jackson.core.JsonParser;
-import com.fasterxml.jackson.core.JsonProcessingException;
-import com.fasterxml.jackson.databind.DeserializationContext;
-import com.fasterxml.jackson.databind.JsonDeserializer;
-import com.fasterxml.jackson.databind.JsonMappingException;
-import com.fasterxml.jackson.databind.PropertyName;
+import com.fasterxml.jackson.databind.*;
 import com.fasterxml.jackson.databind.deser.SettableBeanProperty;
 import com.fasterxml.jackson.databind.deser.UnresolvedForwardReference;
 import com.fasterxml.jackson.databind.deser.impl.ReadableObjectId.Referring;
@@ -16,8 +12,9 @@
 import com.fasterxml.jackson.databind.introspect.ObjectIdInfo;
 
 public class ObjectIdReferenceProperty extends SettableBeanProperty {
-    private static final long serialVersionUID = 8465266677345565407L;
-    private SettableBeanProperty _forward;
+    private static final long serialVersionUID = 1L;
+
+    private final SettableBeanProperty _forward;
 
     public ObjectIdReferenceProperty(SettableBeanProperty forward, ObjectIdInfo objectIdInfo)
     {
@@ -61,20 +58,18 @@
     }
 
     @Override
-    public void deserializeAndSet(JsonParser jp, DeserializationContext ctxt, Object instance)
-        throws IOException, JsonProcessingException
-    {
+    public void deserializeAndSet(JsonParser jp, DeserializationContext ctxt, Object instance) throws IOException {
         deserializeSetAndReturn(jp, ctxt, instance);
     }
 
     @Override
     public Object deserializeSetAndReturn(JsonParser jp, DeserializationContext ctxt, Object instance)
-        throws IOException, JsonProcessingException
+        throws IOException
     {
-        boolean usingIdentityInfo = (_objectIdInfo != null) || (_valueDeserializer.getObjectIdReader() != null);
         try {
             return setAndReturn(instance, deserialize(jp, ctxt));
         } catch (UnresolvedForwardReference reference) {
+            boolean usingIdentityInfo = (_objectIdInfo != null) || (_valueDeserializer.getObjectIdReader() != null);
             if (!usingIdentityInfo) {
                 throw JsonMappingException.from(jp, "Unresolved forward reference but no identity info.", reference);
             }
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 d899d44..7e06b60 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
@@ -108,8 +108,7 @@
     /**
      * Helper method called to handle Object Id value collected earlier, if any
      */
-    public Object handleIdValue(final DeserializationContext ctxt, Object bean)
-        throws IOException
+    public Object handleIdValue(final DeserializationContext ctxt, Object bean) throws IOException
     {
         if (_objectIdReader != null) {
             if (_idValue != null) {
@@ -122,6 +121,8 @@
                 }
             } else {
                 // TODO: is this an error case?
+                throw ctxt.mappingException("No _idValue when handleIdValue called, on instance of "
+                        +bean.getClass().getName());
             }
         }
         return bean;
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 1d127fe..7b250db 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
@@ -99,7 +99,7 @@
 
         // For [#501] fix we need to implement this but:
         if (_valueTypeDeserializer != null) {
-            throw new JsonMappingException("Problem deserializing 'setterless' property: no way to handle typed deser with setterless yet");
+            throw new JsonMappingException("Problem deserializing 'setterless' property (\""+getName()+"\"): no way to handle typed deser with setterless yet");
 //            return _valueDeserializer.deserializeWithType(jp, ctxt, _valueTypeDeserializer);
         }
         
diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/impl/TypeWrappedDeserializer.java b/src/main/java/com/fasterxml/jackson/databind/deser/impl/TypeWrappedDeserializer.java
index 1a29481..744bcaa 100644
--- a/src/main/java/com/fasterxml/jackson/databind/deser/impl/TypeWrappedDeserializer.java
+++ b/src/main/java/com/fasterxml/jackson/databind/deser/impl/TypeWrappedDeserializer.java
@@ -3,9 +3,7 @@
 import java.io.IOException;
 
 import com.fasterxml.jackson.core.JsonParser;
-import com.fasterxml.jackson.core.JsonProcessingException;
-import com.fasterxml.jackson.databind.DeserializationContext;
-import com.fasterxml.jackson.databind.JsonDeserializer;
+import com.fasterxml.jackson.databind.*;
 import com.fasterxml.jackson.databind.jsontype.TypeDeserializer;
 
 /**
@@ -18,15 +16,19 @@
  */
 public final class TypeWrappedDeserializer
     extends JsonDeserializer<Object>
+    implements java.io.Serializable // since 2.5
 {
-    final TypeDeserializer _typeDeserializer;
-    final JsonDeserializer<Object> _deserializer;
+    private static final long serialVersionUID = 1L;
 
-    public TypeWrappedDeserializer(TypeDeserializer typeDeser, JsonDeserializer<Object> deser)
+    final protected TypeDeserializer _typeDeserializer;
+    final protected JsonDeserializer<Object> _deserializer;
+
+    @SuppressWarnings("unchecked")
+    public TypeWrappedDeserializer(TypeDeserializer typeDeser, JsonDeserializer<?> deser)
     {
         super();
         _typeDeserializer = typeDeser;
-        _deserializer = deser;
+        _deserializer = (JsonDeserializer<Object>) deser;
     }
 
     @Override
@@ -35,16 +37,14 @@
     }
     
     @Override
-    public Object deserialize(JsonParser jp, DeserializationContext ctxt)
-            throws IOException, JsonProcessingException
+    public Object deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
     {
         return _deserializer.deserializeWithType(jp, ctxt, _typeDeserializer);
     }
 
     @Override
     public Object deserializeWithType(JsonParser jp, DeserializationContext ctxt,
-        TypeDeserializer typeDeserializer)
-            throws IOException, JsonProcessingException
+        TypeDeserializer typeDeserializer) throws IOException
     {
         // should never happen? (if it can, could call on that object)
         throw new IllegalStateException("Type-wrapped deserializer's deserializeWithType should never get called");
@@ -52,8 +52,7 @@
 
     @Override
     public Object deserialize(JsonParser jp, DeserializationContext ctxt,
-            Object intoValue)
-        throws IOException, JsonProcessingException
+            Object intoValue) throws IOException
     {
         /* 01-Mar-2013, tatu: Hmmh. Tough call as to what to do... need
          *   to delegate, but will this work reliably? Let's just hope so:
diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/std/ContainerDeserializerBase.java b/src/main/java/com/fasterxml/jackson/databind/deser/std/ContainerDeserializerBase.java
index 063cb22..bf2ae16 100644
--- a/src/main/java/com/fasterxml/jackson/databind/deser/std/ContainerDeserializerBase.java
+++ b/src/main/java/com/fasterxml/jackson/databind/deser/std/ContainerDeserializerBase.java
@@ -1,7 +1,11 @@
 package com.fasterxml.jackson.databind.deser.std;
 
+import java.io.IOException;
+import java.lang.reflect.InvocationTargetException;
+
 import com.fasterxml.jackson.databind.JavaType;
 import com.fasterxml.jackson.databind.JsonDeserializer;
+import com.fasterxml.jackson.databind.JsonMappingException;
 import com.fasterxml.jackson.databind.deser.SettableBeanProperty;
 
 /**
@@ -57,4 +61,30 @@
      * Accesor for deserializer use for deserializing content values.
      */
     public abstract JsonDeserializer<Object> getContentDeserializer();
+
+    /*
+    /**********************************************************
+    /* Shared methods for sub-classes
+    /**********************************************************
+     */
+
+    /**
+     * Helper method called by various Map(-like) deserializers.
+     */
+    protected void wrapAndThrow(Throwable t, Object ref, String key) throws IOException
+    {
+        // to handle StackOverflow:
+        while (t instanceof InvocationTargetException && t.getCause() != null) {
+            t = t.getCause();
+        }
+        // Errors and "plain" IOExceptions to be passed as is
+        if (t instanceof Error) {
+            throw (Error) t;
+        }
+        // ... except for mapping exceptions
+        if (t instanceof IOException && !(t instanceof JsonMappingException)) {
+            throw (IOException) t;
+        }
+        throw JsonMappingException.wrapWithPath(t, ref, key);
+    }
 }
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 e401f5e..14881ba 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
@@ -4,9 +4,10 @@
 import java.lang.reflect.Method;
 
 import com.fasterxml.jackson.core.*;
-
 import com.fasterxml.jackson.databind.*;
+import com.fasterxml.jackson.databind.deser.ContextualDeserializer;
 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.EnumResolver;
 
@@ -17,7 +18,7 @@
 public class EnumDeserializer
     extends StdScalarDeserializer<Enum<?>>
 {
-    private static final long serialVersionUID = -5893263645879532318L;
+    private static final long serialVersionUID = 1L;
 
     protected final EnumResolver<?> _resolver;
     
@@ -39,16 +40,6 @@
     {
         // note: caller has verified there's just one arg; but we must verify its type
         Class<?> paramClass = factory.getRawParameterType(0);
-        if (paramClass == String.class) {
-            paramClass = null;
-        } else  if (paramClass == Integer.TYPE || paramClass == Integer.class) {
-            paramClass = Integer.class;
-        } else  if (paramClass == Long.TYPE || paramClass == Long.class) {
-            paramClass = Long.class;
-        } else {
-            throw new IllegalArgumentException("Parameter #0 type for factory method ("+factory
-                    +") not suitable, must be java.lang.String or int/Integer/long/Long");
-        }
         if (config.canOverrideAccessModifiers()) {
             ClassUtil.checkAndFixAccess(factory.getMember());
         }
@@ -158,48 +149,71 @@
      * for locating Enum values by String id.
      */
     protected static class FactoryBasedDeserializer
-        extends StdScalarDeserializer<Object>
+        extends StdDeserializer<Object>
+        implements ContextualDeserializer
     {
-        private static final long serialVersionUID = -7775129435872564122L;
+        private static final long serialVersionUID = 1;
 
-        protected final Class<?> _enumClass;
         // 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(Enum.class);
-            _enumClass = cls;
+            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 Object deserialize(JsonParser jp, DeserializationContext ctxt)
-            throws IOException, JsonProcessingException
+        public JsonDeserializer<?> createContextual(DeserializationContext ctxt,
+                BeanProperty property)
+            throws JsonMappingException
         {
-            // couple of accepted types...
+            if ((_deser == null) && (_inputType != String.class)) {
+                return new FactoryBasedDeserializer(this,
+                        ctxt.findContextualValueDeserializer(ctxt.constructType(_inputType), property));
+            }
+            return this;
+        }
+        
+        @Override
+        public Object deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
+        {
             Object value;
-            if (_inputType == null) {
-                value = jp.getText();
-            } else  if (_inputType == Integer.class) {
-                value = Integer.valueOf(jp.getValueAsInt());
-            } else  if (_inputType == Long.class) {
-                value = Long.valueOf(jp.getValueAsLong());
+            if (_deser != null) {
+                value = _deser.deserialize(jp, ctxt);
             } else {
-                throw ctxt.mappingException(_enumClass);
+                value = jp.getValueAsString();
             }
             try {
-                return _factory.invoke(_enumClass, value);
+                return _factory.invoke(_valueClass, value);
             } catch (Exception e) {
                 Throwable t = ClassUtil.getRootCause(e);
                 if (t instanceof IOException) {
                     throw (IOException) t;
                 }
-                throw ctxt.instantiationException(_enumClass, t);
+                throw ctxt.instantiationException(_valueClass, t);
             }
         }
+
+        @Override
+        public Object deserializeWithType(JsonParser jp, DeserializationContext ctxt, TypeDeserializer typeDeserializer) throws IOException {
+            if (_deser == null) { // String never has type info
+                return deserialize(jp, ctxt);
+            }
+            return typeDeserializer.deserializeTypedFromAny(jp, 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 552af52..396b862 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
@@ -4,10 +4,8 @@
 import java.util.*;
 
 import com.fasterxml.jackson.core.*;
-
 import com.fasterxml.jackson.databind.*;
 import com.fasterxml.jackson.databind.deser.ContextualDeserializer;
-import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
 import com.fasterxml.jackson.databind.jsontype.TypeDeserializer;
 
 /**
@@ -15,21 +13,19 @@
  * <p>
  * Note: casting within this class is all messed up -- just could not figure out a way
  * to properly deal with recursive definition of "EnumMap<K extends Enum<K>, V>
- * 
- * @author tsaloranta
  */
 @SuppressWarnings({ "unchecked", "rawtypes" }) 
 public class EnumMapDeserializer
-    extends StdDeserializer<EnumMap<?,?>>
+    extends ContainerDeserializerBase<EnumMap<?,?>>
     implements ContextualDeserializer
 {
-    private static final long serialVersionUID = 4564890642370311174L;
+    private static final long serialVersionUID = 1;
 
     protected final JavaType _mapType;
     
     protected final Class<?> _enumClass;
 
-    protected JsonDeserializer<Enum<?>> _keyDeserializer;
+    protected KeyDeserializer _keyDeserializer;
 
     protected JsonDeserializer<Object> _valueDeserializer;
 
@@ -45,17 +41,17 @@
     /**********************************************************
      */
 
-    public EnumMapDeserializer(JavaType mapType, JsonDeserializer<?> keyDeserializer, JsonDeserializer<?> valueDeser, TypeDeserializer valueTypeDeser)
+    public EnumMapDeserializer(JavaType mapType, KeyDeserializer keyDeserializer, JsonDeserializer<?> valueDeser, TypeDeserializer valueTypeDeser)
     {
-        super(EnumMap.class);
+        super(mapType);
         _mapType = mapType;
         _enumClass = mapType.getKeyType().getRawClass();
-        _keyDeserializer = (JsonDeserializer<Enum<?>>) keyDeserializer;
+        _keyDeserializer = keyDeserializer;
         _valueDeserializer = (JsonDeserializer<Object>) valueDeser;
         _valueTypeDeserializer = valueTypeDeser;
     }
 
-    public EnumMapDeserializer withResolved(JsonDeserializer<?> keyDeserializer, JsonDeserializer<?> valueDeserializer, TypeDeserializer valueTypeDeser)
+    public EnumMapDeserializer withResolved(KeyDeserializer keyDeserializer, JsonDeserializer<?> valueDeserializer, TypeDeserializer valueTypeDeser)
     {
         if ((keyDeserializer == _keyDeserializer) && (valueDeserializer == _valueDeserializer) && (valueTypeDeser == _valueTypeDeserializer)) {
             return this;
@@ -73,9 +69,9 @@
         // note: instead of finding key deserializer, with enums we actually
         // work with regular deserializers (less code duplication; but not
         // quite as clean as it ought to be)
-        JsonDeserializer<?> kd = _keyDeserializer;
+        KeyDeserializer kd = _keyDeserializer;
         if (kd == null) {
-            kd = ctxt.findContextualValueDeserializer(_mapType.getKeyType(), property);
+            kd = ctxt.findKeyDeserializer(_mapType.getKeyType(), property);
         }
         JsonDeserializer<?> vd = _valueDeserializer;
         if (vd == null) {
@@ -96,38 +92,52 @@
      */
     @Override
     public boolean isCachable() { return true; }
-    
+
+    /*
+    /**********************************************************
+    /* ContainerDeserializerBase API
+    /**********************************************************
+     */
+
+    @Override
+    public JavaType getContentType() {
+        return _mapType.getContentType();
+    }
+
+    @Override
+    public JsonDeserializer<Object> getContentDeserializer() {
+        return _valueDeserializer;
+    }
+
     /*
     /**********************************************************
     /* Actual deserialization
     /**********************************************************
      */
-
+    
     @Override
-    public EnumMap<?,?> deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException
+    public EnumMap<?,?> deserialize(JsonParser jp, DeserializationContext ctxt)
+        throws IOException
     {
         // Ok: must point to START_OBJECT
         if (jp.getCurrentToken() != JsonToken.START_OBJECT) {
-            throw ctxt.mappingException(EnumMap.class);
+            return _deserializeFromEmpty(jp, ctxt);
         }
         EnumMap result = constructMap();
         final JsonDeserializer<Object> valueDes = _valueDeserializer;
         final TypeDeserializer typeDeser = _valueTypeDeserializer;
 
-        while ((jp.nextToken()) != JsonToken.END_OBJECT) {
-            Enum<?> key = _keyDeserializer.deserialize(jp, ctxt);
+        while ((jp.nextToken()) == JsonToken.FIELD_NAME) {
+            String keyName = jp.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)) {
-                    String value = null;
-                    try { // bit ugly, but will have to do; works with usual scalars
-                        if (jp.hasCurrentToken()) {
-                            value = jp.getText();
-                        }
-                    } catch (Exception e) { }
-                    throw ctxt.weirdStringException(value, _enumClass, "value not one of declared Enum instance names");
+                    throw ctxt.weirdStringException(keyName, _enumClass, "value not one of declared Enum instance names for "
+                            +_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 then.
+                 *  just skip the entry then. But we must skip the value as well, if so.
                  */
                 jp.nextToken();
                 jp.skipChildren();
@@ -139,13 +149,18 @@
              * not handle them (and maybe fail or return bogus data)
              */
             Object value;
-            
-            if (t == JsonToken.VALUE_NULL) {
-                value = valueDes.getNullValue();
-            } else if (typeDeser == null) {
-                value =  valueDes.deserialize(jp, ctxt);
-            } else {
-                value = valueDes.deserializeWithType(jp, ctxt, typeDeser);
+
+            try {
+                if (t == JsonToken.VALUE_NULL) {
+                    value = valueDes.getNullValue();
+                } else if (typeDeser == null) {
+                    value =  valueDes.deserialize(jp, ctxt);
+                } else {
+                    value = valueDes.deserializeWithType(jp, ctxt, typeDeser);
+                }
+            } catch (Exception e) {
+                wrapAndThrow(e, result, keyName);
+                return null;
             }
             result.put(key, value);
         }
@@ -153,14 +168,15 @@
     }
 
     @Override
-   public Object deserializeWithType(JsonParser jp, DeserializationContext ctxt, TypeDeserializer typeDeserializer)
+    public Object deserializeWithType(JsonParser jp, DeserializationContext ctxt, TypeDeserializer typeDeserializer)
         throws IOException, JsonProcessingException
     {
         // In future could check current token... for now this should be enough:
         return typeDeserializer.deserializeTypedFromObject(jp, ctxt);
     }
     
-    private EnumMap<?,?> constructMap() {
+    protected EnumMap<?,?> constructMap() {
         return new EnumMap(_enumClass);
     }
 }
+
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 7c719f0..1af0083 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
@@ -1,7 +1,6 @@
 package com.fasterxml.jackson.databind.deser.std;
 
 import java.io.IOException;
-import java.lang.reflect.InvocationTargetException;
 import java.util.*;
 
 import com.fasterxml.jackson.core.*;
@@ -28,7 +27,7 @@
     extends ContainerDeserializerBase<Map<Object,Object>>
     implements ContextualDeserializer, ResolvableDeserializer
 {
-    private static final long serialVersionUID = -3378654289961736240L;
+    private static final long serialVersionUID = 1L;
 
     // // Configuration: typing, deserializers
 
@@ -259,7 +258,7 @@
         }
         return withResolved(kd, vtd, vd, ignored);
     }
-    
+
     /*
     /**********************************************************
     /* ContainerDeserializerBase API
@@ -304,7 +303,8 @@
             if (t == JsonToken.VALUE_STRING) {
                 return (Map<Object,Object>) _valueInstantiator.createFromString(ctxt, jp.getText());
             }
-            throw ctxt.mappingException(getMapClass());
+            // slightly redundant (since String was passed above), but
+            return _deserializeFromEmpty(jp, ctxt);
         }
         final Map<Object,Object> result = (Map<Object,Object>) _valueInstantiator.createUsingDefault(ctxt);
         if (_standardStringKey) {
@@ -538,24 +538,6 @@
     protected void wrapAndThrow(Throwable t, Object ref) throws IOException {
         wrapAndThrow(t, ref, null);
     }
-    
-    // note: copied from BeanDeserializer; should try to share somehow...
-    protected void wrapAndThrow(Throwable t, Object ref, String key) throws IOException
-    {
-        // to handle StackOverflow:
-        while (t instanceof InvocationTargetException && t.getCause() != null) {
-            t = t.getCause();
-        }
-        // Errors and "plain" IOExceptions to be passed as is
-        if (t instanceof Error) {
-            throw (Error) t;
-        }
-        // ... except for mapping exceptions
-        if (t instanceof IOException && !(t instanceof JsonMappingException)) {
-            throw (IOException) t;
-        }
-        throw JsonMappingException.wrapWithPath(t, ref, key);
-    }
 
     private void handleUnresolvedReference(JsonParser jp, MapReferringAccumulator accumulator, Object key,
             UnresolvedForwardReference reference)
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
new file mode 100644
index 0000000..d524529
--- /dev/null
+++ b/src/main/java/com/fasterxml/jackson/databind/deser/std/MapEntryDeserializer.java
@@ -0,0 +1,246 @@
+package com.fasterxml.jackson.databind.deser.std;
+
+import java.io.IOException;
+import java.util.*;
+
+import com.fasterxml.jackson.core.*;
+import com.fasterxml.jackson.databind.*;
+import com.fasterxml.jackson.databind.annotation.JacksonStdImpl;
+import com.fasterxml.jackson.databind.deser.*;
+import com.fasterxml.jackson.databind.jsontype.TypeDeserializer;
+
+/**
+ * Basic serializer that can take JSON "Object" structure and
+ * construct a {@link java.util.Map} instance, with typed contents.
+ *<p>
+ * Note: for untyped content (one indicated by passing Object.class
+ * as the type), {@link UntypedObjectDeserializer} is used instead.
+ * It can also construct {@link java.util.Map}s, but not with specific
+ * POJO types, only other containers and primitives/wrappers.
+ */
+@JacksonStdImpl
+public class MapEntryDeserializer
+    extends ContainerDeserializerBase<Map.Entry<Object,Object>>
+    implements ContextualDeserializer
+{
+    private static final long serialVersionUID = 1;
+
+    // // Configuration: typing, deserializers
+
+    protected final JavaType _type;
+
+    /**
+     * Key deserializer to use; either passed via constructor
+     * (when indicated by annotations), or resolved when
+     * {@link #resolve} is called;
+     */
+    protected final KeyDeserializer _keyDeserializer;
+
+    /**
+     * Value deserializer.
+     */
+    protected final JsonDeserializer<Object> _valueDeserializer;
+
+    /**
+     * If value instances have polymorphic type information, this
+     * is the type deserializer that can handle it
+     */
+    protected final TypeDeserializer _valueTypeDeserializer;
+
+    /*
+    /**********************************************************
+    /* Life-cycle
+    /**********************************************************
+     */
+
+    public MapEntryDeserializer(JavaType type,
+            KeyDeserializer keyDeser, JsonDeserializer<Object> valueDeser,
+            TypeDeserializer valueTypeDeser)
+    {
+        super(type);
+        if (type.containedTypeCount() != 2) { // sanity check
+            throw new IllegalArgumentException("Missing generic type information for "+type);
+        }
+        _type = type;
+        _keyDeserializer = keyDeser;
+        _valueDeserializer = valueDeser;
+        _valueTypeDeserializer = valueTypeDeser;
+    }
+
+    /**
+     * Copy-constructor that can be used by sub-classes to allow
+     * copy-on-write styling copying of settings of an existing instance.
+     */
+    protected MapEntryDeserializer(MapEntryDeserializer src)
+    {
+        super(src._type);
+        _type = src._type;
+        _keyDeserializer = src._keyDeserializer;
+        _valueDeserializer = src._valueDeserializer;
+        _valueTypeDeserializer = src._valueTypeDeserializer;
+    }
+
+    protected MapEntryDeserializer(MapEntryDeserializer src,
+            KeyDeserializer keyDeser, JsonDeserializer<Object> valueDeser,
+            TypeDeserializer valueTypeDeser)
+    {
+        super(src._type);
+        _type = src._type;
+        _keyDeserializer = keyDeser;
+        _valueDeserializer = valueDeser;
+        _valueTypeDeserializer = valueTypeDeser;
+    }
+
+    /**
+     * Fluent factory method used to create a copy with slightly
+     * different settings. When sub-classing, MUST be overridden.
+     */
+    @SuppressWarnings("unchecked")
+    protected MapEntryDeserializer withResolved(KeyDeserializer keyDeser,
+            TypeDeserializer valueTypeDeser, JsonDeserializer<?> valueDeser)
+    {
+        
+        if ((_keyDeserializer == keyDeser) && (_valueDeserializer == valueDeser)
+                && (_valueTypeDeserializer == valueTypeDeser)) {
+            return this;
+        }
+        return new MapEntryDeserializer(this,
+                keyDeser, (JsonDeserializer<Object>) valueDeser, valueTypeDeser);
+    }
+
+    /*
+    /**********************************************************
+    /* Validation, post-processing (ResolvableDeserializer)
+    /**********************************************************
+     */
+
+    /**
+     * Method called to finalize setup of this deserializer,
+     * when it is known for which property deserializer is needed for.
+     */
+    @Override
+    public JsonDeserializer<?> createContextual(DeserializationContext ctxt,
+            BeanProperty property) throws JsonMappingException
+    {
+        KeyDeserializer kd = _keyDeserializer;
+        if (kd == null) {
+            kd = ctxt.findKeyDeserializer(_type.containedType(0), property);
+        } else {
+            if (kd instanceof ContextualKeyDeserializer) {
+                kd = ((ContextualKeyDeserializer) kd).createContextual(ctxt, property);
+            }
+        }
+        JsonDeserializer<?> vd = _valueDeserializer;
+        vd = findConvertingContentDeserializer(ctxt, property, vd);
+        if (vd == null) {
+            vd = ctxt.findContextualValueDeserializer(_type.containedType(1), property);
+        } else { // if directly assigned, probably not yet contextual, so:
+            vd = ctxt.handleSecondaryContextualization(vd, property);
+        }
+        TypeDeserializer vtd = _valueTypeDeserializer;
+        if (vtd != null) {
+            vtd = vtd.forProperty(property);
+        }
+        return withResolved(kd, vtd, vd);
+    }
+
+    /*
+    /**********************************************************
+    /* ContainerDeserializerBase API
+    /**********************************************************
+     */
+
+    @Override
+    public JavaType getContentType() {
+        return _type.containedType(1);
+    }
+
+    @Override
+    public JsonDeserializer<Object> getContentDeserializer() {
+        return _valueDeserializer;
+    }
+    
+    /*
+    /**********************************************************
+    /* JsonDeserializer API
+    /**********************************************************
+     */
+
+    @Override
+    public Map.Entry<Object,Object> deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
+    {
+        // Ok: must point to START_OBJECT, FIELD_NAME or END_OBJECT
+        JsonToken t = jp.getCurrentToken();
+        if (t != JsonToken.START_OBJECT && t != JsonToken.FIELD_NAME && t != JsonToken.END_OBJECT) {
+            // [JACKSON-620] (empty) String may be ok however:
+            // slightly redundant (since String was passed above), but
+            return _deserializeFromEmpty(jp, ctxt);
+        }
+        if (t == JsonToken.START_OBJECT) {
+            t = jp.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");
+            }
+            throw ctxt.mappingException(handledType(), t);
+        }
+        
+        final KeyDeserializer keyDes = _keyDeserializer;
+        final JsonDeserializer<Object> valueDes = _valueDeserializer;
+        final TypeDeserializer typeDeser = _valueTypeDeserializer;
+
+        final String keyStr = jp.getCurrentName();
+        Object key = keyDes.deserializeKey(keyStr, ctxt);
+        Object value = null;
+        // And then the value...
+        t = jp.nextToken();
+        try {
+            // Note: must handle null explicitly here; value deserializers won't
+            if (t == JsonToken.VALUE_NULL) {
+                value = valueDes.getNullValue();
+            } else if (typeDeser == null) {
+                value = valueDes.deserialize(jp, ctxt);
+            } else {
+                value = valueDes.deserializeWithType(jp, ctxt, typeDeser);
+            }
+        } catch (Exception e) {
+            wrapAndThrow(e, Map.Entry.class, keyStr);
+        }
+
+        // Close, but also verify that we reached the END_OBJECT
+        t = jp.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()+"')");
+            }
+            // how would this occur?
+            throw ctxt.mappingException("Problem binding JSON into Map.Entry: unexpected content after JSON Object entry: "+t);
+        }
+        return new AbstractMap.SimpleEntry<Object,Object>(key, value);
+    }
+
+    @Override
+    public Map.Entry<Object,Object> deserialize(JsonParser jp, 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,
+            TypeDeserializer typeDeserializer)
+        throws IOException, JsonProcessingException
+    {
+        // In future could check current token... for now this should be enough:
+        return typeDeserializer.deserializeTypedFromObject(jp, ctxt);
+    }
+
+    /*
+    /**********************************************************
+    /* Other public accessors
+    /**********************************************************
+     */
+
+    @Override public JavaType getValueType() { return _type; }
+}
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 45174c6..49d447e 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
@@ -157,7 +157,7 @@
                 chunk[ix++] = value;
             }
         } catch (Exception e) {
-            throw JsonMappingException.wrapWithPath(e, chunk, ix);
+            throw JsonMappingException.wrapWithPath(e, chunk, buffer.bufferedSize() + ix);
         }
 
         Object[] result;
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 ea5ac60..7ecdd90 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
@@ -165,7 +165,7 @@
                     chunk[ix++] = value;
                 }
             } catch (Exception e) {
-                throw JsonMappingException.wrapWithPath(e, chunk, ix);
+                throw JsonMappingException.wrapWithPath(e, chunk, builder.bufferedSize() + ix);
             }
             return builder.completeAndClearBuffer(chunk, ix);
         }
@@ -245,7 +245,7 @@
                     chunk[ix++] = value;
                 }
             } catch (Exception e) {
-                throw JsonMappingException.wrapWithPath(e, chunk, ix);
+                throw JsonMappingException.wrapWithPath(e, chunk, builder.bufferedSize() + ix);
             }
             return builder.completeAndClearBuffer(chunk, ix);
         }
@@ -308,7 +308,7 @@
                     chunk[ix++] = value;
                 }
             } catch (Exception e) {
-                throw JsonMappingException.wrapWithPath(e, chunk, ix);
+                throw JsonMappingException.wrapWithPath(e, chunk, builder.bufferedSize() + ix);
             }
             return builder.completeAndClearBuffer(chunk, ix);
         }
@@ -362,7 +362,7 @@
                     chunk[ix++] = value;
                 }
             } catch (Exception e) {
-                throw JsonMappingException.wrapWithPath(e, chunk, ix);
+                throw JsonMappingException.wrapWithPath(e, chunk, builder.bufferedSize() + ix);
             }
             return builder.completeAndClearBuffer(chunk, ix);
         }
@@ -415,7 +415,7 @@
                     chunk[ix++] = value;
                 }
             } catch (Exception e) {
-                throw JsonMappingException.wrapWithPath(e, chunk, ix);
+                throw JsonMappingException.wrapWithPath(e, chunk, builder.bufferedSize() + ix);
             }
             return builder.completeAndClearBuffer(chunk, ix);
         }
@@ -467,7 +467,7 @@
                     chunk[ix++] = value;
                 }
             } catch (Exception e) {
-                throw JsonMappingException.wrapWithPath(e, chunk, ix);
+                throw JsonMappingException.wrapWithPath(e, chunk, builder.bufferedSize() + ix);
             }
             return builder.completeAndClearBuffer(chunk, ix);
         }
@@ -518,7 +518,7 @@
                     chunk[ix++] = value;
                 }
             } catch (Exception e) {
-                throw JsonMappingException.wrapWithPath(e, chunk, ix);
+                throw JsonMappingException.wrapWithPath(e, chunk, builder.bufferedSize() + ix);
             }
             return builder.completeAndClearBuffer(chunk, ix);
         }
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 e4eeddc..3f9fa66 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
@@ -800,6 +800,35 @@
     }
 
     /**
+     * Helper method that may be used to support fallback for Empty String / Empty Array
+     * non-standard representations; usually for things serialized as JSON Objects.
+     * 
+     * @since 2.5
+     */
+    protected T _deserializeFromEmpty(JsonParser jp, DeserializationContext ctxt)
+        throws IOException
+    {
+        JsonToken t = jp.getCurrentToken();
+        if (t == JsonToken.START_ARRAY) {
+            if (ctxt.isEnabled(DeserializationFeature.ACCEPT_EMPTY_ARRAY_AS_NULL_OBJECT)) {
+                t = jp.nextToken();
+                if (t == JsonToken.END_ARRAY) {
+                    return null;
+                }
+                throw ctxt.mappingException(handledType(), JsonToken.START_ARRAY);
+            }
+        } else if (t == JsonToken.VALUE_STRING) {
+            if (ctxt.isEnabled(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT)) {
+                String str = jp.getText().trim();
+                if (str.isEmpty()) {
+                    return null;
+                }
+            }
+        }
+        throw ctxt.mappingException(handledType());
+    }
+    
+    /**
      * Helper method called to determine if we are seeing String value of
      * "null", and, further, that it should be coerced to null just like
      * null token.
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 b174bef..c73a196 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
@@ -162,9 +162,7 @@
             return _parseLong(key);
 
         case TYPE_FLOAT:
-            /* 22-Jan-2009, tatu: Bounds/range checks would be tricky
-             *   here, so let's not bother even trying...
-             */
+            // Bounds/range checks would be tricky here, so let's not bother even trying...
             return Float.valueOf((float) _parseDouble(key));
         case TYPE_DOUBLE:
             return _parseDouble(key);
diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/std/StdKeyDeserializers.java b/src/main/java/com/fasterxml/jackson/databind/deser/std/StdKeyDeserializers.java
index 95a560e..32e2a4a 100644
--- a/src/main/java/com/fasterxml/jackson/databind/deser/std/StdKeyDeserializers.java
+++ b/src/main/java/com/fasterxml/jackson/databind/deser/std/StdKeyDeserializers.java
@@ -28,7 +28,7 @@
 public class StdKeyDeserializers
     implements KeyDeserializers, java.io.Serializable
 {
-    private static final long serialVersionUID = 923268084968181479L;
+    private static final long serialVersionUID = 1L;
     
     public static KeyDeserializer constructEnumKeyDeserializer(EnumResolver<?> enumResolver) {
         return new StdKeyDeserializer.EnumKD(enumResolver, null);
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 387a43d..439c256 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
@@ -2,7 +2,6 @@
 
 import java.io.IOException;
 
-import com.fasterxml.jackson.core.JsonProcessingException;
 import com.fasterxml.jackson.databind.*;
 import com.fasterxml.jackson.databind.annotation.JacksonStdImpl;
 import com.fasterxml.jackson.databind.deser.*;
@@ -204,8 +203,7 @@
      */
     
     @Override
-    public Object createUsingDefault(DeserializationContext ctxt)
-        throws IOException, JsonProcessingException
+    public Object createUsingDefault(DeserializationContext ctxt) throws IOException
     {
         if (_defaultCreator == null) { // sanity-check; caller should check
             throw new IllegalStateException("No default constructor for "+getValueTypeDesc());
@@ -220,8 +218,7 @@
     }
     
     @Override
-    public Object createFromObjectWith(DeserializationContext ctxt, Object[] args)
-        throws IOException, JsonProcessingException
+    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());
@@ -236,8 +233,7 @@
     }
 
     @Override
-    public Object createUsingDelegate(DeserializationContext ctxt, Object delegate)
-        throws IOException, JsonProcessingException
+    public Object createUsingDelegate(DeserializationContext ctxt, Object delegate) throws IOException
     {
         if (_delegateCreator == null) { // sanity-check; caller should check
             throw new IllegalStateException("No delegate constructor for "+getValueTypeDesc());
@@ -274,8 +270,7 @@
      */
     
     @Override
-    public Object createFromString(DeserializationContext ctxt, String value)
-            throws IOException, JsonProcessingException
+    public Object createFromString(DeserializationContext ctxt, String value) throws IOException
     {
         if (_fromStringCreator != null) {
             try {
@@ -290,8 +285,7 @@
     }
     
     @Override
-    public Object createFromInt(DeserializationContext ctxt, int value)
-            throws IOException, JsonProcessingException
+    public Object createFromInt(DeserializationContext ctxt, int value) throws IOException
     {
         try {
             // First: "native" int methods work best:
@@ -312,8 +306,7 @@
     }
 
     @Override
-    public Object createFromLong(DeserializationContext ctxt, long value)
-            throws IOException, JsonProcessingException
+    public Object createFromLong(DeserializationContext ctxt, long value) throws IOException
     {
         try {
             if (_fromLongCreator != null) {
@@ -329,8 +322,7 @@
     }
 
     @Override
-    public Object createFromDouble(DeserializationContext ctxt, double value)
-            throws IOException, JsonProcessingException
+    public Object createFromDouble(DeserializationContext ctxt, double value) throws IOException
     {
         try {
             if (_fromDoubleCreator != null) {
@@ -346,8 +338,7 @@
     }
 
     @Override
-    public Object createFromBoolean(DeserializationContext ctxt, boolean value)
-            throws IOException, JsonProcessingException
+    public Object createFromBoolean(DeserializationContext ctxt, boolean value) throws IOException
     {
         try {
             if (_fromBooleanCreator != null) {
@@ -387,7 +378,7 @@
     public AnnotatedParameter getIncompleteParameter() {
         return _incompleteParameter;
     }
-    
+
     /*
     /**********************************************************
     /* Internal methods
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 a4e08e4..142eda3 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
@@ -19,7 +19,7 @@
     extends StdDeserializer<String[]>
     implements ContextualDeserializer
 {
-    private static final long serialVersionUID = -7589512013334920693L;
+    private static final long serialVersionUID = 1L;
 
     public final static StringArrayDeserializer instance = new StringArrayDeserializer();
     
@@ -74,7 +74,7 @@
                 chunk[ix++] = value;
             }
         } catch (Exception e) {
-            throw JsonMappingException.wrapWithPath(e, chunk, ix);
+            throw JsonMappingException.wrapWithPath(e, chunk, buffer.bufferedSize() + ix);
         }
         String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
         ctxt.returnObjectBuffer(buffer);
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 3512003..2d6441c 100644
--- a/src/main/java/com/fasterxml/jackson/databind/introspect/Annotated.java
+++ b/src/main/java/com/fasterxml/jackson/databind/introspect/Annotated.java
@@ -85,5 +85,15 @@
      * not exposed to developers since instances are mutable.
      */
     protected abstract AnnotationMap getAllAnnotations();
-}
 
+    // Also: ensure we can use #equals, #hashCode
+    
+    @Override
+    public abstract boolean equals(Object o);
+
+    @Override
+    public abstract int hashCode();
+
+    @Override
+    public abstract String toString();
+}
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 fa379b1..9b9d1c2 100644
--- a/src/main/java/com/fasterxml/jackson/databind/introspect/AnnotatedClass.java
+++ b/src/main/java/com/fasterxml/jackson/databind/introspect/AnnotatedClass.java
@@ -908,13 +908,13 @@
         if (anns != null) {
             List<Annotation[]> bundles = null;
             for (Annotation ann : anns) { // first: direct annotations
-                if (_isAnnotationBundle(ann)) {
+                // note: we will NOT filter out non-Jackson anns any more
+                boolean wasNotPresent = result.addIfNotPresent(ann);
+                if (wasNotPresent && _isAnnotationBundle(ann)) {
                     if (bundles == null) {
                         bundles = new LinkedList<Annotation[]>();
                     }
                     bundles.add(ann.annotationType().getDeclaredAnnotations());
-                } else { // note: we will NOT filter out non-Jackson anns any more
-                    result.addIfNotPresent(ann);
                 }
             }
             if (bundles != null) { // and secondarily handle bundles, if any found: precedence important
@@ -930,13 +930,13 @@
         if (anns != null) {
             List<Annotation[]> bundles = null;
             for (Annotation ann : anns) { // first: direct annotations
-                if (_isAnnotationBundle(ann)) {
+                // note: we will NOT filter out non-Jackson anns any more
+                boolean wasNotPresent = target.addIfNotPresent(ann);
+                if (wasNotPresent && _isAnnotationBundle(ann)) {
                     if (bundles == null) {
                         bundles = new LinkedList<Annotation[]>();
                     }
                     bundles.add(ann.annotationType().getDeclaredAnnotations());
-                } else { // note: we will NOT filter out non-Jackson anns any more
-                    target.addIfNotPresent(ann);
                 }
             }
             if (bundles != null) { // and secondarily handle bundles, if any found: precedence important
@@ -952,13 +952,13 @@
         if (anns != null) {
             List<Annotation[]> bundles = null;
             for (Annotation ann : anns) { // first: direct annotations
-                if (_isAnnotationBundle(ann)) {
+                // note: we will NOT filter out non-Jackson anns any more
+                boolean wasModified = target.addOrOverride(ann);
+                if (wasModified && _isAnnotationBundle(ann)) {
                     if (bundles == null) {
                         bundles = new LinkedList<Annotation[]>();
                     }
                     bundles.add(ann.annotationType().getDeclaredAnnotations());
-                } else { // note: no filtering by jackson-annotations
-                    target.addOrOverride(ann);
                 }
             }
             if (bundles != null) { // and then bundles, if any: important for precedence
@@ -1013,8 +1013,7 @@
         _addAnnotationsIfNotPresent(target, src.getDeclaredAnnotations());
     }
 
-   private final boolean _isAnnotationBundle(Annotation ann)
-   {
+   private final boolean _isAnnotationBundle(Annotation ann) {
        return (_annotationIntrospector != null) && _annotationIntrospector.isAnnotationBundle(ann);
    }
    
@@ -1025,8 +1024,19 @@
      */
 
     @Override
-    public String toString()
-    {
+    public String toString() {
         return "[AnnotedClass "+_class.getName()+"]";
     }
+
+    @Override
+    public int hashCode() {
+        return _class.getName().hashCode();
+    }
+    
+    @Override
+    public boolean equals(Object o) {
+        if (o == this) return true;
+        if (o == null || o.getClass() != getClass()) return false;
+        return ((AnnotatedClass) o)._class == _class;
+    }
 }
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 d94c091..1829cb3 100644
--- a/src/main/java/com/fasterxml/jackson/databind/introspect/AnnotatedConstructor.java
+++ b/src/main/java/com/fasterxml/jackson/databind/introspect/AnnotatedConstructor.java
@@ -169,6 +169,18 @@
         return "[constructor for "+getName()+", annotations: "+_annotations+"]";
     }
 
+    @Override
+    public int hashCode() {
+        return _constructor.getName().hashCode();
+    }
+    
+    @Override
+    public boolean equals(Object o) {
+        if (o == this) return true;
+        if (o == null || o.getClass() != getClass()) return false;
+        return ((AnnotatedConstructor) o)._constructor == _constructor;
+    }
+    
     /*
     /**********************************************************
     /* JDK serialization handling
diff --git a/src/main/java/com/fasterxml/jackson/databind/introspect/AnnotatedField.java b/src/main/java/com/fasterxml/jackson/databind/introspect/AnnotatedField.java
index a0ce14a..ebc48cb 100644
--- a/src/main/java/com/fasterxml/jackson/databind/introspect/AnnotatedField.java
+++ b/src/main/java/com/fasterxml/jackson/databind/introspect/AnnotatedField.java
@@ -73,8 +73,7 @@
     public String getName() { return _field.getName(); }
 
     @Override
-    public <A extends Annotation> A getAnnotation(Class<A> acls)
-    {
+    public <A extends Annotation> A getAnnotation(Class<A> acls) {
         return (_annotations == null) ? null : _annotations.get(acls);
     }
 
@@ -135,8 +134,19 @@
     public int getAnnotationCount() { return _annotations.size(); }
 
     @Override
-    public String toString()
-    {
+    public int hashCode() {
+        return _field.getName().hashCode();
+    }
+    
+    @Override
+    public boolean equals(Object o) {
+        if (o == this) return true;
+        if (o == null || o.getClass() != getClass()) return false;
+        return ((AnnotatedField) o)._field == _field;
+    }
+
+    @Override
+    public String toString() {
         return "[field "+getFullName()+"]";
     }
 
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 871a65c..d5114d8 100644
--- a/src/main/java/com/fasterxml/jackson/databind/introspect/AnnotatedMember.java
+++ b/src/main/java/com/fasterxml/jackson/databind/introspect/AnnotatedMember.java
@@ -11,8 +11,6 @@
  * a class; fields, methods and constructors. This is a superset
  * of things that can represent logical properties as it contains
  * constructors in addition to fields and methods.
- * 
- * @author tatu
  */
 public abstract class AnnotatedMember
     extends Annotated
@@ -51,8 +49,8 @@
      * annotation masking or overriding an annotation 'real' constructor
      * has.
      */
-    public final void addOrOverride(Annotation a) {
-        _annotations.add(a);
+    public final boolean addOrOverride(Annotation a) {
+        return _annotations.add(a);
     }
 
     /**
@@ -60,8 +58,8 @@
      * annotation if and only if it is not yet present in the
      * annotation map we have.
      */
-    public final void addIfNotPresent(Annotation a) {
-        _annotations.addIfNotPresent(a);
+    public final boolean addIfNotPresent(Annotation a) {
+        return _annotations.addIfNotPresent(a);
     }
     
     /**
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 3fc2838..bf5afd2 100644
--- a/src/main/java/com/fasterxml/jackson/databind/introspect/AnnotatedMethod.java
+++ b/src/main/java/com/fasterxml/jackson/databind/introspect/AnnotatedMethod.java
@@ -138,8 +138,7 @@
     public Method getMember() { return _method; }
 
     @Override
-    public void setValue(Object pojo, Object value)
-        throws IllegalArgumentException
+    public void setValue(Object pojo, Object value) throws IllegalArgumentException
     {
         try {
             _method.invoke(pojo, value);
@@ -235,11 +234,22 @@
      */
 
     @Override
-    public String toString()
-    {
+    public String toString() {
         return "[method "+getFullName()+"]";
     }
 
+    @Override
+    public int hashCode() {
+        return _method.getName().hashCode();
+    }
+    
+    @Override
+    public boolean equals(Object o) {
+        if (o == this) return true;
+        if (o == null || o.getClass() != getClass()) return false;
+        return ((AnnotatedMethod) o)._method == _method;
+    }
+    
     /*
     /**********************************************************
     /* JDK serialization handling
diff --git a/src/main/java/com/fasterxml/jackson/databind/introspect/AnnotatedParameter.java b/src/main/java/com/fasterxml/jackson/databind/introspect/AnnotatedParameter.java
index 4c2bfcb..718d0f5 100644
--- a/src/main/java/com/fasterxml/jackson/databind/introspect/AnnotatedParameter.java
+++ b/src/main/java/com/fasterxml/jackson/databind/introspect/AnnotatedParameter.java
@@ -5,7 +5,6 @@
 import java.lang.reflect.Member;
 import java.lang.reflect.Type;
 
-
 import com.fasterxml.jackson.databind.JavaType;
 import com.fasterxml.jackson.databind.type.TypeFactory;
 
@@ -175,8 +174,20 @@
      */
     
     @Override
-    public String toString()
-    {
+    public int hashCode() {
+        return _owner.hashCode() + _index;
+    }
+    
+    @Override
+    public boolean equals(Object o) {
+        if (o == this) return true;
+        if (o == null || o.getClass() != getClass()) return false;
+        AnnotatedParameter other = (AnnotatedParameter) o;
+        return other._owner.equals(_owner) && (other._index == _index);
+    }
+    
+    @Override
+    public String toString() {
         return "[parameter #"+getIndex()+", annotations: "+_annotations+"]";
     }
 }
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 39d4fcd..98b0ecb 100644
--- a/src/main/java/com/fasterxml/jackson/databind/introspect/AnnotationIntrospectorPair.java
+++ b/src/main/java/com/fasterxml/jackson/databind/introspect/AnnotationIntrospectorPair.java
@@ -315,16 +315,15 @@
     public JsonInclude.Include findSerializationInclusion(Annotated a,
             JsonInclude.Include defValue)
     {
-        /* This is bit trickier: need to combine results in a meaningful
-         * way. Seems like it should be a disjoint; that is, most
-         * restrictive value should be returned.
-         * For enumerations, comparison is done by indexes, which
-         * works: largest value is the last one, which is the most
-         * restrictive value as well.
-         */
-        /* 09-Mar-2010, tatu: Actually, as per [JACKSON-256], it is probably better to just
-         *    use strict overriding. Simpler, easier to understand.
-         */
+        // note: call secondary first, to give lower priority
+        defValue = _secondary.findSerializationInclusion(a, defValue);
+        defValue = _primary.findSerializationInclusion(a, defValue);
+        return defValue;
+    }
+
+    @Override
+    public JsonInclude.Include findSerializationInclusionForContent(Annotated a, JsonInclude.Include defValue)
+    {
         // note: call secondary first, to give lower priority
         defValue = _secondary.findSerializationInclusion(a, defValue);
         defValue = _primary.findSerializationInclusion(a, defValue);
@@ -333,7 +332,7 @@
     
     @Override
     public Class<?> findSerializationType(Annotated a) {
-    	Class<?> r = _primary.findSerializationType(a);
+        Class<?> r = _primary.findSerializationType(a);
         return (r == null) ? _secondary.findSerializationType(a) : r;
     }
 
diff --git a/src/main/java/com/fasterxml/jackson/databind/introspect/AnnotationMap.java b/src/main/java/com/fasterxml/jackson/databind/introspect/AnnotationMap.java
index 1b350fe..0b514ff 100644
--- a/src/main/java/com/fasterxml/jackson/databind/introspect/AnnotationMap.java
+++ b/src/main/java/com/fasterxml/jackson/databind/introspect/AnnotationMap.java
@@ -71,18 +71,20 @@
      * Method called to add specified annotation in the Map, but
      * only if it didn't yet exist.
      */
-    public void addIfNotPresent(Annotation ann)
+    public boolean addIfNotPresent(Annotation ann)
     {
         if (_annotations == null || !_annotations.containsKey(ann.annotationType())) {
             _add(ann);
+            return true;
         }
+        return false;
     }
 
     /**
      * Method called to add specified annotation in the Map.
      */
-    public void add(Annotation ann) {
-        _add(ann);
+    public boolean add(Annotation ann) {
+        return _add(ann);
     }
 
     @Override
@@ -99,11 +101,12 @@
     /**********************************************************
      */
 
-    protected final void _add(Annotation ann) {
+    protected final boolean _add(Annotation ann) {
         if (_annotations == null) {
             _annotations = new HashMap<Class<? extends Annotation>,Annotation>();
         }
-        _annotations.put(ann.annotationType(), ann);
+        Annotation previous = _annotations.put(ann.annotationType(), ann);
+        return (previous != null) && previous.equals(ann);
     }
 }
 
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 f8745dd..de54967 100644
--- a/src/main/java/com/fasterxml/jackson/databind/introspect/BasicBeanDescription.java
+++ b/src/main/java/com/fasterxml/jackson/databind/introspect/BasicBeanDescription.java
@@ -330,13 +330,20 @@
      * and per-class annotation (highest priority).
      */
     @Override
-    public JsonInclude.Include findSerializationInclusion(JsonInclude.Include defValue)
-    {
+    public JsonInclude.Include findSerializationInclusion(JsonInclude.Include defValue) {
         if (_annotationIntrospector == null) {
             return defValue;
         }
         return _annotationIntrospector.findSerializationInclusion(_classInfo, defValue);
     }
+
+    @Override
+    public JsonInclude.Include findSerializationInclusionForContent(JsonInclude.Include defValue) {
+        if (_annotationIntrospector == null) {
+            return defValue;
+        }
+        return _annotationIntrospector.findSerializationInclusionForContent(_classInfo, defValue);
+    }
     
     /**
      * Method used to locate the method of introspected class that
@@ -363,7 +370,20 @@
     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
+             *   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...
+             *   so commented out part does not work, alas
+             */
+            /*
+            if (hasIgnored && _ignoredPropertyNames.contains(property.getName())) {
+                continue;
+            }
+            */
             AnnotatedMember am = property.getMutator();
             if (am == null) {
                 continue;
@@ -457,7 +477,7 @@
 
         /* Also: must be a recognized factory method, meaning:
          * (a) marked with @JsonCreator annotation, or
-         * (a) "valueOf" (at this point, need not be public)
+         * (b) "valueOf" (at this point, need not be public)
          */
         if (_annotationIntrospector.hasCreatorAnnotation(am)) {
             return true;
@@ -479,7 +499,7 @@
     }
 
     /**
-     * @deprecated Since 2.4, use {@link #findCreatorParameterNames()} instead.
+     * @deprecated Since 2.4, use <code>findCreatorParameterNames()</code> instead.
      */
     @Deprecated
     public List<String> findCreatorPropertyNames()
@@ -496,16 +516,9 @@
     }
     
     /**
-     * Method for getting ordered list of named Creator properties.
-     * Returns an empty list is none found. If multiple Creator
-     * methods are defined, order between properties from different
-     * methods is undefined; however, properties for each such
-     * Creator are ordered properly relative to each other.
-     * For the usual case of just a single Creator, named properties are
-     * thus properly ordered.
-     * 
-     * @since 2.4
+     * @deprecated Since 2.5, does not seem to be used at all.
      */
+    @Deprecated
     public List<PropertyName> findCreatorParameterNames()
     {
         for (int i = 0; i < 2; ++i) {
diff --git a/src/main/java/com/fasterxml/jackson/databind/introspect/BasicClassIntrospector.java b/src/main/java/com/fasterxml/jackson/databind/introspect/BasicClassIntrospector.java
index dbab578..d908a09 100644
--- a/src/main/java/com/fasterxml/jackson/databind/introspect/BasicClassIntrospector.java
+++ b/src/main/java/com/fasterxml/jackson/databind/introspect/BasicClassIntrospector.java
@@ -1,5 +1,8 @@
 package com.fasterxml.jackson.databind.introspect;
 
+import java.util.Collection;
+import java.util.Map;
+
 import com.fasterxml.jackson.databind.AnnotationIntrospector;
 import com.fasterxml.jackson.databind.DeserializationConfig;
 import com.fasterxml.jackson.databind.JavaType;
@@ -7,6 +10,7 @@
 import com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder;
 import com.fasterxml.jackson.databind.cfg.MapperConfig;
 import com.fasterxml.jackson.databind.type.SimpleType;
+import com.fasterxml.jackson.databind.util.LRUMap;
 
 public class BasicClassIntrospector
     extends ClassIntrospector
@@ -19,6 +23,8 @@
      * This is strictly performance optimization to reduce what is
      * usually one-time cost, but seems useful for some cases considering
      * simplicity.
+     * 
+     * @since 2.4
      */
     
     protected final static BasicBeanDescription STRING_DESC;
@@ -48,9 +54,21 @@
     /**********************************************************
      */
 
+    @Deprecated // since 2.5: construct instance directly
     public final static BasicClassIntrospector instance = new BasicClassIntrospector();
 
-    public BasicClassIntrospector() { }
+    /**
+     * Looks like 'forClassAnnotations()' gets called so frequently that we
+     * should consider caching to avoid some of the lookups.
+     * 
+     * @since 2.5
+     */
+    protected final LRUMap<JavaType,BasicBeanDescription> _cachedFCA;
+
+    public BasicClassIntrospector() {
+        // a small cache should go a long way here
+        _cachedFCA = new LRUMap<JavaType,BasicBeanDescription>(16, 64);
+    }
     
     /*
     /**********************************************************
@@ -62,11 +80,18 @@
     public BasicBeanDescription forSerialization(SerializationConfig cfg,
             JavaType type, MixInResolver r)
     {
-        // minor optimization: for JDK types do minimal introspection
-        BasicBeanDescription desc = _findCachedDesc(type);
+        // minor optimization: for some JDK types do minimal introspection
+        BasicBeanDescription desc = _findStdTypeDesc(type);
         if (desc == null) {
-            desc = BasicBeanDescription.forSerialization(collectProperties(cfg,
-            		type, r, true, "set"));
+            // As per [Databind#550], skip full introspection for some of standard
+            // structured types as well
+            desc = _findStdJdkCollectionDesc(cfg, type, r);
+            if (desc == null) {
+                desc = BasicBeanDescription.forSerialization(collectProperties(cfg,
+                        type, r, true, "set"));
+            }
+            // Also: this is a superset of "forClassAnnotations", so may optimize by optional add:
+            _cachedFCA.putIfAbsent(type, desc);
         }
         return desc;
     }
@@ -75,11 +100,18 @@
     public BasicBeanDescription forDeserialization(DeserializationConfig cfg,
             JavaType type, MixInResolver r)
     {
-        // minor optimization: for JDK types do minimal introspection
-        BasicBeanDescription desc = _findCachedDesc(type);
+        // minor optimization: for some JDK types do minimal introspection
+        BasicBeanDescription desc = _findStdTypeDesc(type);
         if (desc == null) {
-            desc = BasicBeanDescription.forDeserialization(collectProperties(cfg,
-            		type, r, false, "set"));
+            // As per [Databind#550], skip full introspection for some of standard
+            // structured types as well
+            desc = _findStdJdkCollectionDesc(cfg, type, r);
+            if (desc == null) {
+                desc = BasicBeanDescription.forDeserialization(collectProperties(cfg,
+                        		type, r, false, "set"));
+            }
+            // Also: this is a superset of "forClassAnnotations", so may optimize by optional add:
+            _cachedFCA.putIfAbsent(type, desc);
         }
         return desc;
     }
@@ -88,20 +120,31 @@
     public BasicBeanDescription forDeserializationWithBuilder(DeserializationConfig cfg,
             JavaType type, MixInResolver r)
     {
-    	// no caching for Builders (no standard JDK builder types):
-    	return BasicBeanDescription.forDeserialization(collectPropertiesWithBuilder(cfg,
-            		type, r, false));
+        // no std JDK types with Builders, so:
+
+        BasicBeanDescription desc = BasicBeanDescription.forDeserialization(collectPropertiesWithBuilder(cfg,
+                type, r, false));
+        // this is still a superset of "forClassAnnotations", so may optimize by optional add:
+        _cachedFCA.putIfAbsent(type, desc);
+        return desc;
     }
     
     @Override
     public BasicBeanDescription forCreation(DeserializationConfig cfg,
             JavaType type, MixInResolver r)
     {
-        BasicBeanDescription desc = _findCachedDesc(type);
+        BasicBeanDescription desc = _findStdTypeDesc(type);
         if (desc == null) {
-            desc = BasicBeanDescription.forDeserialization(
+
+            // As per [Databind#550], skip full introspection for some of standard
+            // structured types as well
+            desc = _findStdJdkCollectionDesc(cfg, type, r);
+            if (desc == null) {
+                desc = BasicBeanDescription.forDeserialization(
             		collectProperties(cfg, type, r, false, "set"));
+            }
         }
+        // should this be cached for FCA?
         return desc;
     }
 
@@ -109,21 +152,33 @@
     public BasicBeanDescription forClassAnnotations(MapperConfig<?> cfg,
             JavaType type, MixInResolver r)
     {
-        boolean useAnnotations = cfg.isAnnotationProcessingEnabled();
-        AnnotatedClass ac = AnnotatedClass.construct(type.getRawClass(),
-                (useAnnotations ? cfg.getAnnotationIntrospector() : null), r);
-        return BasicBeanDescription.forOtherUse(cfg, type, ac);
+        BasicBeanDescription desc = _findStdTypeDesc(type);
+        if (desc == null) {
+            desc = _cachedFCA.get(type);
+            if (desc == null) {
+                boolean useAnnotations = cfg.isAnnotationProcessingEnabled();
+                AnnotatedClass ac = AnnotatedClass.construct(type.getRawClass(),
+                        (useAnnotations ? cfg.getAnnotationIntrospector() : null), r);
+                desc = BasicBeanDescription.forOtherUse(cfg, type, ac);
+                _cachedFCA.put(type, desc);
+            }
+        }
+        return desc;
     }
 
     @Override
     public BasicBeanDescription forDirectClassAnnotations(MapperConfig<?> cfg,
             JavaType type, MixInResolver r)
     {
-        boolean useAnnotations = cfg.isAnnotationProcessingEnabled();
-        AnnotationIntrospector ai =  cfg.getAnnotationIntrospector();
-        AnnotatedClass ac = AnnotatedClass.constructWithoutSuperTypes(type.getRawClass(),
-                (useAnnotations ? ai : null), r);
-        return BasicBeanDescription.forOtherUse(cfg, type, ac);
+        BasicBeanDescription desc = _findStdTypeDesc(type);
+        if (desc == null) {
+            boolean useAnnotations = cfg.isAnnotationProcessingEnabled();
+            AnnotationIntrospector ai =  cfg.getAnnotationIntrospector();
+            AnnotatedClass ac = AnnotatedClass.constructWithoutSuperTypes(type.getRawClass(),
+                    (useAnnotations ? ai : null), r);
+            desc = BasicBeanDescription.forOtherUse(cfg, type, ac);
+        }
+        return desc;
     }
     
     /*
@@ -167,20 +222,62 @@
      * Method called to see if type is one of core JDK types
      * that we have cached for efficiency.
      */
-    protected BasicBeanDescription _findCachedDesc(JavaType type)
+    protected BasicBeanDescription _findStdTypeDesc(JavaType type)
     {
         Class<?> cls = type.getRawClass();
-        if (cls == String.class) {
-            return STRING_DESC;
+        if (cls.isPrimitive()) {
+            if (cls == Boolean.TYPE) {
+                return BOOLEAN_DESC;
+            }
+            if (cls == Integer.TYPE) {
+                return INT_DESC;
+            }
+            if (cls == Long.TYPE) {
+                return LONG_DESC;
+            }
+        } else {
+            if (cls == String.class) {
+                return STRING_DESC;
+            }
         }
-        if (cls == Boolean.TYPE) {
-            return BOOLEAN_DESC;
+        return null;
+    }
+
+    /**
+     * Helper method used to decide whether we can omit introspection
+     * for members (methods, fields, constructors); we may do so for
+     * a limited number of container types JDK provides.
+     */
+    protected boolean _isStdJDKCollection(JavaType type)
+    {
+        if (!type.isContainerType() || type.isArrayType()) {
+            return false;
         }
-        if (cls == Integer.TYPE) {
-            return INT_DESC;
+        Class<?> raw = type.getRawClass();
+        Package pkg = raw.getPackage();
+        if (pkg != null) {
+            String pkgName = pkg.getName();
+            if (pkgName.startsWith("java.lang")
+                    || pkgName.startsWith("java.util")) {
+                /* 23-Sep-2014, tatu: Should we be conservative here (minimal number
+                 *    of matches), or ambitious? Let's do latter for now.
+                 */
+                if (Collection.class.isAssignableFrom(raw)
+                        || Map.class.isAssignableFrom(raw)) {
+                    return true;
+                }
+            }
         }
-        if (cls == Long.TYPE) {
-            return LONG_DESC;
+        return false;
+    }
+
+    protected BasicBeanDescription _findStdJdkCollectionDesc(MapperConfig<?> cfg,
+            JavaType type, MixInResolver r)
+    {
+        if (_isStdJDKCollection(type)) {
+            AnnotatedClass ac = AnnotatedClass.construct(type.getRawClass(),
+                    (cfg.isAnnotationProcessingEnabled() ? cfg.getAnnotationIntrospector() : null), r);
+            return BasicBeanDescription.forOtherUse(cfg, type, ac);
         }
         return null;
     }
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 809a97c..dce8b3c 100644
--- a/src/main/java/com/fasterxml/jackson/databind/introspect/BeanPropertyDefinition.java
+++ b/src/main/java/com/fasterxml/jackson/databind/introspect/BeanPropertyDefinition.java
@@ -1,9 +1,9 @@
 package com.fasterxml.jackson.databind.introspect;
 
-import com.fasterxml.jackson.databind.AnnotationIntrospector;
-import com.fasterxml.jackson.databind.BeanProperty;
-import com.fasterxml.jackson.databind.PropertyMetadata;
-import com.fasterxml.jackson.databind.PropertyName;
+import java.util.Iterator;
+
+import com.fasterxml.jackson.databind.*;
+import com.fasterxml.jackson.databind.util.EmptyIterator;
 import com.fasterxml.jackson.databind.util.Named;
 
 /**
@@ -135,6 +135,16 @@
     public abstract AnnotatedParameter getConstructorParameter();
 
     /**
+     * Additional method that may be called instead of {@link #getConstructorParameter()}
+     * to get access to all constructor parameters, not just the highest priority one.
+     * 
+     * @since 2.5
+     */
+    public Iterator<AnnotatedParameter> getConstructorParameters() {
+        return EmptyIterator.instance();
+    }
+    
+    /**
      * Method used to find accessor (getter, field to access) to use for accessing
      * value of the property.
      * Null if no such member exists.
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 6998126..62f6167 100644
--- a/src/main/java/com/fasterxml/jackson/databind/introspect/JacksonAnnotationIntrospector.java
+++ b/src/main/java/com/fasterxml/jackson/databind/introspect/JacksonAnnotationIntrospector.java
@@ -69,7 +69,7 @@
     @Override
     public PropertyName findRootName(AnnotatedClass ac)
     {
-        JsonRootName ann = ac.getAnnotation(JsonRootName.class);
+        JsonRootName ann = _findAnnotation(ac, JsonRootName.class);
         if (ann == null) {
             return null;
         }
@@ -82,19 +82,19 @@
 
     @Override
     public String[] findPropertiesToIgnore(Annotated ac) {
-        JsonIgnoreProperties ignore = ac.getAnnotation(JsonIgnoreProperties.class);
+        JsonIgnoreProperties ignore = _findAnnotation(ac, JsonIgnoreProperties.class);
         return (ignore == null) ? null : ignore.value();
     }
 
     @Override
     public Boolean findIgnoreUnknownProperties(AnnotatedClass ac) {
-        JsonIgnoreProperties ignore = ac.getAnnotation(JsonIgnoreProperties.class);
+        JsonIgnoreProperties ignore = _findAnnotation(ac, JsonIgnoreProperties.class);
         return (ignore == null) ? null : ignore.ignoreUnknown();
     }
 
     @Override
     public Boolean isIgnorableType(AnnotatedClass ac) {
-        JsonIgnoreType ignore = ac.getAnnotation(JsonIgnoreType.class);
+        JsonIgnoreType ignore = _findAnnotation(ac, JsonIgnoreType.class);
         return (ignore == null) ? null : ignore.value();
     }
 
@@ -114,7 +114,7 @@
 
     protected final Object _findFilterId(Annotated a)
     {
-        JsonFilter ann = a.getAnnotation(JsonFilter.class);
+        JsonFilter ann = _findAnnotation(a, JsonFilter.class);
         if (ann != null) {
             String id = ann.value();
             // Empty String is same as not having annotation, to allow overrides
@@ -128,7 +128,7 @@
     @Override
     public Object findNamingStrategy(AnnotatedClass ac)
     {
-        JsonNaming ann = ac.getAnnotation(JsonNaming.class);
+        JsonNaming ann = _findAnnotation(ac, JsonNaming.class);
         return (ann == null) ? null : ann.value();
     } 
 
@@ -142,7 +142,7 @@
     public VisibilityChecker<?> findAutoDetectVisibility(AnnotatedClass ac,
         VisibilityChecker<?> checker)
     {
-        JsonAutoDetect ann = ac.getAnnotation(JsonAutoDetect.class);
+        JsonAutoDetect ann = _findAnnotation(ac, JsonAutoDetect.class);
         return (ann == null) ? checker : checker.with(ann);
     }
 
@@ -155,11 +155,11 @@
     @Override        
     public ReferenceProperty findReferenceType(AnnotatedMember member)
     {
-        JsonManagedReference ref1 = member.getAnnotation(JsonManagedReference.class);
+        JsonManagedReference ref1 = _findAnnotation(member, JsonManagedReference.class);
         if (ref1 != null) {
             return AnnotationIntrospector.ReferenceProperty.managed(ref1.value());
         }
-        JsonBackReference ref2 = member.getAnnotation(JsonBackReference.class);
+        JsonBackReference ref2 = _findAnnotation(member, JsonBackReference.class);
         if (ref2 != null) {
             return AnnotationIntrospector.ReferenceProperty.back(ref2.value());
         }
@@ -169,7 +169,7 @@
     @Override
     public NameTransformer findUnwrappingNameTransformer(AnnotatedMember member)
     {
-        JsonUnwrapped ann = member.getAnnotation(JsonUnwrapped.class);
+        JsonUnwrapped ann = _findAnnotation(member, JsonUnwrapped.class);
         // if not enabled, just means annotation is not enabled; not necessarily
         // that unwrapping should not be done (relevant when using chained introspectors)
         if (ann == null || !ann.enabled()) {
@@ -188,7 +188,7 @@
     @Override
     public Boolean hasRequiredMarker(AnnotatedMember m)
     {
-        JsonProperty ann = m.getAnnotation(JsonProperty.class);
+        JsonProperty ann = _findAnnotation(m, JsonProperty.class);
         if (ann != null) {
             return ann.required();
         }
@@ -198,7 +198,7 @@
     @Override
     public Object findInjectableValueId(AnnotatedMember m)
     {
-        JacksonInject ann = m.getAnnotation(JacksonInject.class);
+        JacksonInject ann = _findAnnotation(m, JacksonInject.class);
         if (ann == null) {
             return null;
         }
@@ -261,7 +261,7 @@
     @Override
     public List<NamedType> findSubtypes(Annotated a)
     {
-        JsonSubTypes t = a.getAnnotation(JsonSubTypes.class);
+        JsonSubTypes t = _findAnnotation(a, JsonSubTypes.class);
         if (t == null) return null;
         JsonSubTypes.Type[] types = t.value();
         ArrayList<NamedType> result = new ArrayList<NamedType>(types.length);
@@ -274,7 +274,7 @@
     @Override        
     public String findTypeName(AnnotatedClass ac)
     {
-        JsonTypeName tn = ac.getAnnotation(JsonTypeName.class);
+        JsonTypeName tn = _findAnnotation(ac, JsonTypeName.class);
         return (tn == null) ? null : tn.value();
     }
 
@@ -287,7 +287,7 @@
     @Override
     public Object findSerializer(Annotated a)
     {
-        JsonSerialize ann = a.getAnnotation(JsonSerialize.class);
+        JsonSerialize ann = _findAnnotation(a, JsonSerialize.class);
         if (ann != null) {
             Class<? extends JsonSerializer<?>> serClass = ann.using();
             if (serClass != JsonSerializer.None.class) {
@@ -299,7 +299,7 @@
          *  if we need to get raw indicator from other sources need to add
          *  separate accessor within {@link AnnotationIntrospector} interface.
          */
-        JsonRawValue annRaw =  a.getAnnotation(JsonRawValue.class);
+        JsonRawValue annRaw =  _findAnnotation(a, JsonRawValue.class);
         if ((annRaw != null) && annRaw.value()) {
             // let's construct instance with nominal type:
             Class<?> cls = a.getRawType();
@@ -311,7 +311,7 @@
     @Override
     public Class<? extends JsonSerializer<?>> findKeySerializer(Annotated a)
     {
-        JsonSerialize ann = a.getAnnotation(JsonSerialize.class);
+        JsonSerialize ann = _findAnnotation(a, JsonSerialize.class);
         if (ann != null) {
             Class<? extends JsonSerializer<?>> serClass = ann.keyUsing();
             if (serClass != JsonSerializer.None.class) {
@@ -324,7 +324,7 @@
     @Override
     public Class<? extends JsonSerializer<?>> findContentSerializer(Annotated a)
     {
-        JsonSerialize ann = a.getAnnotation(JsonSerialize.class);
+        JsonSerialize ann = _findAnnotation(a, JsonSerialize.class);
         if (ann != null) {
             Class<? extends JsonSerializer<?>> serClass = ann.contentUsing();
             if (serClass != JsonSerializer.None.class) {
@@ -337,7 +337,7 @@
     @Override
     public Object findNullSerializer(Annotated a)
     {
-        JsonSerialize ann = a.getAnnotation(JsonSerialize.class);
+        JsonSerialize ann = _findAnnotation(a, JsonSerialize.class);
         if (ann != null) {
             Class<? extends JsonSerializer<?>> serClass = ann.nullsUsing();
             if (serClass != JsonSerializer.None.class) {
@@ -350,11 +350,11 @@
     @Override
     public JsonInclude.Include findSerializationInclusion(Annotated a, JsonInclude.Include defValue)
     {
-        JsonInclude inc = a.getAnnotation(JsonInclude.class);
+        JsonInclude inc = _findAnnotation(a, JsonInclude.class);
         if (inc != null) {
             return inc.value();
         }
-        JsonSerialize ann = a.getAnnotation(JsonSerialize.class);
+        JsonSerialize ann = _findAnnotation(a, JsonSerialize.class);
         if (ann != null) {
             @SuppressWarnings("deprecation")
             JsonSerialize.Inclusion i2 = ann.include();
@@ -375,60 +375,67 @@
     }
 
     @Override
+    public JsonInclude.Include findSerializationInclusionForContent(Annotated a, JsonInclude.Include defValue)
+    {
+        JsonInclude inc = _findAnnotation(a, JsonInclude.class);
+        return (inc == null) ? defValue : inc.content();
+    }
+
+    @Override
     public Class<?> findSerializationType(Annotated am)
     {
-        JsonSerialize ann = am.getAnnotation(JsonSerialize.class);
+        JsonSerialize ann = _findAnnotation(am, JsonSerialize.class);
         return (ann == null) ? null : _classIfExplicit(ann.as());
     }
     
     @Override
     public Class<?> findSerializationKeyType(Annotated am, JavaType baseType)
     {
-        JsonSerialize ann = am.getAnnotation(JsonSerialize.class);
+        JsonSerialize ann = _findAnnotation(am, JsonSerialize.class);
         return (ann == null) ? null : _classIfExplicit(ann.keyAs());
     }
 
     @Override
     public Class<?> findSerializationContentType(Annotated am, JavaType baseType)
     {
-        JsonSerialize ann = am.getAnnotation(JsonSerialize.class);
+        JsonSerialize ann = _findAnnotation(am, JsonSerialize.class);
         return (ann == null) ? null : _classIfExplicit(ann.contentAs());
     }
     
     @Override
     public JsonSerialize.Typing findSerializationTyping(Annotated a)
     {
-        JsonSerialize ann = a.getAnnotation(JsonSerialize.class);
+        JsonSerialize ann = _findAnnotation(a, JsonSerialize.class);
         return (ann == null) ? null : ann.typing();
     }
 
     @Override
     public Object findSerializationConverter(Annotated a) {
-        JsonSerialize ann = a.getAnnotation(JsonSerialize.class);
+        JsonSerialize ann = _findAnnotation(a, JsonSerialize.class);
         return (ann == null) ? null : _classIfExplicit(ann.converter(), Converter.None.class);
     }
 
     @Override
     public Object findSerializationContentConverter(AnnotatedMember a) {
-        JsonSerialize ann = a.getAnnotation(JsonSerialize.class);
+        JsonSerialize ann = _findAnnotation(a, JsonSerialize.class);
         return (ann == null) ? null : _classIfExplicit(ann.contentConverter(), Converter.None.class);
     }
     
     @Override
     public Class<?>[] findViews(Annotated a)
     {
-        JsonView ann = a.getAnnotation(JsonView.class);
+        JsonView ann = _findAnnotation(a, JsonView.class);
         return (ann == null) ? null : ann.value();
     }
 
     @Override
     public Boolean isTypeId(AnnotatedMember member) {
-        return member.hasAnnotation(JsonTypeId.class);
+        return _hasAnnotation(member, JsonTypeId.class);
     }
 
     @Override
     public ObjectIdInfo findObjectIdInfo(Annotated ann) {
-        JsonIdentityInfo info = ann.getAnnotation(JsonIdentityInfo.class);
+        JsonIdentityInfo info = _findAnnotation(ann, JsonIdentityInfo.class);
         if (info == null || info.generator() == ObjectIdGenerators.None.class) {
             return null;
         }
@@ -439,7 +446,7 @@
 
     @Override
     public ObjectIdInfo findObjectReferenceInfo(Annotated ann, ObjectIdInfo objectIdInfo) {
-        JsonIdentityReference ref = ann.getAnnotation(JsonIdentityReference.class);
+        JsonIdentityReference ref = _findAnnotation(ann, JsonIdentityReference.class);
         if (ref != null) {
             objectIdInfo = objectIdInfo.withAlwaysAsId(ref.alwaysAsId());
         }
@@ -447,22 +454,22 @@
     }
     
     @Override
-    public JsonFormat.Value findFormat(Annotated annotated) {
-        JsonFormat ann = annotated.getAnnotation(JsonFormat.class);
-        return (ann == null)  ? null : new JsonFormat.Value(ann);
+    public JsonFormat.Value findFormat(Annotated ann) {
+        JsonFormat f = _findAnnotation(ann, JsonFormat.class);
+        return (f == null)  ? null : new JsonFormat.Value(f);
     }
 
     @Override
-    public String findPropertyDescription(Annotated annotated) {
-        JsonPropertyDescription desc = annotated.getAnnotation(JsonPropertyDescription.class);
+    public String findPropertyDescription(Annotated ann) {
+        JsonPropertyDescription desc = _findAnnotation(ann, JsonPropertyDescription.class);
         return (desc == null) ? null : desc.value();
     }
 
     @Override
-    public Integer findPropertyIndex(Annotated annotated) {
-        JsonProperty ann = annotated.getAnnotation(JsonProperty.class);
-        if (ann != null) {
-        	int ix = ann.index();
+    public Integer findPropertyIndex(Annotated ann) {
+        JsonProperty prop = _findAnnotation(ann, JsonProperty.class);
+        if (prop != null) {
+        	int ix = prop.index();
         	if (ix != JsonProperty.INDEX_UNKNOWN) {
         		return Integer.valueOf(ix);
         	}
@@ -485,7 +492,7 @@
 
     @Override
     public String[] findSerializationPropertyOrder(AnnotatedClass ac) {
-        JsonPropertyOrder order = ac.getAnnotation(JsonPropertyOrder.class);
+        JsonPropertyOrder order = _findAnnotation(ac, JsonPropertyOrder.class);
         return (order == null) ? null : order.value();
     }
 
@@ -501,7 +508,7 @@
     }
 
     private final Boolean _findSortAlpha(Annotated ann) {
-        JsonPropertyOrder order = ann.getAnnotation(JsonPropertyOrder.class);
+        JsonPropertyOrder order = _findAnnotation(ann, JsonPropertyOrder.class);
         return (order == null) ? null : order.alphabetic();
     }
     
@@ -516,14 +523,14 @@
     {
         String name = null;
 
-        JsonGetter jg = a.getAnnotation(JsonGetter.class);
+        JsonGetter jg = _findAnnotation(a, JsonGetter.class);
         if (jg != null) {
             name = jg.value();
         } else {
-            JsonProperty pann = a.getAnnotation(JsonProperty.class);
+            JsonProperty pann = _findAnnotation(a, JsonProperty.class);
             if (pann != null) {
                 name = pann.value();
-            } else if (a.hasAnnotation(JsonSerialize.class) || a.hasAnnotation(JsonView.class)) {
+            } else if (_hasAnnotation(a, JsonSerialize.class) || _hasAnnotation(a, JsonView.class)) {
                 name = "";
             } else {
                 return null;
@@ -537,7 +544,7 @@
 
     @Override
     public boolean hasAsValueAnnotation(AnnotatedMethod am) {
-        JsonValue ann = am.getAnnotation(JsonValue.class);
+        JsonValue ann = _findAnnotation(am, JsonValue.class);
         // value of 'false' means disabled...
         return (ann != null && ann.value());
     }
@@ -551,7 +558,7 @@
     @Override
     public Class<? extends JsonDeserializer<?>> findDeserializer(Annotated a)
     {
-        JsonDeserialize ann = a.getAnnotation(JsonDeserialize.class);
+        JsonDeserialize ann = _findAnnotation(a, JsonDeserialize.class);
         if (ann != null) {
             Class<? extends JsonDeserializer<?>> deserClass = ann.using();
             if (deserClass != JsonDeserializer.None.class) {
@@ -564,7 +571,7 @@
     @Override
     public Class<? extends KeyDeserializer> findKeyDeserializer(Annotated a)
     {
-        JsonDeserialize ann = a.getAnnotation(JsonDeserialize.class);
+        JsonDeserialize ann = _findAnnotation(a, JsonDeserialize.class);
         if (ann != null) {
             Class<? extends KeyDeserializer> deserClass = ann.keyUsing();
             if (deserClass != KeyDeserializer.None.class) {
@@ -577,7 +584,7 @@
     @Override
     public Class<? extends JsonDeserializer<?>> findContentDeserializer(Annotated a)
     {
-        JsonDeserialize ann = a.getAnnotation(JsonDeserialize.class);
+        JsonDeserialize ann = _findAnnotation(a, JsonDeserialize.class);
         if (ann != null) {
             Class<? extends JsonDeserializer<?>> deserClass = ann.contentUsing();
             if (deserClass != JsonDeserializer.None.class) {
@@ -589,34 +596,34 @@
 
     @Override
     public Class<?> findDeserializationType(Annotated am, JavaType baseType) {
-        JsonDeserialize ann = am.getAnnotation(JsonDeserialize.class);
+        JsonDeserialize ann = _findAnnotation(am, JsonDeserialize.class);
         return (ann == null) ? null : _classIfExplicit(ann.as());
     }
 
     @Override
     public Class<?> findDeserializationKeyType(Annotated am, JavaType baseKeyType) {
-        JsonDeserialize ann = am.getAnnotation(JsonDeserialize.class);
+        JsonDeserialize ann = _findAnnotation(am, JsonDeserialize.class);
         return (ann == null) ? null : _classIfExplicit(ann.keyAs());
     }
 
     @Override
     public Class<?> findDeserializationContentType(Annotated am, JavaType baseContentType)
     {
-        JsonDeserialize ann = am.getAnnotation(JsonDeserialize.class);
+        JsonDeserialize ann = _findAnnotation(am, JsonDeserialize.class);
         return (ann == null) ? null : _classIfExplicit(ann.contentAs());
     }
 
     @Override
     public Object findDeserializationConverter(Annotated a)
     {
-        JsonDeserialize ann = a.getAnnotation(JsonDeserialize.class);
+        JsonDeserialize ann = _findAnnotation(a, JsonDeserialize.class);
         return (ann == null) ? null : _classIfExplicit(ann.converter(), Converter.None.class);
     }
 
     @Override
     public Object findDeserializationContentConverter(AnnotatedMember a)
     {
-        JsonDeserialize ann = a.getAnnotation(JsonDeserialize.class);
+        JsonDeserialize ann = _findAnnotation(a, JsonDeserialize.class);
         return (ann == null) ? null : _classIfExplicit(ann.contentConverter(), Converter.None.class);
     }
 
@@ -629,7 +636,7 @@
     @Override
     public Object findValueInstantiator(AnnotatedClass ac)
     {
-        JsonValueInstantiator ann = ac.getAnnotation(JsonValueInstantiator.class);
+        JsonValueInstantiator ann = _findAnnotation(ac, JsonValueInstantiator.class);
         // no 'null' marker yet, so:
         return (ann == null) ? null : ann.value();
     }
@@ -637,14 +644,14 @@
     @Override
     public Class<?> findPOJOBuilder(AnnotatedClass ac)
     {
-        JsonDeserialize ann = ac.getAnnotation(JsonDeserialize.class);
+        JsonDeserialize ann = _findAnnotation(ac, JsonDeserialize.class);
         return (ann == null) ? null : _classIfExplicit(ann.builder());
     }
 
     @Override
     public JsonPOJOBuilder.Value findPOJOBuilderConfig(AnnotatedClass ac)
     {
-        JsonPOJOBuilder ann = ac.getAnnotation(JsonPOJOBuilder.class);
+        JsonPOJOBuilder ann = _findAnnotation(ac, JsonPOJOBuilder.class);
         return (ann == null) ? null : new JsonPOJOBuilder.Value(ann);
     }
     
@@ -661,22 +668,22 @@
 
         // @JsonSetter has precedence over @JsonProperty, being more specific
         // @JsonDeserialize implies that there is a property, but no name
-        JsonSetter js = a.getAnnotation(JsonSetter.class);
+        JsonSetter js = _findAnnotation(a, JsonSetter.class);
         if (js != null) {
             name = js.value();
         } else {
-            JsonProperty pann = a.getAnnotation(JsonProperty.class);
+            JsonProperty pann = _findAnnotation(a, JsonProperty.class);
             if (pann != null) {
                 name = pann.value();
                 /* 22-Apr-2014, tatu: Should figure out a better way to do this, but
                  *   it's actually bit tricky to do it more efficiently (meta-annotations
                  *   add more lookups; AnnotationMap costs etc)
                  */
-            } else if (a.hasAnnotation(JsonDeserialize.class)
-                    || a.hasAnnotation(JsonView.class)
-                    || a.hasAnnotation(JsonUnwrapped.class) // [#442]
-                    || a.hasAnnotation(JsonBackReference.class)
-                    || a.hasAnnotation(JsonManagedReference.class)) {
+            } else if (_hasAnnotation(a, JsonDeserialize.class)
+                    || _hasAnnotation(a, JsonView.class)
+                    || _hasAnnotation(a, JsonUnwrapped.class) // [#442]
+                    || _hasAnnotation(a, JsonBackReference.class)
+                    || _hasAnnotation(a, JsonManagedReference.class)) {
                     name = "";
             } else {
                 return null;
@@ -695,7 +702,7 @@
          * if needs to be ignored (and if so, is handled prior
          * to this method getting called)
          */
-        return am.hasAnnotation(JsonAnySetter.class);
+        return _hasAnnotation(am, JsonAnySetter.class);
     }
 
     @Override
@@ -704,7 +711,7 @@
         /* No dedicated disabling; regular @JsonIgnore used
          * if needs to be ignored (handled separately
          */
-        return am.hasAnnotation(JsonAnyGetter.class);
+        return _hasAnnotation(am, JsonAnyGetter.class);
     }
     
     @Override
@@ -714,9 +721,9 @@
          * if needs to be ignored (and if so, is handled prior
          * to this method getting called)
          */
-        return a.hasAnnotation(JsonCreator.class);
+        return _hasAnnotation(a, JsonCreator.class);
     }
-
+    
     /*
     /**********************************************************
     /* Helper methods
@@ -725,7 +732,7 @@
 
     protected boolean _isIgnorable(Annotated a)
     {
-        JsonIgnore ann = a.getAnnotation(JsonIgnore.class);
+        JsonIgnore ann = _findAnnotation(a, JsonIgnore.class);
         return (ann != null && ann.value());
     }
 
@@ -745,13 +752,14 @@
      * Helper method called to construct and initialize instance of {@link TypeResolverBuilder}
      * if given annotated element indicates one is needed.
      */
+    @SuppressWarnings("deprecation")
     protected TypeResolverBuilder<?> _findTypeResolver(MapperConfig<?> config,
             Annotated ann, JavaType baseType)
     {
         // First: maybe we have explicit type resolver?
         TypeResolverBuilder<?> b;
-        JsonTypeInfo info = ann.getAnnotation(JsonTypeInfo.class);
-        JsonTypeResolver resAnn = ann.getAnnotation(JsonTypeResolver.class);
+        JsonTypeInfo info = _findAnnotation(ann, JsonTypeInfo.class);
+        JsonTypeResolver resAnn = _findAnnotation(ann, JsonTypeResolver.class);
         
         if (resAnn != null) {
             if (info == null) {
@@ -773,7 +781,7 @@
             b = _constructStdTypeResolverBuilder();
         }
         // Does it define a custom type id resolver?
-        JsonTypeIdResolver idResInfo = ann.getAnnotation(JsonTypeIdResolver.class);
+        JsonTypeIdResolver idResInfo = _findAnnotation(ann, JsonTypeIdResolver.class);
         TypeIdResolver idRes = (idResInfo == null) ? null
                 : config.typeIdResolverInstance(ann, idResInfo.value());
         if (idRes != null) { // [JACKSON-359]
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 4fc330d..f7c0028 100644
--- a/src/main/java/com/fasterxml/jackson/databind/introspect/POJOPropertiesCollector.java
+++ b/src/main/java/com/fasterxml/jackson/databind/introspect/POJOPropertiesCollector.java
@@ -467,11 +467,15 @@
         if (!expl) {
             if (impl.isEmpty()) {
                 /* Important: if neither implicit nor explicit name, can not make use
-                 * of this creator paramter -- may or may not be a problem, verified
+                 * of this creator parameter -- may or may not be a problem, verified
                  * at a later point.
                  */
                 return;
             }
+            // Also: if this occurs, there MUST be explicit annotation on creator itself
+            if (!_annotationIntrospector.hasCreatorAnnotation(param.getOwner())) {
+                return;
+            }
             pn = new PropertyName(impl);
         }
 
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 54db8a8..1beecfc 100644
--- a/src/main/java/com/fasterxml/jackson/databind/introspect/POJOPropertyBuilder.java
+++ b/src/main/java/com/fasterxml/jackson/databind/introspect/POJOPropertyBuilder.java
@@ -3,6 +3,7 @@
 import java.util.*;
 
 import com.fasterxml.jackson.databind.*;
+import com.fasterxml.jackson.databind.util.EmptyIterator;
 
 /**
  * Helper class used for aggregating information about a single
@@ -53,13 +54,6 @@
         _annotationIntrospector = annotationIntrospector;
         _forSerialization = forSerialization;
     }
-    
-    @Deprecated // since 2.3
-    public POJOPropertyBuilder(String simpleInternalName,
-            AnnotationIntrospector annotationIntrospector, boolean forSerialization)
-    {
-        this(new PropertyName(simpleInternalName), annotationIntrospector, forSerialization);
-    }
 
     public POJOPropertyBuilder(POJOPropertyBuilder src, PropertyName newName)
     {
@@ -79,12 +73,6 @@
     /**********************************************************
      */
 
-    @Deprecated // since 2.3
-    @Override
-    public POJOPropertyBuilder withName(String newName) {
-        return withSimpleName(newName);
-    }
-
     @Override
     public POJOPropertyBuilder withName(PropertyName newName) {
         return new POJOPropertyBuilder(this, newName);
@@ -359,6 +347,14 @@
         } while (curr != null);
         return _ctorParameters.value;
     }
+
+    @Override
+    public Iterator<AnnotatedParameter> getConstructorParameters() {
+        if (_ctorParameters == null) {
+            return EmptyIterator.instance();
+        }
+        return new MemberIterator<AnnotatedParameter>(_ctorParameters);
+    }
     
     @Override
     public AnnotatedMember getAccessor()
@@ -981,6 +977,38 @@
     private interface WithMember<T> {
         public T withMember(AnnotatedMember member);
     }
+
+    /**
+     * @since 2.5
+     */
+    protected static class MemberIterator<T extends AnnotatedMember>
+        implements Iterator<T>
+    {
+        private Linked<T> next;
+        
+        public MemberIterator(Linked<T> first) {
+            next = first;
+        }
+        
+        @Override
+        public boolean hasNext() {
+            return (next != null);
+        }
+
+        @Override
+        public T next() {
+            if (next == null) throw new NoSuchElementException();
+            T result = next.value;
+            next = next.next;
+            return result;
+        }
+
+        @Override
+        public void remove() {
+            throw new UnsupportedOperationException();
+        }
+        
+    }
     
     /**
      * Node used for creating simple linked lists to efficiently store small sets
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 3f03e27..0a55496 100644
--- a/src/main/java/com/fasterxml/jackson/databind/introspect/VisibilityChecker.java
+++ b/src/main/java/com/fasterxml/jackson/databind/introspect/VisibilityChecker.java
@@ -16,8 +16,6 @@
  *<p>
  * Note on type declaration: funky recursive type is necessary to
  * support builder/fluent pattern.
- * 
- * @author tatu
  */
 public interface VisibilityChecker<T extends VisibilityChecker<T>>
 {
@@ -163,7 +161,7 @@
         implements VisibilityChecker<Std>,
             java.io.Serializable
     {
-        private static final long serialVersionUID = -7073939237187922755L;
+        private static final long serialVersionUID = 1;
 
         /**
          * This is the canonical base instance, configured with default
@@ -208,7 +206,7 @@
         }
 
         /**
-         * Costructor that will assign given visibility value for all
+         * Constructor that will assign given visibility value for all
          * properties.
          * 
          * @param v level to use for all property types
@@ -238,158 +236,158 @@
         /********************************************************
          */
 
-    @Override
-    public Std with(JsonAutoDetect ann)
-    {
-        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());
-	    }
-	    return curr;
-	}
-
-    @Override
-    public Std with(Visibility v)
-    {
-        if (v == Visibility.DEFAULT) {
-            return DEFAULT;
+        @Override
+        public Std with(JsonAutoDetect ann)
+        {
+            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());
+            }
+            return curr;
         }
-        return new Std(v);
-    }
 
-    @Override
-    public Std withVisibility(PropertyAccessor method, Visibility v)
-    {
-	    switch (method) {
-	    case GETTER:
-	        return withGetterVisibility(v);
-	    case SETTER:
-	        return withSetterVisibility(v);
-	    case CREATOR:
-	        return withCreatorVisibility(v);
-	    case FIELD:
-	        return withFieldVisibility(v);
-	    case IS_GETTER:
-	        return withIsGetterVisibility(v);
+        @Override
+        public Std with(Visibility v)
+        {
+            if (v == Visibility.DEFAULT) {
+                return DEFAULT;
+            }
+            return new Std(v);
+        }
+    
+        @Override
+        public Std withVisibility(PropertyAccessor method, Visibility v)
+        {
+            switch (method) {
+            case GETTER:
+                return withGetterVisibility(v);
+            case SETTER:
+                return withSetterVisibility(v);
+            case CREATOR:
+                return withCreatorVisibility(v);
+            case FIELD:
+                return withFieldVisibility(v);
+            case IS_GETTER:
+                return withIsGetterVisibility(v);
             case ALL:
                 return with(v);
-        //case NONE:
-        default:
-            // break;
-            return this;
-	    }
-	}
+            //case NONE:
+            default:
+                // break;
+                return this;
+            }
+        }
 	
-    @Override
-	public Std withGetterVisibility(Visibility v) {
-	    if (v == Visibility.DEFAULT)  v = DEFAULT._getterMinLevel;
+        @Override
+        public Std withGetterVisibility(Visibility v) {
+            if (v == Visibility.DEFAULT)  v = DEFAULT._getterMinLevel;
             if (_getterMinLevel == v) return this;
-	    return new Std(v, _isGetterMinLevel, _setterMinLevel, _creatorMinLevel, _fieldMinLevel);
-	}
+            return new Std(v, _isGetterMinLevel, _setterMinLevel, _creatorMinLevel, _fieldMinLevel);
+        }
 
-    @Override
+        @Override
         public Std withIsGetterVisibility(Visibility v) {
             if (v == Visibility.DEFAULT)  v = DEFAULT._isGetterMinLevel;
             if (_isGetterMinLevel == v) return this;
             return new Std(_getterMinLevel, v, _setterMinLevel, _creatorMinLevel, _fieldMinLevel);
         }
+
+        @Override
+        public Std withSetterVisibility(Visibility v) {
+            if (v == Visibility.DEFAULT)  v = DEFAULT._setterMinLevel;
+            if (_setterMinLevel == v) return this;
+            return new Std(_getterMinLevel, _isGetterMinLevel, v, _creatorMinLevel, _fieldMinLevel);
+        }
+    
+        @Override
+        public Std withCreatorVisibility(Visibility v) {
+            if (v == Visibility.DEFAULT)  v = DEFAULT._creatorMinLevel;
+            if (_creatorMinLevel == v) return this;
+            return new Std(_getterMinLevel, _isGetterMinLevel, _setterMinLevel, v, _fieldMinLevel);
+        }
+    
+        @Override
+        public Std withFieldVisibility(Visibility v) {
+            if (v == Visibility.DEFAULT)  v = DEFAULT._fieldMinLevel;
+            if (_fieldMinLevel == v) return this;
+            return new Std(_getterMinLevel, _isGetterMinLevel, _setterMinLevel, _creatorMinLevel, v);
+        }
 		
-    @Override
-    public Std withSetterVisibility(Visibility v) {
-        if (v == Visibility.DEFAULT)  v = DEFAULT._setterMinLevel;
-        if (_setterMinLevel == v) return this;
-        return new Std(_getterMinLevel, _isGetterMinLevel, v, _creatorMinLevel, _fieldMinLevel);
-    }
+        /*
+        /********************************************************
+        /* Public API impl
+        /********************************************************
+         */
 
-    @Override
-    public Std withCreatorVisibility(Visibility v) {
-        if (v == Visibility.DEFAULT)  v = DEFAULT._creatorMinLevel;
-        if (_creatorMinLevel == v) return this;
-        return new Std(_getterMinLevel, _isGetterMinLevel, _setterMinLevel, v, _fieldMinLevel);
-    }
+        @Override
+        public boolean isCreatorVisible(Member m) {
+            return _creatorMinLevel.isVisible(m);
+        }
+    	
+        @Override
+        public boolean isCreatorVisible(AnnotatedMember m) {
+            return isCreatorVisible(m.getMember());
+        }
 
-    @Override
-    public Std withFieldVisibility(Visibility v) {
-        if (v == Visibility.DEFAULT)  v = DEFAULT._fieldMinLevel;
-        if (_fieldMinLevel == v) return this;
-        return new Std(_getterMinLevel, _isGetterMinLevel, _setterMinLevel, _creatorMinLevel, v);
-    }
-		
-    /*
-    /********************************************************
-    /* Public API impl
-    /********************************************************
-     */
-
-    @Override
-    public boolean isCreatorVisible(Member m) {
-        return _creatorMinLevel.isVisible(m);
-    }
-	
-    @Override
-    public boolean isCreatorVisible(AnnotatedMember m) {
-        return isCreatorVisible(m.getMember());
-    }
+        @Override
+        public boolean isFieldVisible(Field f) {
+            return _fieldMinLevel.isVisible(f);
+        }
+        
+        @Override
+        public boolean isFieldVisible(AnnotatedField f) {
+            return isFieldVisible(f.getAnnotated());
+        }
+        
+        @Override
+        public boolean isGetterVisible(Method m) {
+            return _getterMinLevel.isVisible(m);
+        }
     
-    @Override
-    public boolean isFieldVisible(Field f) {
-        return _fieldMinLevel.isVisible(f);
-    }
+        @Override
+        public boolean isGetterVisible(AnnotatedMethod m) {
+             return isGetterVisible(m.getAnnotated());
+        }
     
-    @Override
-    public boolean isFieldVisible(AnnotatedField f) {
-        return isFieldVisible(f.getAnnotated());
-    }
+        @Override
+        public boolean isIsGetterVisible(Method m) {
+            return _isGetterMinLevel.isVisible(m);
+        }    
     
-    @Override
-    public boolean isGetterVisible(Method m) {
-        return _getterMinLevel.isVisible(m);
-    }
-
-    @Override
-    public boolean isGetterVisible(AnnotatedMethod m) {
-         return isGetterVisible(m.getAnnotated());
-    }
-
-    @Override
-    public boolean isIsGetterVisible(Method m) {
-        return _isGetterMinLevel.isVisible(m);
-    }    
-
-    @Override
-    public boolean isIsGetterVisible(AnnotatedMethod m) {
-        return isIsGetterVisible(m.getAnnotated());
-    }
-
-    @Override
-    public boolean isSetterVisible(Method m) {
-        return _setterMinLevel.isVisible(m);
-    }
+        @Override
+        public boolean isIsGetterVisible(AnnotatedMethod m) {
+            return isIsGetterVisible(m.getAnnotated());
+        }
     
-    @Override
-    public boolean isSetterVisible(AnnotatedMethod m) {
-        return isSetterVisible(m.getAnnotated());
-    }
+        @Override
+        public boolean isSetterVisible(Method m) {
+            return _setterMinLevel.isVisible(m);
+        }
+        
+        @Override
+        public boolean isSetterVisible(AnnotatedMethod m) {
+            return isSetterVisible(m.getAnnotated());
+        }
 
-    /*
-    /********************************************************
-    /* Standard methods
-    /********************************************************
-     */
-
-    @Override
-    public String toString() {
-        return new StringBuilder("[Visibility:")
-        .append(" getter: ").append(_getterMinLevel)
-        .append(", isGetter: ").append(_isGetterMinLevel)
-        .append(", setter: ").append(_setterMinLevel)
-        .append(", creator: ").append(_creatorMinLevel)
-        .append(", field: ").append(_fieldMinLevel)
-        .append("]").toString();
-    }
+        /*
+        /********************************************************
+        /* Standard methods
+        /********************************************************
+         */
+    
+        @Override
+        public String toString() {
+            return new StringBuilder("[Visibility:")
+            .append(" getter: ").append(_getterMinLevel)
+            .append(", isGetter: ").append(_isGetterMinLevel)
+            .append(", setter: ").append(_setterMinLevel)
+            .append(", creator: ").append(_creatorMinLevel)
+            .append(", field: ").append(_fieldMinLevel)
+            .append("]").toString();
+        }
     }
 }
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 fb6d026..9a06915 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
@@ -21,7 +21,7 @@
     extends TypeDeserializerBase
     implements java.io.Serializable
 {
-    private static final long serialVersionUID = 5345570420394408290L;
+    private static final long serialVersionUID = 1L;
 
     public AsArrayTypeDeserializer(JavaType bt, TypeIdResolver idRes,
             String typePropertyName, boolean typeIdVisible, Class<?> defaultImpl)
@@ -93,7 +93,12 @@
         String typeId = _locateTypeId(jp, ctxt);
         JsonDeserializer<Object> deser = _findDeserializer(ctxt, typeId);
         // Minor complication: we may need to merge type id in?
-        if (_typeIdVisible && jp.getCurrentToken() == JsonToken.START_OBJECT) {
+        if (_typeIdVisible
+                // 06-Oct-2014, tatu: To fix [databind#408], must distinguish between
+                //   internal and external properties
+                //  TODO: but does it need to be injected in external case? Why not?
+                && !_usesExternalId()
+                && jp.getCurrentToken() == JsonToken.START_OBJECT) {
             // but what if there's nowhere to add it in? Error? Or skip? For now, skip.
             TokenBuffer tb = new TokenBuffer(null, false);
             tb.writeStartObject(); // recreate START_OBJECT
@@ -114,7 +119,7 @@
     protected final String _locateTypeId(JsonParser jp, DeserializationContext ctxt) throws IOException
     {
         if (!jp.isExpectedStartArrayToken()) {
-            // [JACKSON-712] Need to allow even more customized handling, if something unexpected seen...
+            // 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();
@@ -133,4 +138,11 @@
         }
         throw ctxt.wrongTokenException(jp, JsonToken.VALUE_STRING, "need JSON String that contains type id (for subtype of "+baseTypeName()+")");
     }
+
+    /**
+     * @since 2.5
+     */
+    protected boolean _usesExternalId() {
+        return false;
+    }
 }
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
new file mode 100644
index 0000000..1311916
--- /dev/null
+++ b/src/main/java/com/fasterxml/jackson/databind/jsontype/impl/AsExistingPropertyTypeSerializer.java
@@ -0,0 +1,69 @@
+package com.fasterxml.jackson.databind.jsontype.impl;
+
+import java.io.IOException;
+
+import com.fasterxml.jackson.annotation.JsonTypeInfo.As;
+import com.fasterxml.jackson.core.*;
+
+import com.fasterxml.jackson.databind.BeanProperty;
+import com.fasterxml.jackson.databind.jsontype.TypeIdResolver;
+
+/**
+ * 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)
+    {
+        super(idRes, property, propName);
+    }
+
+    @Override
+    public AsExistingPropertyTypeSerializer forProperty(BeanProperty prop) {
+        return (_property == prop) ? this : new AsExistingPropertyTypeSerializer(this._idResolver, prop, this._typePropertyName);
+    }
+    
+    @Override
+    public As getTypeInclusion() { return As.EXISTING_PROPERTY; }
+    
+    @Override
+    public void writeTypePrefixForObject(Object value, JsonGenerator jgen) throws IOException
+    {
+        final String typeId = idFromValue(value);
+        if (jgen.canWriteTypeId()) {
+            jgen.writeTypeId(typeId);
+            jgen.writeStartObject();
+        } else {
+            jgen.writeStartObject();
+        }
+    }
+
+    @Override
+    public void writeTypePrefixForObject(Object value, JsonGenerator jgen, Class<?> type) throws IOException
+    {
+        final String typeId = idFromValueAndType(value, type);
+        if (jgen.canWriteTypeId()) {
+            jgen.writeTypeId(typeId);
+            jgen.writeStartObject();
+        } else {
+            jgen.writeStartObject();
+        }
+    }
+    
+    @Override
+    public void writeCustomTypePrefixForObject(Object value, JsonGenerator jgen, String typeId) throws IOException
+    {
+    	if (jgen.canWriteTypeId()) {
+            jgen.writeTypeId(typeId);
+            jgen.writeStartObject();
+        } else {
+            jgen.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 4352564..3bd4539 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
@@ -39,4 +39,10 @@
     
     @Override
     public As getTypeInclusion() { return As.EXTERNAL_PROPERTY; }
+
+    // yes, very important distinction...
+    @Override
+    protected boolean _usesExternalId() {
+        return true;
+    }
 }
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 ffbddc8..484cb0b 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,25 @@
 {
     private static final long serialVersionUID = 1L;
 
+    protected final As _inclusion;
+
     public AsPropertyTypeDeserializer(JavaType bt, TypeIdResolver idRes,
             String typePropertyName, boolean typeIdVisible, Class<?> defaultImpl)
     {
+        this(bt, idRes, typePropertyName, typeIdVisible, defaultImpl, As.PROPERTY);
+    }
+    
+    public AsPropertyTypeDeserializer(JavaType bt, TypeIdResolver idRes,
+            String typePropertyName, boolean typeIdVisible, Class<?> defaultImpl,
+            As inclusion)
+    {
         super(bt, idRes, typePropertyName, typeIdVisible, defaultImpl);
+        _inclusion = inclusion;
     }
 
     public AsPropertyTypeDeserializer(AsPropertyTypeDeserializer src, BeanProperty property) {
         super(src, property);
+        _inclusion = src._inclusion;
     }
     
     @Override
@@ -40,7 +51,7 @@
     }
     
     @Override
-    public As getTypeInclusion() { return As.PROPERTY; }
+    public As getTypeInclusion() { return _inclusion; }
 
     /**
      * This is the trickiest thing to handle, since property we are looking
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 b299e7f..fe6753d 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
@@ -66,7 +66,6 @@
         return this;
     }
 
-    @SuppressWarnings("incomplete-switch")
     @Override
     public TypeSerializer buildTypeSerializer(SerializationConfig config,
             JavaType baseType, Collection<NamedType> subtypes)
@@ -84,11 +83,19 @@
         case EXTERNAL_PROPERTY:
             return new AsExternalTypeSerializer(idRes, null,
                     _typeProperty);
+        case EXISTING_PROPERTY:
+        	// as per [#528]
+        	return new AsExistingPropertyTypeSerializer(idRes, null, _typeProperty);
         }
         throw new IllegalStateException("Do not know how to construct standard type serializer for inclusion type: "+_includeAs);
     }
 
-    @SuppressWarnings("incomplete-switch")
+    // as per [#368]
+    // removed when fix [#528]
+    //private IllegalArgumentException _noExisting() {
+    //    return new IllegalArgumentException("Inclusion type "+_includeAs+" not yet supported");
+    //}
+
     @Override
     public TypeDeserializer buildTypeDeserializer(DeserializationConfig config,
             JavaType baseType, Collection<NamedType> subtypes)
@@ -103,8 +110,9 @@
             return new AsArrayTypeDeserializer(baseType, idRes,
                     _typeProperty, _typeIdVisible, _defaultImpl);
         case PROPERTY:
+        case EXISTING_PROPERTY: // as per [#528] same class as PROPERTY
             return new AsPropertyTypeDeserializer(baseType, idRes,
-                    _typeProperty, _typeIdVisible, _defaultImpl);
+                    _typeProperty, _typeIdVisible, _defaultImpl, _includeAs);
         case WRAPPER_OBJECT:
             return new AsWrapperTypeDeserializer(baseType, idRes,
                     _typeProperty, _typeIdVisible, _defaultImpl);
diff --git a/src/main/java/com/fasterxml/jackson/databind/module/SimpleKeyDeserializers.java b/src/main/java/com/fasterxml/jackson/databind/module/SimpleKeyDeserializers.java
index 9e660c7..531141d 100644
--- a/src/main/java/com/fasterxml/jackson/databind/module/SimpleKeyDeserializers.java
+++ b/src/main/java/com/fasterxml/jackson/databind/module/SimpleKeyDeserializers.java
@@ -22,7 +22,7 @@
 public class SimpleKeyDeserializers
     implements KeyDeserializers, java.io.Serializable // since 2.1
 {
-    private static final long serialVersionUID = -6786398737835438187L;
+    private static final long serialVersionUID = 1L;
 
     protected HashMap<ClassKey,KeyDeserializer> _classMappings = 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 9704471..a862c70 100644
--- a/src/main/java/com/fasterxml/jackson/databind/node/ArrayNode.java
+++ b/src/main/java/com/fasterxml/jackson/databind/node/ArrayNode.java
@@ -96,14 +96,13 @@
     @Override
     public void serialize(JsonGenerator jg, SerializerProvider provider) throws IOException, JsonProcessingException
     {
-        jg.writeStartArray();
-        for (JsonNode n : _children) {
-            /* 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)n).serialize(jg, provider);
+    	final List<JsonNode> c = _children;
+    	final int size = c.size();
+        jg.writeStartArray(size);
+        for (int i = 0; i < size; ++i) { // we'll typically have array list
+        	// Can we trust that all nodes will always extend BaseJsonNode? Or if not,
+        	// at least implement JsonSerializable? Let's start with former, change if must
+            ((BaseJsonNode) c.get(i)).serialize(jg, provider);
         }
         jg.writeEndArray();
     }
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 bfa8518..3bfa7b2 100644
--- a/src/main/java/com/fasterxml/jackson/databind/ser/AnyGetterWriter.java
+++ b/src/main/java/com/fasterxml/jackson/databind/ser/AnyGetterWriter.java
@@ -60,7 +60,8 @@
                 throw new JsonMappingException("Value returned by 'any-getter' ("
                         +_accessor.getName()+"()) not java.util.Map but "+value.getClass().getName());
             }
-            _serializer.serializeFilteredFields((Map<?,?>) value, jgen, provider, filter);
+            // 19-Oct-2014, tatu: Should we try to support @JsonInclude options here?
+            _serializer.serializeFilteredFields((Map<?,?>) value, jgen, provider, filter, null);
         }
     
     // Note: NOT part of ResolvableSerializer...
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 2a710f1..16fac48 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,8 @@
 import java.util.*;
 
 import com.fasterxml.jackson.annotation.JsonFormat;
+import com.fasterxml.jackson.annotation.JsonInclude;
+
 import com.fasterxml.jackson.databind.*;
 import com.fasterxml.jackson.databind.annotation.JsonSerialize;
 import com.fasterxml.jackson.databind.cfg.SerializerFactoryConfig;
@@ -20,10 +22,7 @@
 import com.fasterxml.jackson.databind.ser.impl.*;
 import com.fasterxml.jackson.databind.ser.std.*;
 import com.fasterxml.jackson.databind.type.*;
-import com.fasterxml.jackson.databind.util.ClassUtil;
-import com.fasterxml.jackson.databind.util.Converter;
-import com.fasterxml.jackson.databind.util.EnumValues;
-import com.fasterxml.jackson.databind.util.TokenBuffer;
+import com.fasterxml.jackson.databind.util.*;
 
 /**
  * Factory class that can provide serializers for standard JDK classes,
@@ -368,6 +367,17 @@
         if (java.util.Date.class.isAssignableFrom(raw)) {
             return DateSerializer.instance;
         }
+        if (Map.Entry.class.isAssignableFrom(raw)) {
+            JavaType kt, vt;
+            JavaType[] params = prov.getTypeFactory().findTypeParameters(type, Map.Entry.class);
+            if (params == null || params.length != 2) { // assume that if we don't get 2, they are wrong...
+                kt = vt = TypeFactory.unknownType();
+            } else {
+                kt = params[0];
+                vt = params[1];
+            }
+            return buildMapEntrySerializer(prov.getConfig(), type, beanDesc, staticTyping, kt, vt);
+        }
         if (ByteBuffer.class.isAssignableFrom(raw)) {
             return new ByteBufferSerializer();
         }
@@ -429,12 +439,17 @@
     {
         Class<?> type = javaType.getRawClass();
 
-        // These need to be in decreasing order of specificity...
         if (Iterator.class.isAssignableFrom(type)) {
-            return buildIteratorSerializer(config, javaType, beanDesc, staticTyping);
+            JavaType[] params = config.getTypeFactory().findTypeParameters(javaType, Iterator.class);
+            JavaType vt = (params == null || params.length != 1) ?
+                    TypeFactory.unknownType() : params[0];
+            return buildIteratorSerializer(config, javaType, beanDesc, staticTyping, vt);
         }
         if (Iterable.class.isAssignableFrom(type)) {
-            return buildIterableSerializer(config, javaType, beanDesc,  staticTyping);
+            JavaType[] params = config.getTypeFactory().findTypeParameters(javaType, Iterable.class);
+            JavaType vt = (params == null || params.length != 1) ?
+                    TypeFactory.unknownType() : params[0];
+            return buildIterableSerializer(config, javaType, beanDesc,  staticTyping, vt);
         }
         if (CharSequence.class.isAssignableFrom(type)) {
             return ToStringSerializer.instance;
@@ -719,9 +734,15 @@
                     elementTypeSerializer, elementValueSerializer);
             } else {
                 Object filterId = findFilterId(config, beanDesc);
-                ser = MapSerializer.construct(config.getAnnotationIntrospector().findPropertiesToIgnore(beanDesc.getClassInfo()),
+                MapSerializer mapSer = MapSerializer.construct(config.getAnnotationIntrospector().findPropertiesToIgnore(beanDesc.getClassInfo()),
                     type, staticTyping, elementTypeSerializer,
                     keySerializer, elementValueSerializer, filterId);
+                Object suppressableValue = findSuppressableContentValue(config,
+                        type.getContentType(), beanDesc);
+                if (suppressableValue != null) {
+                    mapSer = mapSer.withContentInclusion(suppressableValue);
+                }
+                ser = mapSer;
             }
         }
         // [Issue#120]: Allow post-processing
@@ -733,6 +754,30 @@
         return ser;
     }
 
+    /**
+     * @since 2.5
+     */
+    protected Object findSuppressableContentValue(SerializationConfig config,
+            JavaType contentType, BeanDescription beanDesc)
+        throws JsonMappingException
+    {
+        JsonInclude.Include incl = beanDesc.findSerializationInclusionForContent(null);
+
+        if (incl != null) {
+            switch (incl) {
+            case NON_DEFAULT:
+                // 19-Oct-2014, tatu: Not sure what this'd mean; so take it to mean "NON_EMPTY"...
+                incl = JsonInclude.Include.NON_EMPTY;
+                break;
+            default:
+                // all other modes actually good as is, unless we'll find better ways
+                break;
+            }
+            return incl;
+        }
+        return null;
+    }
+    
     /*
     /**********************************************************
     /* Factory methods, for Arrays
@@ -789,39 +834,67 @@
     /**********************************************************
      */
 
+    /**
+     * @since 2.5
+     */
     protected JsonSerializer<?> buildIteratorSerializer(SerializationConfig config,
-            JavaType type, BeanDescription beanDesc,
-            boolean staticTyping)
+            JavaType type, BeanDescription beanDesc, boolean staticTyping,
+            JavaType valueType)
         throws JsonMappingException
     {
-        // if there's generic type, it'll be the first contained type
-        JavaType valueType = type.containedType(0);
-        if (valueType == null) {
-            valueType = TypeFactory.unknownType();
-        }
-        TypeSerializer vts = createTypeSerializer(config, valueType);
-        return new IteratorSerializer(valueType, staticTyping, vts, null);
+        return new IteratorSerializer(valueType, staticTyping, createTypeSerializer(config, valueType), null);
     }
 
+    @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
+     */
+    protected JsonSerializer<?> buildIterableSerializer(SerializationConfig config,
+            JavaType type, BeanDescription beanDesc, boolean staticTyping,
+            JavaType valueType)
+        throws JsonMappingException
+    {
+        return new IterableSerializer(valueType, staticTyping, createTypeSerializer(config, valueType), null);
+    }
+
+    @Deprecated // since 2.5
     protected JsonSerializer<?> buildIterableSerializer(SerializationConfig config,
             JavaType type, BeanDescription beanDesc,
             boolean staticTyping)
         throws JsonMappingException
     {
-        // if there's generic type, it'll be the first contained type
-        JavaType valueType = type.containedType(0);
-        if (valueType == null) {
-            valueType = TypeFactory.unknownType();
-        }
-        TypeSerializer vts = createTypeSerializer(config, valueType);
-        return new IterableSerializer(valueType, staticTyping, vts, null);
+        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
+     */
+    protected JsonSerializer<?> buildMapEntrySerializer(SerializationConfig config,
+            JavaType type, BeanDescription beanDesc, boolean staticTyping,
+            JavaType keyType, JavaType valueType)
+        throws JsonMappingException
+    {
+        return new MapEntrySerializer(valueType, keyType, valueType,
+                staticTyping, createTypeSerializer(config, valueType), null);
+    }
+
     protected JsonSerializer<?> buildEnumSerializer(SerializationConfig config,
             JavaType type, BeanDescription beanDesc)
         throws JsonMappingException
     {
-        /* As per [Issue#24], may want to use alternate shape, serialize as JSON Object.
+        /* As per [databind#24], may want to use alternate shape, serialize as JSON Object.
          * Challenge here is that EnumSerializer does not know how to produce
          * POJO style serialization, so we must handle that special case separately;
          * otherwise pass it to EnumSerializer.
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 1e50a26..1811c7d 100644
--- a/src/main/java/com/fasterxml/jackson/databind/ser/BeanPropertyWriter.java
+++ b/src/main/java/com/fasterxml/jackson/databind/ser/BeanPropertyWriter.java
@@ -6,6 +6,7 @@
 import java.lang.reflect.Type;
 import java.util.HashMap;
 
+import com.fasterxml.jackson.annotation.JsonInclude;
 import com.fasterxml.jackson.core.JsonGenerator;
 import com.fasterxml.jackson.core.SerializableString;
 import com.fasterxml.jackson.core.io.SerializedString;
@@ -37,8 +38,8 @@
     /**
      * Marker object used to indicate "do not serialize if empty"
      */
-    public final static Object MARKER_FOR_EMPTY = new Object();
-    
+    public final static Object MARKER_FOR_EMPTY = JsonInclude.Include.NON_EMPTY;
+
     /*
     /**********************************************************
     /* Settings for accessing property value to serialize
@@ -320,12 +321,14 @@
     @Override public PropertyName getWrapperName() { return _wrapperName; }
     @Override public boolean isRequired() { return _metadata.isRequired(); }
     @Override public PropertyMetadata getMetadata() { return _metadata; }
-    
+
+    // Note: also part of 'PropertyWriter'
     @Override
     public <A extends Annotation> A getAnnotation(Class<A> acls) {
         return _member.getAnnotation(acls);
     }
 
+    // Note: also part of 'PropertyWriter'
     @Override
     public <A extends Annotation> A getContextAnnotation(Class<A> acls) {
         return _contextAnnotations.get(acls);
@@ -434,20 +437,6 @@
 
     public Class<?>[] getViews() { return _includeInViews; }
 
-    /**
-     *<p>
-     * NOTE: due to introspection, this is a <b>slow</b> method to call
-     * and should never be called during actual serialization or filtering
-     * of the property. Rather it is needed for traversal needed for things
-     * like constructing JSON Schema instances.
-     * 
-     * @since 2.1
-     * 
-     * @deprecated since 2.2, use {@link #isRequired()} instead.
-     */
-    @Deprecated
-    protected boolean isRequired(AnnotationIntrospector intr) { return _metadata.isRequired(); }
-    
     /*
     /**********************************************************
     /* PropertyWriter methods (serialization)
@@ -687,15 +676,6 @@
     }
 
     /**
-     * @deprecated Since 2.3 Use overloaded variants
-     */
-    @Deprecated
-    protected void _handleSelfReference(Object bean, JsonSerializer<?> ser)
-        throws JsonMappingException {
-        _handleSelfReference(bean, null, null, ser);
-    }
-    
-    /**
      * 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
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 605f8b7..1eb949d 100644
--- a/src/main/java/com/fasterxml/jackson/databind/ser/BeanSerializer.java
+++ b/src/main/java/com/fasterxml/jackson/databind/ser/BeanSerializer.java
@@ -113,8 +113,8 @@
         /* Can not:
          * 
          * - have Object Id (may be allowed in future)
-         * - have any getter
-         * 
+         * - have "any getter"
+         * - have per-property filters
          */
         if ((_objectIdWriter == null)
                 && (_anyGetterWriter == null)
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 2f10c9f..71dd6e0 100644
--- a/src/main/java/com/fasterxml/jackson/databind/ser/BeanSerializerFactory.java
+++ b/src/main/java/com/fasterxml/jackson/databind/ser/BeanSerializerFactory.java
@@ -223,6 +223,12 @@
                     // Finally: maybe we can still deal with it as an implementation of some basic JDK interface?
                     if (ser == null) {
                         ser = findSerializerByAddonType(config, type, beanDesc, staticTyping);
+                        // 18-Sep-2014, tatu: Actually, as per [jackson-databind#539], need to get
+                        //   'unknown' serializer assigned earlier, here, so that it gets properly
+                        //   post-processed
+                        if (ser == null) {
+                            ser = prov.getUnknownTypeSerializer(beanDesc.getBeanClass());
+                        }
                     }
                 }
             }
@@ -403,14 +409,10 @@
         
         JsonSerializer<Object> ser = (JsonSerializer<Object>) builder.build();
         
-        /* However, after all modifications: no properties, no serializer
-         * (note; as per [JACKSON-670], check was moved later on from an earlier location)
-         */
         if (ser == null) {
-            /* 27-Nov-2009, tatu: Except that as per [JACKSON-201], we are
-             *   ok with that as long as it has a recognized class annotation
-             *  (which may come from a mix-in too)
-             */
+            // If we get this far, there were no properties found, so no regular BeanSerializer
+            // would be constructed. But, couple of exceptions.
+            // First: if there are known annotations, just create 'empty bean' serializer
             if (beanDesc.hasKnownClassAnnotations()) {
                 return builder.createDummy();
             }
diff --git a/src/main/java/com/fasterxml/jackson/databind/ser/ContainerSerializer.java b/src/main/java/com/fasterxml/jackson/databind/ser/ContainerSerializer.java
index a72700c..c3e3fe0 100644
--- a/src/main/java/com/fasterxml/jackson/databind/ser/ContainerSerializer.java
+++ b/src/main/java/com/fasterxml/jackson/databind/ser/ContainerSerializer.java
@@ -23,6 +23,13 @@
     protected ContainerSerializer(Class<T> t) {
         super(t);
     }
+
+    /**
+     * @since 2.5
+     */
+    protected ContainerSerializer(JavaType fullType) {
+        super(fullType);
+    }
     
     /**
      * Alternate constructor that is (alas!) needed to work
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 d13728a..17ad71c 100644
--- a/src/main/java/com/fasterxml/jackson/databind/ser/DefaultSerializerProvider.java
+++ b/src/main/java/com/fasterxml/jackson/databind/ser/DefaultSerializerProvider.java
@@ -330,11 +330,6 @@
         findValueSerializer(javaType, null).acceptJsonFormatVisitor(visitor, javaType);
     }
 
-    @Deprecated // since 2.3; use the overloaded variant
-    public boolean hasSerializerFor(Class<?> cls) {
-        return hasSerializerFor(cls, null);
-    }
-    
     /**
      * Method that can be called to see if this serializer provider
      * can find a serializer for an instance of given class.
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 00b6adc..623a020 100644
--- a/src/main/java/com/fasterxml/jackson/databind/ser/PropertyBuilder.java
+++ b/src/main/java/com/fasterxml/jackson/databind/ser/PropertyBuilder.java
@@ -48,23 +48,6 @@
     }
 
     /**
-     * @deprecated Since 2.3, use variant that takes {@link SerializerProvider} as
-     *   first argument -- to be removed from 2.4
-     */
-    @Deprecated
-    protected final BeanPropertyWriter buildWriter(BeanPropertyDefinition propDef,
-            JavaType declaredType, JsonSerializer<?> ser,
-            TypeSerializer typeSer, TypeSerializer contentTypeSer,
-            AnnotatedMember am, boolean defaultUseStaticTyping)
-    {
-        /* We will only retain this method until 2.4; left for now to explicitly
-         * cause compilation/linking issue iff anyone has overridden the method
-         * (hopefully not)
-         */
-        throw new IllegalStateException();
-    }
-
-    /**
      * @param contentTypeSer Optional explicit type information serializer
      *    to use for contained values (only used for properties that are
      *    of container type)
@@ -90,7 +73,7 @@
             }
             JavaType ct = serializationType.getContentType();
             /* 03-Sep-2010, tatu: This is somehow related to [JACKSON-356], but I don't completely
-             *   yet understand how pieces fit together. Still, better be explicit than rely on
+             *   yet understand how pieces fit together. Still, better to be explicit than rely on
              *   NPE to indicate an issue...
              */
             if (ct == null) {
@@ -140,13 +123,12 @@
                 am, _beanDesc.getClassAnnotations(), declaredType,
                 ser, typeSer, serializationType, suppressNulls, valueToSuppress);
 
-        // 14-Oct-2013, tatu: And how about custom null serializer?
+        // How about custom null serializer?
         Object serDef = _annotationIntrospector.findNullSerializer(am);
         if (serDef != null) {
             bpw.assignNullSerializer(prov.serializerInstance(am, serDef));
         }
-        
-        // [JACKSON-132]: Unwrapping
+        // And then, handling of unwrapping
         NameTransformer unwrapper = _annotationIntrospector.findUnwrappingNameTransformer(am);
         if (unwrapper != null) {
             bpw = bpw.unwrappingWriter(unwrapper);
diff --git a/src/main/java/com/fasterxml/jackson/databind/ser/PropertyWriter.java b/src/main/java/com/fasterxml/jackson/databind/ser/PropertyWriter.java
index 6e1d363..1091aa8 100644
--- a/src/main/java/com/fasterxml/jackson/databind/ser/PropertyWriter.java
+++ b/src/main/java/com/fasterxml/jackson/databind/ser/PropertyWriter.java
@@ -1,7 +1,8 @@
 package com.fasterxml.jackson.databind.ser;
 
-import com.fasterxml.jackson.core.JsonGenerator;
+import java.lang.annotation.Annotation;
 
+import com.fasterxml.jackson.core.JsonGenerator;
 import com.fasterxml.jackson.databind.*;
 import com.fasterxml.jackson.databind.jsonFormatVisitors.JsonObjectFormatVisitor;
 import com.fasterxml.jackson.databind.node.ObjectNode;
@@ -25,7 +26,52 @@
     public abstract String getName();
 
     public abstract PropertyName getFullName();
+
+    /**
+     * Convenience method for accessing annotation that may be associated
+     * either directly on property, or, if not, via enclosing class (context).
+     * This allows adding baseline contextual annotations, for example, by adding
+     * an annotation for a given class and making that apply to all properties
+     * unless overridden by per-property annotations.
+     *<p>
+     * This method is functionally equivalent to:
+     *<pre>
+     *  MyAnnotation ann = propWriter.getAnnotation(MyAnnotation.class);
+     *  if (ann == null) {
+     *    ann = propWriter.getContextAnnotation(MyAnnotation.class);
+     *  }
+     *</pre>
+     * that is, tries to find a property annotation first, but if one is not
+     * found, tries to find context-annotation (from enclosing class) of
+     * same type.
+     * 
+     * @since 2.5
+     */
+    public <A extends Annotation> A findAnnotation(Class<A> acls) {
+        A ann = getAnnotation(acls);
+        if (ann == null) {
+            ann = getContextAnnotation(acls);
+        }
+        return ann;
+    }
     
+    /**
+     * Method for accessing annotations directly declared for property that this
+     * writer is associated with.
+     * 
+     * @since 2.5
+     */
+    public abstract <A extends Annotation> A getAnnotation(Class<A> acls);
+
+    /**
+     * Method for accessing annotations declared in context of the property that this
+     * writer is associated with; usually this means annotations on enclosing class
+     * for property.
+     * 
+     * @since 2.5
+     */
+    public abstract <A extends Annotation> A getContextAnnotation(Class<A> acls);
+
     /*
     /**********************************************************
     /* Serialization methods, regular output
@@ -35,7 +81,7 @@
     /**
      * The main serialization method called by filter when property is to be written normally.
      */
-    public abstract void serializeAsField(Object pojo, JsonGenerator jgen, SerializerProvider prov)
+    public abstract void serializeAsField(Object value, JsonGenerator jgen, SerializerProvider provider)
         throws Exception;
 
     /**
@@ -43,7 +89,7 @@
      * filtered, but the underlying data format requires a placeholder of some kind.
      * This is usually the case for tabular (positional) data formats such as CSV.
      */
-    public abstract void serializeAsOmittedField(Object pojo, JsonGenerator jgen, SerializerProvider prov)
+    public abstract void serializeAsOmittedField(Object value, JsonGenerator jgen, SerializerProvider provider)
         throws Exception;
 
     /*
@@ -62,7 +108,7 @@
      * data format; so it is typically NOT called for fully tabular formats such as CSV,
      * where logical output is still as form of POJOs.
      */
-    public abstract void serializeAsElement(Object pojo, JsonGenerator jgen, SerializerProvider prov)
+    public abstract void serializeAsElement(Object value, JsonGenerator jgen, SerializerProvider provider)
         throws Exception;
 
     /**
@@ -70,7 +116,7 @@
      * but then value is to be omitted. This requires output of a placeholder value
      * of some sort; often similar to {@link #serializeAsOmittedField}.
      */
-    public abstract void serializeAsPlaceholder(Object pojo, JsonGenerator jgen, SerializerProvider prov)
+    public abstract void serializeAsPlaceholder(Object value, JsonGenerator jgen, SerializerProvider provider)
         throws Exception;
 
     /*
diff --git a/src/main/java/com/fasterxml/jackson/databind/ser/impl/IndexedListSerializer.java b/src/main/java/com/fasterxml/jackson/databind/ser/impl/IndexedListSerializer.java
index 86a9246..417db79 100644
--- a/src/main/java/com/fasterxml/jackson/databind/ser/impl/IndexedListSerializer.java
+++ b/src/main/java/com/fasterxml/jackson/databind/ser/impl/IndexedListSerializer.java
@@ -1,12 +1,10 @@
 package com.fasterxml.jackson.databind.ser.impl;
 
 import java.io.IOException;
-import java.util.LinkedList;
-import java.util.List;
+import java.util.*;
 
 import com.fasterxml.jackson.core.JsonGenerationException;
 import com.fasterxml.jackson.core.JsonGenerator;
-
 import com.fasterxml.jackson.databind.*;
 import com.fasterxml.jackson.databind.annotation.JacksonStdImpl;
 import com.fasterxml.jackson.databind.jsontype.TypeSerializer;
@@ -60,6 +58,19 @@
     public ContainerSerializer<?> _withValueTypeSerializer(TypeSerializer vts) {
         return new IndexedListSerializer(_elementType, _staticTyping, vts, _property, _elementSerializer);
     }
+
+    @Override
+    public final void serialize(List<?> value, JsonGenerator jgen, SerializerProvider provider) throws IOException
+    {
+    	final int len = value.size();
+        if ((len == 1) && provider.isEnabled(SerializationFeature.WRITE_SINGLE_ELEM_ARRAYS_UNWRAPPED)) {
+            serializeContents(value, jgen, provider);
+            return;
+        }
+        jgen.writeStartArray(len);
+        serializeContents(value, jgen, provider);
+        jgen.writeEndArray();
+    }
     
     @Override
     public void serializeContents(List<?> value, JsonGenerator jgen, SerializerProvider provider)
@@ -101,14 +112,13 @@
                 }
             }
         } catch (Exception e) {
-            // [JACKSON-55] Need to add reference information
             wrapAndThrow(provider, e, value, i);
         }
     }
     
     public void serializeContentsUsing(List<?> value, JsonGenerator jgen, SerializerProvider provider,
             JsonSerializer<Object> ser)
-        throws IOException, JsonGenerationException
+        throws IOException
     {
         final int len = value.size();
         if (len == 0) {
@@ -133,7 +143,7 @@
     }
 
     public void serializeTypedContents(List<?> value, JsonGenerator jgen, SerializerProvider provider)
-        throws IOException, JsonGenerationException
+        throws IOException
     {
         final int len = value.size();
         if (len == 0) {
diff --git a/src/main/java/com/fasterxml/jackson/databind/ser/impl/IndexedStringListSerializer.java b/src/main/java/com/fasterxml/jackson/databind/ser/impl/IndexedStringListSerializer.java
index 00f11df..1c4d784 100644
--- a/src/main/java/com/fasterxml/jackson/databind/ser/impl/IndexedStringListSerializer.java
+++ b/src/main/java/com/fasterxml/jackson/databind/ser/impl/IndexedStringListSerializer.java
@@ -112,7 +112,7 @@
             return;
         }
         
-        jgen.writeStartArray();
+        jgen.writeStartArray(len);
         if (_serializer == null) {
             serializeContents(value, jgen, provider, len);
         } else {
diff --git a/src/main/java/com/fasterxml/jackson/databind/ser/impl/IteratorSerializer.java b/src/main/java/com/fasterxml/jackson/databind/ser/impl/IteratorSerializer.java
index 1999212..20e86b3 100644
--- a/src/main/java/com/fasterxml/jackson/databind/ser/impl/IteratorSerializer.java
+++ b/src/main/java/com/fasterxml/jackson/databind/ser/impl/IteratorSerializer.java
@@ -3,7 +3,6 @@
 import java.io.IOException;
 import java.util.Iterator;
 
-import com.fasterxml.jackson.core.JsonGenerationException;
 import com.fasterxml.jackson.core.JsonGenerator;
 import com.fasterxml.jackson.databind.*;
 import com.fasterxml.jackson.databind.annotation.JacksonStdImpl;
@@ -50,8 +49,20 @@
     }
 
     @Override
+    public final void serialize(Iterator<?> value, JsonGenerator jgen, SerializerProvider provider) throws IOException
+    {
+        if (provider.isEnabled(SerializationFeature.WRITE_SINGLE_ELEM_ARRAYS_UNWRAPPED) && hasSingleElement(value)) {
+            serializeContents(value, jgen, provider);
+            return;
+        }
+        jgen.writeStartArray();
+        serializeContents(value, jgen, provider);
+        jgen.writeEndArray();
+    }
+    
+    @Override
     public void serializeContents(Iterator<?> value, JsonGenerator jgen, SerializerProvider provider)
-        throws IOException, JsonGenerationException
+        throws IOException
     {
         if (value.hasNext()) {
             final TypeSerializer typeSer = _valueTypeSerializer;
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
new file mode 100644
index 0000000..cfbbfe5
--- /dev/null
+++ b/src/main/java/com/fasterxml/jackson/databind/ser/impl/MapEntrySerializer.java
@@ -0,0 +1,324 @@
+package com.fasterxml.jackson.databind.ser.impl;
+
+import java.io.IOException;
+import java.util.Map;
+import java.util.Map.Entry;
+
+import com.fasterxml.jackson.core.JsonGenerationException;
+import com.fasterxml.jackson.core.JsonGenerator;
+import com.fasterxml.jackson.databind.*;
+import com.fasterxml.jackson.databind.annotation.JacksonStdImpl;
+import com.fasterxml.jackson.databind.introspect.AnnotatedMember;
+import com.fasterxml.jackson.databind.jsontype.TypeSerializer;
+import com.fasterxml.jackson.databind.ser.ContainerSerializer;
+import com.fasterxml.jackson.databind.ser.ContextualSerializer;
+
+/**
+ * @since 2.5
+ */
+@JacksonStdImpl
+public class MapEntrySerializer
+    extends ContainerSerializer<Map.Entry<?,?>>
+    implements ContextualSerializer
+{
+    /**
+     * Map-valued property being serialized with this instance
+     */
+    protected final BeanProperty _property;
+
+    /**
+     * Whether static types should be used for serialization of values
+     * or not (if not, dynamic runtime type is used)
+     */
+    protected final boolean _valueTypeIsStatic;
+
+    protected final JavaType _entryType, _keyType, _valueType;
+
+    /**
+     * Key serializer to use, if it can be statically determined
+     */
+    protected JsonSerializer<Object> _keySerializer;
+    
+    /**
+     * Value serializer to use, if it can be statically determined
+     */
+    protected JsonSerializer<Object> _valueSerializer;
+
+    /**
+     * Type identifier serializer used for values, if any.
+     */
+    protected final TypeSerializer _valueTypeSerializer;
+
+    /**
+     * If value type can not be statically determined, mapping from
+     * runtime value types to serializers are stored in this object.
+     */
+    protected PropertySerializerMap _dynamicValueSerializers;
+
+    /*
+    /**********************************************************
+    /* Construction, initialization
+    /**********************************************************
+     */
+    
+    public MapEntrySerializer(JavaType type, JavaType keyType, JavaType valueType,
+            boolean staticTyping, TypeSerializer vts,
+            BeanProperty property)
+    {
+        super(type);
+        _entryType = type;
+        _keyType = keyType;
+        _valueType = valueType;
+        _valueTypeIsStatic = staticTyping;
+        _valueTypeSerializer = vts;
+        _property = property;
+        _dynamicValueSerializers = PropertySerializerMap.emptyMap();
+    }
+
+    @SuppressWarnings("unchecked")
+    protected MapEntrySerializer(MapEntrySerializer src, BeanProperty property,
+            TypeSerializer vts,
+            JsonSerializer<?> keySer, JsonSerializer<?> valueSer)
+    {
+        super(Map.class, false);
+        _entryType = src._entryType;
+        _keyType = src._keyType;
+        _valueType = src._valueType;
+        _valueTypeIsStatic = src._valueTypeIsStatic;
+        _valueTypeSerializer = src._valueTypeSerializer;
+        _keySerializer = (JsonSerializer<Object>) keySer;
+        _valueSerializer = (JsonSerializer<Object>) valueSer;
+        _dynamicValueSerializers = src._dynamicValueSerializers;
+        _property = src._property;
+    }
+
+    @Override
+    public ContainerSerializer<?> _withValueTypeSerializer(TypeSerializer vts) {
+        return new MapEntrySerializer(this, _property, vts, _keySerializer, _valueSerializer);
+    }
+
+    public MapEntrySerializer withResolved(BeanProperty property,
+            JsonSerializer<?> keySerializer, JsonSerializer<?> valueSerializer) {
+        return new MapEntrySerializer(this, property, _valueTypeSerializer, keySerializer, valueSerializer);
+    }
+
+    @Override
+    public JsonSerializer<?> createContextual(SerializerProvider provider,
+            BeanProperty property) throws JsonMappingException
+    {
+        JsonSerializer<?> ser = null;
+        JsonSerializer<?> keySer = null;
+        final AnnotationIntrospector intr = provider.getAnnotationIntrospector();
+        final AnnotatedMember propertyAcc = (property == null) ? null : property.getMember();
+
+        // First: if we have a property, may have property-annotation overrides
+        if (propertyAcc != null && intr != null) {
+            Object serDef = intr.findKeySerializer(propertyAcc);
+            if (serDef != null) {
+                keySer = provider.serializerInstance(propertyAcc, serDef);
+            }
+            serDef = intr.findContentSerializer(propertyAcc);
+            if (serDef != null) {
+                ser = provider.serializerInstance(propertyAcc, serDef);
+            }
+        }
+        if (ser == null) {
+            ser = _valueSerializer;
+        }
+        // [Issue#124]: May have a content converter
+        ser = findConvertingContentSerializer(provider, 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.
+            // 20-Aug-2013, tatu: Need to avoid trying to access serializer for java.lang.Object tho
+            if ((_valueTypeIsStatic && _valueType.getRawClass() != Object.class)
+                    || hasContentTypeAnnotation(provider, property)) {
+                ser = provider.findValueSerializer(_valueType, property);
+            }
+        } else {
+            ser = provider.handleSecondaryContextualization(ser, property);
+        }
+        if (keySer == null) {
+            keySer = _keySerializer;
+        }
+        if (keySer == null) {
+            keySer = provider.findKeySerializer(_keyType, property);
+        } else {
+            keySer = provider.handleSecondaryContextualization(keySer, property);
+        }
+        MapEntrySerializer mser = withResolved(property, keySer, ser);
+        // but note: no filtering, ignored entries or sorting (unlike Maps)
+        return mser;
+    }
+
+    /*
+    /**********************************************************
+    /* Accessors
+    /**********************************************************
+     */
+
+    @Override
+    public JavaType getContentType() {
+        return _valueType;
+    }
+
+    @Override
+    public JsonSerializer<?> getContentSerializer() {
+        return _valueSerializer;
+    }
+
+    @Override
+    public boolean hasSingleElement(Map.Entry<?,?> value) {
+        return true;
+    }
+
+    @Override
+    public boolean isEmpty(Entry<?, ?> value) {
+        return (value == null);
+    }
+
+    /*
+    /**********************************************************
+    /* Serialization methods
+    /**********************************************************
+     */
+
+    @Override
+    public void serialize(Map.Entry<?, ?> value, JsonGenerator jgen, SerializerProvider provider)
+        throws IOException
+    {
+        jgen.writeStartObject();
+        if (_valueSerializer != null) {
+            serializeUsing(value, jgen, provider, _valueSerializer);
+        } else {
+            serializeDynamic(value, jgen, provider);
+        }
+        jgen.writeEndObject();
+    }
+
+    @Override
+    public void serializeWithType(Map.Entry<?, ?> value, JsonGenerator jgen, SerializerProvider provider,
+            TypeSerializer typeSer) throws IOException
+    {
+        typeSer.writeTypePrefixForObject(value, jgen);
+        if (_valueSerializer != null) {
+            serializeUsing(value, jgen, provider, _valueSerializer);
+        } else {
+            serializeDynamic(value, jgen, provider);
+        }
+        typeSer.writeTypeSuffixForObject(value, jgen);
+    }
+
+    protected void serializeDynamic(Map.Entry<?, ?> value, JsonGenerator jgen, SerializerProvider provider)
+        throws IOException
+    {
+        final JsonSerializer<Object> keySerializer = _keySerializer;
+        final boolean skipNulls = !provider.isEnabled(SerializationFeature.WRITE_NULL_MAP_VALUES);
+        final TypeSerializer vts = _valueTypeSerializer;
+
+        PropertySerializerMap serializers = _dynamicValueSerializers;
+
+        Object valueElem = value.getValue();
+        Object keyElem = value.getKey();
+        if (keyElem == null) {
+            provider.findNullKeySerializer(_keyType, _property).serialize(null, jgen, provider);
+        } else {
+            // [JACKSON-314] skip entries with null values?
+            if (skipNulls && valueElem == null) return;
+            keySerializer.serialize(keyElem, jgen, provider);
+        }
+        // And then value
+        if (valueElem == null) {
+            provider.defaultSerializeNull(jgen);
+        } else {
+            Class<?> cc = valueElem.getClass();
+            JsonSerializer<Object> ser = serializers.serializerFor(cc);
+            if (ser == null) {
+                if (_valueType.hasGenericTypes()) {
+                    ser = _findAndAddDynamic(serializers,
+                            provider.constructSpecializedType(_valueType, cc), provider);
+                } else {
+                    ser = _findAndAddDynamic(serializers, cc, provider);
+                }
+                serializers = _dynamicValueSerializers;
+            }
+            try {
+                if (vts == null) {
+                    ser.serialize(valueElem, jgen, provider);
+                } else {
+                    ser.serializeWithType(valueElem, jgen, provider, vts);
+                }
+            } catch (Exception e) {
+                // [JACKSON-55] Need to add reference information
+                String keyDesc = ""+keyElem;
+                wrapAndThrow(provider, e, value, keyDesc);
+            }
+        }
+    }
+
+    /**
+     * Method called to serialize fields, when the value type is statically known,
+     * so that value serializer is passed and does not need to be fetched from
+     * provider.
+     */
+    protected void serializeUsing(Map.Entry<?, ?> value, JsonGenerator jgen, SerializerProvider provider,
+            JsonSerializer<Object> ser)
+        throws IOException, JsonGenerationException
+    {
+        final JsonSerializer<Object> keySerializer = _keySerializer;
+        final TypeSerializer vts = _valueTypeSerializer;
+        final boolean skipNulls = !provider.isEnabled(SerializationFeature.WRITE_NULL_MAP_VALUES);
+
+        Object valueElem = value.getValue();
+        Object keyElem = value.getKey();
+        if (keyElem == null) {
+            provider.findNullKeySerializer(_keyType, _property).serialize(null, jgen, provider);
+        } else {
+            // [JACKSON-314] also may need to skip entries with null values
+            if (skipNulls && valueElem == null) return;
+            keySerializer.serialize(keyElem, jgen, provider);
+        }
+        if (valueElem == null) {
+            provider.defaultSerializeNull(jgen);
+        } else {
+            try {
+                if (vts == null) {
+                    ser.serialize(valueElem, jgen, provider);
+                } else {
+                    ser.serializeWithType(valueElem, jgen, provider, vts);
+                }
+            } catch (Exception e) {
+                // [JACKSON-55] Need to add reference information
+                String keyDesc = ""+keyElem;
+                wrapAndThrow(provider, e, value, keyDesc);
+            }
+        }
+    }
+
+    /*
+    /**********************************************************
+    /* Internal helper methods
+    /**********************************************************
+     */
+    
+    protected final JsonSerializer<Object> _findAndAddDynamic(PropertySerializerMap map,
+            Class<?> type, SerializerProvider provider) throws JsonMappingException
+    {
+        PropertySerializerMap.SerializerAndMapResult result = map.findAndAddSecondarySerializer(type, provider, _property);
+        if (map != result.map) {
+            _dynamicValueSerializers = result.map;
+        }
+        return result.serializer;
+    }
+
+    protected final JsonSerializer<Object> _findAndAddDynamic(PropertySerializerMap map,
+            JavaType type, SerializerProvider provider) throws JsonMappingException
+    {
+        PropertySerializerMap.SerializerAndMapResult result = map.findAndAddSecondarySerializer(type, provider, _property);
+        if (map != result.map) {
+            _dynamicValueSerializers = result.map;
+        }
+        return result.serializer;
+    }
+
+}
\ No newline at end of file
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 f0f7f48..7dd804f 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
@@ -5,7 +5,6 @@
 
 import com.fasterxml.jackson.core.JsonGenerationException;
 import com.fasterxml.jackson.core.JsonGenerator;
-
 import com.fasterxml.jackson.databind.*;
 import com.fasterxml.jackson.databind.annotation.JacksonStdImpl;
 import com.fasterxml.jackson.databind.introspect.AnnotatedMember;
@@ -146,6 +145,20 @@
      */
     
     @Override
+    public final void serialize(String[] value, JsonGenerator jgen, SerializerProvider provider)
+        throws IOException, JsonGenerationException
+    {
+    	final int len = value.length;
+        if ((len == 1) && provider.isEnabled(SerializationFeature.WRITE_SINGLE_ELEM_ARRAYS_UNWRAPPED)) {
+            serializeContents(value, jgen, provider);
+            return;
+        }
+        jgen.writeStartArray(len);
+        serializeContents(value, jgen, provider);
+        jgen.writeEndArray();
+    }
+    
+    @Override
     public void serializeContents(String[] value, JsonGenerator jgen, SerializerProvider provider)
         throws IOException, JsonGenerationException
     {
diff --git a/src/main/java/com/fasterxml/jackson/databind/ser/impl/StringCollectionSerializer.java b/src/main/java/com/fasterxml/jackson/databind/ser/impl/StringCollectionSerializer.java
index ae40648..110c9fa 100644
--- a/src/main/java/com/fasterxml/jackson/databind/ser/impl/StringCollectionSerializer.java
+++ b/src/main/java/com/fasterxml/jackson/databind/ser/impl/StringCollectionSerializer.java
@@ -116,11 +116,12 @@
         throws IOException, JsonGenerationException
     {
         // [JACKSON-805]
-        if ((value.size() == 1) && provider.isEnabled(SerializationFeature.WRITE_SINGLE_ELEM_ARRAYS_UNWRAPPED)) {
+    	final int len = value.size();
+        if ((len == 1) && provider.isEnabled(SerializationFeature.WRITE_SINGLE_ELEM_ARRAYS_UNWRAPPED)) {
             _serializeUnwrapped(value, jgen, provider);
             return;
         }      
-        jgen.writeStartArray();
+        jgen.writeStartArray(len);
         if (_serializer == null) {
             serializeContents(value, jgen, provider);
         } else {
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 1f68d91..877066a 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
@@ -42,12 +42,13 @@
         super(src._handledType, false);
         _property = property;
     }
-    
+
+    // NOTE: as of 2.5, sub-classes SHOULD override (in 2.4 and before, was final),
+    // at least if they can provide access to actual size of value and use `writeStartArray()`
+    // variant that passes size of array to output, which is helpful with some data formats
     @Override
-    public final void serialize(T value, JsonGenerator jgen, SerializerProvider provider)
-        throws IOException, JsonGenerationException
+    public void serialize(T value, JsonGenerator jgen, SerializerProvider provider) throws IOException
     {
-        // [JACKSON-805]
         if (provider.isEnabled(SerializationFeature.WRITE_SINGLE_ELEM_ARRAYS_UNWRAPPED)
                 && hasSingleElement(value)) {
             serializeContents(value, jgen, provider);
@@ -57,7 +58,7 @@
         serializeContents(value, jgen, provider);
         jgen.writeEndArray();
     }
-    
+
     @Override
     public final void serializeWithType(T value, JsonGenerator jgen, SerializerProvider provider,
             TypeSerializer typeSer)
@@ -68,7 +69,7 @@
         serializeContents(value, jgen, provider);
         typeSer.writeTypeSuffixForArray(value, jgen);
     }
-
+    
     protected abstract void serializeContents(T value, JsonGenerator jgen, SerializerProvider provider)
         throws IOException, JsonGenerationException;
 }
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 ada854c..3558fb8 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
@@ -1,7 +1,6 @@
 package com.fasterxml.jackson.databind.ser.std;
 
 import java.io.IOException;
-import java.lang.reflect.ParameterizedType;
 import java.lang.reflect.Type;
 
 import com.fasterxml.jackson.core.*;
@@ -15,7 +14,6 @@
 import com.fasterxml.jackson.databind.ser.ContainerSerializer;
 import com.fasterxml.jackson.databind.ser.ContextualSerializer;
 import com.fasterxml.jackson.databind.ser.impl.PropertySerializerMap;
-import com.fasterxml.jackson.databind.type.TypeFactory;
 
 /**
  * Base class for serializers that will output contents as JSON
@@ -168,12 +166,13 @@
     /* Serialization
     /**********************************************************
      */
-    
+
+    // NOTE: as of 2.5, sub-classes SHOULD override (in 2.4 and before, was final),
+    // at least if they can provide access to actual size of value and use `writeStartArray()`
+    // variant that passes size of array to output, which is helpful with some data formats
     @Override
-    public final void serialize(T value, JsonGenerator jgen, SerializerProvider provider)
-        throws IOException, JsonGenerationException
+    public void serialize(T value, JsonGenerator jgen, SerializerProvider provider) throws IOException
     {
-        // [JACKSON-805]
         if (provider.isEnabled(SerializationFeature.WRITE_SINGLE_ELEM_ARRAYS_UNWRAPPED)
                 && hasSingleElement(value)) {
             serializeContents(value, jgen, provider);
@@ -184,11 +183,9 @@
         jgen.writeEndArray();
     }
 
-    // Note: was 'final' modifier in 2.2 and before; no real need to be, removed
     @Override
     public void serializeWithType(T value, JsonGenerator jgen, SerializerProvider provider,
-            TypeSerializer typeSer)
-        throws IOException, JsonGenerationException
+            TypeSerializer typeSer) throws IOException
     {
         // note: let's NOT consider [JACKSON-805] here; gets too complicated, and probably just won't work
         typeSer.writeTypePrefixForArray(value, jgen);
@@ -197,7 +194,7 @@
     }
 
     protected abstract void serializeContents(T value, JsonGenerator jgen, SerializerProvider provider)
-        throws IOException, JsonGenerationException;
+        throws IOException;
 
     @SuppressWarnings("deprecation")
     @Override
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 c136a2f..eac13f4 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
@@ -369,19 +369,49 @@
         return null;
     }
 
+    @SuppressWarnings("incomplete-switch")
     @Override
     public JsonSerializer<?> createContextual(SerializerProvider provider,
             BeanProperty property)
         throws JsonMappingException
     {
-        ObjectIdWriter oiw = _objectIdWriter;
-        String[] ignorals = null;
-        Object newFilterId = null;
         final AnnotationIntrospector intr = provider.getAnnotationIntrospector();
         final AnnotatedMember accessor = (property == null || intr == null)
                 ? null : property.getMember();
+        final SerializationConfig config = provider.getConfig();
         
-        // First: may have an override for Object Id:
+        // Let's start with one big transmutation: Enums that are annotated
+        // to serialize as Objects may want to revert
+        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);
+                        }
+                    }
+                }
+            }
+        }
+
+        ObjectIdWriter oiw = _objectIdWriter;
+        String[] ignorals = null;
+        Object newFilterId = null;
+        
+        // Then we may have an override for Object Id
         if (accessor != null) {
             ignorals = intr.findPropertiesToIgnore(accessor);
             ObjectIdInfo objectIdInfo = intr.findObjectIdInfo(accessor);
@@ -467,21 +497,11 @@
         if (newFilterId != null) {
             contextual = contextual.withFilterId(newFilterId);
         }
-        
-        // One more thing: are we asked to serialize POJO as array?
-        JsonFormat.Shape shape = null;
-        if (accessor != null) {
-            JsonFormat.Value format = intr.findFormat((Annotated) accessor);
-
-            if (format != null) {
-                shape = format.getShape();
-            }
-        }
         if (shape == null) {
             shape = _serializationShape;
         }
         if (shape == JsonFormat.Shape.ARRAY) {
-            contextual = contextual.asArraySerializer();
+            return contextual.asArraySerializer();
         }
         return contextual;
     }
diff --git a/src/main/java/com/fasterxml/jackson/databind/ser/std/CollectionSerializer.java b/src/main/java/com/fasterxml/jackson/databind/ser/std/CollectionSerializer.java
index e99a9ea..bdbcbc3 100644
--- a/src/main/java/com/fasterxml/jackson/databind/ser/std/CollectionSerializer.java
+++ b/src/main/java/com/fasterxml/jackson/databind/ser/std/CollectionSerializer.java
@@ -8,6 +8,7 @@
 import com.fasterxml.jackson.databind.BeanProperty;
 import com.fasterxml.jackson.databind.JavaType;
 import com.fasterxml.jackson.databind.JsonSerializer;
+import com.fasterxml.jackson.databind.SerializationFeature;
 import com.fasterxml.jackson.databind.SerializerProvider;
 import com.fasterxml.jackson.databind.jsontype.TypeSerializer;
 import com.fasterxml.jackson.databind.ser.ContainerSerializer;
@@ -72,16 +73,28 @@
         it.next();
         return !it.hasNext();
     }
-    
+
     /*
     /**********************************************************
     /* Actual serialization
     /**********************************************************
      */
+
+    @Override
+    public final void serialize(Collection<?> value, JsonGenerator jgen, SerializerProvider provider) throws IOException
+    {
+    	final int len = value.size();
+        if ((len == 1) && provider.isEnabled(SerializationFeature.WRITE_SINGLE_ELEM_ARRAYS_UNWRAPPED)) {
+            serializeContents(value, jgen, provider);
+            return;
+        }
+        jgen.writeStartArray(len);
+        serializeContents(value, jgen, provider);
+        jgen.writeEndArray();
+    }
     
     @Override
-    public void serializeContents(Collection<?> value, JsonGenerator jgen, SerializerProvider provider)
-        throws IOException, JsonGenerationException
+    public void serializeContents(Collection<?> value, JsonGenerator jgen, SerializerProvider provider) throws IOException
     {
         if (_elementSerializer != null) {
             serializeContentsUsing(value, jgen, provider, _elementSerializer);
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 ff42872..2825a0a 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
@@ -108,7 +108,7 @@
         //todo: (ryan) add a format for the date in the schema?
         return createSchemaNode(_asTimestamp(provider) ? "number" : "string", true);
     }
-    
+
     @Override
     public void acceptJsonFormatVisitor(JsonFormatVisitorWrapper visitor, JavaType typeHint) throws JsonMappingException
     {
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 47c24e6..ddfddfd 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
@@ -7,7 +7,6 @@
 import com.fasterxml.jackson.annotation.JsonFormat;
 import com.fasterxml.jackson.annotation.JsonFormat.Shape;
 import com.fasterxml.jackson.core.*;
-
 import com.fasterxml.jackson.databind.*;
 import com.fasterxml.jackson.databind.annotation.JacksonStdImpl;
 import com.fasterxml.jackson.databind.introspect.Annotated;
@@ -75,11 +74,12 @@
      * 
      * @since 2.1
      */
-    public static EnumSerializer construct(Class<Enum<?>> enumClass, SerializationConfig config,
+    @SuppressWarnings("unchecked")
+    public static EnumSerializer construct(Class<?> enumClass, SerializationConfig config,
             BeanDescription beanDesc, JsonFormat.Value format)
     {
         // [JACKSON-212]: If toString() is to be used instead, leave EnumValues null
-        EnumValues v = EnumValues.construct(config, enumClass);
+        EnumValues v = EnumValues.construct(config, (Class<Enum<?>>) enumClass);
         Boolean serializeAsIndex = _isShapeWrittenUsingIndex(enumClass, format, true);
         return new EnumSerializer(v, serializeAsIndex);
     }
@@ -120,7 +120,7 @@
     
     @Override
     public final void serialize(Enum<?> en, JsonGenerator jgen, SerializerProvider provider)
-        throws IOException, JsonGenerationException
+        throws IOException
     {
         // [JACKSON-684]: serialize as index?
         if (_serializeAsIndex(provider)) {
@@ -205,7 +205,8 @@
         if (shape == Shape.STRING) {
             return Boolean.FALSE;
         }
-        if (shape.isNumeric()) {
+        // 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()
diff --git a/src/main/java/com/fasterxml/jackson/databind/ser/std/EnumSetSerializer.java b/src/main/java/com/fasterxml/jackson/databind/ser/std/EnumSetSerializer.java
index e1edbf6..cefea7a 100644
--- a/src/main/java/com/fasterxml/jackson/databind/ser/std/EnumSetSerializer.java
+++ b/src/main/java/com/fasterxml/jackson/databind/ser/std/EnumSetSerializer.java
@@ -1,10 +1,9 @@
 package com.fasterxml.jackson.databind.ser.std;
 
 import java.io.IOException;
-import java.util.EnumSet;
+import java.util.*;
 
 import com.fasterxml.jackson.core.*;
-
 import com.fasterxml.jackson.databind.*;
 import com.fasterxml.jackson.databind.jsontype.TypeSerializer;
 
@@ -43,6 +42,19 @@
     public boolean hasSingleElement(EnumSet<? extends Enum<?>> value) {
         return value.size() == 1;
     }
+
+    @Override
+    public final void serialize(EnumSet<? extends Enum<?>> value, JsonGenerator jgen, SerializerProvider provider) throws IOException
+    {
+    	final int len = value.size();
+        if ((len == 1) && provider.isEnabled(SerializationFeature.WRITE_SINGLE_ELEM_ARRAYS_UNWRAPPED)) {
+            serializeContents(value, jgen, provider);
+            return;
+        }
+        jgen.writeStartArray(len);
+        serializeContents(value, jgen, provider);
+        jgen.writeEndArray();
+    }
     
     @Override
     public void serializeContents(EnumSet<? extends Enum<?>> value, JsonGenerator jgen, SerializerProvider provider)
diff --git a/src/main/java/com/fasterxml/jackson/databind/ser/std/IterableSerializer.java b/src/main/java/com/fasterxml/jackson/databind/ser/std/IterableSerializer.java
index a7cb0b5..470ede4 100644
--- a/src/main/java/com/fasterxml/jackson/databind/ser/std/IterableSerializer.java
+++ b/src/main/java/com/fasterxml/jackson/databind/ser/std/IterableSerializer.java
@@ -1,14 +1,11 @@
 package com.fasterxml.jackson.databind.ser.std;
 
 import java.io.IOException;
-import java.util.Iterator;
+import java.util.*;
 
 import com.fasterxml.jackson.core.*;
-
 import com.fasterxml.jackson.databind.BeanProperty;
-import com.fasterxml.jackson.databind.JavaType;
-import com.fasterxml.jackson.databind.JsonSerializer;
-import com.fasterxml.jackson.databind.SerializerProvider;
+import com.fasterxml.jackson.databind.*;
 import com.fasterxml.jackson.databind.annotation.JacksonStdImpl;
 import com.fasterxml.jackson.databind.jsontype.TypeSerializer;
 import com.fasterxml.jackson.databind.ser.ContainerSerializer;
@@ -60,6 +57,18 @@
         }
         return false;
     }
+
+    @Override
+    public final void serialize(Iterable<?> value, JsonGenerator jgen, SerializerProvider provider) throws IOException
+    {
+        if (provider.isEnabled(SerializationFeature.WRITE_SINGLE_ELEM_ARRAYS_UNWRAPPED) && hasSingleElement(value)) {
+            serializeContents(value, jgen, provider);
+            return;
+        }
+        jgen.writeStartArray();
+        serializeContents(value, jgen, provider);
+        jgen.writeEndArray();
+    }
     
     @Override
     public void serializeContents(Iterable<?> value, JsonGenerator jgen, SerializerProvider provider)
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 8821964..57761f2 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
@@ -125,7 +125,7 @@
                  *   to serializer factory at this point... 
                  */
                 // 05-Sep-2013, tatu: I _think_ this can be considered a primary property...
-                ser = provider.findPrimaryPropertySerializer(t, _property);
+                ser = provider.findPrimaryPropertySerializer(t, property);
                 /* 09-Dec-2010, tatu: Turns out we must add special handling for
                  *   cases where "native" (aka "natural") type is being serialized,
                  *   using standard serializer
diff --git a/src/main/java/com/fasterxml/jackson/databind/ser/std/MapProperty.java b/src/main/java/com/fasterxml/jackson/databind/ser/std/MapProperty.java
index a0c8cc6..89e8f41 100644
--- a/src/main/java/com/fasterxml/jackson/databind/ser/std/MapProperty.java
+++ b/src/main/java/com/fasterxml/jackson/databind/ser/std/MapProperty.java
@@ -1,8 +1,10 @@
 package com.fasterxml.jackson.databind.ser.std;
 
 import java.io.IOException;
+import java.lang.annotation.Annotation;
 
 import com.fasterxml.jackson.core.JsonGenerator;
+import com.fasterxml.jackson.databind.BeanProperty;
 import com.fasterxml.jackson.databind.JsonMappingException;
 import com.fasterxml.jackson.databind.JsonSerializer;
 import com.fasterxml.jackson.databind.PropertyName;
@@ -20,26 +22,48 @@
  */
 public class MapProperty extends PropertyWriter
 {
-    protected TypeSerializer _typeSerializer;
-    
-    protected Object _key, _value;
+    protected final TypeSerializer _typeSerializer;
+
+    protected final BeanProperty _property;
+
+    protected Object _key;
 
     protected JsonSerializer<Object> _keySerializer, _valueSerializer;
 
-    public MapProperty(TypeSerializer typeSer)
+    /**
+     * @deprecated since 2.4
+     */
+    @Deprecated // since 2.4
+    public MapProperty(TypeSerializer typeSer) {
+        this(typeSer, null);
+    }
+    
+    public MapProperty(TypeSerializer typeSer, BeanProperty prop)
     {
         _typeSerializer = typeSer;
+        _property = prop;
+    }
+
+    /**
+     * Deprecated method with wrong signature; value should not be assigned
+     * to property, should be passed via proper call-through methods.
+     * 
+     * @deprecated Since 2.5, remove in 2.6
+     */
+    @Deprecated // since 2.5
+    public void reset(Object key, Object value,
+            JsonSerializer<Object> keySer, JsonSerializer<Object> valueSer) {
+        reset(key, keySer, valueSer);
     }
     
     /**
      * Initialization method that needs to be called before passing
      * property to filter.
      */
-    public void reset(Object key, Object value,
+    public void reset(Object key,
             JsonSerializer<Object> keySer, JsonSerializer<Object> valueSer)
     {
         _key = key;
-        _value = value;
         _keySerializer = keySer;
         _valueSerializer = valueSer;
     }
@@ -58,19 +82,29 @@
     }
 
     @Override
-    public void serializeAsField(Object pojo, JsonGenerator jgen,
+    public <A extends Annotation> A getAnnotation(Class<A> acls) {
+        return (_property == null) ? null : _property.getAnnotation(acls);
+    }
+
+    @Override
+    public <A extends Annotation> A getContextAnnotation(Class<A> acls) {
+        return (_property == null) ? null : _property.getContextAnnotation(acls);
+    }
+    
+    @Override
+    public void serializeAsField(Object value, JsonGenerator jgen,
             SerializerProvider provider) throws IOException
     {
         _keySerializer.serialize(_key, jgen, provider);
         if (_typeSerializer == null) {
-            _valueSerializer.serialize(_value, jgen, provider);
+            _valueSerializer.serialize(value, jgen, provider);
         } else {
-            _valueSerializer.serializeWithType(_value, jgen, provider, _typeSerializer);
+            _valueSerializer.serializeWithType(value, jgen, provider, _typeSerializer);
         }
     }
 
     @Override
-    public void serializeAsOmittedField(Object pojo, JsonGenerator jgen,
+    public void serializeAsOmittedField(Object value, JsonGenerator jgen,
             SerializerProvider provider) throws Exception
     {
         if (!jgen.canOmitFields()) {
@@ -79,18 +113,18 @@
     }
 
     @Override
-    public void serializeAsElement(Object pojo, JsonGenerator jgen,
+    public void serializeAsElement(Object value, JsonGenerator jgen,
             SerializerProvider provider) throws Exception
     {
         if (_typeSerializer == null) {
-            _valueSerializer.serialize(_value, jgen, provider);
+            _valueSerializer.serialize(value, jgen, provider);
         } else {
-            _valueSerializer.serializeWithType(_value, jgen, provider, _typeSerializer);
+            _valueSerializer.serializeWithType(value, jgen, provider, _typeSerializer);
         }
     }
     
     @Override
-    public void serializeAsPlaceholder(Object pojo, JsonGenerator jgen,
+    public void serializeAsPlaceholder(Object value, JsonGenerator jgen,
             SerializerProvider provider) throws Exception
     {
         jgen.writeNull();
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 6e465b9..53cd683 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,6 +4,7 @@
 import java.lang.reflect.Type;
 import java.util.*;
 
+import com.fasterxml.jackson.annotation.JsonInclude;
 import com.fasterxml.jackson.core.*;
 import com.fasterxml.jackson.databind.*;
 import com.fasterxml.jackson.databind.annotation.JacksonStdImpl;
@@ -17,6 +18,7 @@
 import com.fasterxml.jackson.databind.ser.PropertyFilter;
 import com.fasterxml.jackson.databind.ser.impl.PropertySerializerMap;
 import com.fasterxml.jackson.databind.type.TypeFactory;
+import com.fasterxml.jackson.databind.util.ArrayBuilders;
 
 /**
  * Standard serializer implementation for serializing {link java.util.Map} types.
@@ -30,12 +32,12 @@
     implements ContextualSerializer
 {
     protected final static JavaType UNSPECIFIED_TYPE = TypeFactory.unknownType();
-    
+
     /**
      * Map-valued property being serialized with this instance
      */
     protected final BeanProperty _property;
-    
+
     /**
      * Set of entries to omit during serialization, if any
      */
@@ -92,6 +94,15 @@
      * @since 2.4
      */
     protected final boolean _sortKeys;
+
+    /**
+     * Value that indicates suppression mechanism to use; either one of
+     * values of {@link JsonInclude.Include}, or actual object to compare
+     * against ("default value")
+     * 
+     * @since 2.5
+     */
+    protected final Object _suppressableValue;
     
     /*
     /**********************************************************
@@ -99,6 +110,9 @@
     /**********************************************************
      */
     
+    /**
+     * @since 2.5
+     */
     @SuppressWarnings("unchecked")
     protected MapSerializer(HashSet<String> ignoredEntries,
             JavaType keyType, JavaType valueType, boolean valueTypeIsStatic,
@@ -117,8 +131,18 @@
         _property = null;
         _filterId = null;
         _sortKeys = false;
+        _suppressableValue = null;
     }
 
+    /**
+     * @since 2.5
+     */
+    protected void _ensureOverride() {
+        if (getClass() != MapSerializer.class) {
+            throw new IllegalStateException("Missing override in class "+getClass().getName());
+        }
+    }
+    
     @SuppressWarnings("unchecked")
     protected MapSerializer(MapSerializer src, BeanProperty property,
             JsonSerializer<?> keySerializer, JsonSerializer<?> valueSerializer,
@@ -136,9 +160,19 @@
         _property = property;
         _filterId = src._filterId;
         _sortKeys = src._sortKeys;
+        _suppressableValue = src._suppressableValue;
     }
 
-    protected MapSerializer(MapSerializer src, TypeSerializer vts)
+    @Deprecated // since 2.5
+    protected MapSerializer(MapSerializer src, TypeSerializer vts) {
+        this(src, vts, src._suppressableValue);
+    }
+
+    /**
+     * @since 2.5
+     */
+    protected MapSerializer(MapSerializer src, TypeSerializer vts,
+            Object suppressableValue)
     {
         super(Map.class, false);
         _ignoredEntries = src._ignoredEntries;
@@ -152,6 +186,7 @@
         _property = src._property;
         _filterId = src._filterId;
         _sortKeys = src._sortKeys;
+        _suppressableValue = suppressableValue;
     }
 
     protected MapSerializer(MapSerializer src, Object filterId, boolean sortKeys)
@@ -168,17 +203,16 @@
         _property = src._property;
         _filterId = filterId;
         _sortKeys = sortKeys;
-    }
-    
-    @Override
-    public MapSerializer _withValueTypeSerializer(TypeSerializer vts) {
-        return new MapSerializer(this, vts);
+        _suppressableValue = src._suppressableValue;
     }
 
-    @Deprecated // since 2.3
-    public MapSerializer withResolved(BeanProperty property,
-            JsonSerializer<?> keySerializer, JsonSerializer<?> valueSerializer, HashSet<String> ignored) {
-        return withResolved(property, keySerializer, valueSerializer, ignored, _sortKeys);
+    @Override
+    public MapSerializer _withValueTypeSerializer(TypeSerializer vts) {
+        if (_valueTypeSerializer == vts) {
+            return this;
+        }
+        _ensureOverride();
+        return new MapSerializer(this, vts, null);
     }
 
     /**
@@ -188,32 +222,39 @@
             JsonSerializer<?> keySerializer, JsonSerializer<?> valueSerializer,
             HashSet<String> ignored, boolean sortKeys)
     {
+        _ensureOverride();
         MapSerializer ser = new MapSerializer(this, property, keySerializer, valueSerializer, ignored);
         if (sortKeys != ser._sortKeys) {
             ser = new MapSerializer(ser, _filterId, sortKeys);
         }
         return ser;
     }
-    
+
     /**
      * @since 2.3
      */
     public MapSerializer withFilterId(Object filterId) {
-        return (_filterId == filterId) ? this : new MapSerializer(this, filterId, _sortKeys);
+        if (_filterId == filterId) {
+            return this;
+        }
+        _ensureOverride();
+        return new MapSerializer(this, filterId, _sortKeys);
     }
 
     /**
-     * @deprecated Since 2.3 use the method that takes `filterId`
+     * Mutant factory for constructing an instance with different inclusion strategy
+     * for content (Map values).
+     * 
+     * @since 2.5
      */
-    @Deprecated
-    public static MapSerializer construct(String[] ignoredList, JavaType mapType,
-            boolean staticValueType, TypeSerializer vts,
-            JsonSerializer<Object> keySerializer, JsonSerializer<Object> valueSerializer)
-    {
-        return construct(ignoredList, mapType, staticValueType, vts,
-                keySerializer, valueSerializer, null);
-    }
-
+    public MapSerializer withContentInclusion(Object suppressableValue) {
+        if (suppressableValue == _suppressableValue) {
+            return this;
+        }
+        _ensureOverride();
+        return new MapSerializer(this, _valueTypeSerializer, suppressableValue);
+    }                
+    
     /**
      * @since 2.3
      */
@@ -222,7 +263,9 @@
             JsonSerializer<Object> keySerializer, JsonSerializer<Object> valueSerializer,
             Object filterId)
     {
-        HashSet<String> ignoredEntries = toSet(ignoredList);
+        HashSet<String> ignoredEntries = (ignoredList == null || ignoredList.length == 0)
+                ? null : ArrayBuilders.arrayToSet(ignoredList);
+
         JavaType keyType, valueType;
         
         if (mapType == null) {
@@ -248,17 +291,6 @@
         return ser;
     }
 
-    private static HashSet<String> toSet(String[] ignoredEntries) {
-        if (ignoredEntries == null || ignoredEntries.length == 0) {
-            return null;
-        }
-        HashSet<String> result = new HashSet<String>(ignoredEntries.length);
-        for (String prop : ignoredEntries) {
-            result.add(prop);
-        }
-        return result;
-    }
-
     /*
     /**********************************************************
     /* Post-processing (contextualization)
@@ -278,6 +310,7 @@
         JsonSerializer<?> keySer = null;
         final AnnotationIntrospector intr = provider.getAnnotationIntrospector();
         final AnnotatedMember propertyAcc = (property == null) ? null : property.getMember();
+        Object suppressableValue = _suppressableValue;
 
         // First: if we have a property, may have property-annotation overrides
         if (propertyAcc != null && intr != null) {
@@ -289,6 +322,10 @@
             if (serDef != null) {
                 ser = provider.serializerInstance(propertyAcc, serDef);
             }
+            JsonInclude.Include incl = intr.findSerializationInclusionForContent(propertyAcc, null);
+            if (incl != null) {
+                suppressableValue = incl;
+            }
         }
         if (ser == null) {
             ser = _valueSerializer;
@@ -328,6 +365,9 @@
             sortKeys = (b != null) && b.booleanValue();
         }
         MapSerializer mser = withResolved(property, keySer, ser, ignored, sortKeys);
+        if (suppressableValue != _suppressableValue) {
+            mser = mser.withContentInclusion(suppressableValue);
+        }
 
         // [Issue#307]: allow filtering
         if (property != null) {
@@ -390,23 +430,30 @@
     /* JsonSerializer implementation
     /**********************************************************
      */
-    
+
     @Override
     public void serialize(Map<?,?> value, JsonGenerator jgen, SerializerProvider provider)
-        throws IOException, JsonGenerationException
+        throws IOException
     {
         jgen.writeStartObject();
         if (!value.isEmpty()) {
-            if (_filterId != null) {
-                serializeFilteredFields(value, jgen, provider,
-                        findPropertyFilter(provider, _filterId, value));
-                jgen.writeEndObject();
-                return;
+            Object suppressableValue = _suppressableValue;
+            if (suppressableValue == null) {
+                if (!provider.isEnabled(SerializationFeature.WRITE_NULL_MAP_VALUES)) {
+                    suppressableValue = JsonInclude.Include.NON_NULL;
+                }
+            } else if (suppressableValue == JsonInclude.Include.ALWAYS) {
+                suppressableValue = null;
             }
             if (_sortKeys || provider.isEnabled(SerializationFeature.ORDER_MAP_ENTRIES_BY_KEYS)) {
                 value = _orderEntries(value);
             }
-            if (_valueSerializer != null) {
+            if (_filterId != null) {
+                serializeFilteredFields(value, jgen, provider,
+                        findPropertyFilter(provider, _filterId, value), suppressableValue);
+            } else if (suppressableValue != null) {
+                serializeOptionalFields(value, jgen, provider, suppressableValue);
+            } else if (_valueSerializer != null) {
                 serializeFieldsUsing(value, jgen, provider, _valueSerializer);
             } else {
                 serializeFields(value, jgen, provider);
@@ -418,14 +465,27 @@
     @Override
     public void serializeWithType(Map<?,?> value, JsonGenerator jgen, SerializerProvider provider,
             TypeSerializer typeSer)
-        throws IOException, JsonGenerationException
+        throws IOException
     {
         typeSer.writeTypePrefixForObject(value, jgen);
         if (!value.isEmpty()) {
+            Object suppressableValue = _suppressableValue;
+            if (suppressableValue == null) {
+                if (!provider.isEnabled(SerializationFeature.WRITE_NULL_MAP_VALUES)) {
+                    suppressableValue = JsonInclude.Include.NON_NULL;
+                }
+            } else if (suppressableValue == JsonInclude.Include.ALWAYS) {
+                suppressableValue = null;
+            }
             if (_sortKeys || provider.isEnabled(SerializationFeature.ORDER_MAP_ENTRIES_BY_KEYS)) {
                 value = _orderEntries(value);
             }
-            if (_valueSerializer != null) {
+            if (_filterId != null) {
+                serializeFilteredFields(value, jgen, provider,
+                        findPropertyFilter(provider, _filterId, value), suppressableValue);
+            } else if (suppressableValue != null) {
+                serializeOptionalFields(value, jgen, provider, suppressableValue);
+            } else if (_valueSerializer != null) {
                 serializeFieldsUsing(value, jgen, provider, _valueSerializer);
             } else {
                 serializeFields(value, jgen, provider);
@@ -441,20 +501,19 @@
      */
     
     /**
-     * Method called to serialize fields, when the value type is not statically known.
+     * Method called to serialize fields, when the value type is not statically known;
+     * but we know that no value suppression is needed (which simplifies processing a bit)
      */
     public void serializeFields(Map<?,?> value, JsonGenerator jgen, SerializerProvider provider)
-        throws IOException, JsonGenerationException
+        throws IOException
     {
         // If value type needs polymorphic type handling, some more work needed:
         if (_valueTypeSerializer != null) {
-            serializeTypedFields(value, jgen, provider);
+            serializeTypedFields(value, jgen, provider, null);
             return;
         }
         final JsonSerializer<Object> keySerializer = _keySerializer;
-        
         final HashSet<String> ignored = _ignoredEntries;
-        final boolean skipNulls = !provider.isEnabled(SerializationFeature.WRITE_NULL_MAP_VALUES);
 
         PropertySerializerMap serializers = _dynamicValueSerializers;
 
@@ -465,8 +524,6 @@
             if (keyElem == null) {
                 provider.findNullKeySerializer(_keyType, _property).serialize(null, jgen, provider);
             } else {
-                // [JACKSON-314] skip entries with null values?
-                if (skipNulls && valueElem == null) continue;
                 // One twist: is entry ignorable? If so, skip
                 if (ignored != null && ignored.contains(keyElem)) continue;
                 keySerializer.serialize(keyElem, jgen, provider);
@@ -490,7 +547,7 @@
                 try {
                     serializer.serialize(valueElem, jgen, provider);
                 } catch (Exception e) {
-                    // [JACKSON-55] Need to add reference information
+                    // Add reference information
                     String keyDesc = ""+keyElem;
                     wrapAndThrow(provider, e, value, keyDesc);
                 }
@@ -498,6 +555,69 @@
         }
     }
 
+    public void serializeOptionalFields(Map<?,?> value, JsonGenerator jgen, SerializerProvider provider,
+            Object suppressableValue)
+        throws IOException
+    {
+        // If value type needs polymorphic type handling, some more work needed:
+        if (_valueTypeSerializer != null) {
+            serializeTypedFields(value, jgen, provider, suppressableValue);
+            return;
+        }
+        final HashSet<String> ignored = _ignoredEntries;
+        PropertySerializerMap serializers = _dynamicValueSerializers;
+
+        for (Map.Entry<?,?> entry : value.entrySet()) {
+            // First find key serializer
+            final Object keyElem = entry.getKey();
+            JsonSerializer<Object> keySerializer;
+            if (keyElem == null) {
+                keySerializer = provider.findNullKeySerializer(_keyType, _property);
+            } else {
+                if (ignored != null && ignored.contains(keyElem)) continue;
+                keySerializer = _keySerializer;
+            }
+
+            // Then value serializer
+            final Object valueElem = entry.getValue();
+            JsonSerializer<Object> valueSer;
+            if (valueElem == null) {
+                if (suppressableValue != null) { // all suppressions include null-suppression
+                    continue;
+                }
+                valueSer = provider.getDefaultNullValueSerializer();
+            } else {
+                valueSer = _valueSerializer;
+                if (valueSer == null) {
+                    Class<?> cc = valueElem.getClass();
+                    valueSer = serializers.serializerFor(cc);
+                    if (valueSer == null) {
+                        if (_valueType.hasGenericTypes()) {
+                            valueSer = _findAndAddDynamic(serializers,
+                                    provider.constructSpecializedType(_valueType, cc), provider);
+                        } else {
+                            valueSer = _findAndAddDynamic(serializers, cc, provider);
+                        }
+                        serializers = _dynamicValueSerializers;
+                    }
+                }
+                // also may need to skip non-empty values:
+                if ((suppressableValue == JsonInclude.Include.NON_EMPTY)
+                        && valueSer.isEmpty(valueElem)) {
+                    continue;
+                }
+            }
+            // and then serialize, if all went well
+            try {
+                keySerializer.serialize(keyElem, jgen, provider);
+                valueSer.serialize(valueElem, jgen, provider);
+            } catch (Exception e) {
+                String keyDesc = ""+keyElem;
+                wrapAndThrow(provider, e, value, keyDesc);
+            }
+        }
+    }
+    
     /**
      * Method called to serialize fields, when the value type is statically known,
      * so that value serializer is passed and does not need to be fetched from
@@ -505,24 +625,22 @@
      */
     protected void serializeFieldsUsing(Map<?,?> value, JsonGenerator jgen, SerializerProvider provider,
             JsonSerializer<Object> ser)
-        throws IOException, JsonGenerationException
+        throws IOException
     {
         final JsonSerializer<Object> keySerializer = _keySerializer;
         final HashSet<String> ignored = _ignoredEntries;
         final TypeSerializer typeSer = _valueTypeSerializer;
-        final boolean skipNulls = !provider.isEnabled(SerializationFeature.WRITE_NULL_MAP_VALUES);
 
         for (Map.Entry<?,?> entry : value.entrySet()) {
-            Object valueElem = entry.getValue();
             Object keyElem = entry.getKey();
+            if (ignored != null && ignored.contains(keyElem)) continue;
+
             if (keyElem == null) {
                 provider.findNullKeySerializer(_keyType, _property).serialize(null, jgen, provider);
             } else {
-                // [JACKSON-314] also may need to skip entries with null values
-                if (skipNulls && valueElem == null) continue;
-                if (ignored != null && ignored.contains(keyElem)) continue;
                 keySerializer.serialize(keyElem, jgen, provider);
             }
+            final Object valueElem = entry.getValue();
             if (valueElem == null) {
                 provider.defaultSerializeNull(jgen);
             } else {
@@ -533,7 +651,6 @@
                         ser.serializeWithType(valueElem, jgen, provider, typeSer);
                     }
                 } catch (Exception e) {
-                    // [JACKSON-55] Need to add reference information
                     String keyDesc = ""+keyElem;
                     wrapAndThrow(provider, e, value, keyDesc);
                 }
@@ -544,40 +661,112 @@
     /**
      * Helper method used when we have a JSON Filter to use for potentially
      * filtering out Map entries.
-     *<p>
-     * NOTE: initially only called externally, by <code>AnyGetterWriter</code>
      * 
-     * @since 2.3
+     * @since 2.5
      */
     public void serializeFilteredFields(Map<?,?> value, JsonGenerator jgen, SerializerProvider provider,
-            PropertyFilter filter)
-        throws IOException, JsonGenerationException
+            PropertyFilter filter,
+            Object suppressableValue) // since 2.5
+        throws IOException
     {
         final HashSet<String> ignored = _ignoredEntries;
-        final boolean skipNulls = !provider.isEnabled(SerializationFeature.WRITE_NULL_MAP_VALUES);
 
         PropertySerializerMap serializers = _dynamicValueSerializers;
-        final MapProperty prop = new MapProperty(_valueTypeSerializer);
+        final MapProperty prop = new MapProperty(_valueTypeSerializer, _property);
 
         for (Map.Entry<?,?> entry : value.entrySet()) {
-            // First, serialize key
+            // First, serialize key; unless ignorable by key
             final Object keyElem = entry.getKey();
-            final Object valueElem = entry.getValue();
-            JsonSerializer<Object> keySer;
+            if (ignored != null && ignored.contains(keyElem)) continue;
+
+            JsonSerializer<Object> keySerializer;
             if (keyElem == null) {
-                keySer = provider.findNullKeySerializer(_keyType, _property);
+                keySerializer = provider.findNullKeySerializer(_keyType, _property);
             } else {
-                // [JACKSON-314] skip entries with null values?
-                if (skipNulls && valueElem == null) continue;
-                // One twist: is entry ignorable? If so, skip
-                if (ignored != null && ignored.contains(keyElem)) continue;
-                keySer = _keySerializer;
+                keySerializer = _keySerializer;
             }
+            // or by value; nulls often suppressed
+            final Object valueElem = entry.getValue();
+
             JsonSerializer<Object> valueSer;
             // And then value
             if (valueElem == null) {
+                if (suppressableValue != null) { // all suppressions include null-suppression
+                    continue;
+                }
                 valueSer = provider.getDefaultNullValueSerializer();
             } else {
+                valueSer = _valueSerializer;
+                if (valueSer == null) {
+                    Class<?> cc = valueElem.getClass();
+                    valueSer = serializers.serializerFor(cc);
+                    if (valueSer == null) {
+                        if (_valueType.hasGenericTypes()) {
+                            valueSer = _findAndAddDynamic(serializers,
+                                    provider.constructSpecializedType(_valueType, cc), provider);
+                        } else {
+                            valueSer = _findAndAddDynamic(serializers, cc, provider);
+                        }
+                        serializers = _dynamicValueSerializers;
+                    }
+                }
+                // also may need to skip non-empty values:
+                if ((suppressableValue == JsonInclude.Include.NON_EMPTY)
+                        && valueSer.isEmpty(valueElem)) {
+                    continue;
+                }
+            }
+            // and with that, ask filter to handle it
+            prop.reset(keyElem, keySerializer, valueSer);
+            try {
+                filter.serializeAsField(valueElem, jgen, provider, prop);
+            } catch (Exception e) {
+                String keyDesc = ""+keyElem;
+                wrapAndThrow(provider, e, value, keyDesc);
+            }
+        }
+    }
+
+    @Deprecated // since 2.5
+    public void serializeFilteredFields(Map<?,?> value, JsonGenerator gen, SerializerProvider provider,
+            PropertyFilter filter) throws IOException {
+        serializeFilteredFields(value, gen, provider, filter,
+                provider.isEnabled(SerializationFeature.WRITE_NULL_MAP_VALUES) ? null : JsonInclude.Include.NON_NULL);
+    }
+    
+    /**
+     * @since 2.5
+     */
+    protected void serializeTypedFields(Map<?,?> value, JsonGenerator gen, SerializerProvider provider,
+            Object suppressableValue) // since 2.5
+        throws IOException
+    {
+        final HashSet<String> ignored = _ignoredEntries;
+        PropertySerializerMap serializers = _dynamicValueSerializers;
+
+        for (Map.Entry<?,?> entry : value.entrySet()) {
+            Object keyElem = entry.getKey();
+            JsonSerializer<Object> keySerializer;
+            if (keyElem == null) {
+                keySerializer = provider.findNullKeySerializer(_keyType, _property);
+            } else {
+                // One twist: is entry ignorable? If so, skip
+                if (ignored != null && ignored.contains(keyElem)) continue;
+                keySerializer = _keySerializer;
+            }
+            final Object valueElem = entry.getValue();
+    
+            // And then value
+            JsonSerializer<Object> valueSer;
+            if (valueElem == null) {
+                if (suppressableValue != null) { // all suppression include null suppression
+                    continue;
+                }
+                valueSer = provider.getDefaultNullValueSerializer();
+                keySerializer.serialize(keyElem, gen, provider);
+                provider.defaultSerializeNull(gen);
+            } else {
+                valueSer = _valueSerializer;
                 Class<?> cc = valueElem.getClass();
                 valueSer = serializers.serializerFor(cc);
                 if (valueSer == null) {
@@ -589,69 +778,35 @@
                     }
                     serializers = _dynamicValueSerializers;
                 }
+                // also may need to skip non-empty values:
+                if ((suppressableValue == JsonInclude.Include.NON_EMPTY)
+                        && valueSer.isEmpty(valueElem)) {
+                    continue;
+                }
             }
-            prop.reset(keyElem, valueElem, keySer, valueSer);
+            keySerializer.serialize(keyElem, gen, provider);
             try {
-                filter.serializeAsField(value, jgen, provider, prop);
+                valueSer.serializeWithType(valueElem, gen, provider, _valueTypeSerializer);
             } catch (Exception e) {
-                // [JACKSON-55] Need to add reference information
                 String keyDesc = ""+keyElem;
                 wrapAndThrow(provider, e, value, keyDesc);
             }
         }
     }
-    
-    protected void serializeTypedFields(Map<?,?> value, JsonGenerator jgen, SerializerProvider provider)
-        throws IOException, JsonGenerationException
-    {
-        final JsonSerializer<Object> keySerializer = _keySerializer;
-        JsonSerializer<Object> prevValueSerializer = null;
-        Class<?> prevValueClass = null;
-        final HashSet<String> ignored = _ignoredEntries;
-        final boolean skipNulls = !provider.isEnabled(SerializationFeature.WRITE_NULL_MAP_VALUES);
-    
-        for (Map.Entry<?,?> entry : value.entrySet()) {
-            Object valueElem = entry.getValue();
-            // First, serialize key
-            Object keyElem = entry.getKey();
-            if (keyElem == null) {
-                provider.findNullKeySerializer(_keyType, _property).serialize(null, jgen, provider);
-            } else {
-                // [JACKSON-314] also may need to skip entries with null values
-                if (skipNulls && valueElem == null) continue;
-                // One twist: is entry ignorable? If so, skip
-                if (ignored != null && ignored.contains(keyElem)) continue;
-                keySerializer.serialize(keyElem, jgen, provider);
-            }
-    
-            // And then value
-            if (valueElem == null) {
-                provider.defaultSerializeNull(jgen);
-            } else {
-                Class<?> cc = valueElem.getClass();
-                JsonSerializer<Object> currSerializer;
-                if (cc == prevValueClass) {
-                    currSerializer = prevValueSerializer;
-                } else {
-                    if (_valueType.hasGenericTypes()) {
-                        currSerializer = provider.findValueSerializer(provider.constructSpecializedType(_valueType, cc), _property);
-                    } else {
-                        currSerializer = provider.findValueSerializer(cc, _property);
-                    }
-                    prevValueSerializer = currSerializer;
-                    prevValueClass = cc;
-                }
-                try {
-                    currSerializer.serializeWithType(valueElem, jgen, provider, _valueTypeSerializer);
-                } catch (Exception e) {
-                    // [JACKSON-55] Need to add reference information
-                    String keyDesc = ""+keyElem;
-                    wrapAndThrow(provider, e, value, keyDesc);
-                }
-            }
-        }
+
+    @Deprecated // since 2.5
+    protected void serializeTypedFields(Map<?,?> value, JsonGenerator gen, SerializerProvider provider)
+        throws IOException {
+        serializeTypedFields(value, gen, provider,
+                provider.isEnabled(SerializationFeature.WRITE_NULL_MAP_VALUES) ? null : JsonInclude.Include.NON_NULL);
     }
     
+    /*
+    /**********************************************************
+    /* Schema related functionality
+    /**********************************************************
+     */
+    
     @Override
     public JsonNode getSchema(SerializerProvider provider, Type typeHint)
     {
@@ -660,7 +815,7 @@
         // there's no way to statically determine the keys, so the "Entries" can't be determined.
         return o;
     }
-    
+
     @Override
     public void acceptJsonFormatVisitor(JsonFormatVisitorWrapper visitor, JavaType typeHint)
         throws JsonMappingException
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 5452a8a..bebc346 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
@@ -187,6 +187,20 @@
     /* Actual serialization
     /**********************************************************
      */
+
+    @Override
+    public final void serialize(Object[] value, JsonGenerator jgen, SerializerProvider provider)
+        throws IOException, JsonGenerationException
+    {
+    	final int len = value.length;
+        if ((len == 1) && provider.isEnabled(SerializationFeature.WRITE_SINGLE_ELEM_ARRAYS_UNWRAPPED)) {
+            serializeContents(value, jgen, provider);
+            return;
+        }
+        jgen.writeStartArray(len);
+        serializeContents(value, jgen, provider);
+        jgen.writeEndArray();
+    }
     
     @Override
     public void serializeContents(Object[] value, JsonGenerator jgen, SerializerProvider provider)
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 81a1b14..19f7929 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
@@ -5,7 +5,6 @@
 import java.util.HashMap;
 
 import com.fasterxml.jackson.core.*;
-
 import com.fasterxml.jackson.databind.*;
 import com.fasterxml.jackson.databind.annotation.JacksonStdImpl;
 import com.fasterxml.jackson.databind.jsonFormatVisitors.JsonArrayFormatVisitor;
@@ -118,6 +117,19 @@
         public boolean hasSingleElement(boolean[] value) {
             return (value.length == 1);
         }
+
+        @Override
+        public final void serialize(boolean[] value, JsonGenerator jgen, SerializerProvider provider) throws IOException
+        {
+        	final int len = value.length;
+            if ((len == 1) && provider.isEnabled(SerializationFeature.WRITE_SINGLE_ELEM_ARRAYS_UNWRAPPED)) {
+                serializeContents(value, jgen, provider);
+                return;
+            }
+            jgen.writeStartArray(len);
+            serializeContents(value, jgen, provider);
+            jgen.writeEndArray();
+        }
         
         @Override
         public void serializeContents(boolean[] value, JsonGenerator jgen, SerializerProvider provider)
@@ -244,6 +256,19 @@
         public boolean hasSingleElement(short[] value) {
             return (value.length == 1);
         }
+
+        @Override
+        public final void serialize(short[] value, JsonGenerator jgen, SerializerProvider provider) throws IOException
+        {
+        	final int len = value.length;
+            if ((len == 1) && provider.isEnabled(SerializationFeature.WRITE_SINGLE_ELEM_ARRAYS_UNWRAPPED)) {
+                serializeContents(value, jgen, provider);
+                return;
+            }
+            jgen.writeStartArray(len);
+            serializeContents(value, jgen, provider);
+            jgen.writeEndArray();
+        }
         
         @SuppressWarnings("cast")
         @Override
@@ -307,7 +332,7 @@
         {
             // [JACKSON-289] allows serializing as 'sparse' char array too:
             if (provider.isEnabled(SerializationFeature.WRITE_CHAR_ARRAYS_AS_JSON_ARRAYS)) {
-                jgen.writeStartArray();
+                jgen.writeStartArray(value.length);
                 _writeArrayContents(jgen, value);
                 jgen.writeEndArray();
             } else {
@@ -401,8 +426,21 @@
         }
 
         @Override
+        public final void serialize(int[] value, JsonGenerator jgen, SerializerProvider provider) throws IOException
+        {
+        	final int len = value.length;
+            if ((len == 1) && provider.isEnabled(SerializationFeature.WRITE_SINGLE_ELEM_ARRAYS_UNWRAPPED)) {
+                serializeContents(value, jgen, provider);
+                return;
+            }
+            jgen.writeStartArray(len);
+            serializeContents(value, jgen, provider);
+            jgen.writeEndArray();
+        }
+
+        @Override
         public void serializeContents(int[] value, JsonGenerator jgen, SerializerProvider provider)
-            throws IOException, JsonGenerationException
+            throws IOException
         {
             for (int i = 0, len = value.length; i < len; ++i) {
                 jgen.writeNumber(value[i]);
@@ -463,10 +501,23 @@
         public boolean hasSingleElement(long[] value) {
             return (value.length == 1);
         }
+
+        @Override
+        public final void serialize(long[] value, JsonGenerator jgen, SerializerProvider provider) throws IOException
+        {
+        	final int len = value.length;
+            if ((len == 1) && provider.isEnabled(SerializationFeature.WRITE_SINGLE_ELEM_ARRAYS_UNWRAPPED)) {
+                serializeContents(value, jgen, provider);
+                return;
+            }
+            jgen.writeStartArray(len);
+            serializeContents(value, jgen, provider);
+            jgen.writeEndArray();
+        }
         
         @Override
         public void serializeContents(long[] value, JsonGenerator jgen, SerializerProvider provider)
-            throws IOException, JsonGenerationException
+            throws IOException
         {
             if (_valueTypeSerializer != null) {
                 for (int i = 0, len = value.length; i < len; ++i) {
@@ -541,6 +592,19 @@
         public boolean hasSingleElement(float[] value) {
             return (value.length == 1);
         }
+
+        @Override
+        public final void serialize(float[] value, JsonGenerator jgen, SerializerProvider provider) throws IOException
+        {
+        	final int len = value.length;
+            if ((len == 1) && provider.isEnabled(SerializationFeature.WRITE_SINGLE_ELEM_ARRAYS_UNWRAPPED)) {
+                serializeContents(value, jgen, provider);
+                return;
+            }
+            jgen.writeStartArray(len);
+            serializeContents(value, jgen, provider);
+            jgen.writeEndArray();
+        }
         
         @Override
         public void serializeContents(float[] value, JsonGenerator jgen, SerializerProvider provider)
@@ -613,10 +677,22 @@
         public boolean hasSingleElement(double[] value) {
             return (value.length == 1);
         }
+
+        @Override
+        public final void serialize(double[] value, JsonGenerator jgen, SerializerProvider provider) throws IOException
+        {
+        	final int len = value.length;
+            if ((len == 1) && provider.isEnabled(SerializationFeature.WRITE_SINGLE_ELEM_ARRAYS_UNWRAPPED)) {
+                serializeContents(value, jgen, provider);
+                return;
+            }
+            jgen.writeStartArray(len);
+            serializeContents(value, jgen, provider);
+            jgen.writeEndArray();
+        }
         
         @Override
-        public void serializeContents(double[] value, JsonGenerator jgen, SerializerProvider provider)
-            throws IOException, JsonGenerationException
+        public void serializeContents(double[] value, JsonGenerator jgen, SerializerProvider provider) throws IOException
         {
             for (int i = 0, len = value.length; i < len; ++i) {
                 jgen.writeNumber(value[i]);
@@ -630,7 +706,7 @@
         
         @Override
         public void acceptJsonFormatVisitor(JsonFormatVisitorWrapper visitor, JavaType typeHint)
-                throws JsonMappingException
+            throws JsonMappingException
         {
             if (visitor != null) {
                 JsonArrayFormatVisitor v2 = visitor.expectArrayFormat(typeHint);
diff --git a/src/main/java/com/fasterxml/jackson/databind/ser/std/StdDelegatingSerializer.java b/src/main/java/com/fasterxml/jackson/databind/ser/std/StdDelegatingSerializer.java
index 3a541bc..9393b49 100644
--- a/src/main/java/com/fasterxml/jackson/databind/ser/std/StdDelegatingSerializer.java
+++ b/src/main/java/com/fasterxml/jackson/databind/ser/std/StdDelegatingSerializer.java
@@ -107,25 +107,21 @@
     public JsonSerializer<?> createContextual(SerializerProvider provider, BeanProperty property)
         throws JsonMappingException
     {
-        // First: if already got serializer to delegate to, contextualize it:
-        if (_delegateSerializer != null) {
-            if (_delegateSerializer instanceof ContextualSerializer) {
-                JsonSerializer<?> ser = provider.handleSecondaryContextualization(_delegateSerializer, property);
-                if (ser == _delegateSerializer) {
-                    return this;
-                }
-                return withDelegate(_converter, _delegateType, ser);
-            }
-            return this;
-        }
-        // Otherwise, need to locate serializer to delegate to. For that we need type information...
+        JsonSerializer<?> delSer = _delegateSerializer;
         JavaType delegateType = _delegateType;
-        if (delegateType == null) {
-            delegateType = _converter.getOutputType(provider.getTypeFactory());
+
+        if (delSer == null) {
+            // Otherwise, need to locate serializer to delegate to. For that we need type information...
+            if (delegateType == null) {
+                delegateType = _converter.getOutputType(provider.getTypeFactory());
+            }
+            delSer = provider.findValueSerializer(delegateType);
         }
-        // and then find the thing...
-        return withDelegate(_converter, delegateType,
-                provider.findValueSerializer(delegateType, property));
+        if (delSer instanceof ContextualSerializer) {
+            delSer = provider.handleSecondaryContextualization(delSer, property);
+        }
+        return (delSer == _delegateSerializer) ? this
+                : withDelegate(_converter, delegateType, delSer);
     }
 
     /*
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 d485016..b946a24 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
@@ -243,6 +243,11 @@
             BeanProperty prop, JsonSerializer<?> existingSerializer)
         throws JsonMappingException
     {
+        /* 19-Oct-2014, tatu: As per [databind#357], need to avoid infinite loop
+         *   when applying contextual content converter; this is not ideal way,
+         *   but should work for most cases.
+         */
+
         final AnnotationIntrospector intr = provider.getAnnotationIntrospector();
         if (intr != null && prop != null) {
             Object convDef = intr.findSerializationContentConverter(prop.getMember());
@@ -250,7 +255,7 @@
                 Converter<Object,Object> conv = provider.converterInstance(prop.getMember(), convDef);
                 JavaType delegateType = conv.getOutputType(provider.getTypeFactory());
                 if (existingSerializer == null) {
-                    existingSerializer = provider.findValueSerializer(delegateType, prop);
+                    existingSerializer = provider.findValueSerializer(delegateType);
                 }
                 return new StdDelegatingSerializer(conv, delegateType, existingSerializer);
             }
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 f7a54a2..5e0544b 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
@@ -37,19 +37,27 @@
      */
     public ToStringSerializer() { super(Object.class); }
 
+    /**
+     * Sometimes it may actually make sense to retain actual handled type, so...
+     * 
+     * @since 2.5
+     */
+    public ToStringSerializer(Class<?> handledType) {
+        super(handledType, false);
+    }
+    
     @Override
     public boolean isEmpty(Object value) {
         if (value == null) {
             return true;
         }
         String str = value.toString();
-        // would use String.isEmpty(), but that's JDK 1.6
-        return (str == null) || (str.length() == 0);
+        return str.isEmpty();
     }
     
     @Override
     public void serialize(Object value, JsonGenerator jgen, SerializerProvider provider)
-        throws IOException, JsonGenerationException
+        throws IOException
     {
         jgen.writeString(value.toString());
     }
@@ -68,7 +76,7 @@
     @Override
     public void serializeWithType(Object value, JsonGenerator jgen, SerializerProvider provider,
             TypeSerializer typeSer)
-        throws IOException, JsonGenerationException
+        throws IOException
     {
         typeSer.writeTypePrefixForScalar(value, jgen);
         serialize(value, jgen, provider);
@@ -76,15 +84,12 @@
     }
     
     @Override
-    public JsonNode getSchema(SerializerProvider provider, Type typeHint)
-        throws JsonMappingException
-    {
+    public JsonNode getSchema(SerializerProvider provider, Type typeHint) throws JsonMappingException {
         return createSchemaNode("string", true);
     }
     
     @Override
-    public void acceptJsonFormatVisitor(JsonFormatVisitorWrapper visitor, JavaType typeHint)
-            throws JsonMappingException
+    public void acceptJsonFormatVisitor(JsonFormatVisitorWrapper visitor, JavaType typeHint) throws JsonMappingException
     {
         if (visitor != null) {
             visitor.expectStringFormat(typeHint);
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 673e704..b40f6eb 100644
--- a/src/main/java/com/fasterxml/jackson/databind/type/ArrayType.java
+++ b/src/main/java/com/fasterxml/jackson/databind/type/ArrayType.java
@@ -200,6 +200,15 @@
         if (index == 0) return "E";
         return null;
     }
+
+    /**
+     * No parameterization for array types themselves; element type
+     * may obviously have parameterization.
+     */
+    @Override
+    public Class<?> getParameterSource() {
+        return null;
+    }
     
     /*
     /**********************************************************
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 963b082..9e696ee 100644
--- a/src/main/java/com/fasterxml/jackson/databind/type/CollectionLikeType.java
+++ b/src/main/java/com/fasterxml/jackson/databind/type/CollectionLikeType.java
@@ -133,6 +133,13 @@
         return null;
     }
 
+    // TODO: should allow construction of instances that do refer
+    //  to parameterization, since it is NOT Collection
+    @Override
+    public Class<?> getParameterSource() {
+        return null;
+    }
+    
     @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 530a1e2..f9e5e6d 100644
--- a/src/main/java/com/fasterxml/jackson/databind/type/CollectionType.java
+++ b/src/main/java/com/fasterxml/jackson/databind/type/CollectionType.java
@@ -88,6 +88,17 @@
         return new CollectionType(_class, _elementType.withStaticTyping(),
                 _valueHandler, _typeHandler, true);
     }
+
+    /*
+    /**********************************************************
+    /* Overridden accessors
+    /**********************************************************
+     */
+    
+    @Override
+    public Class<?> getParameterSource() {
+        return java.util.Collection.class;
+    }
     
     /*
     /**********************************************************
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 fc39074..f0708f8 100644
--- a/src/main/java/com/fasterxml/jackson/databind/type/MapLikeType.java
+++ b/src/main/java/com/fasterxml/jackson/databind/type/MapLikeType.java
@@ -179,6 +179,13 @@
         return null;
     }
 
+    // TODO: should allow construction of instances that do refer
+    //  to parameterization, since it is NOT Map
+    @Override
+    public Class<?> getParameterSource() {
+        return null;
+    }
+    
     @Override
     public StringBuilder getErasedSignature(StringBuilder sb) {
         return _classSignature(_class, sb, true);
diff --git a/src/main/java/com/fasterxml/jackson/databind/type/MapType.java b/src/main/java/com/fasterxml/jackson/databind/type/MapType.java
index 2b14896..81859ad 100644
--- a/src/main/java/com/fasterxml/jackson/databind/type/MapType.java
+++ b/src/main/java/com/fasterxml/jackson/databind/type/MapType.java
@@ -108,6 +108,17 @@
 
     /*
     /**********************************************************
+    /* Overridden accessors
+    /**********************************************************
+     */
+    
+    @Override
+    public Class<?> getParameterSource() {
+        return java.util.Map.class;
+    }
+    
+    /*
+    /**********************************************************
     /* Extended API
     /**********************************************************
      */
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 b7c89b2..b19b633 100644
--- a/src/main/java/com/fasterxml/jackson/databind/type/SimpleType.java
+++ b/src/main/java/com/fasterxml/jackson/databind/type/SimpleType.java
@@ -16,6 +16,14 @@
     private static final long serialVersionUID = -800374828948534376L;
 
     /**
+     * In case there are resolved type parameters, this field stores reference
+     * to that type. It must be {@link #getRawClass()} or its supertype.
+     * 
+     * @since 2.5
+     */
+    protected final Class<?> _typeParametersFor;
+    
+    /**
      * Generic type arguments for this type.
      */
     protected final JavaType[] _typeParameters;
@@ -33,12 +41,30 @@
      */
 
     protected SimpleType(Class<?> cls) {
-        this(cls, null, null, null, null, false);
+        this(cls, null, null, null, null, false, null);
     }
 
+    /**
+     * @deprecated Since 2.5 use variant that takes one more argument
+     */
+    @Deprecated
     protected SimpleType(Class<?> cls, String[] typeNames, JavaType[] typeParams,
             Object valueHandler, Object typeHandler, boolean asStatic)
     {
+        this(cls, typeNames, typeParams, valueHandler, typeHandler, asStatic, null);
+    }
+
+    /**
+     * 
+     * @param parametersFrom Interface or abstract class implemented by this type,
+     *   and for which type parameters apply. It may be <code>cls</code> itself,
+     *   but more commonly it is one of its supertypes.
+     */
+    protected SimpleType(Class<?> cls,
+            String[] typeNames, JavaType[] typeParams,
+            Object valueHandler, Object typeHandler, boolean asStatic,
+            Class<?> parametersFrom)
+    {
         super(cls, 0, valueHandler, typeHandler, asStatic);
         if (typeNames == null || typeNames.length == 0) {
             _typeNames = null;
@@ -47,6 +73,7 @@
             _typeNames = typeNames;
             _typeParameters = typeParams;
         }
+        _typeParametersFor = parametersFrom;
     }
 
     /**
@@ -56,7 +83,7 @@
      * not in same package
      */
     public static SimpleType constructUnsafe(Class<?> raw) {
-        return new SimpleType(raw, null, null, null, null, false);
+        return new SimpleType(raw, null, null, null, null, false, null);
     }
 
     @Override
@@ -64,7 +91,7 @@
     {
         // Should we check that there is a sub-class relationship?
         return new SimpleType(subclass, _typeNames, _typeParameters, _valueHandler, _typeHandler,
-                _asStatic);
+                _asStatic, _typeParametersFor);
     }
 
     @Override
@@ -102,7 +129,7 @@
     @Override
     public SimpleType withTypeHandler(Object h)
     {
-        return new SimpleType(_class, _typeNames, _typeParameters, _valueHandler, h, _asStatic);
+        return new SimpleType(_class, _typeNames, _typeParameters, _valueHandler, h, _asStatic, _typeParametersFor);
     }
 
     @Override
@@ -116,7 +143,7 @@
         if (h == _valueHandler) {
             return this;
         }
-        return new SimpleType(_class, _typeNames, _typeParameters, h, _typeHandler, _asStatic);
+        return new SimpleType(_class, _typeNames, _typeParameters, h, _typeHandler, _asStatic, _typeParametersFor);
     }
     
     @Override
@@ -128,7 +155,7 @@
     @Override
     public SimpleType withStaticTyping() {
         return _asStatic ? this : new SimpleType(_class,
-                _typeNames, _typeParameters, _valueHandler, _typeHandler, _asStatic);
+                _typeNames, _typeParameters, _valueHandler, _typeHandler, _asStatic, _typeParametersFor);
     }
 
     @Override
@@ -183,6 +210,11 @@
         }
         return _typeNames[index];
     }
+
+    @Override
+    public Class<?> getParameterSource() {
+        return _typeParametersFor;
+    }
     
     @Override
     public StringBuilder getErasedSignature(StringBuilder sb) {
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 13504dc..f013b3f 100644
--- a/src/main/java/com/fasterxml/jackson/databind/type/TypeFactory.java
+++ b/src/main/java/com/fasterxml/jackson/databind/type/TypeFactory.java
@@ -255,8 +255,7 @@
          * case actually fully works; and former mostly works. In future may need to
          * rewrite former part, which requires changes to JavaType as well.
          */
-        Class<?> raw = type.getRawClass();
-        if (raw == expType) {
+        if (expType == type.getParameterSource()) {
             // Direct type info; good since we can return it as is
             int count = type.containedTypeCount();
             if (count == 0) return null;
@@ -272,13 +271,14 @@
          * if/when there are problems; current handling is an improvement over earlier
          * code.
          */
+        Class<?> raw = type.getRawClass();
         return findTypeParameters(raw, expType, new TypeBindings(this, type));
     }
 
     public JavaType[] findTypeParameters(Class<?> clz, Class<?> expType) {
         return findTypeParameters(clz, expType, new TypeBindings(this, clz));
     }
-    
+
     public JavaType[] findTypeParameters(Class<?> clz, Class<?> expType, TypeBindings bindings)
     {
         // First: find full inheritance chain
@@ -383,8 +383,7 @@
 
         // simple class?
         if (type instanceof Class<?>) {
-            Class<?> cls = (Class<?>) type;
-            resultType = _fromClass(cls, context);
+            resultType = _fromClass((Class<?>) type, context);
         }
         // But if not, need to start resolving.
         else if (type instanceof ParameterizedType) {
@@ -525,21 +524,29 @@
     
     /**
      * Method for constructing a type instance with specified parameterization.
+     * 
+     * @deprecated Since 2.5, use variant that takes one more argument
      */
-    public JavaType constructSimpleType(Class<?> rawType, JavaType[] parameterTypes)
+    @Deprecated
+    public JavaType constructSimpleType(Class<?> rawType, JavaType[] parameterTypes) {
+        return constructSimpleType(rawType, rawType, parameterTypes);
+    }
+    
+    public JavaType constructSimpleType(Class<?> rawType, Class<?> parameterTarget,
+            JavaType[] parameterTypes)
     {
         // Quick sanity check: must match numbers of types with expected...
-        TypeVariable<?>[] typeVars = rawType.getTypeParameters();
+        TypeVariable<?>[] typeVars = parameterTarget.getTypeParameters();
         if (typeVars.length != parameterTypes.length) {
             throw new IllegalArgumentException("Parameter type mismatch for "+rawType.getName()
-                    +": expected "+typeVars.length+" parameters, was given "+parameterTypes.length);
+                    +" (and target "+parameterTarget.getName()+"): expected "+typeVars.length
+                    +" parameters, was given "+parameterTypes.length);
         }
         String[] names = new String[typeVars.length];
         for (int i = 0, len = typeVars.length; i < len; ++i) {
             names[i] = typeVars[i].getName();
         }
-        JavaType resultType = new SimpleType(rawType, names, parameterTypes, null, null, false);
-        return resultType;
+        return new SimpleType(rawType, names, parameterTypes, null, null, false, parameterTarget);
     } 
 
     /**
@@ -564,15 +571,31 @@
      *<p>
      * NOTE: type modifiers are NOT called on constructed type itself; but are called
      * for contained types.
+     * 
+     * @param parametrized Type-erased type of instance being constructed
+     * @param parametersFor class or interface for which type parameters are applied; either
+     *   <code>parametrized</code> or one of its supertypes
+     * @parameterClasses Type parameters to apply
+     * 
+     * @since 2.5
      */
-    public JavaType constructParametricType(Class<?> parametrized, Class<?>... parameterClasses)
+    public JavaType constructParametrizedType(Class<?> parametrized, Class<?> parametersFor,
+            Class<?>... parameterClasses)
     {
         int len = parameterClasses.length;
         JavaType[] pt = new JavaType[len];
         for (int i = 0; i < len; ++i) {
             pt[i] = _fromClass(parameterClasses[i], null);
         }
-        return constructParametricType(parametrized, pt);
+        return constructParametrizedType(parametrized, parametersFor, pt);
+    }
+
+    /**
+     * @deprecated Since 2.5, use {@link #constructParametrizedType} instead.
+     */
+    @Deprecated
+    public JavaType constructParametricType(Class<?> parametrized, Class<?>... parameterClasses) {
+        return constructParametrizedType(parametrized, parametrized, parameterClasses);
     }
 
     /**
@@ -587,8 +610,17 @@
      *<p>
      * NOTE: type modifiers are NOT called on constructed type itself; but are called
      * for contained types.
+     * 
+     * 
+     * @param parametrized Actual full type
+     * @param parametersFor class or interface for which type parameters are applied; either
+     *   <code>parametrized</code> or one of its supertypes
+     * @parameterClasses Type parameters to apply
+     * 
+     * @since 2.5
      */
-    public JavaType constructParametricType(Class<?> parametrized, JavaType... parameterTypes)
+    public JavaType constructParametrizedType(Class<?> parametrized, Class<?> parametersFor,
+            JavaType... parameterTypes)
     {
         JavaType resultType;
         
@@ -612,11 +644,19 @@
             }
             resultType = constructCollectionType((Class<Collection<?>>)parametrized, parameterTypes[0]);
         } else {
-            resultType = constructSimpleType(parametrized, parameterTypes);
+            resultType = constructSimpleType(parametrized, parametersFor, parameterTypes);
         }
         return resultType;
     }
 
+    /**
+     * @deprecated Since 2.5, use {@link #constructParametrizedType} instead.
+     */
+    @Deprecated
+    public JavaType constructParametricType(Class<?> parametrized, JavaType... parameterTypes) {
+        return constructParametrizedType(parametrized, parametrized, parameterTypes);
+    }
+    
     /*
     /**********************************************************
     /* Direct factory methods for "raw" variants, used when
@@ -733,7 +773,20 @@
         } else if (Collection.class.isAssignableFrom(clz)) {
             result =  _collectionType(clz);
         } else {
-            result = new SimpleType(clz);
+            // 29-Sep-2014, tatu: We may want to pre-resolve well-known generic types
+            if (Map.Entry.class.isAssignableFrom(clz)) {
+                JavaType[] pts = this.findTypeParameters(clz, Map.Entry.class);
+                JavaType kt, vt;
+                if (pts == null || pts.length != 2) {
+                    kt = vt = unknownType();
+                } else {
+                    kt = pts[0];
+                    vt = pts[1];
+                }
+                result = constructSimpleType(clz, Map.Entry.class, new JavaType[] { kt, vt });
+            } else {
+                result = new SimpleType(clz);
+            }
         }
         _typeCache.put(key, result); // cache object syncs
         return result;
@@ -771,8 +824,9 @@
         if (paramTypes.size() == 0) {
             return new SimpleType(clz);
         }
+        // Hmmh. Does this actually occur?
         JavaType[] pt = paramTypes.toArray(new JavaType[paramTypes.size()]);
-        return constructSimpleType(clz, pt);
+        return constructSimpleType(clz, clz, pt);
     }
     
     /**
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 5fce78e..1192450 100644
--- a/src/main/java/com/fasterxml/jackson/databind/util/ISO8601Utils.java
+++ b/src/main/java/com/fasterxml/jackson/databind/util/ISO8601Utils.java
@@ -5,11 +5,15 @@
 import java.text.ParseException;
 
 /**
- * Utilities methods for manipulating dates in iso8601 format. This is much much faster and GC friendly than
- * using SimpleDateFormat so highly suitable if you (un)serialize lots of date objects.
+ * Utilities methods for manipulating dates in iso8601 format. This is much much faster and GC friendly than using SimpleDateFormat so
+ * highly suitable if you (un)serialize lots of date objects.
+ * 
+ * Supported parse format: [yyyy-MM-dd|yyyyMMdd][T(hh:mm[:ss[.sss]]|hhmm[ss[.sss]])]?[Z|[+-]hh:mm]]
+ * 
+ * @see <a href="http://www.w3.org/TR/NOTE-datetime">this specification</a>
  */
-public class ISO8601Utils {
-
+public class ISO8601Utils
+{
     /**
      * ID to represent the 'GMT' string
      */
@@ -25,21 +29,23 @@
     /* Static factories
     /**********************************************************
      */
-    
+
     /**
      * Accessor for static GMT timezone instance.
      */
-    public static TimeZone timeZoneGMT() { return TIMEZONE_GMT; }
+    public static TimeZone timeZoneGMT() {
+        return TIMEZONE_GMT;
+    }
 
     /*
     /**********************************************************
     /* Formatting
     /**********************************************************
      */
-    
+
     /**
      * Format a date into 'yyyy-MM-ddThh:mm:ssZ' (GMT timezone, no milliseconds precision)
-     *
+     * 
      * @param date the date to format
      * @return the date formatted as 'yyyy-MM-ddThh:mm:ssZ'
      */
@@ -49,8 +55,8 @@
 
     /**
      * Format a date into 'yyyy-MM-ddThh:mm:ss[.sss]Z' (GMT timezone)
-     *
-     * @param date   the date to format
+     * 
+     * @param date the date to format
      * @param millis true to include millis precision otherwise false
      * @return the date formatted as 'yyyy-MM-ddThh:mm:ss[.sss]Z'
      */
@@ -60,10 +66,10 @@
 
     /**
      * Format date into yyyy-MM-ddThh:mm:ss[.sss][Z|[+-]hh:mm]
-     *
-     * @param date   the date to format
+     * 
+     * @param date the date to format
      * @param millis true to include millis precision otherwise false
-     * @param tz     timezone to use for the formatting (GMT will produce 'Z')
+     * @param tz timezone to use for the formatting (GMT will produce 'Z')
      * @return the date formatted as yyyy-MM-ddThh:mm:ss[.sss][Z|[+-]hh:mm]
      */
     public static String format(Date date, boolean millis, TimeZone tz) {
@@ -114,48 +120,68 @@
      */
 
     /**
-     * Parse a date from ISO-8601 formatted string. It expects a format yyyy-MM-ddThh:mm:ss[.sss][Z|[+-]hh:mm]
-     *
+     * Parse a date from ISO-8601 formatted string. It expects a format
+     * [yyyy-MM-dd|yyyyMMdd][T(hh:mm[:ss[.sss]]|hhmm[ss[.sss]])]?[Z|[+-]hh:mm]]
+     * 
      * @param date ISO string to parse in the appropriate format.
      * @param pos The position to start parsing from, updated to where parsing stopped.
      * @return the parsed date
      * @throws ParseException if the date is not in the appropriate format
      */
-    public static Date parse(String date, ParsePosition pos) throws ParseException
-    {
+    public static Date parse(String date, ParsePosition pos) throws ParseException {
         Exception fail = null;
         try {
             int offset = pos.getIndex();
 
             // extract year
             int year = parseInt(date, offset, offset += 4);
-            checkOffset(date, offset, '-');
+            if (checkOffset(date, offset, '-')) {
+                offset += 1;
+            }
 
             // extract month
-            int month = parseInt(date, offset += 1, offset += 2);
-            checkOffset(date, offset, '-');
+            int month = parseInt(date, offset, offset += 2);
+            if (checkOffset(date, offset, '-')) {
+                offset += 1;
+            }
 
             // extract day
-            int day = parseInt(date, offset += 1, offset += 2);
-            checkOffset(date, offset, 'T');
-
-            // extract hours, minutes, seconds and milliseconds
-            int hour = parseInt(date, offset += 1, offset += 2);
-            checkOffset(date, offset, ':');
-
-            int minutes = parseInt(date, offset += 1, offset += 2);
-            checkOffset(date, offset, ':');
-
-            int seconds = parseInt(date, offset += 1, offset += 2);
-            // milliseconds can be optional in the format
+            int day = parseInt(date, offset, offset += 2);
+            // default time value
+            int hour = 0;
+            int minutes = 0;
+            int seconds = 0;
             int milliseconds = 0; // always use 0 otherwise returned date will include millis of current time
-            if (date.charAt(offset) == '.') {
-                checkOffset(date, offset, '.');
-                milliseconds = parseInt(date, offset += 1, offset += 3);
+            if (checkOffset(date, offset, 'T')) {
+
+                // extract hours, minutes, seconds and milliseconds
+                hour = parseInt(date, offset += 1, offset += 2);
+                if (checkOffset(date, offset, ':')) {
+                    offset += 1;
+                }
+
+                minutes = parseInt(date, offset, offset += 2);
+                if (checkOffset(date, offset, ':')) {
+                    offset += 1;
+                }
+                // second and milliseconds can be optional
+                if (date.length() > offset) {
+                    char c = date.charAt(offset);
+                    if (c != 'Z' && c != '+' && c != '-') {
+                        seconds = parseInt(date, offset, offset += 2);
+                        // milliseconds can be optional in the format
+                        if (checkOffset(date, offset, '.')) {
+                            milliseconds = parseInt(date, offset += 1, offset += 3);
+                        }
+                    }
+                }
             }
 
             // extract timezone
             String timezoneId;
+            if (date.length() <= offset) {
+                throw new IllegalArgumentException("No time zone indicator");
+            }
             char timezoneIndicator = date.charAt(offset);
             if (timezoneIndicator == '+' || timezoneIndicator == '-') {
                 String timezoneOffset = date.substring(offset);
@@ -185,8 +211,8 @@
 
             pos.setIndex(offset);
             return calendar.getTime();
-            //If we get a ParseException it'll already have the right message/offset.
-            //Other exception types can convert here.
+            // If we get a ParseException it'll already have the right message/offset.
+            // Other exception types can convert here.
         } catch (IndexOutOfBoundsException e) {
             fail = e;
         } catch (NumberFormatException e) {
@@ -194,32 +220,28 @@
         } catch (IllegalArgumentException e) {
             fail = e;
         }
-        String input = (date == null) ? null : ('"'+date+"'");
-        throw new ParseException("Failed to parse date ["+input
-            +"]: "+fail.getMessage(), pos.getIndex());
+        String input = (date == null) ? null : ('"' + date + "'");
+        throw new ParseException("Failed to parse date [" + input + "]: " + fail.getMessage(), pos.getIndex());
     }
 
     /**
-     * Check if the expected character exist at the given offset of the
-     *
-     * @param value    the string to check at the specified offset
-     * @param offset   the offset to look for the expected character
+     * Check if the expected character exist at the given offset in the value.
+     * 
+     * @param value the string to check at the specified offset
+     * @param offset the offset to look for the expected character
      * @param expected the expected character
-     * @throws IndexOutOfBoundsException if the expected character is not found
+     * @return true if the expected character exist at the given offset
      */
-    private static void checkOffset(String value, int offset, char expected) throws ParseException {
-        char found = value.charAt(offset);
-        if (found != expected) {
-            throw new ParseException("Expected '" + expected + "' character but found '" + found + "'", offset);
-        }
+    private static boolean checkOffset(String value, int offset, char expected) {
+        return (offset < value.length()) && (value.charAt(offset) == expected);
     }
 
     /**
      * Parse an integer located between 2 given offsets in a string
-     *
-     * @param value      the string to parse
+     * 
+     * @param value the string to parse
      * @param beginIndex the start index for the integer in the string
-     * @param endIndex   the end index for the integer in the string
+     * @param endIndex the end index for the integer in the string
      * @return the int
      * @throws NumberFormatException if the value is not a number
      */
@@ -251,9 +273,9 @@
 
     /**
      * Zero pad a number to a specified length
-     *
+     * 
      * @param buffer buffer to use for padding
-     * @param value  the integer value to pad if necessary.
+     * @param value the integer value to pad if necessary.
      * @param length the length of the string we should zero pad
      */
     private static void padInt(StringBuilder buffer, int value, int length) {
@@ -264,4 +286,3 @@
         buffer.append(strValue);
     }
 }
-
diff --git a/src/main/java/com/fasterxml/jackson/databind/util/LRUMap.java b/src/main/java/com/fasterxml/jackson/databind/util/LRUMap.java
index 8f37121..e67a765 100644
--- a/src/main/java/com/fasterxml/jackson/databind/util/LRUMap.java
+++ b/src/main/java/com/fasterxml/jackson/databind/util/LRUMap.java
@@ -13,7 +13,12 @@
  * NOTE: since version 2.4.2, this is <b>NOT</b> an LRU-based at all; reason
  * being that it is not possible to use JDK components that do LRU _AND_ perform
  * well wrt synchronization on multi-core systems. So we choose efficient synchronization
- * over potentially more effecient handling of entries.
+ * over potentially more efficient handling of entries.
+ *<p>
+ * And yes, there are efficient LRU implementations such as
+ * <a href="https://code.google.com/p/concurrentlinkedhashmap/">concurrentlinkedhashmap</a>;
+ * but at this point we really try to keep external deps to minimum. But perhaps
+ * a shaded variant may be used one day.
  */
 public class LRUMap<K,V>
     implements java.io.Serializable
@@ -43,6 +48,22 @@
         return _map.put(key, value);
     }
 
+    /**
+     * @since 2.5
+     */
+    public V putIfAbsent(K key, V value) {
+        // not 100% optimal semantically, but better from correctness (never exceeds
+        // defined maximum) and close enough all in all:
+        if (_map.size() >= _maxEntries) {
+            synchronized (this) {
+                if (_map.size() >= _maxEntries) {
+                    clear();
+                }
+            }
+        }
+        return _map.putIfAbsent(key, value);
+    }
+    
     // NOTE: key is of type Object only to retain binary backwards-compatibility
     public V get(Object key) {  return _map.get(key); }
 
diff --git a/src/main/java/com/fasterxml/jackson/databind/util/PrimitiveArrayBuilder.java b/src/main/java/com/fasterxml/jackson/databind/util/PrimitiveArrayBuilder.java
index 468f392..69c902f 100644
--- a/src/main/java/com/fasterxml/jackson/databind/util/PrimitiveArrayBuilder.java
+++ b/src/main/java/com/fasterxml/jackson/databind/util/PrimitiveArrayBuilder.java
@@ -50,6 +50,8 @@
     /**********************************************************
      */
 
+    public int bufferedSize() { return _bufferedEntryCount; }
+    
     public T resetAndStart()
     {
         _reset();
diff --git a/src/main/java/com/fasterxml/jackson/databind/util/SimpleBeanPropertyDefinition.java b/src/main/java/com/fasterxml/jackson/databind/util/SimpleBeanPropertyDefinition.java
index 666efbf..2ff3c0d 100644
--- a/src/main/java/com/fasterxml/jackson/databind/util/SimpleBeanPropertyDefinition.java
+++ b/src/main/java/com/fasterxml/jackson/databind/util/SimpleBeanPropertyDefinition.java
@@ -1,5 +1,8 @@
 package com.fasterxml.jackson.databind.util;
 
+import java.util.Collections;
+import java.util.Iterator;
+
 import com.fasterxml.jackson.databind.AnnotationIntrospector;
 import com.fasterxml.jackson.databind.PropertyMetadata;
 import com.fasterxml.jackson.databind.PropertyName;
@@ -178,6 +181,15 @@
         return (_member instanceof AnnotatedParameter) ? (AnnotatedParameter) _member : null;
     }
 
+    @Override
+    public Iterator<AnnotatedParameter> getConstructorParameters() {
+        AnnotatedParameter param = getConstructorParameter();
+        if (param == null) {
+            return EmptyIterator.instance();
+        }
+        return Collections.singleton(param).iterator();
+    }
+    
     /**
      * Method used to find accessor (getter, field to access) to use for accessing
      * value of the property.
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 58d3e08..2dbb7df 100644
--- a/src/main/java/com/fasterxml/jackson/databind/util/TokenBuffer.java
+++ b/src/main/java/com/fasterxml/jackson/databind/util/TokenBuffer.java
@@ -1129,14 +1129,6 @@
         /**********************************************************
          */
 
-        @Deprecated // since 2.3
-        protected Parser(Segment firstSeg, ObjectCodec codec) {
-            this(firstSeg, codec, false, false);
-        }
-
-        /**
-         * @since 2.3
-         */
         public Parser(Segment firstSeg, ObjectCodec codec,
                 boolean hasNativeTypeIds,
                 boolean hasNativeObjectIds)
diff --git a/src/test/java/com/fasterxml/jackson/databind/BaseMapTest.java b/src/test/java/com/fasterxml/jackson/databind/BaseMapTest.java
index 65c51ce..3623d9e 100644
--- a/src/test/java/com/fasterxml/jackson/databind/BaseMapTest.java
+++ b/src/test/java/com/fasterxml/jackson/databind/BaseMapTest.java
@@ -7,11 +7,8 @@
 
 import com.fasterxml.jackson.annotation.JsonCreator;
 import com.fasterxml.jackson.annotation.JsonValue;
-
 import com.fasterxml.jackson.databind.ObjectMapper;
 
-import com.fasterxml.jackson.test.BaseTest;
-
 public abstract class BaseMapTest
     extends BaseTest
 {
@@ -238,7 +235,7 @@
         }
     }
 
-    protected String aposToQuotes(String json) {
+    protected static String aposToQuotes(String json) {
         return json.replace("'", "\"");
     }
 }
diff --git a/src/test/java/com/fasterxml/jackson/test/BaseTest.java b/src/test/java/com/fasterxml/jackson/databind/BaseTest.java
similarity index 99%
rename from src/test/java/com/fasterxml/jackson/test/BaseTest.java
rename to src/test/java/com/fasterxml/jackson/databind/BaseTest.java
index 0a0d833..8226035 100644
--- a/src/test/java/com/fasterxml/jackson/test/BaseTest.java
+++ b/src/test/java/com/fasterxml/jackson/databind/BaseTest.java
@@ -1,4 +1,4 @@
-package com.fasterxml.jackson.test;
+package com.fasterxml.jackson.databind;
 
 import java.io.*;
 import java.util.Arrays;
diff --git a/src/test/java/com/fasterxml/jackson/databind/TestObjectMapper.java b/src/test/java/com/fasterxml/jackson/databind/TestObjectMapper.java
index 6a6ab67..6fb488c 100644
--- a/src/test/java/com/fasterxml/jackson/databind/TestObjectMapper.java
+++ b/src/test/java/com/fasterxml/jackson/databind/TestObjectMapper.java
@@ -152,7 +152,7 @@
         assertEquals(0, m.getDeserializationConfig().mixInCount());
         assertEquals(0, m2.getDeserializationConfig().mixInCount());
 
-        m.addMixInAnnotations(String.class, Integer.class);
+        m.addMixIn(String.class, Integer.class);
         assertEquals(1, m.getSerializationConfig().mixInCount());
         assertEquals(0, m2.getSerializationConfig().mixInCount());
         assertEquals(1, m.getDeserializationConfig().mixInCount());
diff --git a/src/test/java/com/fasterxml/jackson/databind/TestObjectMapperBeanDeserializer.java b/src/test/java/com/fasterxml/jackson/databind/TestObjectMapperBeanDeserializer.java
index 1263c2f..6778274 100644
--- a/src/test/java/com/fasterxml/jackson/databind/TestObjectMapperBeanDeserializer.java
+++ b/src/test/java/com/fasterxml/jackson/databind/TestObjectMapperBeanDeserializer.java
@@ -10,7 +10,6 @@
 import com.fasterxml.jackson.databind.ObjectMapper;
 import com.fasterxml.jackson.databind.SerializerProvider;
 import com.fasterxml.jackson.databind.jsontype.TypeSerializer;
-import com.fasterxml.jackson.test.BaseTest;
 
 /**
  * Unit tests for verifying deserialization of Beans.
diff --git a/src/test/java/com/fasterxml/jackson/databind/TestObjectMapperBeanSerializer.java b/src/test/java/com/fasterxml/jackson/databind/TestObjectMapperBeanSerializer.java
index 2c03177..844420f 100644
--- a/src/test/java/com/fasterxml/jackson/databind/TestObjectMapperBeanSerializer.java
+++ b/src/test/java/com/fasterxml/jackson/databind/TestObjectMapperBeanSerializer.java
@@ -8,7 +8,6 @@
 
 import com.fasterxml.jackson.core.*;
 import com.fasterxml.jackson.databind.ObjectMapper;
-import com.fasterxml.jackson.test.BaseTest;
 
 /**
  * This unit test suite tries to verify that the "Native" java type
diff --git a/src/test/java/com/fasterxml/jackson/databind/TestParserUsingMapper.java b/src/test/java/com/fasterxml/jackson/databind/TestParserUsingMapper.java
index 8f8ebf3..c0db914 100644
--- a/src/test/java/com/fasterxml/jackson/databind/TestParserUsingMapper.java
+++ b/src/test/java/com/fasterxml/jackson/databind/TestParserUsingMapper.java
@@ -8,7 +8,7 @@
 import com.fasterxml.jackson.core.io.SerializedString;
 import com.fasterxml.jackson.databind.ObjectMapper;
 
-public class TestParserUsingMapper  extends com.fasterxml.jackson.test.BaseTest
+public class TestParserUsingMapper  extends BaseMapTest
 {
     final static int TWO_BYTE_ESCAPED = 0x111;
     final static int THREE_BYTE_ESCAPED = 0x1111;
diff --git a/src/test/java/com/fasterxml/jackson/databind/TestReadValues.java b/src/test/java/com/fasterxml/jackson/databind/TestReadValues.java
index 54da2b2..643a66e 100644
--- a/src/test/java/com/fasterxml/jackson/databind/TestReadValues.java
+++ b/src/test/java/com/fasterxml/jackson/databind/TestReadValues.java
@@ -17,8 +17,16 @@
 
     static class Bean {
         public int a;
+
+        @Override
+        public boolean equals(Object o) {
+            if (o == null || o.getClass() != getClass()) return false;
+            Bean other = (Bean) o;
+            return other.a == this.a;
+        }
+        @Override public int hashCode() { return a; }
     }
-    
+
     /*
     /**********************************************************
     /* Unit tests; root-level value sequences via Mapper
@@ -30,9 +38,10 @@
     public void testRootBeans() throws Exception
     {
         final String JSON = "{\"a\":3}{\"a\":27}  ";
-        Iterator<Bean> it = MAPPER.reader(Bean.class).readValues(JSON);
 
-        assertNotNull(((MappingIterator<?>) it).getCurrentLocation());
+        MappingIterator<Bean> it = MAPPER.reader(Bean.class).readValues(JSON);
+
+        assertNotNull(it.getCurrentLocation());
         assertTrue(it.hasNext());
         Bean b = it.next();
         assertEquals(3, b.a);
@@ -40,6 +49,19 @@
         b = it.next();
         assertEquals(27, b.a);
         assertFalse(it.hasNext());
+        it.close();
+
+        // Also, test 'readAll()'
+        it = MAPPER.reader(Bean.class).readValues(JSON);
+        List<Bean> all = it.readAll();
+        assertEquals(2, all.size());
+        it.close();
+
+        it = MAPPER.reader(Bean.class).readValues("{\"a\":3}{\"a\":3}");
+        Set<Bean> set = it.readAll(new HashSet<Bean>());
+        assertEquals(HashSet.class, set.getClass());
+        assertEquals(1, set.size());
+        assertEquals(3, set.iterator().next().a);
     }
 
     public void testRootMaps() throws Exception
diff --git a/src/test/java/com/fasterxml/jackson/databind/TestVersions.java b/src/test/java/com/fasterxml/jackson/databind/TestVersions.java
index 5b5df44..182e9c6 100644
--- a/src/test/java/com/fasterxml/jackson/databind/TestVersions.java
+++ b/src/test/java/com/fasterxml/jackson/databind/TestVersions.java
@@ -11,7 +11,7 @@
  * Tests to ensure that we get proper Version information via
  * things defined as Versioned.
  */
-public class TestVersions extends com.fasterxml.jackson.test.BaseTest
+public class TestVersions extends BaseMapTest
 {
     public void testMapperVersions()
     {
diff --git a/src/test/java/com/fasterxml/jackson/databind/contextual/TestContextAttributeWithDeser.java b/src/test/java/com/fasterxml/jackson/databind/contextual/TestContextAttributeWithDeser.java
index cdfb75f..adf8a55 100644
--- a/src/test/java/com/fasterxml/jackson/databind/contextual/TestContextAttributeWithDeser.java
+++ b/src/test/java/com/fasterxml/jackson/databind/contextual/TestContextAttributeWithDeser.java
@@ -72,9 +72,9 @@
 
         // as above, should not carry on state
         TestPOJO pojo2 = MAPPER.reader(TestPOJO.class)
-                .withAttribute(KEY, Integer.valueOf(3))
+                .withAttribute(KEY, Integer.valueOf(5))
                 .readValue(INPUT);
-        assertEquals("x/3", pojo2.value);
+        assertEquals("x/5", pojo2.value);
     }
 
     public void testHierarchic() throws Exception
diff --git a/src/test/java/com/fasterxml/jackson/databind/creators/SingleArgCreatorTest.java b/src/test/java/com/fasterxml/jackson/databind/creators/SingleArgCreatorTest.java
index 0e4ce69..8a39da0 100644
--- a/src/test/java/com/fasterxml/jackson/databind/creators/SingleArgCreatorTest.java
+++ b/src/test/java/com/fasterxml/jackson/databind/creators/SingleArgCreatorTest.java
@@ -1,8 +1,10 @@
 package com.fasterxml.jackson.databind.creators;
 
 import com.fasterxml.jackson.annotation.*;
-
 import com.fasterxml.jackson.databind.*;
+import com.fasterxml.jackson.databind.introspect.AnnotatedMember;
+import com.fasterxml.jackson.databind.introspect.AnnotatedParameter;
+import com.fasterxml.jackson.databind.introspect.JacksonAnnotationIntrospector;
 
 public class SingleArgCreatorTest extends BaseMapTest
 {
@@ -20,6 +22,35 @@
         public String getSs() { return _ss; }
     }
 
+    // [Databind#557]
+    
+    static class StringyBean
+    {
+        public final String value;
+
+        private StringyBean(String value) { this.value = value; }
+
+        public String getValue() {
+            return value;
+        }
+    }
+
+    @SuppressWarnings("serial")
+    static class MyParamIntrospector extends JacksonAnnotationIntrospector
+    {
+        @Override
+        public String findImplicitPropertyName(AnnotatedMember param) {
+            if (param instanceof AnnotatedParameter) {
+                AnnotatedParameter ap = (AnnotatedParameter) param;
+                switch (ap.getIndex()) {
+                case 0: return "value";
+                }
+                return "param"+ap.getIndex();
+            }
+            return super.findImplicitPropertyName(param);
+        }
+    }
+
     /*
     /**********************************************************
     /* Test methods
@@ -34,4 +65,13 @@
                 SingleNamedStringBean.class);
         assertEquals("foobar", bean._ss);
     }
+
+    public void testSingleStringArgWithImplicitName() throws Exception
+    {
+        final ObjectMapper mapper = new ObjectMapper();
+        mapper.setAnnotationIntrospector(new MyParamIntrospector());
+        StringyBean bean = mapper.readValue(quote("foobar"), StringyBean.class);
+        assertEquals("foobar", bean.getValue());
+    }    
 }
+
diff --git a/src/test/java/com/fasterxml/jackson/databind/creators/TestBuilderSimple.java b/src/test/java/com/fasterxml/jackson/databind/creators/TestBuilderSimple.java
index 6575426..78c60ec 100644
--- a/src/test/java/com/fasterxml/jackson/databind/creators/TestBuilderSimple.java
+++ b/src/test/java/com/fasterxml/jackson/databind/creators/TestBuilderSimple.java
@@ -22,18 +22,17 @@
         }
     }
 
-    @SuppressWarnings("hiding")
     static class SimpleBuilderXY
     {
         public int x, y;
     	
-        public SimpleBuilderXY withX(int x) {
-    		    this.x = x;
+        public SimpleBuilderXY withX(int x0) {
+    		    this.x = x0;
     		    return this;
         }
 
-        public SimpleBuilderXY withY(int y) {
-    		    this.y = y;
+        public SimpleBuilderXY withY(int y0) {
+    		    this.y = y0;
     		    return this;
         }
 
@@ -56,22 +55,21 @@
         }
     }
 
-    @SuppressWarnings("hiding")
     static class BuildABC
     {
         public int a; // to be used as is
         private int b, c;
     	
         @JsonProperty("b")
-        public BuildABC assignB(int b) {
-            this.b = b;
+        public BuildABC assignB(int b0) {
+            this.b = b0;
             return this;
         }
 
         // Also ok NOT to return 'this'
         @JsonSetter("c")
-        public void c(int c) {
-            this.c = c;
+        public void c(int c0) {
+            this.c = c0;
         }
 
         public ValueClassABC build() {
diff --git a/src/test/java/com/fasterxml/jackson/databind/creators/TestCreatorWithNamingStrategy556.java b/src/test/java/com/fasterxml/jackson/databind/creators/TestCreatorWithNamingStrategy556.java
new file mode 100644
index 0000000..0911fcf
--- /dev/null
+++ b/src/test/java/com/fasterxml/jackson/databind/creators/TestCreatorWithNamingStrategy556.java
@@ -0,0 +1,82 @@
+package com.fasterxml.jackson.databind.creators;
+
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.databind.*;
+import com.fasterxml.jackson.databind.introspect.AnnotatedMember;
+import com.fasterxml.jackson.databind.introspect.AnnotatedParameter;
+import com.fasterxml.jackson.databind.introspect.JacksonAnnotationIntrospector;
+
+public class TestCreatorWithNamingStrategy556
+    extends BaseMapTest
+{
+    static class RenamingCtorBean
+    {
+        protected String myName;
+        protected int myAge;
+
+        @JsonCreator
+        public RenamingCtorBean(int myAge, String myName)
+        {
+            this.myName = myName;
+            this.myAge = myAge;
+        }
+    }
+
+    // Try the same with factory, too
+    static class RenamedFactoryBean
+    {
+        protected String myName;
+        protected int myAge;
+
+        private RenamedFactoryBean(int a, String n, boolean foo) {
+            myAge = a;
+            myName = n;
+        }
+        
+        @JsonCreator
+        public static RenamedFactoryBean create(int age, String name) {
+            return new RenamedFactoryBean(age, name, true);
+        }
+    }
+    
+    @SuppressWarnings("serial")
+    static class MyParamIntrospector extends JacksonAnnotationIntrospector
+    {
+        @Override
+        public String findImplicitPropertyName(AnnotatedMember param) {
+            if (param instanceof AnnotatedParameter) {
+                AnnotatedParameter ap = (AnnotatedParameter) param;
+                switch (ap.getIndex()) {
+                case 0: return "myAge";
+                case 1: return "myName";
+                default:
+                    return "param"+ap.getIndex();
+                }
+            }
+            return super.findImplicitPropertyName(param);
+        }
+    }
+    
+    private final ObjectMapper MAPPER = new ObjectMapper()
+            .setPropertyNamingStrategy(PropertyNamingStrategy.PASCAL_CASE_TO_CAMEL_CASE)
+            ;
+    {
+        MAPPER.setAnnotationIntrospector(new MyParamIntrospector());
+    }
+
+    private final static String CTOR_JSON = aposToQuotes("{ 'MyAge' : 42,  'MyName' : 'NotMyRealName' }");
+    
+    public void testRenameViaCtor() throws Exception
+    {
+        RenamingCtorBean bean = MAPPER.readValue(CTOR_JSON, RenamingCtorBean.class);
+        assertEquals(42, bean.myAge);
+        assertEquals("NotMyRealName", bean.myName);
+    }
+
+    public void testRenameViaFactory() throws Exception
+    {
+        RenamedFactoryBean bean = MAPPER.readValue(CTOR_JSON, RenamedFactoryBean.class);
+        assertEquals(42, bean.myAge);
+        assertEquals("NotMyRealName", bean.myName);
+    }
+}
\ No newline at end of file
diff --git a/src/test/java/com/fasterxml/jackson/failing/TestCreatorWithPolymorphic113.java b/src/test/java/com/fasterxml/jackson/databind/creators/TestCreatorWithPolymorphic113.java
similarity index 96%
rename from src/test/java/com/fasterxml/jackson/failing/TestCreatorWithPolymorphic113.java
rename to src/test/java/com/fasterxml/jackson/databind/creators/TestCreatorWithPolymorphic113.java
index b7f161c..eb39a57 100644
--- a/src/test/java/com/fasterxml/jackson/failing/TestCreatorWithPolymorphic113.java
+++ b/src/test/java/com/fasterxml/jackson/databind/creators/TestCreatorWithPolymorphic113.java
@@ -1,4 +1,4 @@
-package com.fasterxml.jackson.failing;
+package com.fasterxml.jackson.databind.creators;
 
 import com.fasterxml.jackson.annotation.*;
 
diff --git a/src/test/java/com/fasterxml/jackson/databind/creators/TestCreators.java b/src/test/java/com/fasterxml/jackson/databind/creators/TestCreators.java
index 0a9a371..73f54a67 100644
--- a/src/test/java/com/fasterxml/jackson/databind/creators/TestCreators.java
+++ b/src/test/java/com/fasterxml/jackson/databind/creators/TestCreators.java
@@ -436,7 +436,7 @@
     public void testFactoryCreatorWithMixin() throws Exception
     {
         ObjectMapper m = new ObjectMapper();
-        m.addMixInAnnotations(CreatorBean.class, MixIn.class);
+        m.addMixIn(CreatorBean.class, MixIn.class);
         CreatorBean bean = m.readValue
             ("{ \"a\" : \"xyz\", \"x\" : 12 }", CreatorBean.class);
         assertEquals(11, bean.x);
@@ -446,7 +446,7 @@
     public void testFactoryCreatorWithRenamingMixin() throws Exception
     {
         ObjectMapper m = new ObjectMapper();
-        m.addMixInAnnotations(FactoryBean.class, FactoryBeanMixIn.class);
+        m.addMixIn(FactoryBean.class, FactoryBeanMixIn.class);
         // override changes property name from "f" to "mixed"
         FactoryBean bean = m.readValue("{ \"mixed\" :  20.5 }", FactoryBean.class);
         assertEquals(20.5, bean.d);
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 a20fcb9..9bca3bc 100644
--- a/src/test/java/com/fasterxml/jackson/databind/creators/TestCreators2.java
+++ b/src/test/java/com/fasterxml/jackson/databind/creators/TestCreators2.java
@@ -105,13 +105,14 @@
     // For [JACKSON-541]: should not need @JsonCreator if SerializationFeature.AUTO_DETECT_CREATORS is on.
     static class AutoDetectConstructorBean
     {
-    	protected final String foo;
-    	protected final String bar;
+        protected final String foo;
+        protected final String bar;
 
-    	public AutoDetectConstructorBean(@JsonProperty("bar") String bar, @JsonProperty("foo") String foo){
-    	    this.bar = bar;
-    	    this.foo = foo;
-    	}
+        public AutoDetectConstructorBean(@JsonProperty("bar") String bar,
+                @JsonProperty("foo") String foo){
+            this.bar = bar;
+            this.foo = foo;
+        }
     }
 
     static class BustedCtor {
@@ -267,7 +268,8 @@
     }
     
     public void testCreatorMultipleArgumentWithoutAnnotation() throws Exception {
-        AutoDetectConstructorBean value = MAPPER.readValue("{\"bar\":\"bar\",\"foo\":\"foo\"}", AutoDetectConstructorBean.class);
+        AutoDetectConstructorBean value = MAPPER.readValue("{\"bar\":\"bar\",\"foo\":\"foo\"}",
+                AutoDetectConstructorBean.class);
         assertEquals("bar", value.bar);
         assertEquals("foo", value.foo);
     }
diff --git a/src/test/java/com/fasterxml/jackson/databind/creators/TestCreators3.java b/src/test/java/com/fasterxml/jackson/databind/creators/TestCreators3.java
deleted file mode 100644
index c116a56..0000000
--- a/src/test/java/com/fasterxml/jackson/databind/creators/TestCreators3.java
+++ /dev/null
@@ -1,46 +0,0 @@
-package com.fasterxml.jackson.databind.creators;
-
-import com.fasterxml.jackson.annotation.JsonCreator;
-import com.fasterxml.jackson.annotation.JsonProperty;
-import com.fasterxml.jackson.databind.*;
-
-public class TestCreators3 extends BaseMapTest
-{
-    static class MultiCtor
-    {
-        protected String _a, _b;
-        
-        @JsonCreator
-        static MultiCtor factory(@JsonProperty("a") String a, @JsonProperty("b") String b) {
-            return new MultiCtor(a, b, Boolean.TRUE);
-        }
-
-        private MultiCtor() { }
-
-        private MultiCtor(String a, String b, Object c) {
-            if (c == null) {
-                throw new RuntimeException("Wrong factory!");
-            }
-            _a = a;
-            _b = b;
-        }
-        
-    }
-    
-    /*
-    /**********************************************************
-    /* Test methods
-    /**********************************************************
-     */
-
-    private final ObjectMapper MAPPER = new ObjectMapper();
-
-    // [Issue#421]
-    public void testMultiCtor421() throws Exception
-    {
-        MultiCtor bean = MAPPER.readValue(aposToQuotes("{'a':'123','b':'foo'}"), MultiCtor.class);
-        assertNotNull(bean);
-        assertEquals("123", bean._a);
-        assertEquals("foo", bean._b);
-    }
-}
diff --git a/src/test/java/com/fasterxml/jackson/databind/creators/TestCreators421.java b/src/test/java/com/fasterxml/jackson/databind/creators/TestCreators421.java
new file mode 100644
index 0000000..27de087
--- /dev/null
+++ b/src/test/java/com/fasterxml/jackson/databind/creators/TestCreators421.java
@@ -0,0 +1,67 @@
+package com.fasterxml.jackson.databind.creators;
+
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.databind.*;
+import com.fasterxml.jackson.databind.introspect.AnnotatedMember;
+import com.fasterxml.jackson.databind.introspect.AnnotatedParameter;
+import com.fasterxml.jackson.databind.introspect.JacksonAnnotationIntrospector;
+
+public class TestCreators421 extends BaseMapTest
+{
+    static class MultiCtor
+    {
+        protected String _a, _b;
+        
+        private MultiCtor() { }
+        private MultiCtor(String a, String b, Boolean c) {
+            if (c == null) {
+                throw new RuntimeException("Wrong factory!");
+            }
+            _a = a;
+            _b = b;
+        }
+
+        @JsonCreator
+        static MultiCtor factory(@JsonProperty("a") String a, @JsonProperty("b") String b) {
+            return new MultiCtor(a, b, Boolean.TRUE);
+        }
+    }
+
+    @SuppressWarnings("serial")
+    static class MyParamIntrospector extends JacksonAnnotationIntrospector
+    {
+        @Override
+        public String findImplicitPropertyName(AnnotatedMember param) {
+            if (param instanceof AnnotatedParameter) {
+                AnnotatedParameter ap = (AnnotatedParameter) param;
+                switch (ap.getIndex()) {
+                case 0: return "a";
+                case 1: return "b";
+                case 2: return "c";
+                default:
+                    return "param"+ap.getIndex();
+                }
+            }
+            return super.findImplicitPropertyName(param);
+        }
+    }
+    
+    /*
+    /**********************************************************
+    /* Test methods
+    /**********************************************************
+     */
+
+    // [Issue#421]
+    public void testMultiCtor421() throws Exception
+    {
+        final ObjectMapper mapper = new ObjectMapper();
+        mapper.setAnnotationIntrospector(new MyParamIntrospector());
+
+        MultiCtor bean = mapper.readValue(aposToQuotes("{'a':'123','b':'foo'}"), MultiCtor.class);
+        assertNotNull(bean);
+        assertEquals("123", bean._a);
+        assertEquals("foo", bean._b);
+    }
+}
diff --git a/src/test/java/com/fasterxml/jackson/databind/creators/TestCreatorsDelegating.java b/src/test/java/com/fasterxml/jackson/databind/creators/TestCreatorsDelegating.java
index ffa1602..0989f8b 100644
--- a/src/test/java/com/fasterxml/jackson/databind/creators/TestCreatorsDelegating.java
+++ b/src/test/java/com/fasterxml/jackson/databind/creators/TestCreatorsDelegating.java
@@ -2,8 +2,10 @@
 
 import com.fasterxml.jackson.annotation.JsonCreator;
 import com.fasterxml.jackson.annotation.JacksonInject;
+
 import com.fasterxml.jackson.core.JsonParser;
 import com.fasterxml.jackson.core.JsonToken;
+
 import com.fasterxml.jackson.databind.*;
 import com.fasterxml.jackson.databind.util.TokenBuffer;
 
@@ -67,7 +69,7 @@
             return new Value592(buffer, false);
         }
     }
-        
+
     /*
     /**********************************************************
     /* Unit tests
diff --git a/src/test/java/com/fasterxml/jackson/databind/creators/TestPolymorphicDelegating.java b/src/test/java/com/fasterxml/jackson/databind/creators/TestPolymorphicDelegating.java
new file mode 100644
index 0000000..0eba60b
--- /dev/null
+++ b/src/test/java/com/fasterxml/jackson/databind/creators/TestPolymorphicDelegating.java
@@ -0,0 +1,53 @@
+package com.fasterxml.jackson.databind.creators;
+
+import com.fasterxml.jackson.annotation.*;
+import com.fasterxml.jackson.databind.*;
+
+public class TestPolymorphicDelegating extends BaseMapTest
+{
+
+    // For [databind#580]
+    
+    @JsonTypeInfo(use = JsonTypeInfo.Id.CLASS)
+    static abstract class Issue580Base {
+    }
+
+    static class Issue580Impl extends Issue580Base {
+        public int id = 3;
+
+        public Issue580Impl() { }
+        public Issue580Impl(int id) { this.id = id; }
+    }
+
+    static class Issue580Bean {
+        public Issue580Base value;
+
+        @JsonCreator
+        public Issue580Bean(Issue580Base v) {
+            value = v;
+        }
+
+        @JsonValue
+        public Issue580Base value() {
+            return value;
+        }
+    }
+
+    /*
+    /**********************************************************
+    /* Unit tests
+    /**********************************************************
+     */
+
+    public void testAbstractDelegateWithCreator() throws Exception
+    {
+        Issue580Bean input = new Issue580Bean(new Issue580Impl(13));
+        ObjectMapper mapper = new ObjectMapper();
+        String json = mapper.writeValueAsString(input);
+
+        Issue580Bean result = mapper.readValue(json, Issue580Bean.class);
+        assertNotNull(result);
+        assertNotNull(result.value);
+        assertEquals(13, ((Issue580Impl) result.value).id);
+    }
+}
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 5c0e0dd..54ce1b2 100644
--- a/src/test/java/com/fasterxml/jackson/databind/creators/TestValueUpdate.java
+++ b/src/test/java/com/fasterxml/jackson/databind/creators/TestValueUpdate.java
@@ -2,10 +2,10 @@
 
 import com.fasterxml.jackson.annotation.JsonCreator;
 import com.fasterxml.jackson.annotation.JsonProperty;
-import com.fasterxml.jackson.databind.ObjectMapper;
-import com.fasterxml.jackson.test.BaseTest;
 
-public class TestValueUpdate extends BaseTest
+import com.fasterxml.jackson.databind.*;
+
+public class TestValueUpdate extends BaseMapTest
 {
     static class Bean
     {
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 34cdfd6..65f6a5f 100644
--- a/src/test/java/com/fasterxml/jackson/databind/deser/TestBeanDeserializer.java
+++ b/src/test/java/com/fasterxml/jackson/databind/deser/TestBeanDeserializer.java
@@ -223,6 +223,8 @@
     /********************************************************
      */
 
+    private final ObjectMapper MAPPER = new ObjectMapper();
+    
     public void testPropertyRemoval() throws Exception
     {
         ObjectMapper mapper = new ObjectMapper();
@@ -258,22 +260,43 @@
     public void testPOJOFromEmptyString() throws Exception
     {
         // first, verify default settings which do not accept empty String:
-        ObjectMapper mapper = new ObjectMapper();
+        assertFalse(MAPPER.isEnabled(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT));
         try {
-            mapper.readValue(quote(""), Bean.class);
+            MAPPER.readValue(quote(""), Bean.class);
             fail("Should not accept Empty String for POJO");
         } catch (JsonProcessingException e) {
             verifyException(e, "from String value");
             assertValidLocation(e.getLocation());
         }
-
-        // should be ok to enable dynamically:
-        mapper = new ObjectMapper();
-        mapper.configure(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT, true);
-        Bean result = mapper.readValue(quote(""), Bean.class);
+        // should be ok to enable dynamically
+        ObjectReader r = MAPPER.reader(Bean.class)
+                .with(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT);
+        Bean result = r.readValue(quote(""));
         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.reader(Bean.class)
+                .with(DeserializationFeature.ACCEPT_EMPTY_ARRAY_AS_NULL_OBJECT);
+        Bean result = r.readValue(JSON);
+        assertNull(result);
+    }
+    
     // [Issue#120]
     public void testModifyArrayDeserializer() throws Exception
     {
diff --git a/src/test/java/com/fasterxml/jackson/databind/deser/TestEnumDeserialization.java b/src/test/java/com/fasterxml/jackson/databind/deser/TestEnumDeserialization.java
index 5c39333..3ac2752 100644
--- a/src/test/java/com/fasterxml/jackson/databind/deser/TestEnumDeserialization.java
+++ b/src/test/java/com/fasterxml/jackson/databind/deser/TestEnumDeserialization.java
@@ -1,13 +1,13 @@
 package com.fasterxml.jackson.databind.deser;
 
 import java.io.IOException;
+import java.math.BigDecimal;
 import java.util.EnumMap;
 import java.util.EnumSet;
 import java.util.Map;
 import java.util.concurrent.TimeUnit;
 
 import com.fasterxml.jackson.annotation.*;
-
 import com.fasterxml.jackson.core.*;
 import com.fasterxml.jackson.core.type.TypeReference;
 import com.fasterxml.jackson.databind.*;
@@ -48,7 +48,7 @@
             return TestEnum.valueOf(jp.getText().toUpperCase());
         }
     }
-    
+
     protected enum EnumWithCreator {
         A, B;
 
@@ -59,6 +59,17 @@
             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;
@@ -194,11 +205,15 @@
     }
 
     // [JACKSON-193]
-    public void testCreatorEnums() throws Exception
-    {
+    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);
+    }
     
     // [JACKSON-212]
     public void testToStringEnums() throws Exception
@@ -336,8 +351,9 @@
     // [JACKSON-834]
     public void testEnumsFromInts() throws Exception
     {
-        TestEnumFor834 res = MAPPER.readValue("1 ", TestEnumFor834.class);
-        assertSame(TestEnumFor834.ENUM_A, res);
+        Object ob = MAPPER.readValue("1 ", TestEnumFor834.class);
+        assertEquals(TestEnumFor834.class, ob.getClass());
+        assertSame(TestEnumFor834.ENUM_A, ob);
     }
 
     // [Issue#141]: allow mapping of empty String into null
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 13a9fd1..adf9296 100644
--- a/src/test/java/com/fasterxml/jackson/databind/deser/TestMapDeserialization.java
+++ b/src/test/java/com/fasterxml/jackson/databind/deser/TestMapDeserialization.java
@@ -9,7 +9,6 @@
 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.deser.std.StdDeserializer;
@@ -18,13 +17,7 @@
 public class TestMapDeserialization
     extends BaseMapTest
 {
-    /*
-    /**********************************************************
-    /* Test classes, enums
-    /**********************************************************
-     */
-
-    enum Key {
+    static enum Key {
         KEY1, KEY2, WHATEVER;
     }
 
@@ -83,8 +76,6 @@
     public static enum ConcreteType implements ITestType {
         ONE, TWO;
     }
-
-    
     
     /*
     /**********************************************************
@@ -302,6 +293,31 @@
         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.reader(Map.class)
+                .with(DeserializationFeature.ACCEPT_EMPTY_ARRAY_AS_NULL_OBJECT);
+
+        Map<?,?> result = r.readValue(JSON);
+        assertNull(result);
+
+        EnumMap<?,?> result2 = r.withType(new TypeReference<EnumMap<Key,String>>() { })
+                .readValue(JSON);
+        assertNull(result2);
+    }
+
     /*
     /**********************************************************
     /* Test methods, maps with enums
@@ -468,7 +484,7 @@
      * Simple test to ensure that @JsonDeserialize.using is
      * recognized
      */
-    public void testMapWithDeserializer() throws IOException
+    public void testMapWithDeserializer() throws Exception
     {
         CustomMap result = MAPPER.readValue(quote("xyz"), CustomMap.class);
         assertEquals(1, result.size());
@@ -477,6 +493,47 @@
 
     /*
     /**********************************************************
+    /* Test methods, annotated Map.Entry
+    /**********************************************************
+     */
+
+    public void testMapEntrySimpleTypes() throws Exception
+    {
+        List<Map.Entry<String,Long>> stuff = MAPPER.readValue(aposToQuotes("[{'a':15},{'b':42}]"),
+                new TypeReference<List<Map.Entry<String,Long>>>() { });
+        assertNotNull(stuff);
+        assertEquals(2, stuff.size());
+        assertNotNull(stuff.get(1));
+        assertEquals("b", stuff.get(1).getKey());
+        assertEquals(Long.valueOf(42), stuff.get(1).getValue());
+    }
+
+    public void testMapEntryWithStringBean() throws Exception
+    {
+        List<Map.Entry<Integer,StringWrapper>> stuff = MAPPER.readValue(aposToQuotes("[{'28':'Foo'},{'13':'Bar'}]"),
+                new TypeReference<List<Map.Entry<Integer,StringWrapper>>>() { });
+        assertNotNull(stuff);
+        assertEquals(2, stuff.size());
+        assertNotNull(stuff.get(1));
+        assertEquals(Integer.valueOf(13), stuff.get(1).getKey());
+        
+        StringWrapper sw = stuff.get(1).getValue();
+        assertEquals("Bar", sw.str);
+    }
+
+    public void testMapEntryFail() throws Exception
+    {
+        try {
+            /*List<Map.Entry<Integer,StringWrapper>> stuff =*/ MAPPER.readValue(aposToQuotes("[{'28':'Foo','13':'Bar'}]"),
+                    new TypeReference<List<Map.Entry<Integer,StringWrapper>>>() { });
+            fail("Should not have passed");
+        } catch (Exception e) {
+            verifyException(e, "more than one entry in JSON");
+        }
+    }
+    
+    /*
+    /**********************************************************
     /* Error tests
     /**********************************************************
      */
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 706a1bc..4a69cc5 100644
--- a/src/test/java/com/fasterxml/jackson/databind/deser/TestValueAnnotations.java
+++ b/src/test/java/com/fasterxml/jackson/databind/deser/TestValueAnnotations.java
@@ -7,7 +7,6 @@
 import com.fasterxml.jackson.databind.*;
 import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
 import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
-import com.fasterxml.jackson.test.BaseTest;
 
 /**
  * This unit test suite tests use of "value" Annotations;
@@ -15,7 +14,7 @@
  * deserialization.
  */
 public class TestValueAnnotations
-    extends BaseTest
+    extends BaseMapTest
 {
     /*
     /**********************************************************
diff --git a/src/test/java/com/fasterxml/jackson/databind/filter/TestMapFiltering.java b/src/test/java/com/fasterxml/jackson/databind/filter/TestMapFiltering.java
index 3f87cb7..f966a72 100644
--- a/src/test/java/com/fasterxml/jackson/databind/filter/TestMapFiltering.java
+++ b/src/test/java/com/fasterxml/jackson/databind/filter/TestMapFiltering.java
@@ -1,21 +1,38 @@
 package com.fasterxml.jackson.databind.filter;
 
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
 import java.util.*;
 
 import com.fasterxml.jackson.annotation.JsonFilter;
+import com.fasterxml.jackson.core.JsonGenerator;
 import com.fasterxml.jackson.databind.*;
+import com.fasterxml.jackson.databind.jsonFormatVisitors.JsonObjectFormatVisitor;
+import com.fasterxml.jackson.databind.node.ObjectNode;
 import com.fasterxml.jackson.databind.ser.FilterProvider;
+import com.fasterxml.jackson.databind.ser.PropertyFilter;
+import com.fasterxml.jackson.databind.ser.PropertyWriter;
 import com.fasterxml.jackson.databind.ser.impl.SimpleBeanPropertyFilter;
 import com.fasterxml.jackson.databind.ser.impl.SimpleFilterProvider;
 
 public class TestMapFiltering extends BaseMapTest
 {
+    @Target({ElementType.FIELD})
+    @Retention(RetentionPolicy.RUNTIME)
+    public @interface CustomOffset
+    {
+        public int value();
+    }
+
     @SuppressWarnings("serial")
     @JsonFilter("filterForMaps")
     static class FilteredBean extends LinkedHashMap<String,Integer> { }
     
     static class MapBean {
         @JsonFilter("filterX")
+        @CustomOffset(1)
         public Map<String,Integer> values;
         
         public MapBean() {
@@ -25,7 +42,46 @@
             values.put("c", 9);
         }
     }
-    
+
+    static class MyMapFilter implements PropertyFilter
+    {
+        @Override
+        public void serializeAsField(Object value, JsonGenerator jgen,
+                SerializerProvider provider, PropertyWriter writer)
+            throws Exception
+        {
+            String name = writer.getName();
+            if (!"a".equals(name)) {
+                return;
+            }
+            CustomOffset n = writer.findAnnotation(CustomOffset.class);
+            int offset = (n == null) ? 0 : n.value();
+            Integer I = offset + ((Integer) value).intValue();
+
+            writer.serializeAsField(I, jgen, provider);
+        }
+
+        @Override
+        public void serializeAsElement(Object elementValue, JsonGenerator jgen,
+                SerializerProvider prov, PropertyWriter writer)
+                throws Exception {
+            // not needed for testing
+        }
+
+        @Override
+        public void depositSchemaProperty(PropertyWriter writer,
+                ObjectNode propertiesNode, SerializerProvider provider)
+                throws JsonMappingException {
+            
+        }
+
+        @Override
+        public void depositSchemaProperty(PropertyWriter writer,
+                JsonObjectFormatVisitor objectVisitor,
+                SerializerProvider provider) throws JsonMappingException {
+        }
+    }
+
     /*
     /**********************************************************
     /* Unit tests
@@ -53,4 +109,13 @@
         assertEquals(aposToQuotes("{'b':3}"), json);
     }
     
+    // [Issue#522]
+    public void testMapFilteringWithAnnotations() throws Exception
+    {
+        FilterProvider prov = new SimpleFilterProvider().addFilter("filterX",
+                new MyMapFilter());
+        String json = MAPPER.writer(prov).writeValueAsString(new MapBean());
+        // a=1 should become a=2
+        assertEquals(aposToQuotes("{'values':{'a':2}}"), json);
+    }
 }
diff --git a/src/test/java/com/fasterxml/jackson/databind/interop/TestCglibUsage.java b/src/test/java/com/fasterxml/jackson/databind/interop/TestCglibUsage.java
index f890325..3a0620b 100644
--- a/src/test/java/com/fasterxml/jackson/databind/interop/TestCglibUsage.java
+++ b/src/test/java/com/fasterxml/jackson/databind/interop/TestCglibUsage.java
@@ -1,7 +1,5 @@
 package com.fasterxml.jackson.databind.interop;
 
-
-import java.io.*;
 import java.lang.reflect.Method;
 import java.util.*;
 
@@ -10,20 +8,12 @@
 import net.sf.cglib.proxy.MethodProxy;
 
 import com.fasterxml.jackson.databind.*;
-import com.fasterxml.jackson.test.BaseTest;
 
 /**
  * Unit test for checking that we can serialize CGLib generated proxies.
  */
-public class TestCglibUsage
-    extends BaseTest
+public class TestCglibUsage extends BaseMapTest
 {
-    /*
-    /**********************************************************
-    /* Helper classes
-    /**********************************************************
-     */
-
     interface BeanInterface {
         public int getX();
     }
@@ -56,20 +46,5 @@
         assertEquals(1, result.size());
         assertEquals(Integer.valueOf(13), result.get("x"));
     }
-
-    /*
-    /**********************************************************
-    /* Helper methods
-    /**********************************************************
-     */
-
-    @SuppressWarnings("unchecked")
-	private Map<String,Object> writeAndMap(ObjectMapper m, Object value)
-        throws IOException
-    {
-        StringWriter sw = new StringWriter();
-        m.writeValue(sw, value);
-        return (Map<String,Object>) m.readValue(sw.toString(), Object.class);
-    }
 }
 
diff --git a/src/test/java/com/fasterxml/jackson/databind/interop/TestHibernate.java b/src/test/java/com/fasterxml/jackson/databind/interop/TestHibernate.java
index 67bdbdb..48dc573 100644
--- a/src/test/java/com/fasterxml/jackson/databind/interop/TestHibernate.java
+++ b/src/test/java/com/fasterxml/jackson/databind/interop/TestHibernate.java
@@ -1,7 +1,5 @@
 package com.fasterxml.jackson.databind.interop;
 
-
-import java.io.*;
 import java.lang.reflect.Method;
 import java.util.*;
 
@@ -10,20 +8,13 @@
 import org.hibernate.repackage.cglib.proxy.MethodProxy;
 
 import com.fasterxml.jackson.databind.*;
-import com.fasterxml.jackson.test.BaseTest;
 
 /**
  * Basic tests covering Hibernate-compatibility features.
  */
 public class TestHibernate
-    extends BaseTest
+    extends BaseMapTest
 {
-    /*
-    /**********************************************************
-    /* Helper classes
-    /**********************************************************
-     */
-
     interface BeanInterfaceHib {
         public int getX();
     }
@@ -66,20 +57,5 @@
         assertEquals(1, result.size());
         assertEquals(Integer.valueOf(13), result.get("x"));
     }
-
-    /*
-    /**********************************************************
-    /* Helper methods
-    /**********************************************************
-     */
-
-    @SuppressWarnings("unchecked")
-    private Map<String,Object> writeAndMap(ObjectMapper m, Object value)
-        throws IOException
-    {
-        StringWriter sw = new StringWriter();
-        m.writeValue(sw, value);
-        return (Map<String,Object>) m.readValue(sw.toString(), Object.class);
-    }
 }
 
diff --git a/src/test/java/com/fasterxml/jackson/databind/introspect/TestAnnotionBundles.java b/src/test/java/com/fasterxml/jackson/databind/introspect/TestAnnotionBundles.java
index ddb7736..804afa8 100644
--- a/src/test/java/com/fasterxml/jackson/databind/introspect/TestAnnotionBundles.java
+++ b/src/test/java/com/fasterxml/jackson/databind/introspect/TestAnnotionBundles.java
@@ -3,9 +3,13 @@
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 
-import com.fasterxml.jackson.annotation.*;
+import com.fasterxml.jackson.annotation.JacksonAnnotationsInside;
+import com.fasterxml.jackson.annotation.JsonAutoDetect;
 import com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility;
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.fasterxml.jackson.annotation.JsonProperty;
 import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.PropertyName;
 
 /* Tests mostly for [JACKSON-754]: ability to create "annotation bundles"
  */
@@ -51,7 +55,47 @@
     public class Bean92 {
         @Bundle92
         protected String id = "abc";
-    }    
+    }
+
+    @HolderB
+    @JacksonAnnotationsInside
+    @Retention(RetentionPolicy.RUNTIME)
+    static @interface HolderA {}
+
+    @HolderA
+    @JacksonAnnotationsInside
+    @Retention(RetentionPolicy.RUNTIME)
+    static @interface HolderB {}
+
+    static class RecursiveHolder {
+        @HolderA public int unimportant = 42;
+    }
+
+    @JsonProperty
+    @JacksonAnnotationsInside
+    @Retention(RetentionPolicy.RUNTIME)
+    static @interface InformativeHolder {
+        // doesn't really contribute to the test, but would be impossible without this feature
+        boolean important() default true;
+    }
+
+    static class InformingHolder {
+        @InformativeHolder public int unimportant = 42;
+    }
+
+    @SuppressWarnings("serial")
+    static class BundleAnnotationIntrospector extends JacksonAnnotationIntrospector {
+        @Override
+        public PropertyName findNameForSerialization(Annotated a)
+        {
+            InformativeHolder informativeHolder = a.getAnnotation(InformativeHolder.class);
+            if ((informativeHolder != null) && informativeHolder.important()) {
+                return new PropertyName("important");
+            }
+            return super.findNameForSerialization(a);
+        }
+    }
+
     /*
     /**********************************************************
     /* Test methods
@@ -59,7 +103,18 @@
      */
 
     private final ObjectMapper MAPPER = new ObjectMapper();
-    
+
+    public void testKeepAnnotationBundle() throws Exception
+    {
+        MAPPER.setAnnotationIntrospector(new BundleAnnotationIntrospector());
+        assertEquals("{\"important\":42}", MAPPER.writeValueAsString(new InformingHolder()));
+    }
+
+    public void testRecursiveBundles() throws Exception
+    {
+        assertEquals("{\"unimportant\":42}", MAPPER.writeValueAsString(new RecursiveHolder()));
+    }
+
     public void testBundledIgnore() throws Exception
     {
         assertEquals("{\"foobar\":13}", MAPPER.writeValueAsString(new Bean()));
diff --git a/src/test/java/com/fasterxml/jackson/databind/deser/TestAutoDetect.java b/src/test/java/com/fasterxml/jackson/databind/introspect/TestAutoDetect.java
similarity index 87%
rename from src/test/java/com/fasterxml/jackson/databind/deser/TestAutoDetect.java
rename to src/test/java/com/fasterxml/jackson/databind/introspect/TestAutoDetect.java
index 32c3ed1..b291be5 100644
--- a/src/test/java/com/fasterxml/jackson/databind/deser/TestAutoDetect.java
+++ b/src/test/java/com/fasterxml/jackson/databind/introspect/TestAutoDetect.java
@@ -1,4 +1,4 @@
-package com.fasterxml.jackson.databind.deser;
+package com.fasterxml.jackson.databind.introspect;
 
 import com.fasterxml.jackson.annotation.*;
 
@@ -9,12 +9,6 @@
 public class TestAutoDetect
     extends BaseMapTest
 {
-    /*
-    /********************************************************
-    /* Helper beans
-    /********************************************************
-     */
-
     static class PrivateBean {
         String a;
 
diff --git a/src/test/java/com/fasterxml/jackson/databind/introspect/TestBuilderMethods.java b/src/test/java/com/fasterxml/jackson/databind/introspect/TestBuilderMethods.java
index 946aeb3..390f5f3 100644
--- a/src/test/java/com/fasterxml/jackson/databind/introspect/TestBuilderMethods.java
+++ b/src/test/java/com/fasterxml/jackson/databind/introspect/TestBuilderMethods.java
@@ -13,9 +13,8 @@
     {
         public int x;
 
-        @SuppressWarnings("hiding")
-        public SimpleBuilder withX(int x) {
-    		    this.x = x;
+        public SimpleBuilder withX(int x0) {
+    		    this.x = x0;
     		    return this;
         }
     }
diff --git a/src/test/java/com/fasterxml/jackson/databind/introspect/TestMixinMerging.java b/src/test/java/com/fasterxml/jackson/databind/introspect/TestMixinMerging.java
index a17e2c1..2595500 100644
--- a/src/test/java/com/fasterxml/jackson/databind/introspect/TestMixinMerging.java
+++ b/src/test/java/com/fasterxml/jackson/databind/introspect/TestMixinMerging.java
@@ -12,10 +12,12 @@
     }
 
     static class ContactImpl implements Contact {
+        @Override
         public String getCity() { return "Seattle"; }
     }
 
     static class ContactMixin implements Contact {
+        @Override
         @JsonProperty
         public String getCity() { return null; }
     }
diff --git a/src/test/java/com/fasterxml/jackson/databind/introspect/TestNameConflicts.java b/src/test/java/com/fasterxml/jackson/databind/introspect/TestNameConflicts.java
index d4fa78e..d14dae7 100644
--- a/src/test/java/com/fasterxml/jackson/databind/introspect/TestNameConflicts.java
+++ b/src/test/java/com/fasterxml/jackson/databind/introspect/TestNameConflicts.java
@@ -5,6 +5,26 @@
 
 public class TestNameConflicts extends BaseMapTest
 {
+    @JsonAutoDetect
+    (fieldVisibility= JsonAutoDetect.Visibility.NONE,getterVisibility= JsonAutoDetect.Visibility.NONE, setterVisibility= JsonAutoDetect.Visibility.NONE, isGetterVisibility= JsonAutoDetect.Visibility.NONE)
+    static class CoreBean158 {
+        private String bar = "x";
+
+        @JsonProperty
+        public String getBar() {
+            return bar;
+        }
+
+        @JsonProperty
+        public void setBar(String bar) {
+            this.bar = bar;
+        }
+
+        public void setBar(java.io.Serializable bar) {
+            this.bar = bar.toString();
+        }
+    }
+    
     static class Bean193
     {
         @JsonProperty("val1")
@@ -64,6 +84,8 @@
     /**********************************************************
      */
 
+    private final ObjectMapper MAPPER = objectMapper();
+    
     // [Issue#193]
     public void testIssue193() throws Exception
     {
@@ -74,7 +96,7 @@
     // [Issue#327]
     public void testNonConflict() throws Exception
     {
-        String json = objectMapper().writeValueAsString(new BogusConflictBean());
+        String json = MAPPER.writeValueAsString(new BogusConflictBean());
         assertEquals(aposToQuotes("{'prop1':2,'prop2':1}"), json);
     }    
 
@@ -83,4 +105,22 @@
         String json = objectWriter().writeValueAsString(new MultipleTheoreticalGetters());
         assertEquals(aposToQuotes("{'a':3}"), json);
     }
+
+    // for [jackson-core#158]
+    public void testOverrideName() throws Exception
+    {
+        final ObjectMapper mapper = objectMapper();
+        String json = mapper.writeValueAsString(new CoreBean158());
+        assertEquals(aposToQuotes("{'bar':'x'}"), json);
+
+        // and back
+        CoreBean158 result = null;
+        try {
+            result = mapper.readValue(aposToQuotes("{'bar':'y'}"), CoreBean158.class);
+        } catch (Exception e) {
+            fail("Unexpected failure when reading CoreBean158: "+e);
+        }
+        assertNotNull(result);
+        assertEquals("y", result.bar);
+    }    
 }
diff --git a/src/test/java/com/fasterxml/jackson/databind/introspect/TestPropertyConflicts.java b/src/test/java/com/fasterxml/jackson/databind/introspect/TestPropertyConflicts.java
index d8cec1d..16942b8 100644
--- a/src/test/java/com/fasterxml/jackson/databind/introspect/TestPropertyConflicts.java
+++ b/src/test/java/com/fasterxml/jackson/databind/introspect/TestPropertyConflicts.java
@@ -22,6 +22,7 @@
     // [Issue#238]
     protected static class Getters1A
     {
+        @JsonProperty
         protected int value = 3;
         
         public int getValue() { return value+1; }
@@ -34,6 +35,7 @@
     {
         public boolean isValue() { return false; }
 
+        @JsonProperty
         protected int value = 3;
         
         public int getValue() { return value+1; }
diff --git a/src/test/java/com/fasterxml/jackson/databind/jsontype/TestDefaultForObject.java b/src/test/java/com/fasterxml/jackson/databind/jsontype/TestDefaultForObject.java
index 80224ae..71d5d4e 100644
--- a/src/test/java/com/fasterxml/jackson/databind/jsontype/TestDefaultForObject.java
+++ b/src/test/java/com/fasterxml/jackson/databind/jsontype/TestDefaultForObject.java
@@ -32,14 +32,14 @@
      * Another enum type, but this time forcing sub-classing
      */
     enum ComplexChoice {
-    	MAYBE(true), PROBABLY_NOT(false);
+        MAYBE(true), PROBABLY_NOT(false);
 
-    	private boolean state;
+        private boolean state;
     	
-    	private ComplexChoice(boolean b) { state = b; }
+        private ComplexChoice(boolean b) { state = b; }
     	
         @Override
-    	public String toString() { return String.valueOf(state); }
+        public String toString() { return String.valueOf(state); }
     }
 
     // [JACKSON-311]
@@ -113,6 +113,22 @@
         assertEquals("abc", ((StringBean) result[0]).name);
     }
 
+    // with 2.5, another test to check that "as-property" is valid option
+    public void testBeanAsObjectUsingAsProperty() throws Exception
+    {
+        ObjectMapper m = new ObjectMapper();
+        m.enableDefaultTypingAsProperty(ObjectMapper.DefaultTyping.NON_FINAL,
+                ".hype");
+        // note: need to wrap, to get declared as Object
+        String json = m.writeValueAsString(new StringBean("abc"));
+        
+        // Ok: serialization seems to work as expected. Now deserialize:
+        Object result = m.readValue(json, Object.class);
+        assertNotNull(result);
+        assertEquals(StringBean.class, result.getClass());
+        assertEquals("abc", ((StringBean) result).name);
+    }
+    
     /**
      * Unit test that verifies that an abstract bean is stored with type information
      * if default type information is enabled for non-concrete types.
@@ -331,6 +347,18 @@
         String json = mapper.writeValueAsString(new BeanHolder(new StringBean("punny")));
         assertEquals("{\"bean\":{\"*CLASS*\":\"com.fasterxml.jackson.databind.jsontype.TestDefaultForObject$StringBean\",\"name\":\"punny\"}}", json);
     }
+
+    public void testNoGoWithExternalProperty() throws Exception
+    {
+        ObjectMapper mapper = new ObjectMapper();
+        try {
+            mapper.enableDefaultTyping(ObjectMapper.DefaultTyping.JAVA_LANG_OBJECT,
+                    JsonTypeInfo.As.EXTERNAL_PROPERTY);
+            fail("Should not have passed");
+        } catch (IllegalArgumentException e) {
+            verifyException(e, "Can not use includeAs of EXTERNAL_PROPERTY");
+        }
+    }
     
     /*
     /**********************************************************
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 365b466..a2d9f32 100644
--- a/src/test/java/com/fasterxml/jackson/databind/jsontype/TestGenericListSerialization.java
+++ b/src/test/java/com/fasterxml/jackson/databind/jsontype/TestGenericListSerialization.java
@@ -5,7 +5,6 @@
 
 import com.fasterxml.jackson.annotation.*;
 
-import com.fasterxml.jackson.core.Version;
 import com.fasterxml.jackson.core.type.TypeReference;
 
 import com.fasterxml.jackson.databind.*;
@@ -50,14 +49,6 @@
     public void testSubTypesFor356() throws Exception
     {
         ObjectMapper mapper = new ObjectMapper();
-        /* 06-Sep-2010, tatus: This was not fixed for 1.6; and to keep junit test
-         *   suite green, let's not run it for versions prior to 1.7...
-         */
-        Version v = mapper.version();
-        if (v.getMajorVersion() == 1 && v.getMinorVersion() == 6) {
-            System.err.println("Note: skipping test for Jackson 1.6");
-            return;
-        }
         
         JSONResponse<List<Parent>> input = new JSONResponse<List<Parent>>();
 
@@ -69,9 +60,6 @@
 
         JavaType rootType = TypeFactory.defaultInstance().constructType(new TypeReference<JSONResponse<List<Parent>>>() { });
         byte[] json = mapper.writerWithType(rootType).writeValueAsBytes(input);
-//        byte[] json = mapper.writeValueAsBytes(input);
-
-//        System.out.println("After Serialization: " + new String(json));
         
         JSONResponse<List<Parent>> out = mapper.readValue(json, 0, json.length, rootType);
 
diff --git a/src/test/java/com/fasterxml/jackson/databind/jsontype/TestSubtypesExistingProperty.java b/src/test/java/com/fasterxml/jackson/databind/jsontype/TestSubtypesExistingProperty.java
new file mode 100644
index 0000000..0bb7275
--- /dev/null
+++ b/src/test/java/com/fasterxml/jackson/databind/jsontype/TestSubtypesExistingProperty.java
@@ -0,0 +1,403 @@
+package com.fasterxml.jackson.databind.jsontype;
+
+import java.util.*;
+
+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.core.type.TypeReference;
+
+import com.fasterxml.jackson.databind.BaseMapTest;
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+public class TestSubtypesExistingProperty extends BaseMapTest {
+
+    /**
+     * Polymorphic base class - existing property as simple property on subclasses
+     */
+	@JsonTypeInfo(use = Id.NAME, include = As.EXISTING_PROPERTY, property = "type",
+	        visible=true)
+	@JsonSubTypes({
+		@Type(value = Apple.class, name = "apple") ,
+		@Type(value = Orange.class, name = "orange") 
+		})
+	static abstract class Fruit {
+        public String name;
+        protected Fruit(String n)  { name = n; }
+    }
+
+    @JsonTypeName("apple")
+    static class Apple extends Fruit
+    {
+        public int seedCount;
+        public String type;
+
+        private Apple() { super(null);; }
+        public Apple(String name, int b) {
+            super(name);
+            seedCount = b;
+            type = "apple";
+        }
+    }
+    
+    @JsonTypeName("orange")
+    static class Orange extends Fruit
+    {
+        public String color;
+        public String type;
+        
+        private Orange() { super(null); }
+        public Orange(String name, String c) {
+            super(name);
+            color = c;
+            type = "orange";
+        }
+    }
+
+    static class FruitWrapper {
+        public Fruit fruit;
+        public FruitWrapper() {}
+        public FruitWrapper(Fruit f) { fruit = f; }
+    }
+    
+    /**
+     * Polymorphic base class - existing property forced by abstract method
+     */
+	@JsonTypeInfo(use = Id.NAME, include = As.EXISTING_PROPERTY, property = "type")
+	@JsonSubTypes({
+		@Type(value = Dog.class, name = "doggie") ,
+		@Type(value = Cat.class, name = "kitty") 
+		})
+	static abstract class Animal {
+        public String name;
+        
+        protected Animal(String n)  { name = n; }
+        
+        public abstract String getType();
+    }
+
+    @JsonTypeName("doggie")
+    static class Dog extends Animal
+    {
+        public int boneCount;
+        
+        private Dog() { super(null); }
+        public Dog(String name, int b) {
+            super(name);
+            boneCount = b;
+        }
+        
+ 		@Override
+		public String getType() {
+        	return "doggie";
+        }        
+    }
+    
+    @JsonTypeName("kitty")
+    static class Cat extends Animal
+    {
+        public String furColor;
+        
+        private Cat() { super(null); }
+        public Cat(String name, String c) {
+            super(name);
+            furColor = c;
+        }
+        
+		@Override
+		public String getType() {
+        	return "kitty";
+        }        
+    }
+
+    static class AnimalWrapper {
+        public Animal animal;
+        public AnimalWrapper() {}
+        public AnimalWrapper(Animal a) { animal = a; }
+    }
+
+
+    /**
+     * Polymorphic base class - existing property NOT forced by abstract method on base class
+     */
+	@JsonTypeInfo(use = Id.NAME, include = As.EXISTING_PROPERTY, property = "type")
+	@JsonSubTypes({
+		@Type(value = Accord.class, name = "accord") ,
+		@Type(value = Camry.class, name = "camry") 
+		})
+	static abstract class Car {
+        public String name;        
+        protected Car(String n)  { name = n; }
+    }
+
+    @JsonTypeName("accord")
+    static class Accord extends Car
+    {
+        public int speakerCount;
+        
+        private Accord() { super(null); }
+        public Accord(String name, int b) {
+            super(name);
+            speakerCount = b;
+        }
+        
+		public String getType() {
+        	return "accord";
+        }        
+    }
+    
+    @JsonTypeName("camry")
+    static class Camry extends Car
+    {
+        public String exteriorColor;
+        
+        private Camry() { super(null); }
+        public Camry(String name, String c) {
+            super(name);
+            exteriorColor = c;
+        }
+        
+		public String getType() {
+        	return "camry";
+        }        
+    }
+
+    static class CarWrapper {
+        public Car car;
+        public CarWrapper() {}
+        public CarWrapper(Car c) { car = c; }
+    }
+    
+    private final ObjectMapper MAPPER = new ObjectMapper();
+
+    /*
+    /**********************************************************
+    /* Mock data
+    /**********************************************************
+     */
+
+	private static final Orange mandarin = new Orange("Mandarin Orange", "orange");
+	private static final String mandarinJson = "{\"name\":\"Mandarin Orange\",\"color\":\"orange\",\"type\":\"orange\"}";	
+	private static final Apple pinguo = new Apple("Apple-A-Day", 16);
+	private static final String pinguoJson = "{\"name\":\"Apple-A-Day\",\"seedCount\":16,\"type\":\"apple\"}";
+	private static final FruitWrapper pinguoWrapper = new FruitWrapper(pinguo);
+	private static final String pinguoWrapperJson = "{\"fruit\":" + pinguoJson + "}";
+	private static final List<Fruit> fruitList = Arrays.asList(pinguo, mandarin);
+	private static final String fruitListJson = "[" + pinguoJson + "," + mandarinJson + "]";
+
+	private static final Cat beelzebub = new Cat("Beelzebub", "tabby");
+	private static final String beelzebubJson = "{\"name\":\"Beelzebub\",\"furColor\":\"tabby\",\"type\":\"kitty\"}";	
+	private static final Dog rover = new Dog("Rover", 42);
+	private static final String roverJson = "{\"name\":\"Rover\",\"boneCount\":42,\"type\":\"doggie\"}";
+	private static final AnimalWrapper beelzebubWrapper = new AnimalWrapper(beelzebub);
+	private static final String beelzebubWrapperJson = "{\"animal\":" + beelzebubJson + "}";
+	private static final List<Animal> animalList = Arrays.asList(beelzebub, rover);
+	private static final String animalListJson = "[" + beelzebubJson + "," + roverJson + "]";
+
+	private static final Camry camry = new Camry("Sweet Ride", "candy-apple-red");
+	private static final String camryJson = "{\"name\":\"Sweet Ride\",\"exteriorColor\":\"candy-apple-red\",\"type\":\"camry\"}";	
+	private static final Accord accord = new Accord("Road Rage", 6);
+	private static final String accordJson = "{\"name\":\"Road Rage\",\"speakerCount\":6,\"type\":\"accord\"}";
+	private static final CarWrapper camryWrapper = new CarWrapper(camry);
+	private static final String camryWrapperJson = "{\"car\":" + camryJson + "}";
+	private static final List<Car> carList = Arrays.asList(camry, accord);
+	private static final String carListJson = "[" + camryJson + "," + accordJson + "]";
+
+    /*
+    /**********************************************************
+    /* Unit tests
+    /**********************************************************
+     */
+
+    /**
+     * Fruits - serialization tests for simple property on sub-classes
+     */
+    public void testExistingPropertySerializationFruits() throws Exception
+    {
+        Map<String,Object> result = writeAndMap(MAPPER, pinguo);
+        assertEquals(3, result.size());
+        assertEquals(pinguo.name, result.get("name"));
+        assertEquals(pinguo.seedCount, result.get("seedCount"));
+        assertEquals(pinguo.type, result.get("type"));
+        
+        result = writeAndMap(MAPPER, mandarin);
+        assertEquals(3, result.size());
+        assertEquals(mandarin.name, result.get("name"));
+        assertEquals(mandarin.color, result.get("color"));
+        assertEquals(mandarin.type, result.get("type"));
+        
+        String pinguoSerialized = MAPPER.writeValueAsString(pinguo);
+        assertEquals(pinguoSerialized, pinguoJson);
+
+        String mandarinSerialized = MAPPER.writeValueAsString(mandarin);
+        assertEquals(mandarinSerialized, mandarinJson);
+
+        String fruitWrapperSerialized = MAPPER.writeValueAsString(pinguoWrapper);
+        assertEquals(fruitWrapperSerialized, pinguoWrapperJson);
+
+        String fruitListSerialized = MAPPER.writeValueAsString(fruitList);
+        assertEquals(fruitListSerialized, fruitListJson);
+    }
+
+    /**
+     * Fruits - deserialization tests for simple property on sub-classes
+     */
+    public void testSimpleClassAsExistingPropertyDeserializationFruits() throws Exception
+    {
+        Fruit pinguoDeserialized = MAPPER.readValue(pinguoJson, Fruit.class);
+        assertTrue(pinguoDeserialized instanceof Apple);
+        assertSame(pinguoDeserialized.getClass(), Apple.class);
+        assertEquals(pinguo.name, pinguoDeserialized.name);
+        assertEquals(pinguo.seedCount, ((Apple) pinguoDeserialized).seedCount);
+        assertEquals(pinguo.type, ((Apple) pinguoDeserialized).type);
+
+        FruitWrapper pinguoWrapperDeserialized = MAPPER.readValue(pinguoWrapperJson, FruitWrapper.class);
+        Fruit pinguoExtracted = pinguoWrapperDeserialized.fruit;
+        assertTrue(pinguoExtracted instanceof Apple);
+        assertSame(pinguoExtracted.getClass(), Apple.class);
+        assertEquals(pinguo.name, pinguoExtracted.name);
+        assertEquals(pinguo.seedCount, ((Apple) pinguoExtracted).seedCount);
+        assertEquals(pinguo.type, ((Apple) pinguoExtracted).type);
+
+        Fruit[] fruits = MAPPER.readValue(fruitListJson, Fruit[].class);
+        assertEquals(2, fruits.length);
+        assertEquals(Apple.class, fruits[0].getClass());
+        assertEquals("apple", ((Apple) fruits[0]).type);
+        assertEquals(Orange.class, fruits[1].getClass());
+        assertEquals("orange", ((Orange) fruits[1]).type);
+        
+        List<Fruit> f2 = MAPPER.readValue(fruitListJson,
+                new TypeReference<List<Fruit>>() { });
+        assertNotNull(f2);
+        assertTrue(f2.size() == 2);
+        assertEquals(Apple.class, f2.get(0).getClass());
+        assertEquals(Orange.class, f2.get(1).getClass());
+    }
+
+    /**
+     * Animals - serialization tests for abstract method in base class
+     */
+    public void testExistingPropertySerializationAnimals() throws Exception
+    {
+        Map<String,Object> result = writeAndMap(MAPPER, beelzebub);
+        assertEquals(3, result.size());
+        assertEquals(beelzebub.name, result.get("name"));
+        assertEquals(beelzebub.furColor, result.get("furColor"));
+        assertEquals(beelzebub.getType(), result.get("type"));
+
+        result = writeAndMap(MAPPER, rover);
+        assertEquals(3, result.size());
+        assertEquals(rover.name, result.get("name"));
+        assertEquals(rover.boneCount, result.get("boneCount"));
+        assertEquals(rover.getType(), result.get("type"));
+        
+        String beelzebubSerialized = MAPPER.writeValueAsString(beelzebub);
+        assertEquals(beelzebubSerialized, beelzebubJson);
+        
+        String roverSerialized = MAPPER.writeValueAsString(rover);
+        assertEquals(roverSerialized, roverJson);
+        
+        String animalWrapperSerialized = MAPPER.writeValueAsString(beelzebubWrapper);
+        assertEquals(animalWrapperSerialized, beelzebubWrapperJson);
+
+        String animalListSerialized = MAPPER.writeValueAsString(animalList);
+        assertEquals(animalListSerialized, animalListJson);
+    }
+
+    /**
+     * Animals - deserialization tests for abstract method in base class
+     */
+    public void testSimpleClassAsExistingPropertyDeserializationAnimals() throws Exception
+    {
+        Animal beelzebubDeserialized = MAPPER.readValue(beelzebubJson, Animal.class);
+        assertTrue(beelzebubDeserialized instanceof Cat);
+        assertSame(beelzebubDeserialized.getClass(), Cat.class);
+        assertEquals(beelzebub.name, beelzebubDeserialized.name);
+        assertEquals(beelzebub.furColor, ((Cat) beelzebubDeserialized).furColor);
+        assertEquals(beelzebub.getType(), beelzebubDeserialized.getType());
+
+        AnimalWrapper beelzebubWrapperDeserialized = MAPPER.readValue(beelzebubWrapperJson, AnimalWrapper.class);
+        Animal beelzebubExtracted = beelzebubWrapperDeserialized.animal;
+        assertTrue(beelzebubExtracted instanceof Cat);
+        assertSame(beelzebubExtracted.getClass(), Cat.class);
+        assertEquals(beelzebub.name, beelzebubExtracted.name);
+        assertEquals(beelzebub.furColor, ((Cat) beelzebubExtracted).furColor);
+        assertEquals(beelzebub.getType(), beelzebubExtracted.getType());
+    	
+        @SuppressWarnings("unchecked")
+        List<Animal> animalListDeserialized = MAPPER.readValue(animalListJson, List.class);
+        assertNotNull(animalListDeserialized);
+        assertTrue(animalListDeserialized.size() == 2);
+        Animal cat = MAPPER.convertValue(animalListDeserialized.get(0), Animal.class);
+        assertTrue(cat instanceof Cat);
+        assertSame(cat.getClass(), Cat.class);
+        Animal dog = MAPPER.convertValue(animalListDeserialized.get(1), Animal.class);
+        assertTrue(dog instanceof Dog);
+        assertSame(dog.getClass(), Dog.class);
+    }
+
+    /**
+     * Cars - serialization tests for no abstract method or type variable in base class
+     */
+    public void testExistingPropertySerializationCars() throws Exception
+    {
+        Map<String,Object> result = writeAndMap(MAPPER, camry);
+        assertEquals(3, result.size());
+        assertEquals(camry.name, result.get("name"));
+        assertEquals(camry.exteriorColor, result.get("exteriorColor"));
+        assertEquals(camry.getType(), result.get("type"));
+
+        result = writeAndMap(MAPPER, accord);
+        assertEquals(3, result.size());
+        assertEquals(accord.name, result.get("name"));
+        assertEquals(accord.speakerCount, result.get("speakerCount"));
+        assertEquals(accord.getType(), result.get("type"));
+        
+        String camrySerialized = MAPPER.writeValueAsString(camry);
+        assertEquals(camrySerialized, camryJson);
+        
+        String accordSerialized = MAPPER.writeValueAsString(accord);
+        assertEquals(accordSerialized, accordJson);
+        
+        String carWrapperSerialized = MAPPER.writeValueAsString(camryWrapper);
+        assertEquals(carWrapperSerialized, camryWrapperJson);
+
+        String carListSerialized = MAPPER.writeValueAsString(carList);
+        assertEquals(carListSerialized, carListJson);
+    }
+
+    /**
+     * Cars - deserialization tests for no abstract method or type variable in base class
+     */
+    public void testSimpleClassAsExistingPropertyDeserializationCars() throws Exception
+    {
+        Car camryDeserialized = MAPPER.readValue(camryJson, Camry.class);
+        assertTrue(camryDeserialized instanceof Camry);
+        assertSame(camryDeserialized.getClass(), Camry.class);
+        assertEquals(camry.name, camryDeserialized.name);
+        assertEquals(camry.exteriorColor, ((Camry) camryDeserialized).exteriorColor);
+        assertEquals(camry.getType(), ((Camry) camryDeserialized).getType());
+
+        CarWrapper camryWrapperDeserialized = MAPPER.readValue(camryWrapperJson, CarWrapper.class);
+        Car camryExtracted = camryWrapperDeserialized.car;
+        assertTrue(camryExtracted instanceof Camry);
+        assertSame(camryExtracted.getClass(), Camry.class);
+        assertEquals(camry.name, camryExtracted.name);
+        assertEquals(camry.exteriorColor, ((Camry) camryExtracted).exteriorColor);
+        assertEquals(camry.getType(), ((Camry) camryExtracted).getType());
+
+        @SuppressWarnings("unchecked")
+        List<Car> carListDeserialized = MAPPER.readValue(carListJson, List.class);
+        assertNotNull(carListDeserialized);
+        assertTrue(carListDeserialized.size() == 2);
+        Car result = MAPPER.convertValue(carListDeserialized.get(0), Car.class);
+        assertTrue(result instanceof Camry);
+        assertSame(result.getClass(), Camry.class);
+
+        result = MAPPER.convertValue(carListDeserialized.get(1), Car.class);
+        assertTrue(result instanceof Accord);
+        assertSame(result.getClass(), Accord.class);
+    }
+}    
diff --git a/src/test/java/com/fasterxml/jackson/databind/jsontype/TestTypedArrayDeserialization.java b/src/test/java/com/fasterxml/jackson/databind/jsontype/TestTypedArrayDeserialization.java
index f9812bb..dfd562e 100644
--- a/src/test/java/com/fasterxml/jackson/databind/jsontype/TestTypedArrayDeserialization.java
+++ b/src/test/java/com/fasterxml/jackson/databind/jsontype/TestTypedArrayDeserialization.java
@@ -104,7 +104,7 @@
     {
         ObjectMapper m = new ObjectMapper();
         // use class name, WRAPPER_OBJECT
-        m.addMixInAnnotations(long[].class, WrapperMixIn.class);
+        m.addMixIn(long[].class, WrapperMixIn.class);
         String JSON = "{\""+long[].class.getName()+"\":[5, 6, 7]}";
         long[] value = m.readValue(JSON, long[].class);
         assertNotNull(value);
diff --git a/src/test/java/com/fasterxml/jackson/databind/jsontype/TestTypedArraySerialization.java b/src/test/java/com/fasterxml/jackson/databind/jsontype/TestTypedArraySerialization.java
index aed0f81..a7ddf02 100644
--- a/src/test/java/com/fasterxml/jackson/databind/jsontype/TestTypedArraySerialization.java
+++ b/src/test/java/com/fasterxml/jackson/databind/jsontype/TestTypedArraySerialization.java
@@ -125,7 +125,7 @@
     public void testIntArray() throws Exception
     {
         ObjectMapper m = new ObjectMapper();
-        m.addMixInAnnotations(int[].class, WrapperMixIn.class);
+        m.addMixIn(int[].class, WrapperMixIn.class);
         int[] input = new int[] { 1, 2, 3 };
         String clsName = int[].class.getName();
         assertEquals("{\""+clsName+"\":[1,2,3]}", serializeAsString(m, input));
diff --git a/src/test/java/com/fasterxml/jackson/databind/jsontype/TestTypedContainerSerialization.java b/src/test/java/com/fasterxml/jackson/databind/jsontype/TestTypedContainerSerialization.java
index b2ee863..5c3cfc1 100644
--- a/src/test/java/com/fasterxml/jackson/databind/jsontype/TestTypedContainerSerialization.java
+++ b/src/test/java/com/fasterxml/jackson/databind/jsontype/TestTypedContainerSerialization.java
@@ -125,7 +125,7 @@
     {
             ArrayList<Animal> animals = new ArrayList<Animal>();
             animals.add(new Dog("Spot"));
-            JavaType rootType = TypeFactory.defaultInstance().constructParametricType(Iterator.class, Animal.class);
+            JavaType rootType = TypeFactory.defaultInstance().constructParametrizedType(Iterator.class, Iterator.class, Animal.class);
             String json = mapper.writerWithType(rootType).writeValueAsString(animals.iterator());
             if (json.indexOf("\"object-type\":\"doggy\"") < 0) {
                 fail("No polymorphic type retained, should be; JSON = '"+json+"'");
diff --git a/src/test/java/com/fasterxml/jackson/databind/jsontype/TestTypedDeserialization.java b/src/test/java/com/fasterxml/jackson/databind/jsontype/TestTypedDeserialization.java
index 4ba8381..c1ea52c 100644
--- a/src/test/java/com/fasterxml/jackson/databind/jsontype/TestTypedDeserialization.java
+++ b/src/test/java/com/fasterxml/jackson/databind/jsontype/TestTypedDeserialization.java
@@ -127,7 +127,7 @@
     public void testTypeAsWrapper() throws Exception
     {
         ObjectMapper m = new ObjectMapper();
-        m.addMixInAnnotations(Animal.class, TypeWithWrapper.class);
+        m.addMixIn(Animal.class, TypeWithWrapper.class);
         String JSON = "{\".TestTypedDeserialization$Dog\" : "
             +asJSONObjectValueString(m, "name", "Scooby", "boneCount", "6")+" }";
         Animal a = m.readValue(JSON, Animal.class);
@@ -142,7 +142,7 @@
     public void testTypeAsArray() throws Exception
     {
         ObjectMapper m = new ObjectMapper();
-        m.addMixInAnnotations(Animal.class, TypeWithArray.class);
+        m.addMixIn(Animal.class, TypeWithArray.class);
         // hmmh. Not good idea to rely on exact output, order may change. But...
         String JSON = "[\""+Dog.class.getName()+"\", "
             +asJSONObjectValueString(m, "name", "Martti", "boneCount", "11")+" ]";
diff --git a/src/test/java/com/fasterxml/jackson/databind/jsontype/TestTypedSerialization.java b/src/test/java/com/fasterxml/jackson/databind/jsontype/TestTypedSerialization.java
index cd857f9..e6c5256 100644
--- a/src/test/java/com/fasterxml/jackson/databind/jsontype/TestTypedSerialization.java
+++ b/src/test/java/com/fasterxml/jackson/databind/jsontype/TestTypedSerialization.java
@@ -102,7 +102,7 @@
     public void testTypeAsWrapper() throws Exception
     {
         ObjectMapper m = new ObjectMapper();
-        m.addMixInAnnotations(Animal.class, TypeWithWrapper.class);
+        m.addMixIn(Animal.class, TypeWithWrapper.class);
         Map<String,Object> result = writeAndMap(m, new Cat("Venla", "black"));
         // should get a wrapper; keyed by minimal class name ("Cat" here)
         assertEquals(1, result.size());
@@ -120,7 +120,7 @@
     public void testTypeAsArray() throws Exception
     {
         ObjectMapper m = new ObjectMapper();
-        m.addMixInAnnotations(Animal.class, TypeWithArray.class);
+        m.addMixIn(Animal.class, TypeWithArray.class);
         // hmmh. Not good idea to rely on exact output, order may change. But...
         Map<String,Object> result = writeAndMap(m, new AnimalWrapper(new Dog("Amadeus", 7)));
         // First level, wrapper
diff --git a/src/test/java/com/fasterxml/jackson/databind/jsontype/TestVisibleTypeId.java b/src/test/java/com/fasterxml/jackson/databind/jsontype/TestVisibleTypeId.java
index 644d187..3b9003e 100644
--- a/src/test/java/com/fasterxml/jackson/databind/jsontype/TestVisibleTypeId.java
+++ b/src/test/java/com/fasterxml/jackson/databind/jsontype/TestVisibleTypeId.java
@@ -1,10 +1,8 @@
 package com.fasterxml.jackson.databind.jsontype;
 
-import com.fasterxml.jackson.annotation.JsonPropertyOrder;
-import com.fasterxml.jackson.annotation.JsonSubTypes;
-import com.fasterxml.jackson.annotation.JsonTypeId;
-import com.fasterxml.jackson.annotation.JsonTypeInfo;
-import com.fasterxml.jackson.annotation.JsonTypeName;
+import com.fasterxml.jackson.annotation.*;
+import com.fasterxml.jackson.annotation.JsonTypeInfo.As;
+import com.fasterxml.jackson.annotation.JsonTypeInfo.Id;
 import com.fasterxml.jackson.databind.*;
 
 /**
@@ -48,13 +46,6 @@
         public void setType(String t) { type = t; }
     }
 
-    // as external id, bit trickier
-    static class ExternalIdWrapper {
-        @JsonTypeInfo(use=JsonTypeInfo.Id.NAME, include=JsonTypeInfo.As.EXTERNAL_PROPERTY,
-                property="type", visible=true)
-        public ExternalIdBean bean = new ExternalIdBean();
-    }
-    
     @JsonTypeName("ExternalType")
     static class ExternalIdBean {
         public int a = 2;
@@ -133,6 +124,32 @@
         
         public int age = 41;
     }
+
+    // [databind#408]
+    static class ExternalBeanWithId
+    {
+        protected String _type;
+        
+        @JsonTypeInfo(use=Id.NAME, include=As.EXTERNAL_PROPERTY, property="type", visible=true)
+        public ValueBean bean;
+
+        public ExternalBeanWithId() { }
+        public ExternalBeanWithId(int v) {
+            bean = new ValueBean(v);
+        }
+
+        public void setType(String t) {
+            _type = t;
+        }
+    }
+
+    @JsonTypeName("vbean")
+    static class ValueBean {
+        public int value;
+        
+        public ValueBean() { }
+        public ValueBean(int v) { value = v; }
+    }
     
     /*
     /**********************************************************
@@ -177,17 +194,6 @@
         assertEquals("ObjectType", result.type);
     }
 
-    public void testVisibleWithExternalId() throws Exception
-    {
-        String json = MAPPER.writeValueAsString(new ExternalIdWrapper());
-        // but then expect to read it back
-        ExternalIdWrapper result = MAPPER.readValue(json, ExternalIdWrapper.class);
-        assertEquals("ExternalType", result.bean.type);
-        assertEquals(2, result.bean.a);
-    }
-
-    // [JACKSON-762]
-
     public void testTypeIdFromProperty() throws Exception
     {
         assertEquals("{\"type\":\"SomeType\",\"a\":3}",
@@ -224,6 +230,21 @@
         assertTrue(result instanceof I263Impl);
         assertEquals(19, ((I263Impl) result).age);
     }
+
+    // [databind#408]
+    /* NOTE: Handling changed between 2.4 and 2.5; earlier, type id was 'injected'
+     *  inside POJO; but with 2.5 this was fixed so it would remain outside, similar
+     *  to how JSON structure is.
+     */
+    public void testVisibleTypeId408() throws Exception
+    {
+        String json = MAPPER.writeValueAsString(new ExternalBeanWithId(3));
+        ExternalBeanWithId result = MAPPER.readValue(json, ExternalBeanWithId.class);
+        assertNotNull(result);
+        assertNotNull(result.bean);
+        assertEquals(3, result.bean.value);
+        assertEquals("vbean", result._type);
+    }
     
     /*
     /**********************************************************
diff --git a/src/test/java/com/fasterxml/jackson/databind/jsontype/TestWithGenerics.java b/src/test/java/com/fasterxml/jackson/databind/jsontype/TestWithGenerics.java
index 4d82810..8c5aab9 100644
--- a/src/test/java/com/fasterxml/jackson/databind/jsontype/TestWithGenerics.java
+++ b/src/test/java/com/fasterxml/jackson/databind/jsontype/TestWithGenerics.java
@@ -157,7 +157,7 @@
     {
         Dog dog = new Dog("Fluffy", 3);
         ContainerWithGetter<Animal> c2 = new ContainerWithGetter<Animal>(dog);
-        String json = MAPPER.writerWithType(MAPPER.getTypeFactory().constructParametricType(ContainerWithGetter.class, Animal.class)).writeValueAsString(c2);
+        String json = MAPPER.writerWithType(MAPPER.getTypeFactory().constructParametrizedType(ContainerWithGetter.class, ContainerWithGetter.class, Animal.class)).writeValueAsString(c2);
         if (json.indexOf("\"object-type\":\"doggy\"") < 0) {
             fail("polymorphic type not kept, result == "+json+"; should contain 'object-type':'...'");
         }
diff --git a/src/test/java/com/fasterxml/jackson/databind/mixins/TestMixinDeserForClass.java b/src/test/java/com/fasterxml/jackson/databind/mixins/TestMixinDeserForClass.java
index 6bfedad..d36132f 100644
--- a/src/test/java/com/fasterxml/jackson/databind/mixins/TestMixinDeserForClass.java
+++ b/src/test/java/com/fasterxml/jackson/databind/mixins/TestMixinDeserForClass.java
@@ -52,7 +52,7 @@
          * use field
          */
         m = new ObjectMapper();
-        m.addMixInAnnotations(LeafClass.class, MixIn.class);
+        m.addMixIn(LeafClass.class, MixIn.class);
         result = m.readValue("{\"a\":\"value\"}", LeafClass.class);
         assertEquals("value", result.a);
     }
@@ -63,7 +63,7 @@
     public void testClassMixInsMidLevel() throws IOException
     {
         ObjectMapper m = new ObjectMapper();
-        m.addMixInAnnotations(BaseClass.class, MixIn.class);
+        m.addMixIn(BaseClass.class, MixIn.class);
         {
             BaseClass result = m.readValue("{\"a\":\"value\"}", BaseClass.class);
             assertEquals("value", result.a);
@@ -82,7 +82,7 @@
     public void testClassMixInsForObjectClass() throws IOException
     {
         ObjectMapper m = new ObjectMapper();
-        m.addMixInAnnotations(Object.class, MixIn.class);
+        m.addMixIn(Object.class, MixIn.class);
         // will be seen for BaseClass
         {
             BaseClass result = m.readValue("{\"a\":\"\"}", BaseClass.class);
diff --git a/src/test/java/com/fasterxml/jackson/databind/mixins/TestMixinDeserForCreators.java b/src/test/java/com/fasterxml/jackson/databind/mixins/TestMixinDeserForCreators.java
index df1eef5..5118711 100644
--- a/src/test/java/com/fasterxml/jackson/databind/mixins/TestMixinDeserForCreators.java
+++ b/src/test/java/com/fasterxml/jackson/databind/mixins/TestMixinDeserForCreators.java
@@ -86,7 +86,7 @@
     public void testForConstructor() throws IOException
     {
         ObjectMapper m = new ObjectMapper();
-        m.addMixInAnnotations(BaseClassWithPrivateCtor.class, MixInForPrivate.class);
+        m.addMixIn(BaseClassWithPrivateCtor.class, MixInForPrivate.class);
         BaseClassWithPrivateCtor result = m.readValue("\"?\"", BaseClassWithPrivateCtor.class);
         assertEquals("?...", result._a);
     }
@@ -102,7 +102,7 @@
 
         // Then with simple mix-in: should change to use the factory method
         m = new ObjectMapper();
-        m.addMixInAnnotations(BaseClass.class, MixIn.class);
+        m.addMixIn(BaseClass.class, MixIn.class);
         result = m.readValue("\"string\"", BaseClass.class);
         assertEquals("stringX", result._a);
     }
@@ -110,7 +110,7 @@
     public void testFactoryMixIn() throws IOException
     {
         ObjectMapper m = new ObjectMapper();
-        m.addMixInAnnotations(StringWrapper.class, StringWrapperMixIn.class);
+        m.addMixIn(StringWrapper.class, StringWrapperMixIn.class);
         StringWrapper result = m.readValue("\"a\"", StringWrapper.class);
         assertEquals("a", result._value);
     }
diff --git a/src/test/java/com/fasterxml/jackson/databind/mixins/TestMixinDeserForMethods.java b/src/test/java/com/fasterxml/jackson/databind/mixins/TestMixinDeserForMethods.java
index 2fcd1d0..0014fea 100644
--- a/src/test/java/com/fasterxml/jackson/databind/mixins/TestMixinDeserForMethods.java
+++ b/src/test/java/com/fasterxml/jackson/databind/mixins/TestMixinDeserForMethods.java
@@ -45,7 +45,7 @@
     public void testWithAnySetter() throws IOException
     {
         ObjectMapper m = new ObjectMapper();
-        m.addMixInAnnotations(BaseClass.class, MixIn.class);
+        m.addMixIn(BaseClass.class, MixIn.class);
         BaseClass result = m.readValue("{ \"a\" : 3, \"b\" : true }", BaseClass.class);
         assertNotNull(result);
         assertEquals(2, result.values.size());
diff --git a/src/test/java/com/fasterxml/jackson/databind/mixins/TestMixinInheritance.java b/src/test/java/com/fasterxml/jackson/databind/mixins/TestMixinInheritance.java
index 6aa8871..6e4f774 100644
--- a/src/test/java/com/fasterxml/jackson/databind/mixins/TestMixinInheritance.java
+++ b/src/test/java/com/fasterxml/jackson/databind/mixins/TestMixinInheritance.java
@@ -52,7 +52,7 @@
     public void testMixinFieldInheritance() throws IOException
     {
         ObjectMapper mapper = new ObjectMapper();
-        mapper.addMixInAnnotations(Beano.class, BeanoMixinSub.class);
+        mapper.addMixIn(Beano.class, BeanoMixinSub.class);
         Map<String,Object> result;
         result = writeAndMap(mapper, new Beano());
         assertEquals(2, result.size());
@@ -63,7 +63,7 @@
     public void testMixinMethodInheritance() throws IOException
     {
         ObjectMapper mapper = new ObjectMapper();
-        mapper.addMixInAnnotations(Beano2.class, BeanoMixinSub2.class);
+        mapper.addMixIn(Beano2.class, BeanoMixinSub2.class);
         Map<String,Object> result;
         result = writeAndMap(mapper, new Beano2());
         assertEquals(2, result.size());
diff --git a/src/test/java/com/fasterxml/jackson/databind/mixins/TestMixinSerForClass.java b/src/test/java/com/fasterxml/jackson/databind/mixins/TestMixinSerForClass.java
index 2dfaa36..9fd211f 100644
--- a/src/test/java/com/fasterxml/jackson/databind/mixins/TestMixinSerForClass.java
+++ b/src/test/java/com/fasterxml/jackson/databind/mixins/TestMixinSerForClass.java
@@ -79,7 +79,7 @@
 
         // then with top-level override
         mapper = new ObjectMapper();
-        mapper.addMixInAnnotations(LeafClass.class, MixIn.class);
+        mapper.addMixIn(LeafClass.class, MixIn.class);
         result = writeAndMap(mapper, new LeafClass("abc"));
         assertEquals(2, result.size());
         assertEquals("abc", result.get("a"));
@@ -87,7 +87,7 @@
 
         // mid-level override; should not have any effect
         mapper = new ObjectMapper();
-        mapper.addMixInAnnotations(BaseClass.class, MixIn.class);
+        mapper.addMixIn(BaseClass.class, MixIn.class);
         result = writeAndMap(mapper, new LeafClass("abc"));
         assertEquals(1, result.size());
         assertEquals("abc", result.get("a"));
@@ -108,7 +108,7 @@
 
         // then with working mid-level override, which effectively suppresses 'a'
         mapper = new ObjectMapper();
-        mapper.addMixInAnnotations(BaseClass.class, MixInAutoDetect.class);
+        mapper.addMixIn(BaseClass.class, MixInAutoDetect.class);
         result = writeAndMap(mapper, bean);
         assertEquals(1, result.size());
         assertEquals("c2", result.get("c"));
@@ -118,7 +118,7 @@
         result = writeAndMap(mapper2, bean);
         assertEquals(2, result.size());
         ObjectMapper mapper3 = mapper2.copy();
-        mapper3.addMixInAnnotations(BaseClass.class, MixInAutoDetect.class);
+        mapper3.addMixIn(BaseClass.class, MixInAutoDetect.class);
         result = writeAndMap(mapper3, bean);
         assertEquals(1, result.size());
         assertEquals("c2", result.get("c"));
diff --git a/src/test/java/com/fasterxml/jackson/databind/mixins/TestMixinSerForFields.java b/src/test/java/com/fasterxml/jackson/databind/mixins/TestMixinSerForFields.java
index 08eed33..2f7bf12 100644
--- a/src/test/java/com/fasterxml/jackson/databind/mixins/TestMixinSerForFields.java
+++ b/src/test/java/com/fasterxml/jackson/databind/mixins/TestMixinSerForFields.java
@@ -69,7 +69,7 @@
 
         // and then with simple mix-in
         mapper = new ObjectMapper();
-        mapper.addMixInAnnotations(BaseClass.class, MixIn.class);
+        mapper.addMixIn(BaseClass.class, MixIn.class);
         result = writeAndMap(mapper, bean);
         assertEquals(2, result.size());
         assertEquals("1", result.get("a"));
@@ -83,7 +83,7 @@
         HashMap<Class<?>,Class<?>> mixins = new HashMap<Class<?>,Class<?>>();
         mixins.put(SubClass.class, MixIn.class);
         mixins.put(BaseClass.class, MixIn2.class);
-        mapper.setMixInAnnotations(mixins);
+        mapper.setMixIns(mixins);
 
         Map<String,Object> result;
         result = writeAndMap(mapper, new SubClass("1", "2"));
diff --git a/src/test/java/com/fasterxml/jackson/databind/mixins/TestMixinSerForMethods.java b/src/test/java/com/fasterxml/jackson/databind/mixins/TestMixinSerForMethods.java
index a20867f..ad46ba9 100644
--- a/src/test/java/com/fasterxml/jackson/databind/mixins/TestMixinSerForMethods.java
+++ b/src/test/java/com/fasterxml/jackson/databind/mixins/TestMixinSerForMethods.java
@@ -115,7 +115,7 @@
 
         // then with leaf-level mix-in
         mapper = new ObjectMapper();
-        mapper.addMixInAnnotations(BaseClass.class, MixIn.class);
+        mapper.addMixIn(BaseClass.class, MixIn.class);
         result = writeAndMap(mapper, bean);
         assertEquals(2, result.size());
         assertEquals("b2", result.get("b2"));
@@ -133,7 +133,7 @@
         Map<String,Object> result;
         LeafClass bean = new LeafClass("XXX", "b2");
 
-        mapper.addMixInAnnotations(BaseClass.class, MixIn.class);
+        mapper.addMixIn(BaseClass.class, MixIn.class);
         result = writeAndMap(mapper, bean);
         assertEquals(1, result.size());
         assertEquals("XXX", result.get("a"));
@@ -146,7 +146,7 @@
     public void testIntermediateMixin2() throws IOException
     {
         ObjectMapper mapper = new ObjectMapper();
-        mapper.addMixInAnnotations(EmptyBean.class, MixInForSimple.class);
+        mapper.addMixIn(EmptyBean.class, MixInForSimple.class);
         Map<String,Object> result = writeAndMap(mapper, new SimpleBean());
         assertEquals(1, result.size());
         assertEquals(Integer.valueOf(42), result.get("x"));
@@ -160,7 +160,7 @@
     public void testObjectMixin() throws IOException
     {
         ObjectMapper mapper = new ObjectMapper();
-        mapper.addMixInAnnotations(Object.class, ObjectMixIn.class);
+        mapper.addMixIn(Object.class, ObjectMixIn.class);
 
         // First, with our bean...
         Map<String,Object> result = writeAndMap(mapper, new BaseClass("a", "b"));
diff --git a/src/test/java/com/fasterxml/jackson/databind/mixins/TestMixinSerWithViews.java b/src/test/java/com/fasterxml/jackson/databind/mixins/TestMixinSerWithViews.java
index 03a8089..62b4310 100644
--- a/src/test/java/com/fasterxml/jackson/databind/mixins/TestMixinSerWithViews.java
+++ b/src/test/java/com/fasterxml/jackson/databind/mixins/TestMixinSerWithViews.java
@@ -176,7 +176,7 @@
 
         // Property SerializationConfig.SerializationFeature.DEFAULT_VIEW_INCLUSION set to false
         mapper.configure(MapperFeature.DEFAULT_VIEW_INCLUSION, Boolean.FALSE);
-        mapper.addMixInAnnotations(A.class, AMixInAnnotation.class);
+        mapper.addMixIn(A.class, AMixInAnnotation.class);
         String json = mapper.writerWithView(AView.class).writeValueAsString(a);
 
         assertTrue(json.indexOf("\"name\"") > 0);
@@ -199,7 +199,7 @@
       sourceMixins.put( SimpleTestData.class, TestDataJAXBMixin.class );
       sourceMixins.put( ComplexTestData.class, TestComplexDataJAXBMixin.class );
       
-      objectMapper.setMixInAnnotations(sourceMixins);
+      objectMapper.setMixIns(sourceMixins);
       return objectMapper;
     }
 }
diff --git a/src/test/java/com/fasterxml/jackson/databind/module/TestTypeModifierNameResolution.java b/src/test/java/com/fasterxml/jackson/databind/module/TestTypeModifierNameResolution.java
index e19a2ae..cdd89ea 100644
--- a/src/test/java/com/fasterxml/jackson/databind/module/TestTypeModifierNameResolution.java
+++ b/src/test/java/com/fasterxml/jackson/databind/module/TestTypeModifierNameResolution.java
@@ -1,17 +1,16 @@
 package com.fasterxml.jackson.databind.module;
 
 import com.fasterxml.jackson.annotation.JsonTypeInfo;
-import com.fasterxml.jackson.databind.JavaType;
-import com.fasterxml.jackson.databind.ObjectMapper;
+
+import com.fasterxml.jackson.databind.*;
 import com.fasterxml.jackson.databind.type.TypeBindings;
 import com.fasterxml.jackson.databind.type.TypeFactory;
 import com.fasterxml.jackson.databind.type.TypeModifier;
-import com.fasterxml.jackson.test.BaseTest;
 
 import java.lang.reflect.Type;
 
-public class TestTypeModifierNameResolution extends BaseTest {
-
+public class TestTypeModifierNameResolution extends BaseMapTest
+{
 	interface MyType {
 		String getData();
 		void setData(String data);
@@ -49,7 +48,7 @@
 	{
 		ObjectMapper mapper = new ObjectMapper();
 		mapper.setTypeFactory(mapper.getTypeFactory().withModifier(new CustomTypeModifier()));
-		mapper.addMixInAnnotations(MyType.class, Mixin.class);
+		mapper.addMixIn(MyType.class, Mixin.class);
 
 		MyType obj = new MyTypeImpl();
 		obj.setData("something");
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 12e4a58..bee4813 100644
--- a/src/test/java/com/fasterxml/jackson/databind/node/TestConversions.java
+++ b/src/test/java/com/fasterxml/jackson/databind/node/TestConversions.java
@@ -126,7 +126,7 @@
     {
         String JSON = "{\"leaf\":{\"value\":13}}";
         ObjectMapper mapper = new ObjectMapper();
-        mapper.addMixInAnnotations(Leaf.class, LeafMixIn.class);
+        mapper.addMixIn(Leaf.class, LeafMixIn.class);
         JsonNode root = mapper.readTree(JSON);
         // Ok, try converting to bean using two mechanisms
         Root r1 = mapper.treeToValue(root, Root.class);
diff --git a/src/test/java/com/fasterxml/jackson/databind/node/TestTreeMapperSerializer.java b/src/test/java/com/fasterxml/jackson/databind/node/TestTreeMapperSerializer.java
index bd22dda..6114ed6 100644
--- a/src/test/java/com/fasterxml/jackson/databind/node/TestTreeMapperSerializer.java
+++ b/src/test/java/com/fasterxml/jackson/databind/node/TestTreeMapperSerializer.java
@@ -6,14 +6,13 @@
 
 import com.fasterxml.jackson.core.*;
 import com.fasterxml.jackson.databind.*;
-import com.fasterxml.jackson.test.BaseTest;
 
 /**
  * This unit test suite tries to verify that the trees ObjectMapper
  * constructs can be serialized properly.
  */
 public class TestTreeMapperSerializer
-    extends BaseTest
+    extends BaseMapTest
 {
     final static String FIELD1 = "first";
     final static String FIELD2 = "Second?";
diff --git a/src/test/java/com/fasterxml/jackson/databind/ser/TestAnnotationInheritance.java b/src/test/java/com/fasterxml/jackson/databind/ser/TestAnnotationInheritance.java
index 12e449c..199a279 100644
--- a/src/test/java/com/fasterxml/jackson/databind/ser/TestAnnotationInheritance.java
+++ b/src/test/java/com/fasterxml/jackson/databind/ser/TestAnnotationInheritance.java
@@ -1,6 +1,5 @@
 package com.fasterxml.jackson.databind.ser;
 
-import java.io.*;
 import java.util.*;
 
 import com.fasterxml.jackson.annotation.*;
@@ -12,7 +11,7 @@
  * bean serialization.
  */
 public class TestAnnotationInheritance
-    extends com.fasterxml.jackson.test.BaseTest
+    extends BaseMapTest
 {
     /*
     /**********************************************************
@@ -92,19 +91,4 @@
         assertEquals(Integer.valueOf(1), result.get("width"));
         assertEquals(Integer.valueOf(2), result.get("length"));
     }
-
-    /*
-    //////////////////////////////////////////////
-    // Helper methods
-    //////////////////////////////////////////////
-     */
-
-    @SuppressWarnings("unchecked")
-	private Map<String,Object> writeAndMap(ObjectMapper m, Object value)
-        throws IOException
-    {
-        StringWriter sw = new StringWriter();
-        m.writeValue(sw, value);
-        return (Map<String,Object>) m.readValue(sw.toString(), Object.class);
-    }
 }
diff --git a/src/test/java/com/fasterxml/jackson/databind/ser/TestAnyGetter.java b/src/test/java/com/fasterxml/jackson/databind/ser/TestAnyGetter.java
index bcf4e8a..1b855da 100644
--- a/src/test/java/com/fasterxml/jackson/databind/ser/TestAnyGetter.java
+++ b/src/test/java/com/fasterxml/jackson/databind/ser/TestAnyGetter.java
@@ -8,15 +8,8 @@
 import com.fasterxml.jackson.databind.ObjectMapper;
 import com.fasterxml.jackson.databind.SerializationFeature;
 
-public class TestAnyGetter
-    extends BaseMapTest
+public class TestAnyGetter extends BaseMapTest
 {
-    /*
-    /**********************************************************
-    /* Helper bean classes
-    /**********************************************************
-     */
-
     static class Bean
     {
         final static Map<String,Boolean> extra = new HashMap<String,Boolean>();
@@ -40,17 +33,32 @@
         }
     }
 
+    static class MapAsAny
+    {
+        protected Map<String,Object> stuff = new LinkedHashMap<String,Object>();
+        
+        @JsonAnyGetter
+        public Map<String,Object> any() {
+            return stuff;
+        }
+
+        public void add(String key, Object value) {
+            stuff.put(key, value);
+        }
+    }
+    
     /*
     /**********************************************************
     /* Test cases
     /**********************************************************
      */
 
+    private final ObjectMapper MAPPER = new ObjectMapper();
+    
     public void testSimpleJsonValue() throws Exception
     {
-        ObjectMapper m = new ObjectMapper();
-        String json = serializeAsString(m, new Bean());
-        Map<?,?> map = m.readValue(json, Map.class);
+        String json = MAPPER.writeValueAsString(new Bean());
+        Map<?,?> map = MAPPER.readValue(json, Map.class);
         assertEquals(2, map.size());
         assertEquals(Integer.valueOf(3), map.get("x"));
         assertEquals(Boolean.TRUE, map.get("a"));
@@ -73,4 +81,13 @@
         json = serializeAsString(m, new AnyOnlyBean());
         assertEquals("{\"a\":3}", json);
     }
+
+    // Trying to repro [databind#577]
+    public void testAnyWithNull() throws Exception
+    {
+        MapAsAny input = new MapAsAny();
+        input.add("bar", null);
+        assertEquals(aposToQuotes("{'bar':null}"),
+                MAPPER.writeValueAsString(input));
+    }
 }
diff --git a/src/test/java/com/fasterxml/jackson/databind/ser/TestBeanSerializer.java b/src/test/java/com/fasterxml/jackson/databind/ser/TestBeanSerializer.java
index 8263a95..c903328 100644
--- a/src/test/java/com/fasterxml/jackson/databind/ser/TestBeanSerializer.java
+++ b/src/test/java/com/fasterxml/jackson/databind/ser/TestBeanSerializer.java
@@ -5,7 +5,6 @@
 
 import com.fasterxml.jackson.annotation.*;
 import com.fasterxml.jackson.core.*;
-
 import com.fasterxml.jackson.databind.*;
 import com.fasterxml.jackson.databind.introspect.AnnotatedField;
 import com.fasterxml.jackson.databind.introspect.POJOPropertyBuilder;
@@ -26,17 +25,11 @@
 @SuppressWarnings("serial")
 public class TestBeanSerializer extends BaseMapTest
 {
-    /*
-    /********************************************************
-    /* Helper types
-    /********************************************************
-     */
-
-    static class ModuleImpl extends SimpleModule
+    static class SerializerModifierModule extends SimpleModule
     {
         protected BeanSerializerModifier modifier;
         
-        public ModuleImpl(BeanSerializerModifier modifier)
+        public SerializerModifierModule(BeanSerializerModifier modifier)
         {
             super("test", Version.unknownVersion());
             this.modifier = modifier;
@@ -178,6 +171,22 @@
         }
     }
 
+    // [Issue#539]: use post-modifier
+    static class EmptyBeanModifier539 extends BeanSerializerModifier
+    {
+        @Override
+        public List<BeanPropertyWriter> changeProperties(SerializationConfig config,
+                BeanDescription beanDesc, List<BeanPropertyWriter> beanProperties)
+        {
+            return beanProperties;
+        }
+        
+        @Override
+        public JsonSerializer<?> modifySerializer(SerializationConfig config,
+                BeanDescription beanDesc, JsonSerializer<?> serializer) {
+            return new BogusBeanSerializer(42);
+        }
+    }
     // [Issue#120], arrays, collections, maps
     
     static class ArraySerializerModifier extends BeanSerializerModifier {
@@ -251,7 +260,7 @@
     public void testPropertyRemoval() throws Exception
     {
         ObjectMapper mapper = new ObjectMapper();
-        mapper.registerModule(new ModuleImpl(new RemovingModifier("a")));
+        mapper.registerModule(new SerializerModifierModule(new RemovingModifier("a")));
         Bean bean = new Bean();
         assertEquals("{\"b\":\"b\"}", mapper.writeValueAsString(bean));
     }
@@ -259,7 +268,7 @@
     public void testPropertyReorder() throws Exception
     {
         ObjectMapper mapper = new ObjectMapper();
-        mapper.registerModule(new ModuleImpl(new ReorderingModifier()));
+        mapper.registerModule(new SerializerModifierModule(new ReorderingModifier()));
         Bean bean = new Bean();
         assertEquals("{\"a\":\"a\",\"b\":\"b\"}", mapper.writeValueAsString(bean));
     }
@@ -267,14 +276,14 @@
     public void testBuilderReplacement() throws Exception
     {
         ObjectMapper mapper = new ObjectMapper();
-        mapper.registerModule(new ModuleImpl(new BuilderModifier(new BogusBeanSerializer(17))));
+        mapper.registerModule(new SerializerModifierModule(new BuilderModifier(new BogusBeanSerializer(17))));
         Bean bean = new Bean();
         assertEquals("17", mapper.writeValueAsString(bean));
     }    
     public void testSerializerReplacement() throws Exception
     {
         ObjectMapper mapper = new ObjectMapper();
-        mapper.registerModule(new ModuleImpl(new ReplacingModifier(new BogusBeanSerializer(123))));
+        mapper.registerModule(new SerializerModifierModule(new ReplacingModifier(new BogusBeanSerializer(123))));
         Bean bean = new Bean();
         assertEquals("123", mapper.writeValueAsString(bean));
     }
@@ -295,6 +304,22 @@
         assertEquals("{\"bogus\":\"foo\"}", json);
     }
 
+    // [Issue#539]
+    public void testEmptyBean539() throws Exception
+    {
+        ObjectMapper mapper = new ObjectMapper();
+        mapper.registerModule(new SimpleModule("test", Version.unknownVersion()) {
+            @Override
+            public void setupModule(SetupContext context)
+            {
+                super.setupModule(context);
+                context.addBeanSerializerModifier(new EmptyBeanModifier539());
+            }
+        });
+        String json = mapper.writeValueAsString(new EmptyBean());
+        assertEquals("42", json);
+    }
+    
     // [Issue#121]
 
     public void testModifyArraySerializer() throws Exception
diff --git a/src/test/java/com/fasterxml/jackson/databind/ser/TestCustomSerializers.java b/src/test/java/com/fasterxml/jackson/databind/ser/TestCustomSerializers.java
index 2f54f5e..5efe029 100644
--- a/src/test/java/com/fasterxml/jackson/databind/ser/TestCustomSerializers.java
+++ b/src/test/java/com/fasterxml/jackson/databind/ser/TestCustomSerializers.java
@@ -110,7 +110,7 @@
     public void testCustomization() throws Exception
     {
         ObjectMapper objectMapper = new ObjectMapper();
-        objectMapper.addMixInAnnotations(Element.class, ElementMixin.class);
+        objectMapper.addMixIn(Element.class, ElementMixin.class);
         Element element = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument().createElement("el");
         StringWriter sw = new StringWriter();
         objectMapper.writeValue(sw, element);
diff --git a/src/test/java/com/fasterxml/jackson/databind/ser/TestEmptyClass.java b/src/test/java/com/fasterxml/jackson/databind/ser/TestEmptyClass.java
index 6aa1857..ed6f291 100644
--- a/src/test/java/com/fasterxml/jackson/databind/ser/TestEmptyClass.java
+++ b/src/test/java/com/fasterxml/jackson/databind/ser/TestEmptyClass.java
@@ -73,7 +73,7 @@
 
         // Including class annotation through mix-ins
         ObjectMapper m2 = new ObjectMapper();
-        m2.addMixInAnnotations(Empty.class, EmptyWithAnno.class);
+        m2.addMixIn(Empty.class, EmptyWithAnno.class);
         assertEquals("{}", m2.writeValueAsString(new Empty()));
     }
 
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 07c9af3..ff657db 100644
--- a/src/test/java/com/fasterxml/jackson/databind/ser/TestEnumSerialization.java
+++ b/src/test/java/com/fasterxml/jackson/databind/ser/TestEnumSerialization.java
@@ -7,9 +7,7 @@
 import com.fasterxml.jackson.annotation.JsonFormat.Shape;
 import com.fasterxml.jackson.annotation.JsonProperty;
 import com.fasterxml.jackson.annotation.JsonValue;
-
 import com.fasterxml.jackson.core.*;
-
 import com.fasterxml.jackson.databind.*;
 import com.fasterxml.jackson.databind.annotation.JsonSerialize;
 import com.fasterxml.jackson.databind.jsontype.TypeSerializer;
@@ -136,8 +134,8 @@
         public OK text = OK.V1;
     }
     
-    @JsonFormat(shape=JsonFormat.Shape.ARRAY) // not supported as of now
-    static enum BrokenPoNum
+    @JsonFormat(shape=JsonFormat.Shape.ARRAY) // alias for 'number', as of 2.5
+    static enum PoAsArray
     {
         A, B;
     }
@@ -152,6 +150,19 @@
             jgen.writeString(value.name().toLowerCase());
         }
     }
+
+    // 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;
+    }
     
     /*
     /**********************************************************
@@ -203,7 +214,7 @@
     {
         // can't share, as new mix-ins are added
         ObjectMapper m = new ObjectMapper();
-        m.addMixInAnnotations(TestEnum.class, ToStringMixin.class);
+        m.addMixIn(TestEnum.class, ToStringMixin.class);
         assertEquals("\"b\"", m.writeValueAsString(TestEnum.B));
     }
 
@@ -273,15 +284,11 @@
     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
     {
-        try {
-            String json = mapper.writeValueAsString(BrokenPoNum.A);
-            fail("Should not have succeeded, produced: "+json);
-        } catch (JsonMappingException e) {
-            verifyException(e, "Unsupported serialization shape");
-        }
+        assertEquals("0", mapper.writeValueAsString(PoAsArray.A));
     }
     
     // [Issue#227]
@@ -294,6 +301,15 @@
         m.registerModule(module);
         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()));
+    }
 }
 
 // [JACKSON-757], non-inner enum
diff --git a/src/test/java/com/fasterxml/jackson/databind/ser/TestExceptionHandling.java b/src/test/java/com/fasterxml/jackson/databind/ser/TestExceptionHandling.java
index a063521..0ebb608 100644
--- a/src/test/java/com/fasterxml/jackson/databind/ser/TestExceptionHandling.java
+++ b/src/test/java/com/fasterxml/jackson/databind/ser/TestExceptionHandling.java
@@ -6,7 +6,6 @@
 import com.fasterxml.jackson.core.*;
 import com.fasterxml.jackson.databind.*;
 import com.fasterxml.jackson.databind.module.SimpleModule;
-import com.fasterxml.jackson.test.BaseTest;
 import com.fasterxml.jackson.test.BrokenStringWriter;
 
 /**
@@ -15,7 +14,7 @@
  * with Object serialization.
  */
 public class TestExceptionHandling
-    extends BaseTest
+    extends BaseMapTest
 {
     /*
     /**********************************************************
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 624e96c..7cee0de 100644
--- a/src/test/java/com/fasterxml/jackson/databind/ser/TestMapSerialization.java
+++ b/src/test/java/com/fasterxml/jackson/databind/ser/TestMapSerialization.java
@@ -4,6 +4,7 @@
 import java.util.*;
 import java.util.concurrent.ConcurrentHashMap;
 
+import com.fasterxml.jackson.annotation.JsonInclude;
 import com.fasterxml.jackson.annotation.JsonPropertyOrder;
 import com.fasterxml.jackson.core.*;
 import com.fasterxml.jackson.databind.*;
@@ -13,12 +14,6 @@
 public class TestMapSerialization
     extends BaseMapTest
 {
-    /*
-    /**********************************************************
-    /* Helper classes
-    /**********************************************************
-     */
-
     /**
      * Class needed for testing [JACKSON-220]
      */
@@ -69,13 +64,66 @@
         }
     }
 
+    // [Databind#565]: Support ser/deser of Map.Entry
+    static class StringIntMapEntry implements Map.Entry<String,Integer> {
+        public final String k;
+        public final Integer v;
+        public StringIntMapEntry(String k, Integer v) {
+            this.k = k;
+            this.v = v;
+        }
+
+        @Override
+        public String getKey() {
+            return k;
+        }
+
+        @Override
+        public Integer getValue() {
+            return v;
+        }
+
+        @Override
+        public Integer setValue(Integer value) {
+            throw new UnsupportedOperationException();
+        }
+    }
+
+    // [databind#527]
+    static class NoNullValuesMapContainer {
+        @JsonInclude(content=JsonInclude.Include.NON_NULL)
+        public Map<String,String> stuff = new LinkedHashMap<String,String>();
+        
+        public NoNullValuesMapContainer add(String key, String value) {
+            stuff.put(key, value);
+            return this;
+        }
+    }
+
+    // [databind#527]
+    @JsonInclude(content=JsonInclude.Include.NON_NULL)
+    static class NoNullsStringMap extends LinkedHashMap<String,String> {
+        public NoNullsStringMap add(String key, String value) {
+            put(key, value);
+            return this;
+        }
+    }
+
+    @JsonInclude(content=JsonInclude.Include.NON_EMPTY)
+    static class NoEmptyStringsMap extends LinkedHashMap<String,String> {
+        public NoEmptyStringsMap add(String key, String value) {
+            put(key, value);
+            return this;
+        }
+    }
+
     /*
     /**********************************************************
     /* Test methods
     /**********************************************************
      */
 
-    final ObjectMapper MAPPER = objectMapper();
+    final private ObjectMapper MAPPER = objectMapper();
 
     public void testUsingObjectWriter() throws IOException
     {
@@ -150,11 +198,53 @@
         assertEquals("{\"a\":6,\"b\":3}", m.writer(SerializationFeature.ORDER_MAP_ENTRIES_BY_KEYS).writeValueAsString(map));
     }
 
-    // [#335[
+    // [Databind#335]
     public void testOrderByKeyViaProperty() throws IOException
     {
         MapOrderingBean input = new MapOrderingBean("c", "b", "a");
         String json = MAPPER.writeValueAsString(input);
         assertEquals(aposToQuotes("{'map':{'a':3,'b':2,'c':1}}"), json);
     }        
+
+    // [Databind#565]
+    public void testEnumMapEntry() throws IOException
+    {
+        StringIntMapEntry input = new StringIntMapEntry("answer", 42);
+        String json = MAPPER.writeValueAsString(input);
+        assertEquals(aposToQuotes("{'answer':42}"), json);
+
+        StringIntMapEntry[] array = new StringIntMapEntry[] { input };
+        json = MAPPER.writeValueAsString(array);
+        assertEquals(aposToQuotes("[{'answer':42}]"), json);
+    }        
+
+    // [databind#527]
+    public void testNonNullValueMap() throws IOException
+    {
+        String json = MAPPER.writeValueAsString(new NoNullsStringMap()
+            .add("a", "foo")
+            .add("b", null)
+            .add("c", "bar"));
+        assertEquals(aposToQuotes("{'a':'foo','c':'bar'}"), json);
+    }
+
+    // [databind#527]
+    public void testNonEmptyValueMap() throws IOException
+    {
+        String json = MAPPER.writeValueAsString(new NoEmptyStringsMap()
+            .add("a", "foo")
+            .add("b", "bar")
+            .add("c", ""));
+        assertEquals(aposToQuotes("{'a':'foo','b':'bar'}"), json);
+    }
+    
+    // [databind#527]
+    public void testNonNullValueMapViaProp() throws IOException
+    {
+        String json = MAPPER.writeValueAsString(new NoNullValuesMapContainer()
+            .add("a", "foo")
+            .add("b", null)
+            .add("c", "bar"));
+        assertEquals(aposToQuotes("{'stuff':{'a':'foo','c':'bar'}}"), json);
+    }
 }
diff --git a/src/test/java/com/fasterxml/jackson/databind/ser/TestSerializationOrder.java b/src/test/java/com/fasterxml/jackson/databind/ser/TestSerializationOrder.java
index f3802f6..6cf1b41 100644
--- a/src/test/java/com/fasterxml/jackson/databind/ser/TestSerializationOrder.java
+++ b/src/test/java/com/fasterxml/jackson/databind/ser/TestSerializationOrder.java
@@ -116,7 +116,7 @@
     public void testOrderWithMixins() throws Exception
     {
         ObjectMapper m = new ObjectMapper();
-        m.addMixInAnnotations(BeanWithOrder.class, OrderMixIn.class);
+        m.addMixIn(BeanWithOrder.class, OrderMixIn.class);
         assertEquals("{\"b\":2,\"a\":1,\"c\":3,\"d\":4}",
                 serializeAsString(m, new BeanWithOrder(1, 2, 3, 4)));
     }
diff --git a/src/test/java/com/fasterxml/jackson/databind/struct/TestObjectIdDeserialization.java b/src/test/java/com/fasterxml/jackson/databind/struct/TestObjectIdDeserialization.java
index 047a80b..37f18a3 100644
--- a/src/test/java/com/fasterxml/jackson/databind/struct/TestObjectIdDeserialization.java
+++ b/src/test/java/com/fasterxml/jackson/databind/struct/TestObjectIdDeserialization.java
@@ -180,8 +180,6 @@
             return new PoolResolver(pool);
         }
     }
-
-    private final ObjectMapper mapper = new ObjectMapper();
     
     /*
     /*****************************************************
@@ -189,6 +187,8 @@
     /*****************************************************
      */
 
+    private final ObjectMapper mapper = new ObjectMapper();
+    
     private final static String EXP_SIMPLE_INT_CLASS = "{\"id\":1,\"value\":13,\"next\":1}";
 
     public void testSimpleDeserializationClass() throws Exception
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 33d2f54..c4fb52f 100644
--- a/src/test/java/com/fasterxml/jackson/databind/struct/TestPOJOAsArray.java
+++ b/src/test/java/com/fasterxml/jackson/databind/struct/TestPOJOAsArray.java
@@ -4,9 +4,7 @@
 import com.fasterxml.jackson.annotation.JsonPropertyOrder;
 import com.fasterxml.jackson.annotation.JsonFormat.Shape;
 
-import com.fasterxml.jackson.databind.BaseMapTest;
-import com.fasterxml.jackson.databind.ObjectMapper;
-import com.fasterxml.jackson.databind.SerializationFeature;
+import com.fasterxml.jackson.databind.*;
 import com.fasterxml.jackson.databind.introspect.Annotated;
 import com.fasterxml.jackson.databind.introspect.JacksonAnnotationIntrospector;
 
@@ -164,6 +162,15 @@
         String json = mapper.writeValueAsString(new SingleBean());
         assertEquals("\"foo\"", json);
     }
+
+    public void testBeanAsArrayUnwrapped() throws Exception
+    {
+        ObjectMapper mapper = new ObjectMapper();
+        mapper.enable(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY);
+        SingleBean result = mapper.readValue("[\"foobar\"]", SingleBean.class);
+        assertNotNull(result);
+        assertEquals("foobar", result.name);
+    }
     
     /*
     /*****************************************************
diff --git a/src/test/java/com/fasterxml/jackson/databind/struct/TestPOJOAsArrayWithBuilder.java b/src/test/java/com/fasterxml/jackson/databind/struct/TestPOJOAsArrayWithBuilder.java
index 5dc72cb..2f572a4 100644
--- a/src/test/java/com/fasterxml/jackson/databind/struct/TestPOJOAsArrayWithBuilder.java
+++ b/src/test/java/com/fasterxml/jackson/databind/struct/TestPOJOAsArrayWithBuilder.java
@@ -29,15 +29,13 @@
     {
         public int x, y;
         
-        @SuppressWarnings("hiding")
-        public SimpleBuilderXY withX(int x) {
-            this.x = x;
+        public SimpleBuilderXY withX(int x0) {
+            this.x = x0;
             return this;
         }
 
-        @SuppressWarnings("hiding")
-        public SimpleBuilderXY withY(int y) {
-            this.y = y;
+        public SimpleBuilderXY withY(int y0) {
+            this.y = y0;
             return this;
         }
 
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 7a3bfa2..aec92c5 100644
--- a/src/test/java/com/fasterxml/jackson/databind/type/TestJavaType.java
+++ b/src/test/java/com/fasterxml/jackson/databind/type/TestJavaType.java
@@ -2,6 +2,7 @@
 
 import java.util.*;
 
+import com.fasterxml.jackson.databind.BaseMapTest;
 import com.fasterxml.jackson.databind.JavaType;
 
 /**
@@ -9,7 +10,7 @@
  * some degree
  */
 public class TestJavaType
-    extends com.fasterxml.jackson.test.BaseTest
+    extends BaseMapTest
 {
     static class BaseType { }
 
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 1aaac42..3a15673 100644
--- a/src/test/java/com/fasterxml/jackson/databind/type/TestTypeBindings.java
+++ b/src/test/java/com/fasterxml/jackson/databind/type/TestTypeBindings.java
@@ -2,6 +2,7 @@
 
 import java.util.*;
 
+import com.fasterxml.jackson.databind.BaseMapTest;
 import com.fasterxml.jackson.databind.JavaType;
 
 /**
@@ -9,7 +10,7 @@
  * implemented by {@link TypeBindings} class.
  */
 public class TestTypeBindings
-    extends com.fasterxml.jackson.test.BaseTest
+    extends BaseMapTest
 {    
     static class AbstractType<A,B> { }
     
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 62dbb9f..e861cb7 100644
--- a/src/test/java/com/fasterxml/jackson/databind/type/TestTypeFactory.java
+++ b/src/test/java/com/fasterxml/jackson/databind/type/TestTypeFactory.java
@@ -5,21 +5,15 @@
 import java.util.concurrent.atomic.AtomicReference;
 
 import com.fasterxml.jackson.core.type.TypeReference;
-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.HierarchicType;
-import com.fasterxml.jackson.databind.type.MapType;
-import com.fasterxml.jackson.databind.type.SimpleType;
-import com.fasterxml.jackson.databind.type.TypeFactory;
-import com.fasterxml.jackson.test.BaseTest;
+
+import com.fasterxml.jackson.databind.*;
 
 /**
  * Simple tests to verify that the {@link TypeFactory} constructs
  * type information as expected.
  */
 public class TestTypeFactory
-    extends BaseTest
+    extends BaseMapTest
 {    
     /*
     /**********************************************************
@@ -198,7 +192,7 @@
     {
         TypeFactory tf = TypeFactory.defaultInstance();
         // first, simple class based
-        JavaType t = tf.constructParametricType(ArrayList.class, String.class); // ArrayList<String>
+        JavaType t = tf.constructParametrizedType(ArrayList.class, Collection.class, String.class); // ArrayList<String>
         assertEquals(CollectionType.class, t.getClass());
         JavaType strC = tf.constructType(String.class);
         assertEquals(1, t.containedTypeCount());
@@ -206,7 +200,7 @@
         assertNull(t.containedType(1));
 
         // Then using JavaType
-        JavaType t2 = tf.constructParametricType(Map.class, strC, t); // Map<String,ArrayList<String>>
+        JavaType t2 = tf.constructParametrizedType(Map.class, Map.class, strC, t); // Map<String,ArrayList<String>>
         // should actually produce a MapType
         assertEquals(MapType.class, t2.getClass());
         assertEquals(2, t2.containedTypeCount());
@@ -215,7 +209,8 @@
         assertNull(t2.containedType(2));
 
         // and then custom generic type as well
-        JavaType custom = tf.constructParametricType(SingleArgGeneric.class, String.class);
+        JavaType custom = tf.constructParametrizedType(SingleArgGeneric.class, SingleArgGeneric.class,
+                String.class);
         assertEquals(SimpleType.class, custom.getClass());
         assertEquals(1, custom.containedTypeCount());
         assertEquals(strC, custom.containedType(0));
@@ -226,14 +221,14 @@
         // And finally, ensure that we can't create invalid combinations
         try {
             // Maps must take 2 type parameters, not just one
-            tf.constructParametricType(Map.class, strC);
+            tf.constructParametrizedType(Map.class, Map.class, strC);
         } catch (IllegalArgumentException e) {
             verifyException(e, "Need exactly 2 parameter types for Map types");
         }
 
         try {
             // Type only accepts one type param
-            tf.constructParametricType(SingleArgGeneric.class, strC, strC);
+            tf.constructParametrizedType(SingleArgGeneric.class, SingleArgGeneric.class, strC, strC);
         } catch (IllegalArgumentException e) {
             verifyException(e, "expected 1 parameters, was given 2");
         }
@@ -316,17 +311,6 @@
         assertNull(sup2.getSuperType());
     }
 
-    public void testAtomicArrayRefParameterDetection()
-    {
-        TypeFactory tf = TypeFactory.defaultInstance();
-        JavaType type = tf.constructType(new TypeReference<AtomicReference<long[]>>() { });
-        HierarchicType sub = tf._findSuperTypeChain(type.getRawClass(), AtomicReference.class);
-        assertNotNull(sub);
-        assertEquals(0, _countSupers(sub));
-        assertTrue(AtomicReference.class.isAssignableFrom(type.getRawClass()));
-        assertNull(sub.getSuperType());
-    }
-
     private int _countSupers(HierarchicType t)
     {
         int depth = 0;
@@ -335,7 +319,7 @@
         }
         return depth;
     }
-    
+
     /*
     /**********************************************************
     /* Unit tests: map/collection type parameter resolution
@@ -431,7 +415,31 @@
         assertEquals(1, list.size());
         assertEquals("...", list.get(0));
     }
-    
+
+    public void testSneakySelfRefs() throws Exception
+    {
+        ObjectMapper mapper = new ObjectMapper();
+        String json = mapper.writeValueAsString(new SneakyBean2());
+        assertEquals("{\"foobar\":null}", json);
+    }
+
+    /*
+    /**********************************************************
+    /* Unit tests: handling of specific JDK types
+    /**********************************************************
+     */
+
+    public void testAtomicArrayRefParameterDetection()
+    {
+        TypeFactory tf = TypeFactory.defaultInstance();
+        JavaType type = tf.constructType(new TypeReference<AtomicReference<long[]>>() { });
+        HierarchicType sub = tf._findSuperTypeChain(type.getRawClass(), AtomicReference.class);
+        assertNotNull(sub);
+        assertEquals(0, _countSupers(sub));
+        assertTrue(AtomicReference.class.isAssignableFrom(type.getRawClass()));
+        assertNull(sub.getSuperType());
+    }
+
     public void testAtomicArrayRefParameters()
     {
         TypeFactory tf = TypeFactory.defaultInstance();
@@ -442,13 +450,19 @@
         assertEquals(tf.constructType(long[].class), params[0]);
     }
 
-    public void testSneakySelfRefs() throws Exception
+    static abstract class StringIntMapEntry implements Map.Entry<String,Integer> { }
+    
+    public void testMapEntryResolution()
     {
-        ObjectMapper mapper = new ObjectMapper();
-        String json = mapper.writeValueAsString(new SneakyBean2());
-        assertEquals("{\"foobar\":null}", json);
+        TypeFactory tf = TypeFactory.defaultInstance();
+        JavaType t = tf.constructType(StringIntMapEntry.class);
+        assertTrue(t.hasGenericTypes());
+        assertEquals(2, t.containedTypeCount());
+        assertEquals(String.class, t.containedType(0).getRawClass());
+        assertEquals(Integer.class, t.containedType(1).getRawClass());
+        // NOTE: no key/content types, at least not as of 2.5
     }
-
+    
     /*
     /**********************************************************
     /* Unit tests: construction of "raw" types
diff --git a/src/test/java/com/fasterxml/jackson/databind/type/TestTypeResolution.java b/src/test/java/com/fasterxml/jackson/databind/type/TestTypeResolution.java
index 30be92e..b9dda04 100644
--- a/src/test/java/com/fasterxml/jackson/databind/type/TestTypeResolution.java
+++ b/src/test/java/com/fasterxml/jackson/databind/type/TestTypeResolution.java
@@ -3,14 +3,14 @@
 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.CollectionType;
 import com.fasterxml.jackson.databind.type.MapType;
 import com.fasterxml.jackson.databind.type.TypeFactory;
 
 @SuppressWarnings("serial")
-public class TestTypeResolution extends com.fasterxml.jackson.test.BaseTest
+public class TestTypeResolution extends BaseMapTest
 {
     public static class LongValuedMap<K> extends HashMap<K, Long> { }
 
diff --git a/src/test/java/com/fasterxml/jackson/databind/util/ISO8601UtilsTest.java b/src/test/java/com/fasterxml/jackson/databind/util/ISO8601UtilsTest.java
index 21b9046..9c97807 100644
--- a/src/test/java/com/fasterxml/jackson/databind/util/ISO8601UtilsTest.java
+++ b/src/test/java/com/fasterxml/jackson/databind/util/ISO8601UtilsTest.java
@@ -1,28 +1,39 @@
 package com.fasterxml.jackson.databind.util;
 
-import java.util.*;
+import java.text.ParseException;
 import java.text.ParsePosition;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.GregorianCalendar;
+import java.util.TimeZone;
 
 import com.fasterxml.jackson.databind.BaseMapTest;
-import com.fasterxml.jackson.databind.util.ISO8601Utils;
 
 /**
  * @see ISO8601Utils
  */
-public class ISO8601UtilsTest extends BaseMapTest
-{
+public class ISO8601UtilsTest extends BaseMapTest {
     private Date date;
+    private Date dateWithoutTime;
     private Date dateZeroMillis;
+    private Date dateZeroSecondAndMillis;
 
     @Override
-    public void setUp()
-    {
+    public void setUp() {
         Calendar cal = new GregorianCalendar(2007, 8 - 1, 13, 19, 51, 23);
         cal.setTimeZone(TimeZone.getTimeZone("GMT"));
         cal.set(Calendar.MILLISECOND, 789);
         date = cal.getTime();
         cal.set(Calendar.MILLISECOND, 0);
         dateZeroMillis = cal.getTime();
+        cal.set(Calendar.SECOND, 0);
+        dateZeroSecondAndMillis = cal.getTime();
+        
+        cal = new GregorianCalendar(2007, 8 - 1, 13, 0, 0, 0);
+        cal.set(Calendar.MILLISECOND, 0);
+        cal.setTimeZone(TimeZone.getTimeZone("GMT"));
+        dateWithoutTime = cal.getTime();
+
     }
 
     public void testFormat() {
@@ -58,4 +69,85 @@
         assertEquals(date, d);
     }
 
+    public void testParseShortDate() throws java.text.ParseException {
+        Date d = ISO8601Utils.parse("20070813T19:51:23.789Z", new ParsePosition(0));
+        assertEquals(date, d);
+
+        d = ISO8601Utils.parse("20070813T19:51:23Z", new ParsePosition(0));
+        assertEquals(dateZeroMillis, d);
+
+        d = ISO8601Utils.parse("20070813T21:51:23.789+02:00", new ParsePosition(0));
+        assertEquals(date, d);
+    }
+
+    public void testParseShortTime() throws java.text.ParseException {
+        Date d = ISO8601Utils.parse("2007-08-13T195123.789Z", new ParsePosition(0));
+        assertEquals(date, d);
+
+        d = ISO8601Utils.parse("2007-08-13T195123Z", new ParsePosition(0));
+        assertEquals(dateZeroMillis, d);
+
+        d = ISO8601Utils.parse("2007-08-13T215123.789+02:00", new ParsePosition(0));
+        assertEquals(date, d);
+    }
+
+    public void testParseShortDateTime() throws java.text.ParseException {
+        Date d = ISO8601Utils.parse("20070813T195123.789Z", new ParsePosition(0));
+        assertEquals(date, d);
+
+        d = ISO8601Utils.parse("20070813T195123Z", new ParsePosition(0));
+        assertEquals(dateZeroMillis, d);
+
+        d = ISO8601Utils.parse("20070813T215123.789+02:00", new ParsePosition(0));
+        assertEquals(date, d);
+    }
+
+    public void testParseWithoutTime() throws ParseException {
+        Date d = ISO8601Utils.parse("2007-08-13Z", new ParsePosition(0));
+        assertEquals(dateWithoutTime, d);
+
+        d = ISO8601Utils.parse("20070813Z", new ParsePosition(0));
+        assertEquals(dateWithoutTime, d);
+
+        d = ISO8601Utils.parse("2007-08-13+00:00", new ParsePosition(0));
+        assertEquals(dateWithoutTime, d);
+
+        d = ISO8601Utils.parse("20070813+00:00", new ParsePosition(0));
+        assertEquals(dateWithoutTime, d);
+    }
+
+    public void testParseWithoutTimeAndTimeZoneMustFail() {
+        try {
+            ISO8601Utils.parse("2007-08-13", new ParsePosition(0));
+            fail();
+        } catch (ParseException p) {
+        }
+        try {
+            ISO8601Utils.parse("20070813", new ParsePosition(0));
+            fail();
+        } catch (ParseException p) {
+        }
+        try {
+            ISO8601Utils.parse("2007-08-13", new ParsePosition(0));
+            fail();
+        } catch (ParseException p) {
+        }
+        try {
+            ISO8601Utils.parse("20070813", new ParsePosition(0));
+            fail();
+        } catch (ParseException p) {
+        }
+    }
+    
+    
+    public void testParseOptional() throws java.text.ParseException {
+        Date d = ISO8601Utils.parse("2007-08-13T19:51Z", new ParsePosition(0));
+        assertEquals(dateZeroSecondAndMillis, d);
+
+        d = ISO8601Utils.parse("2007-08-13T1951Z", new ParsePosition(0));
+        assertEquals(dateZeroSecondAndMillis, d);
+
+        d = ISO8601Utils.parse("2007-08-13T21:51+02:00", new ParsePosition(0));
+        assertEquals(dateZeroSecondAndMillis, d);
+    }
 }
diff --git a/src/test/java/com/fasterxml/jackson/databind/util/TestObjectBuffer.java b/src/test/java/com/fasterxml/jackson/databind/util/TestObjectBuffer.java
index e709136..bdaba8f 100644
--- a/src/test/java/com/fasterxml/jackson/databind/util/TestObjectBuffer.java
+++ b/src/test/java/com/fasterxml/jackson/databind/util/TestObjectBuffer.java
@@ -2,10 +2,10 @@
 
 import java.util.*;
 
-import com.fasterxml.jackson.test.BaseTest;
+import com.fasterxml.jackson.databind.BaseMapTest;
 
 public class TestObjectBuffer
-    extends BaseTest
+    extends BaseMapTest
 {
     /**
      * First a test that treats results as plain old Object[]
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 1e9b566..c0b201f 100644
--- a/src/test/java/com/fasterxml/jackson/databind/util/TestTokenBuffer.java
+++ b/src/test/java/com/fasterxml/jackson/databind/util/TestTokenBuffer.java
@@ -5,9 +5,10 @@
 
 import com.fasterxml.jackson.core.*;
 import com.fasterxml.jackson.core.util.JsonParserSequence;
+import com.fasterxml.jackson.databind.BaseMapTest;
 import com.fasterxml.jackson.databind.ObjectMapper;
 
-public class TestTokenBuffer extends com.fasterxml.jackson.test.BaseTest
+public class TestTokenBuffer extends BaseMapTest
 {
     /*
     /**********************************************************
diff --git a/src/test/java/com/fasterxml/jackson/failing/TestConvertingSerializer357.java b/src/test/java/com/fasterxml/jackson/failing/TestConvertingSerializer357.java
index d72721e..46aec41 100644
--- a/src/test/java/com/fasterxml/jackson/failing/TestConvertingSerializer357.java
+++ b/src/test/java/com/fasterxml/jackson/failing/TestConvertingSerializer357.java
@@ -9,16 +9,16 @@
     extends com.fasterxml.jackson.databind.BaseMapTest
 {
     // [Issue#357]
-    static class A { }
+    static class Value { }
 
-    static class B {
-        @JsonSerialize(contentConverter = AToStringConverter.class)
-        public List<A> list = Arrays.asList(new A());
+    static class ListWrapper {
+        @JsonSerialize(contentConverter = ValueToStringListConverter.class)
+        public List<Value> list = Arrays.asList(new Value());
     }
 
-    static class AToStringConverter extends StdConverter<A, List<String>> {
+    static class ValueToStringListConverter extends StdConverter<Value, List<String>> {
         @Override
-        public List<String> convert(A value) {
+        public List<String> convert(Value value) {
             return Arrays.asList("Hello world!");
         }
     }
@@ -31,7 +31,7 @@
 
     // [Issue#357]
     public void testConverterForList357() throws Exception {
-        String json = objectWriter().writeValueAsString(new B());
+        String json = objectWriter().writeValueAsString(new ListWrapper());
         assertEquals("{\"list\":[[\"Hello world!\"]]}", json);
     }
 }
diff --git a/src/test/java/com/fasterxml/jackson/failing/TestExternalTypeId.java b/src/test/java/com/fasterxml/jackson/failing/TestExternalTypeId222.java
similarity index 97%
rename from src/test/java/com/fasterxml/jackson/failing/TestExternalTypeId.java
rename to src/test/java/com/fasterxml/jackson/failing/TestExternalTypeId222.java
index ab68534..8f1649c 100644
--- a/src/test/java/com/fasterxml/jackson/failing/TestExternalTypeId.java
+++ b/src/test/java/com/fasterxml/jackson/failing/TestExternalTypeId222.java
@@ -6,7 +6,7 @@
 import com.fasterxml.jackson.annotation.*;
 import com.fasterxml.jackson.databind.*;
 
-public class TestExternalTypeId extends BaseMapTest
+public class TestExternalTypeId222 extends BaseMapTest
 {
 	@SuppressWarnings("unused")
 	public void testTypes() throws IOException {
@@ -105,6 +105,4 @@
         String json = mapper.writeValueAsString(input);
         assertEquals("{\"value\":{\"x\":13},\"type\":\"foo\"}", json);
     }
-    
-
 }
diff --git a/src/test/java/com/fasterxml/jackson/failing/TestJavaType76.java b/src/test/java/com/fasterxml/jackson/failing/TestJavaType76.java
index 836882e..74bb097 100644
--- a/src/test/java/com/fasterxml/jackson/failing/TestJavaType76.java
+++ b/src/test/java/com/fasterxml/jackson/failing/TestJavaType76.java
@@ -2,14 +2,14 @@
 
 import java.util.*;
 
+import com.fasterxml.jackson.databind.BaseMapTest;
 import com.fasterxml.jackson.databind.JavaType;
 import com.fasterxml.jackson.databind.type.TypeFactory;
 
 /**
  * Failing test related to [Issue#76]
  */
-public class TestJavaType76
-    extends com.fasterxml.jackson.test.BaseTest
+public class TestJavaType76 extends BaseMapTest
 {
     @SuppressWarnings("serial")
     static class HashTree<K, V> extends HashMap<K, HashTree<K, V>> { }
diff --git a/src/test/java/com/fasterxml/jackson/failing/TestMapSerialization588.java b/src/test/java/com/fasterxml/jackson/failing/TestMapSerialization588.java
new file mode 100644
index 0000000..19136e4
--- /dev/null
+++ b/src/test/java/com/fasterxml/jackson/failing/TestMapSerialization588.java
@@ -0,0 +1,40 @@
+package com.fasterxml.jackson.failing;
+
+import java.io.IOException;
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.databind.*;
+
+public class TestMapSerialization588 extends BaseMapTest
+{
+    static class NoEmptiesMapContainer {
+        @JsonInclude(value=JsonInclude.Include.NON_EMPTY,
+                content=JsonInclude.Include.NON_EMPTY)
+        public Map<String,String> stuff = new LinkedHashMap<String,String>();
+        
+        public NoEmptiesMapContainer add(String key, String value) {
+            stuff.put(key, value);
+            return this;
+        }
+    }
+
+    /*
+    /**********************************************************
+    /* Test methods
+    /**********************************************************
+     */
+
+    final private ObjectMapper MAPPER = objectMapper();
+
+    // [databind#588]
+    public void testNonNullValueMapViaProp() throws IOException
+    {
+        String json = MAPPER.writeValueAsString(new NoEmptiesMapContainer()
+            .add("a", null)
+            .add("b", ""));
+        assertEquals(aposToQuotes("{}"), json);
+    }
+
+}
diff --git a/src/test/java/com/fasterxml/jackson/failing/TestMultipleExternalIds.java b/src/test/java/com/fasterxml/jackson/failing/TestMultipleExternalIds291.java
similarity index 96%
rename from src/test/java/com/fasterxml/jackson/failing/TestMultipleExternalIds.java
rename to src/test/java/com/fasterxml/jackson/failing/TestMultipleExternalIds291.java
index f89643a..7b942d8 100644
--- a/src/test/java/com/fasterxml/jackson/failing/TestMultipleExternalIds.java
+++ b/src/test/java/com/fasterxml/jackson/failing/TestMultipleExternalIds291.java
@@ -5,7 +5,7 @@
 import com.fasterxml.jackson.annotation.JsonTypeInfo.Id;
 import com.fasterxml.jackson.databind.*;
 
-public class TestMultipleExternalIds extends BaseMapTest
+public class TestMultipleExternalIds291 extends BaseMapTest
 {
     // For [Issue#291]
     interface F1 {}
diff --git a/src/test/java/com/fasterxml/jackson/failing/TestObjectIdWithInjectables538.java b/src/test/java/com/fasterxml/jackson/failing/TestObjectIdWithInjectables538.java
new file mode 100644
index 0000000..8c04b57
--- /dev/null
+++ b/src/test/java/com/fasterxml/jackson/failing/TestObjectIdWithInjectables538.java
@@ -0,0 +1,57 @@
+package com.fasterxml.jackson.failing;
+
+import com.fasterxml.jackson.annotation.*;
+
+import com.fasterxml.jackson.databind.*;
+
+public class TestObjectIdWithInjectables538 extends BaseMapTest
+{
+    @JsonIdentityInfo(generator = ObjectIdGenerators.IntSequenceGenerator.class)
+    public static class A {
+        public B b;
+
+        public A(@JacksonInject("i1") String injected) {
+        }
+    }
+
+    @JsonIdentityInfo(generator = ObjectIdGenerators.IntSequenceGenerator.class)
+    public static class B {
+        public A a;
+
+        public B(@JacksonInject("i2") String injected) {
+        }
+    } 
+
+    /*
+    /*****************************************************
+    /* Test methods
+    /*****************************************************
+     */
+    
+    private final ObjectMapper MAPPER = new ObjectMapper();
+
+    public void testWithInjectables538() throws Exception
+    {
+        A a = new A("a");
+        B b = new B("b");
+        a.b = b;
+        b.a = a;
+
+        String json = MAPPER.writeValueAsString(a);
+
+        InjectableValues.Std inject = new InjectableValues.Std();
+        inject.addValue("i1", "e1");
+        inject.addValue("i2", "e2");
+        A output = null;
+
+        try {
+            output = MAPPER.reader(inject).withType(A.class).readValue(json);
+        } catch (Exception e) {
+            throw new IllegalStateException("Failed to deserialize from JSON '"+json+"'", e);
+        }
+        assertNotNull(output);
+
+        assertNotNull(output.b);
+    }
+}
+
diff --git a/src/test/java/com/fasterxml/jackson/failing/TestPOJOAsArray.java b/src/test/java/com/fasterxml/jackson/failing/TestPOJOAsArray.java
deleted file mode 100644
index 31fde8d..0000000
--- a/src/test/java/com/fasterxml/jackson/failing/TestPOJOAsArray.java
+++ /dev/null
@@ -1,29 +0,0 @@
-package com.fasterxml.jackson.failing;
-
-import com.fasterxml.jackson.annotation.JsonFormat;
-import com.fasterxml.jackson.annotation.JsonFormat.Shape;
-
-import com.fasterxml.jackson.databind.BaseMapTest;
-import com.fasterxml.jackson.databind.DeserializationFeature;
-import com.fasterxml.jackson.databind.ObjectMapper;
-
-public class TestPOJOAsArray extends BaseMapTest
-{
-    // for [JACKSON-805]
-    @JsonFormat(shape=Shape.ARRAY)
-    static class SingleBean {
-        public String name = "foo";
-    }
-
-    
-    // for [JACKSON-805]
-    public void testBeanAsArrayUnwrapped() throws Exception
-    {
-        ObjectMapper mapper = new ObjectMapper();
-        mapper.enable(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY);
-        SingleBean result = mapper.readValue(quote("foobar"), SingleBean.class);
-        assertNotNull(result);
-        assertEquals("foobar", result.name);
-    }
-
-}
diff --git a/src/test/java/com/fasterxml/jackson/failing/TestPolymorphicDeserialization.java b/src/test/java/com/fasterxml/jackson/failing/TestPolymorphicDeserialization.java
index 77081ef..f37b6ad 100644
--- a/src/test/java/com/fasterxml/jackson/failing/TestPolymorphicDeserialization.java
+++ b/src/test/java/com/fasterxml/jackson/failing/TestPolymorphicDeserialization.java
@@ -15,7 +15,7 @@
  * deserializer comes to different conclusion (using default implementation class),
  * resulting in a <code>ClassCastException</code>.
  * Whether this is wrong, and if so, can we fix it, is unknown at this point
- * (2.3.0-SNAPSHOT): quite possibly this can not be changed.
+ * (2.3): quite possibly this can not be changed.
  */
 public class TestPolymorphicDeserialization extends BaseMapTest
 {
diff --git a/src/test/java/com/fasterxml/jackson/failing/TestScalaLikeImplicitProperties.java b/src/test/java/com/fasterxml/jackson/failing/TestScalaLikeImplicitProperties.java
index cd3ea37..a0cf4c2 100644
--- a/src/test/java/com/fasterxml/jackson/failing/TestScalaLikeImplicitProperties.java
+++ b/src/test/java/com/fasterxml/jackson/failing/TestScalaLikeImplicitProperties.java
@@ -31,19 +31,38 @@
             String name = null;
             if (member instanceof AnnotatedField) {
                 name = member.getName();
-            }
-            if (name != null) {
-                if (name.endsWith("‿")) {                    
+                if (name.endsWith("‿")) {
                     return name.substring(0, name.length()-1);
                 }
+            } else if (member instanceof AnnotatedMethod) {
+                name = member.getName();
+                if (name.endsWith("_⁀")) {
+                    return name.substring(0, name.length()-2);
+                }
+                if (!name.startsWith("get") && !name.startsWith("set")) {
+                    return name;
+                }
+            } else if (member instanceof AnnotatedParameter) {
+                // A placeholder for legitimate property name detection
+                // such as what the JDK8 module provides
+                return "prop";
             }
             return null;
         }
+
+        @Override
+        public boolean hasCreatorAnnotation(Annotated a) {
+            // A placeholder for legitmate creator detection.
+            // In Scala, all primary constructors should be creators,
+            // but I can't obtain a reference to the AnnotatedClass from the
+            // AnnotatedConstructor, so it's simulated here.
+            return (a instanceof AnnotatedConstructor);
+        }
     }
     
     static class ValProperty
     {
-        public final String prop‿;
+        private final String prop‿;
         public String prop() { return prop‿; }
 
         public ValProperty(String prop) {
@@ -54,7 +73,7 @@
 
     static class ValWithBeanProperty
     {
-        public final String prop‿;
+        private final String prop‿;
         public String prop() { return prop‿; }
         public String getProp() { return prop‿; }
 
@@ -66,7 +85,7 @@
 
     static class VarProperty
     {
-        public String prop‿;
+        private String prop‿;
         public String prop() { return prop‿; }
         public void prop_⁀(String p) { prop‿ = p; }
 
@@ -78,7 +97,7 @@
 
     static class VarWithBeanProperty
     {
-        public String prop‿;
+        private String prop‿;
         public String prop() { return prop‿; }
         public void prop_⁀(String p) { prop‿ = p; }
         public String getProp() { return prop‿; }
@@ -105,8 +124,6 @@
     {
         ObjectMapper m = manglingMapper();
 
-        // TODO: Activate whatever handler implements the property detection style
-
         assertEquals("{\"prop\":\"val\"}", m.writeValueAsString(new ValProperty("val")));
     }
 
@@ -115,8 +132,6 @@
     {
         ObjectMapper m = manglingMapper();
 
-        // TODO: Activate whatever handler implements the property detection style
-
         assertEquals("{\"prop\":\"val\"}", m.writeValueAsString(new ValWithBeanProperty("val")));
     }
 
@@ -125,8 +140,6 @@
     {
         ObjectMapper m = manglingMapper();
 
-        // TODO: Activate whatever handler implements the property detection style
-
         assertEquals("{\"prop\":\"var\"}", m.writeValueAsString(new VarProperty("var")));
         VarProperty result = m.readValue("{\"prop\":\"read\"}", VarProperty.class);
         assertEquals("read", result.prop());
@@ -137,8 +150,6 @@
     {
         ObjectMapper m = manglingMapper();
 
-        // TODO: Activate whatever handler implements the property detection style
-
         assertEquals("{\"prop\":\"var\"}", m.writeValueAsString(new VarWithBeanProperty("var")));
         VarWithBeanProperty result = m.readValue("{\"prop\":\"read\"}", VarWithBeanProperty.class);
         assertEquals("read", result.prop());
@@ -149,8 +160,6 @@
     {
         ObjectMapper m = manglingMapper();
 
-        // TODO: Activate whatever handler implements the property detection style
-
         assertEquals("{\"prop\":\"get/set\"}", m.writeValueAsString(new GetterSetterProperty()));
         GetterSetterProperty result = m.readValue("{\"prop\":\"read\"}", GetterSetterProperty.class);
         assertEquals("read", result.prop());
diff --git a/src/test/java/com/fasterxml/jackson/failing/TestSetterlessProperties501.java b/src/test/java/com/fasterxml/jackson/failing/TestSetterlessProperties501.java
index 2d822a6..8363e75 100644
--- a/src/test/java/com/fasterxml/jackson/failing/TestSetterlessProperties501.java
+++ b/src/test/java/com/fasterxml/jackson/failing/TestSetterlessProperties501.java
@@ -6,12 +6,6 @@
 
 import com.fasterxml.jackson.databind.*;
 
-/**
- * Unit tests for verifying that feature requested
- * via [JACKSON-88] ("setterless collections") work as
- * expected, similar to how Collections and Maps work
- * with JAXB.
- */
 public class TestSetterlessProperties501
     extends BaseMapTest
 {
diff --git a/src/test/java/com/fasterxml/jackson/failing/TestTypeWithJsonValue466.java b/src/test/java/com/fasterxml/jackson/failing/TestTypeWithJsonValue466.java
index 3cda760..fa90f2a 100644
--- a/src/test/java/com/fasterxml/jackson/failing/TestTypeWithJsonValue466.java
+++ b/src/test/java/com/fasterxml/jackson/failing/TestTypeWithJsonValue466.java
@@ -1,6 +1,7 @@
 package com.fasterxml.jackson.failing;
 
 import java.io.*;
+import java.math.BigDecimal;
 import java.util.*;
 
 import com.fasterxml.jackson.annotation.*;
@@ -12,17 +13,17 @@
     // The following is required for the testDecimalMetadata test case. That case fails.
     @JsonTypeName(value = "decimalValue")
     public static class DecimalValue {
-        private java.math.BigDecimal value;
-        public DecimalValue(){ this.value = java.math.BigDecimal.valueOf( 1234.4321 ); }
+        private BigDecimal value;
+        public DecimalValue() { value = new BigDecimal("111.1"); }
      
         @JsonValue
-        public java.math.BigDecimal getValue(){ return value; }
+        public BigDecimal getValue(){ return value; }
     }
 
     @JsonPropertyOrder({"key","value"})
     public static class DecimalEntry {
-    public DecimalEntry(){}
-        public String getKey(){ return "num"; }
+    public DecimalEntry() {}
+        public String getKey() { return "num"; }
          
         @JsonTypeInfo(use=JsonTypeInfo.Id.NAME, include=JsonTypeInfo.As.EXTERNAL_PROPERTY)
         public DecimalValue getValue(){
@@ -41,10 +42,10 @@
     @JsonTypeName(value = "doubleValue")
     public static class DoubleValue {
         private Double value;
-        public DoubleValue(){ this.value = 1234.4321; }
+        public DoubleValue() { value = 1234.25; }
          
         @JsonValue
-        public Double getValue(){ return value; }
+        public Double getValue() { return value; }
     }
 
     @JsonPropertyOrder({"key","value"})
@@ -67,14 +68,14 @@
     
     public void testDoubleMetadata() throws IOException {
         DoubleMetadata doub = new DoubleMetadata();
-        String expected = "{\"metadata\":[{\"key\":\"num\",\"value\":1234.4321,\"@type\":\"doubleValue\"}]}";
+        String expected = "{\"metadata\":[{\"key\":\"num\",\"value\":1234.25,\"@type\":\"doubleValue\"}]}";
         String json = MAPPER.writeValueAsString(doub);
         assertEquals("Serialized json not equivalent", expected, json);
     }
 
     public void testDecimalMetadata() throws IOException{
         DecimalMetadata dec = new DecimalMetadata();
-        String expected = "{\"metadata\":[{\"key\":\"num\",\"value\":1234.4321,\"@type\":\"decimalValue\"}]}";
+        String expected = "{\"metadata\":[{\"key\":\"num\",\"value\":111.1,\"@type\":\"decimalValue\"}]}";
         String json = MAPPER.writeValueAsString(dec);
         assertEquals("Serialized json not equivalent", expected, json);
     }
diff --git a/src/test/java/com/fasterxml/jackson/failing/TestUnknownProperty426.java b/src/test/java/com/fasterxml/jackson/failing/TestUnknownProperty426.java
index 53468d7..d9083ff 100644
--- a/src/test/java/com/fasterxml/jackson/failing/TestUnknownProperty426.java
+++ b/src/test/java/com/fasterxml/jackson/failing/TestUnknownProperty426.java
@@ -10,8 +10,8 @@
 public class TestUnknownProperty426 extends BaseMapTest
 {
     // For [Issue#426]
-    @JsonIgnoreProperties({ "userId"})
-    public class User {
+    @JsonIgnoreProperties({ "userId" })
+    static class User {
         Integer userId; 
 
         void setUserId(String id) {
@@ -37,8 +37,8 @@
 
     public void testIssue426() throws Exception
     {
-        String jsonString = "{id: 9, firstName: \"Mike\" }";
-        User result = MAPPER.reader( User.class ).readValue(jsonString);
+        final String JSON = aposToQuotes("{'id': 9, 'firstName': 'Mike' }");
+        User result = MAPPER.reader(User.class).readValue(JSON);
         assertNotNull(result);
     }
 }
diff --git a/src/test/java/com/fasterxml/jackson/failing/TestVisibleExternalId.java b/src/test/java/com/fasterxml/jackson/failing/TestVisibleExternalId.java
deleted file mode 100644
index 1e00054..0000000
--- a/src/test/java/com/fasterxml/jackson/failing/TestVisibleExternalId.java
+++ /dev/null
@@ -1,43 +0,0 @@
-package com.fasterxml.jackson.failing;
-
-import com.fasterxml.jackson.annotation.*;
-import com.fasterxml.jackson.annotation.JsonTypeInfo.As;
-import com.fasterxml.jackson.annotation.JsonTypeInfo.Id;
-
-import com.fasterxml.jackson.databind.BaseMapTest;
-import com.fasterxml.jackson.databind.ObjectMapper;
-
-public class TestVisibleExternalId extends BaseMapTest
-{
-    // [Issue#408]
-    static class ExternalBeanWithId
-    {
-        @JsonTypeInfo(use=Id.NAME, include=As.EXTERNAL_PROPERTY, property="type", visible=true)
-        public ValueBean bean;
-
-        public ExternalBeanWithId() { }
-        public ExternalBeanWithId(int v) {
-            bean = new ValueBean(v);
-        }
-    }
-
-    @JsonTypeName("vbean")
-    static class ValueBean {
-        public int value;
-        
-        public ValueBean() { }
-        public ValueBean(int v) { value = v; }
-    }
-
-    private final ObjectMapper MAPPER = objectMapper();
-    
-    // [Issue#408]
-    public void testVisibleTypeId() throws Exception
-    {
-        String json = MAPPER.writeValueAsString(new ExternalBeanWithId(3));
-        ExternalBeanWithId result = MAPPER.readValue(json, ExternalBeanWithId.class);
-        assertNotNull(result);
-        assertNotNull(result.bean);
-        assertEquals(3, result.bean.value);
-    }
-}