Improved JacksonJsonProvider based on suggestions by Ryan H.

diff --git a/src/jaxrs/java/org/codehaus/jackson/jaxrs/JacksonJsonProvider.java b/src/jaxrs/java/org/codehaus/jackson/jaxrs/JacksonJsonProvider.java
index 0c80647..dbff6e7 100644
--- a/src/jaxrs/java/org/codehaus/jackson/jaxrs/JacksonJsonProvider.java
+++ b/src/jaxrs/java/org/codehaus/jackson/jaxrs/JacksonJsonProvider.java
@@ -5,11 +5,10 @@
 import java.lang.reflect.Type;
 
 import javax.ws.rs.*;
+import javax.ws.rs.core.Context;
 import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.MultivaluedMap;
-import javax.ws.rs.ext.MessageBodyReader;
-import javax.ws.rs.ext.MessageBodyWriter;
-import javax.ws.rs.ext.Provider;
+import javax.ws.rs.ext.*;
 
 import org.codehaus.jackson.*;
 import org.codehaus.jackson.map.ObjectMapper;
@@ -37,19 +36,11 @@
 {
     /*
     ///////////////////////////////////////////////////////
-    // Provider objects we use
+    // Context configuration
     ///////////////////////////////////////////////////////
      */
 
-    /**
-     * Factory used to construct underlying JSON parsers and generators
-     */
-    JsonFactory _jsonFactory;
-
-    /**
-     * Mapper that is responsible for data binding.
-     */
-    ObjectMapper _objectMapper;
+    protected final ContextResolver<ObjectMapper> _resolver;
 
     /*
     ///////////////////////////////////////////////////////
@@ -80,24 +71,34 @@
      */
 
     /**
-     * Default constructor that is usually used when instances are to
-     * be constructed from given class. If so, an instance of
-     * {@link ObjectMapper} is constructed with default settings.
+     * Default constructor that shouldn't be needed when used it
+     * with actul JAX-RS implementation. But it may be needed from
+     * tests or such; if so, it will construct appropriate
+     * set up to still work as expected.
      */
     public JacksonJsonProvider()
     {
-        this(new ObjectMapper());
+        this(null);
     }
 
-    public JacksonJsonProvider(ObjectMapper m)
+    public JacksonJsonProvider(@Context Providers providers)
     {
-        _objectMapper = m;
-        _jsonFactory = m.getJsonFactory();
-        /* note: we have to prevent underlying parser/generator from
-         * closing the stream we deal with, so:
-         */
-        _jsonFactory.disableParserFeature(JsonParser.Feature.AUTO_CLOSE_SOURCE);
-        _jsonFactory.disableGeneratorFeature(JsonGenerator.Feature.AUTO_CLOSE_TARGET);
+        ContextResolver<ObjectMapper> resolver;
+
+        if (providers == null) {
+            resolver = null;
+        } else {
+            // null -> no filtering by MediaType
+            resolver = providers.getContextResolver(ObjectMapper.class, null);
+        }
+        ObjectMapper mapper;
+
+        if (resolver == null) {
+            mapper = new ObjectMapper();
+            // If not accessible via injection, let's still create one
+            resolver = new SingleContextResolver<ObjectMapper>(mapper);
+        }
+        _resolver = resolver;
     }
 
     /*
@@ -106,9 +107,6 @@
     ///////////////////////////////////////////////////////
      */
 
-    public ObjectMapper getObjectMapper() { return _objectMapper; }
-    public void setObjectMapper(ObjectMapper m) { _objectMapper = m; }
-
     public void checkCanDeserialize(boolean state) { _cfgCheckCanDeserialize = state; }
     public void checkCanSerialize(boolean state) { _cfgCheckCanSerialize = state; }
 
@@ -126,7 +124,8 @@
         }
         // Also: if we really want to verify that we can serialize, we'll check:
         if (_cfgCheckCanSerialize) {
-            if (!_objectMapper.canDeserialize(_convertType(type))) {
+            ObjectMapper mapper = _resolver.getContext(type);
+            if (!mapper.canDeserialize(_convertType(type))) {
                 return false;
             }
         }
@@ -136,8 +135,13 @@
     public Object readFrom(Class<Object> type, Type genericType, Annotation[] annotations, MediaType mediaType, MultivaluedMap<String,String> httpHeaders, InputStream entityStream) 
         throws IOException
     {
-        JsonParser jp = _jsonFactory.createJsonParser(entityStream);
-        return _objectMapper.readValue(jp, _convertType(genericType));
+        ObjectMapper mapper = _resolver.getContext(type);
+        JsonParser jp = mapper.getJsonFactory().createJsonParser(entityStream);
+        /* Important: we are NOT to close the underlying stream after
+         * mapping, so we need to instruct parser:
+         */
+        jp.disableFeature(JsonParser.Feature.AUTO_CLOSE_SOURCE);
+        return mapper.readValue(jp, _convertType(genericType));
     }
 
     /*
@@ -162,14 +166,12 @@
         }
         // Also: if we really want to verify that we can deserialize, we'll check:
         if (_cfgCheckCanSerialize) {
-            if (!_objectMapper.canSerialize(type)) {
+            ObjectMapper mapper = _resolver.getContext(type);
+            if (!mapper.canSerialize(type)) {
                 return false;
             }
         }
-        /* To know for sure we'd need to find a serializer; for now,
-         * let's claim we can handle anything.
-         */
-        return (MediaType.APPLICATION_JSON_TYPE.equals(mediaType));
+        return true;
     }
 
     public void writeTo(Object value, Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType, MultivaluedMap<String,Object> httpHeaders, OutputStream entityStream) 
@@ -178,8 +180,10 @@
         /* 27-Feb-2009, tatu: Where can we find desired encoding? Within
          *   http headers?
          */
-        JsonGenerator jg = _jsonFactory.createJsonGenerator(entityStream, JsonEncoding.UTF8);
-        _objectMapper.writeValue(jg, value);
+        ObjectMapper mapper = _resolver.getContext(type);
+        JsonGenerator jg = mapper.getJsonFactory().createJsonGenerator(entityStream, JsonEncoding.UTF8);
+        jg.disableFeature(JsonGenerator.Feature.AUTO_CLOSE_TARGET);
+        mapper.writeValue(jg, value);
     }
 
     /*
@@ -196,4 +200,28 @@
     {
         return TypeFactory.fromType(jdkType);
     }
+
+    /*
+    ////////////////////////////////////////////////////
+    // Helper classes
+    ////////////////////////////////////////////////////
+     */
+
+    /**
+     * We need a simple container to use for feeding our ObjectMapper,
+     * in case it's not injected from outside.
+     */
+  final static class SingleContextResolver<T>
+      implements ContextResolver<T>
+  {
+      private final T _singleton;
+
+      public SingleContextResolver(T s) { _singleton = s; }
+
+      public T getContext(Class<?> cls)
+      {
+          // should we use 'cls' somehow? Shouldn't need to?
+          return _singleton;
+      }
+  }
 }