/*
 *
 *  Copyright 2016 Netflix, Inc.
 *
 *     Licensed under the Apache License, Version 2.0 (the "License");
 *     you may not use this file except in compliance with the License.
 *     You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0
 *
 *     Unless required by applicable law or agreed to in writing, software
 *     distributed under the License is distributed on an "AS IS" BASIS,
 *     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *     See the License for the specific language governing permissions and
 *     limitations under the License.
 *
 */
package com.netflix.metacat.client.module;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.RuntimeJsonMappingException;
import feign.Response;
import feign.codec.Decoder;
import lombok.NonNull;

import javax.annotation.Nonnull;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Type;

/**
 * Decoder for Metacat response.
 *
 * @author amajumdar
 */
public class JacksonDecoder implements Decoder {
    private final ObjectMapper mapper;

    /**
     * Constructor.
     *
     * @param mapper Jackson mapper for Metacat response.
     */
    public JacksonDecoder(@Nonnull @NonNull final ObjectMapper mapper) {
        this.mapper = mapper;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public Object decode(final Response response, final Type type) throws IOException {
        if (
            response.body() == null
                || response.status() == 204
                || (response.body().length() != null && response.body().length() == 0)
            ) {
            return null;
        }
        final InputStream inputStream = response.body().asInputStream();
        try {
            return mapper.readValue(inputStream, mapper.constructType(type));
        } catch (RuntimeJsonMappingException e) {
            if (e.getCause() != null && e.getCause() instanceof IOException) {
                throw IOException.class.cast(e.getCause());
            }
            throw e;
        }
    }
}

@@ -677,16 +677,76 @@
 odule;%0A%0A
+import com.fasterxml.jackson.databind.JsonMappingException;%0A
 import c
@@ -785,24 +785,24 @@
 jectMapper;%0A
-
 import com.f
@@ -1007,27 +1007,22 @@
 java.io.
-InputStream
+Reader
 ;%0Aimport
@@ -1045,16 +1045,51 @@
 ct.Type;
+%0Aimport java.net.HttpURLConnection;
 %0A%0A/**%0A *
@@ -1196,16 +1196,110 @@
 coder %7B%0A
+    private static final String NO_CONTENT_MESSAGE = %22No content to map due to end-of-input%22;%0A
     priv
@@ -1718,22 +1718,53 @@
 nse.
-body() == null
+status() == HttpURLConnection.HTTP_NO_CONTENT
 %0A   
@@ -1792,23 +1792,22 @@
 nse.
-status
+body
 () == 
-204
+null
 %0A   
@@ -1941,24 +1941,25 @@
       %7D%0A
+%0A
         
 final In
@@ -1954,163 +1954,623 @@
     
+try (
 final 
-InputStream inputStream = response.body().asInputStream();%0A        try %7B%0A            return mapper.readValue(inputStream, mapper.constructType(type))
+Reader reader = response.body().asReader()) %7B%0A            return this.mapper.readValue(reader, this.mapper.constructType(type));%0A        %7D catch (final JsonMappingException jme) %7B%0A            // The case where for whatever reason (most likely bad design) where the server returned OK and%0A            // trying to de-serialize the content had no content (e.g. the return status should have been no-content)%0A            if (response.status() == HttpURLConnection.HTTP_OK%0A                && jme.getMessage().startsWith(NO_CONTENT_MESSAGE)) %7B%0A                return null;%0A            %7D%0A%0A            throw jme
 ;%0A  
@@ -2584,16 +2584,22 @@
  catch (
+final 
 RuntimeJ

Fix HTTP OK no-content edge case in client body handler (#185)