more work on [#120], now Map type
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 5f8e332..261ffc8 100644
--- a/src/main/java/com/fasterxml/jackson/databind/deser/BasicDeserializerFactory.java
+++ b/src/main/java/com/fasterxml/jackson/databind/deser/BasicDeserializerFactory.java
@@ -827,26 +827,6 @@
         return deser;
     }
 
-    // Copied almost verbatim from "createCollectionDeserializer" -- should try to share more code
-    @Override
-    public JsonDeserializer<?> createCollectionLikeDeserializer(DeserializationContext ctxt,
-            CollectionLikeType type, final BeanDescription beanDesc)
-        throws JsonMappingException
-    {
-        JavaType contentType = type.getContentType();
-        // Very first thing: is deserializer hard-coded for elements?
-        JsonDeserializer<Object> contentDeser = contentType.getValueHandler();
-
-        // Then optional type info (1.5): if type has been resolved, we may already know type deserializer:
-        TypeDeserializer contentTypeDeser = contentType.getTypeHandler();
-        // but if not, may still be possible to find:
-        if (contentTypeDeser == null) {
-            contentTypeDeser = findTypeDeserializer(ctxt.getConfig(), contentType);
-        }
-        return _findCustomCollectionLikeDeserializer(type, ctxt.getConfig(), beanDesc,
-                contentTypeDeser, contentDeser);
-    }
-  
     protected JsonDeserializer<?> _findCustomCollectionDeserializer(CollectionType type,
             DeserializationConfig config, BeanDescription beanDesc,
             TypeDeserializer elementTypeDeserializer, JsonDeserializer<?> elementDeserializer)
@@ -861,6 +841,36 @@
         }
         return null;
     }
+    
+    // Copied almost verbatim from "createCollectionDeserializer" -- should try to share more code
+    @Override
+    public JsonDeserializer<?> createCollectionLikeDeserializer(DeserializationContext ctxt,
+            CollectionLikeType type, final BeanDescription beanDesc)
+        throws JsonMappingException
+    {
+        JavaType contentType = type.getContentType();
+        // Very first thing: is deserializer hard-coded for elements?
+        JsonDeserializer<Object> contentDeser = contentType.getValueHandler();
+        final DeserializationConfig config = ctxt.getConfig();
+
+        // Then optional type info (1.5): if type has been resolved, we may already know type deserializer:
+        TypeDeserializer contentTypeDeser = contentType.getTypeHandler();
+        // but if not, may still be possible to find:
+        if (contentTypeDeser == null) {
+            contentTypeDeser = findTypeDeserializer(config, contentType);
+        }
+        JsonDeserializer<?> deser = _findCustomCollectionLikeDeserializer(type, config, beanDesc,
+                contentTypeDeser, contentDeser);
+        if (deser != null) {
+            // and then new with 2.2: ability to post-process it too (Issue#120)
+            if (_factoryConfig.hasDeserializerModifiers()) {
+                for (BeanDeserializerModifier mod : _factoryConfig.deserializerModifiers()) {
+                    deser = mod.modifyCollectionLikeDeserializer(config, type, beanDesc, deser);
+                }
+            }
+        }
+        return deser;
+    }
 
     protected JsonDeserializer<?> _findCustomCollectionLikeDeserializer(CollectionLikeType type,
             DeserializationConfig config, BeanDescription beanDesc,
@@ -906,48 +916,56 @@
         }
 
         // 23-Nov-2010, tatu: Custom deserializer?
