io.blobkeeper.server.handler.BaseFileHandler.java Source code

Java tutorial

Introduction

Here is the source code for io.blobkeeper.server.handler.BaseFileHandler.java

Source

package io.blobkeeper.server.handler;

/*
 * Copyright (C) 2015 by Denis M. Gabaydulin
 *
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You 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.
 */

import com.google.common.collect.ImmutableMap;
import io.blobkeeper.cluster.service.ClusterMembershipService;
import io.blobkeeper.common.domain.api.ReturnValue;
import io.blobkeeper.common.logging.MdcContext;
import io.blobkeeper.server.util.ErrorCodeResolver;
import io.blobkeeper.server.util.JsonUtils;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.*;
import io.netty.handler.codec.http.*;
import io.netty.util.CharsetUtil;
import org.jetbrains.annotations.NotNull;

import javax.inject.Inject;

import static io.blobkeeper.common.logging.MdcContext.SRC_NODE;
import static io.blobkeeper.common.util.MdcUtils.setCurrentContext;
import static io.netty.buffer.Unpooled.copiedBuffer;
import static io.netty.channel.ChannelFutureListener.CLOSE;
import static io.netty.handler.codec.http.HttpHeaders.Names.*;
import static io.netty.handler.codec.http.HttpHeaders.Values.KEEP_ALIVE;
import static io.netty.handler.codec.http.HttpResponseStatus.OK;
import static io.netty.handler.codec.http.HttpVersion.HTTP_1_0;
import static io.netty.handler.codec.http.HttpVersion.HTTP_1_1;
import static io.netty.util.CharsetUtil.UTF_8;

public abstract class BaseFileHandler<T> extends SimpleChannelInboundHandler<T> {

    @Inject
    private JsonUtils jsonUtils;

    @Inject
    private ErrorCodeResolver errorCodeResolver;

    @Inject
    protected ClusterMembershipService clusterMembershipService;

    protected void writeResponse(Channel channel, String result, HttpRequest request) {
        // Convert the response content to a ChannelBuffer.
        ByteBuf buf = copiedBuffer(result, CharsetUtil.UTF_8);

        // Decide whether to close the connection or not.
        boolean close = HttpHeaders.Values.CLOSE.equalsIgnoreCase(request.headers().get(CONNECTION))
                || request.getProtocolVersion().equals(HTTP_1_0)
                        && !KEEP_ALIVE.equalsIgnoreCase(request.headers().get(CONNECTION));

        // Build the response object.
        FullHttpResponse response = new DefaultFullHttpResponse(HTTP_1_1, OK, buf);
        response.headers().set(CONTENT_TYPE, "application/json; charset=UTF-8");

        if (!close) {
            // There's no need to add 'Content-Length' header
            // if this is the last response.
            response.headers().set(CONTENT_LENGTH, buf.readableBytes());
        }

        // Write the response.
        ChannelFuture future = channel.writeAndFlush(response);
        // Close the connection after the write operation is done if necessary.
        if (close) {
            future.addListener(ChannelFutureListener.CLOSE);
        }
    }

    protected void sendError(ChannelHandlerContext ctx, HttpResponseStatus status,
            io.blobkeeper.common.domain.Error error) {
        sendError(ctx, status, new ReturnValue<>(error));
    }

    protected void sendError(ChannelHandlerContext ctx, HttpResponseStatus status, ReturnValue<?> returnValue) {
        FullHttpResponse response = new DefaultFullHttpResponse(HTTP_1_1, status,
                Unpooled.copiedBuffer(getJson(returnValue), UTF_8));
        response.headers().set(CONTENT_TYPE, "application/json; charset=UTF-8");

        // Close the connection as soon as the error message is sent.
        ctx.writeAndFlush(response).addListener(CLOSE);
    }

    protected void writeResponse(ChannelHandlerContext ctx, ReturnValue<?> returnValue, HttpRequest request) {
        if (returnValue.hasError()) {
            HttpResponseStatus responseStatus = errorCodeResolver
                    .getResponseStatus(returnValue.getError().getCode());
            sendError(ctx, responseStatus, returnValue);
        } else {
            writeResponse(ctx.channel(), getJson(returnValue), request);
        }
    }

    protected String getJson(@NotNull Object responseContent) {
        return jsonUtils.toJson(responseContent);
    }

    protected void setContext() {
        setCurrentContext(
                new MdcContext(ImmutableMap.of(SRC_NODE, clusterMembershipService.getSelfNode().toString())));
    }
}