/*
 * Copyright 2015 Bounce Storage, Inc. <info@bouncestorage.com>
 *
 * 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.bouncestorage.swiftproxy;

import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;

import org.glassfish.grizzly.filterchain.FilterChainBuilder;
import org.glassfish.grizzly.filterchain.FilterChainContext;
import org.glassfish.grizzly.http.HttpCodecFilter;
import org.glassfish.grizzly.http.HttpHeader;
import org.glassfish.grizzly.http.HttpResponsePacket;
import org.glassfish.grizzly.http.HttpServerFilter;
import org.glassfish.grizzly.http.server.AddOn;
import org.glassfish.grizzly.http.server.NetworkListener;

public final class ContentLengthAddOn implements AddOn {
    @Override
    public void setup(NetworkListener networkListener, FilterChainBuilder builder) {

        // Get the index of HttpCodecFilter in the HttpServer filter chain
        final int httpCodecFilterIdx = builder.indexOfType(HttpCodecFilter.class);

        if (httpCodecFilterIdx >= 0) {
            // Insert the WebSocketFilter right after HttpCodecFilter
            builder.set(httpCodecFilterIdx, new ContentLengthFilter());
        }
    }

    private static class ContentLengthFilter extends HttpServerFilter {
        @Override
        protected void onInitialLineEncoded(HttpHeader header, FilterChainContext ctx) {
            super.onInitialLineEncoded(header, ctx);

            if (!header.isCommitted()) {
                final HttpResponsePacket response = (HttpResponsePacket) header;
                if (response.getStatus() == Response.Status.NO_CONTENT.getStatusCode()) {
                    response.getHeaders().setValue("Content-Length").setString("0");
                    response.getHeaders().setValue("Content-Type").setString(MediaType.TEXT_PLAIN);
                }
            }
        }
    }
}

@@ -658,16 +658,94 @@
 proxy;%0A%0A
+import static java.util.Objects.requireNonNull;%0A%0Aimport java.io.IOException;%0A%0A
 import j
@@ -806,16 +806,70 @@
 ponse;%0A%0A
+import org.glassfish.grizzly.filterchain.FilterChain;%0A
 import o
@@ -1015,28 +1015,89 @@
 zly.
-http.HttpCodecFilter
+filterchain.FilterChainEvent;%0Aimport org.glassfish.grizzly.filterchain.NextAction
 ;%0Aim
@@ -1644,29 +1644,30 @@
 xOfType(Http
-Codec
+Server
 Filter.class
@@ -1779,16 +1779,114 @@
 cFilter%0A
+            HttpServerFilter originalFilter = (HttpServerFilter) builder.get(httpCodecFilterIdx);%0A
         
@@ -1945,16 +1945,30 @@
 hFilter(
+originalFilter
 ));%0A    
@@ -2052,16 +2052,182 @@
 ilter %7B%0A
+        private HttpServerFilter delegate;%0A%0A        ContentLengthFilter(HttpServerFilter delegate) %7B%0A            this.delegate = requireNonNull(delegate);%0A        %7D%0A%0A
         
@@ -2813,21 +2813,1817 @@
  %7D%0A        %7D
+%0A%0A        @Override%0A        public void onAdded(FilterChain filterChain) %7B%0A            delegate.onAdded(filterChain);%0A        %7D%0A%0A        @Override%0A        public void onRemoved(FilterChain filterChain) %7B%0A            delegate.onRemoved(filterChain);%0A        %7D%0A%0A        @Override%0A        public void onFilterChainChanged(FilterChain filterChain) %7B%0A            delegate.onFilterChainChanged(filterChain);%0A        %7D%0A%0A        @Override%0A        public NextAction handleRead(FilterChainContext filterChainContext) throws IOException %7B%0A            return delegate.handleRead(filterChainContext);%0A        %7D%0A%0A        @Override%0A        public NextAction handleWrite(FilterChainContext filterChainContext) throws IOException %7B%0A            return delegate.handleWrite(filterChainContext);%0A        %7D%0A%0A        @Override%0A        public NextAction handleConnect(FilterChainContext filterChainContext) throws IOException %7B%0A            return delegate.handleConnect(filterChainContext);%0A        %7D%0A%0A        @Override%0A        public NextAction handleAccept(FilterChainContext filterChainContext) throws IOException %7B%0A            return delegate.handleAccept(filterChainContext);%0A        %7D%0A%0A        @Override%0A        public NextAction handleEvent(FilterChainContext filterChainContext, FilterChainEvent filterChainEvent) throws IOException %7B%0A            return delegate.handleEvent(filterChainContext, filterChainEvent);%0A        %7D%0A%0A        @Override%0A        public NextAction handleClose(FilterChainContext filterChainContext) throws IOException %7B%0A            return delegate.handleClose(filterChainContext);%0A        %7D%0A%0A        @Override%0A        public void exceptionOccurred(FilterChainContext filterChainContext, Throwable throwable) %7B%0A            delegate.exceptionOccurred(filterChainContext, throwable);%0A        %7D
 %0A    %7D%0A%7D%0A

fix DELETE with body