package ameba.message.jackson; import ameba.core.Application; import ameba.core.ws.rs.HttpPatchProperties; import ameba.message.internal.MediaType; import ameba.message.jackson.internal.*; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.dataformat.xml.XmlMapper; import org.glassfish.hk2.api.ServiceLocator; import org.glassfish.hk2.api.TypeLiteral; import org.glassfish.hk2.utilities.ServiceLocatorUtilities; import org.glassfish.hk2.utilities.binding.AbstractBinder; import org.glassfish.jersey.CommonProperties; import org.glassfish.jersey.internal.InternalProperties; import org.glassfish.jersey.internal.util.PropertiesHelper; import org.glassfish.jersey.message.filtering.EntityFilteringFeature; import javax.inject.Inject; import javax.ws.rs.ConstrainedTo; import javax.ws.rs.RuntimeType; import javax.ws.rs.core.Configuration; import javax.ws.rs.core.Feature; import javax.ws.rs.core.FeatureContext; import javax.ws.rs.ext.ContextResolver; import javax.ws.rs.ext.MessageBodyReader; import javax.ws.rs.ext.MessageBodyWriter; import java.util.Collections; /** * <p>JacksonFeature class.</p> * * @author ICode * @since 13-8-11 上午6:00 */ @ConstrainedTo(RuntimeType.SERVER) public class JacksonFeature implements Feature { private final static String JSON_FEATURE = JacksonFeature.class.getSimpleName(); @Inject private ServiceLocator locator; @Inject private Application.Mode mode; /** * {@inheritDoc} */ @Override public boolean configure(final FeatureContext context) { final Configuration config = context.getConfiguration(); final String jsonFeature = CommonProperties.getValue(config.getProperties(), config.getRuntimeType(), InternalProperties.JSON_FEATURE, JSON_FEATURE, String.class); // Other JSON providers registered. if (!JSON_FEATURE.equalsIgnoreCase(jsonFeature)) { return false; } // Disable other JSON providers. context.property( PropertiesHelper.getPropertyNameForRuntime(InternalProperties.JSON_FEATURE, config.getRuntimeType()), JSON_FEATURE); if (!config.isRegistered(JacksonJsonProvider.class)) { ServiceLocatorUtilities.bind(locator, new AbstractBinder() { @Override protected void configure() { { final XmlMapper xmlMapper = new XmlMapper(); JacksonUtils.configureMapper(xmlMapper, mode); // 不能用 jdk lambda,否则无法绑定 bind(new ContextResolver<XmlMapper>() { @Override public XmlMapper getContext(Class<?> type) { return xmlMapper; } }).to(new TypeLiteral<ContextResolver<XmlMapper>>() { }); bind(xmlMapper).to(XmlMapper.class).proxy(false); } { final ObjectMapper objectMapper = new ObjectMapper(); JacksonUtils.configureMapper(objectMapper, mode); // 不能用 jdk lambda,否则无法绑定 bind(new ContextResolver<ObjectMapper>() { @Override public ObjectMapper getContext(Class<?> type) { return objectMapper; } }).to(new TypeLiteral<ContextResolver<ObjectMapper>>() { }); bind(objectMapper).to(ObjectMapper.class).proxy(false); } } }); context.register(JsonProcessingExceptionMapper.class); if (EntityFilteringFeature.enabled(config)) { context.register(JacksonFilteringFeature.class); context.register(FilteringJacksonJsonProvider.class, MessageBodyReader.class, MessageBodyWriter.class); context.register(FilteringJacksonXMLProvider.class, MessageBodyReader.class, MessageBodyWriter.class); } else { context.register(JacksonJsonProvider.class, MessageBodyReader.class, MessageBodyWriter.class); context.register(JacksonXMLProvider.class, MessageBodyReader.class, MessageBodyWriter.class); } Collections.addAll(HttpPatchProperties.SUPPORT_PATCH_MEDIA_TYPES, MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML, MediaType.TEXT_XML); return true; } return false; } }