-        JsonDeserializer<?> custom = _findCustomMapDeserializer(type, config, beanDesc,
+        JsonDeserializer<?> deser = _findCustomMapDeserializer(type, config, beanDesc,
                 keyDes, contentTypeDeser, contentDeser);
 
-        if (custom != null) {
-            return custom;
-        }
-        // Value handling is identical for all, but EnumMap requires special handling for keys
-        Class<?> mapClass = type.getRawClass();
-        if (EnumMap.class.isAssignableFrom(mapClass)) {
-            Class<?> kt = keyType.getRawClass();
-            if (kt == null || !kt.isEnum()) {
-                throw new IllegalArgumentException("Can not construct EnumMap; generic (key) type not available");
+        if (deser == null) {
+            // Value handling is identical for all, but EnumMap requires special handling for keys
+            Class<?> mapClass = type.getRawClass();
+            if (EnumMap.class.isAssignableFrom(mapClass)) {
+                Class<?> kt = keyType.getRawClass();
+                if (kt == null || !kt.isEnum()) {
+                    throw new IllegalArgumentException("Can not construct EnumMap; generic (key) type not available");
+                }
+                deser = new EnumMapDeserializer(type, null, contentDeser);
             }
-            return new EnumMapDeserializer(type, null, contentDeser);
-        }
 
-        // Otherwise, generic handler works ok.
-
-        /* But there is one more twist: if we are being asked to instantiate
-         * an interface or abstract Map, we need to either find something
-         * that implements the thing, or give up.
-         *
-         * Note that we do NOT try to guess based on secondary interfaces
-         * here; that would probably not work correctly since casts would
-         * fail later on (as the primary type is not the interface we'd
-         * be implementing)
-         */
-        if (type.isInterface() || type.isAbstract()) {
-            @SuppressWarnings("rawtypes")
-            Class<? extends Map> fallback = _mapFallbacks.get(mapClass.getName());
-            if (fallback == null) {
-                throw new IllegalArgumentException("Can not find a deserializer for non-concrete Map type "+type);
+            // Otherwise, generic handler works ok.
+    
+            /* But there is one more twist: if we are being asked to instantiate
+             * an interface or abstract Map, we need to either find something
+             * that implements the thing, or give up.
+             *
+             * Note that we do NOT try to guess based on secondary interfaces
+             * here; that would probably not work correctly since casts would
+             * fail later on (as the primary type is not the interface we'd
+             * be implementing)
+             */
+            if (deser == null) {
+                if (type.isInterface() || type.isAbstract()) {
+                    @SuppressWarnings("rawtypes")
+                    Class<? extends Map> fallback = _mapFallbacks.get(mapClass.getName());
+                    if (fallback == null) {
+                        throw new IllegalArgumentException("Can not find a deserializer for non-concrete Map type "+type);
+                    }
+                    mapClass = fallback;
+                    type = (MapType) config.constructSpecializedType(type, mapClass);
+                    // But if so, also need to re-check creators...
+                    beanDesc = config.introspectForCreation(type);
+                }
+                ValueInstantiator inst = findValueInstantiator(ctxt, beanDesc);
+                MapDeserializer md = new MapDeserializer(type, inst, keyDes, contentDeser, contentTypeDeser);
+                md.setIgnorableProperties(config.getAnnotationIntrospector().findPropertiesToIgnore(beanDesc.getClassInfo()));
+                deser = md;
             }
-            mapClass = fallback;
-            type = (MapType) config.constructSpecializedType(type, mapClass);
-            // But if so, also need to re-check creators...
-            beanDesc = config.introspectForCreation(type);
         }
-        ValueInstantiator inst = findValueInstantiator(ctxt, beanDesc);
-        MapDeserializer md = new MapDeserializer(type, inst, keyDes, contentDeser, contentTypeDeser);
-        md.setIgnorableProperties(config.getAnnotationIntrospector().findPropertiesToIgnore(beanDesc.getClassInfo()));
-        return md;
+        // and then new with 2.2: ability to post-process it too (Issue#120)
+        if (_factoryConfig.hasDeserializerModifiers()) {
+            for (BeanDeserializerModifier mod : _factoryConfig.deserializerModifiers()) {
+                deser = mod.modifyMapDeserializer(config, type, beanDesc, deser);
+            }
+        }
+        return deser;
     }
 
     // Copied almost verbatim from "createMapDeserializer" -- should try to share more code
@@ -958,6 +976,7 @@
     {
         JavaType keyType = type.getKeyType();
         JavaType contentType = type.getContentType();
+        final DeserializationConfig config = ctxt.getConfig();
         
         // First: is there annotation-specified deserializer for values?
         @SuppressWarnings("unchecked")
@@ -974,10 +993,19 @@
         TypeDeserializer contentTypeDeser = contentType.getTypeHandler();
         // but if not, may still be possible to find:
         if (contentTypeDeser == null) {
-            contentTypeDeser = findTypeDeserializer(ctxt.getConfig(), contentType);
+            contentTypeDeser = findTypeDeserializer(config, contentType);
         }
-        return _findCustomMapLikeDeserializer(type, ctxt.getConfig(),
+        JsonDeserializer<?> deser = _findCustomMapLikeDeserializer(type, config,
                 beanDesc, keyDes, contentTypeDeser, contentDeser);
+        if (deser != null) {
+            // and then new with 2.2: ability to post-process it too (Issue#120)
+            if (_factoryConfig.hasDeserializerModifiers()) {
+                for (BeanDeserializerModifier mod : _factoryConfig.deserializerModifiers()) {
+                    deser = mod.modifyMapLikeDeserializer(config, type, beanDesc, deser);
+                }
+            }
+        }
+        return deser;
     }
 
     protected JsonDeserializer<?> _findCustomMapDeserializer(MapType type,
diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/BeanDeserializerModifier.java b/src/main/java/com/fasterxml/jackson/databind/deser/BeanDeserializerModifier.java
index 759ee12..08be681 100644
--- a/src/main/java/com/fasterxml/jackson/databind/deser/BeanDeserializerModifier.java
+++ b/src/main/java/com/fasterxml/jackson/databind/deser/BeanDeserializerModifier.java
@@ -130,6 +130,22 @@
             CollectionLikeType type, BeanDescription beanDesc, JsonDeserializer<?> deserializer) {
         return deserializer;
     }
+
+    /**
+     * @since 2.2
+     */
+    public JsonDeserializer<?> modifyMapDeserializer(DeserializationConfig config,
+            MapType type, BeanDescription beanDesc, JsonDeserializer<?> deserializer) {
+        return deserializer;
+    }
+
+    /**
+     * @since 2.2
+     */
+    public JsonDeserializer<?> modifyMapLikeDeserializer(DeserializationConfig config,
+            MapLikeType type, BeanDescription beanDesc, JsonDeserializer<?> deserializer) {
+        return deserializer;
+    }
     
     /*
     
@@ -137,14 +153,6 @@
             JavaType type, BeanDescription beanDesc)
         throws JsonMappingException;
 
-    public abstract JsonDeserializer<?> createMapDeserializer(DeserializationContext ctxt,
-            MapType type, BeanDescription beanDesc)
-        throws JsonMappingException;
-
-    public abstract JsonDeserializer<?> createMapLikeDeserializer(DeserializationContext ctxt,
-            MapLikeType type, BeanDescription beanDesc)
-        throws JsonMappingException;
-
     public abstract KeyDeserializer createKeyDeserializer(DeserializationContext ctxt,
             JavaType type)
         throws JsonMappingException;
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 0af98cb..c85ee72 100644
--- a/src/test/java/com/fasterxml/jackson/databind/deser/TestBeanDeserializer.java
+++ b/src/test/java/com/fasterxml/jackson/databind/deser/TestBeanDeserializer.java
@@ -12,6 +12,7 @@
 import com.fasterxml.jackson.databind.module.SimpleModule;
 import com.fasterxml.jackson.databind.type.ArrayType;
 import com.fasterxml.jackson.databind.type.CollectionType;
+import com.fasterxml.jackson.databind.type.MapType;
 
 @SuppressWarnings("serial")
 public class TestBeanDeserializer extends BaseMapTest
@@ -169,6 +170,20 @@
             };
         }
     }
+
+    static class MapDeserializerModifier extends BeanDeserializerModifier {
+        public JsonDeserializer<?> modifyMapDeserializer(DeserializationConfig config, MapType valueType,
+                BeanDescription beanDesc, JsonDeserializer<?> deserializer) {
+            return (JsonDeserializer<?>) new StdDeserializer<Object>(Object.class) {
+                @Override public Object deserialize(JsonParser jp,
+                        DeserializationContext ctxt) {
+                    HashMap<String,String> map = new HashMap<String,String>();
+                    map.put("a", "foo");
+                    return map;
+                }
+            };
+        }
+    }
     
     /*
     /********************************************************
@@ -247,4 +262,15 @@
         assertEquals(1, result.size());
         assertEquals("foo", result.get(0));
     }
+
+    public void testModifyMapDeserializer() throws Exception
+    {
+        ObjectMapper mapper = new ObjectMapper();
+        mapper.registerModule(new SimpleModule("test")
+            .setDeserializerModifier(new MapDeserializerModifier())
+        );
+        Map<?,?> result = mapper.readValue("{\"a\":1,\"b\":2}", Map.class);
+        assertEquals(1, result.size());
+        assertEquals("foo", result.get("a"));
+    }
 }