io.liveoak.common.codec.ResourceCodecManager.java Source code

Java tutorial

Introduction

Here is the source code for io.liveoak.common.codec.ResourceCodecManager.java

Source

/*
 * Copyright 2013 Red Hat, Inc. and/or its affiliates.
 *
 * Licensed under the Eclipse Public License version 1.0, available at http://www.eclipse.org/legal/epl-v10.html
 */
package io.liveoak.common.codec;

import java.util.Collections;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.stream.Collectors;

import io.liveoak.common.DefaultMediaTypeMatcher;
import io.liveoak.common.codec.binary.DefaultBinaryResourceState;
import io.liveoak.spi.MediaType;
import io.liveoak.spi.MediaTypeMatcher;
import io.liveoak.spi.RequestContext;
import io.liveoak.spi.ResourceErrorResponse;
import io.liveoak.spi.ResourceResponse;
import io.liveoak.spi.resource.async.BinaryResource;
import io.liveoak.spi.resource.async.Resource;
import io.liveoak.spi.state.ResourceState;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import org.jboss.logging.Logger;

/**
 * @author Bob McWhirter
 * @author <a href="http://community.jboss.org/people/kenfinni">Ken Finnigan</a>
 */
public class ResourceCodecManager {

    public void registerResourceCodec(MediaType mediaType, ResourceCodec codec) {
        this.codecs.add(new CodecRegistration(mediaType, codec));
    }

    public ResourceState decode(MediaType mediaType, ByteBuf buf) throws Exception {
        if (buf == null) {
            buf = Unpooled.EMPTY_BUFFER;
        }
        if (MediaType.OCTET_STREAM.equals(mediaType)) {
            return new DefaultBinaryResourceState(buf.retain());
        }

        ResourceCodec codec = getResourceCodec(mediaType);
        if (codec == null || !codec.hasDecoder()) {
            throw new UnsupportedMediaTypeException(MediaTypeMatcher.singleton(mediaType));
        }
        return codec.decode(buf);
    }

    public EncodingResult encode(RequestContext ctx, MediaTypeMatcher mediaTypeMatcher, ResourceResponse response)
            throws Exception {
        Resource resource = response.resource();
        if (resource instanceof BinaryResource) {
            MediaType match = mediaTypeMatcher
                    .findBestMatch(Collections.singletonList(((BinaryResource) resource).mediaType()));

            if (match != null) {
                return new EncodingResult(match, null);
            } else {
                throw new IncompatibleMediaTypeException(mediaTypeMatcher, (BinaryResource) resource);
            }
        }

        MediaType bestMatch = mediaTypeMatcher.findBestMatch(this.codecs.stream().map((e) -> {
            return e.mediaType;
        }).collect(Collectors.toList()));

        // if we don't have a match and the response isn't already an error response, then return a error response
        if (bestMatch == null && !(response instanceof ResourceErrorResponse)) {
            throw new UnsupportedMediaTypeException(mediaTypeMatcher);
        }

        ResourceCodec codec = getResourceCodec(bestMatch);

        if (codec == null) {
            codec = getResourceCodec(MediaType.JSON);
            bestMatch = MediaType.JSON;
        }

        if (!codec.hasEncoder()) {
            log.trace("This media is not supported: " + mediaTypeMatcher + " (codecs: " + codecs + ")");
            throw new UnsupportedMediaTypeException(mediaTypeMatcher);
        }

        return new EncodingResult(bestMatch, codec.encode(ctx, response.state()));
    }

    public List<MediaType> mediaTypes() {
        return this.codecs.stream().map(e -> e.mediaType).collect(Collectors.toList());
    }

    public ResourceCodec getResourceCodec(MediaType mediaType) {
        for (CodecRegistration each : this.codecs) {
            if (each.mediaType.equals(mediaType)) {
                return each.codec;
            }
        }
        return null;
    }

    public MediaType determineMediaType(String acceptMediaTypes, String extension) {
        if (acceptMediaTypes == null && extension == null) {
            return MediaType.JSON;
        }

        MediaTypeMatcher matcher = new DefaultMediaTypeMatcher(acceptMediaTypes, extension);

        MediaType match = matcher.findBestMatch(this.codecs.stream().map((e) -> {
            return e.mediaType;
        }).collect(Collectors.toList()));

        return match;
    }

    private List<CodecRegistration> codecs = new CopyOnWriteArrayList<>();

    private static final Logger log = Logger.getLogger(ResourceCodecManager.class);

    private static class CodecRegistration {

        private MediaType mediaType;
        private ResourceCodec codec;

        CodecRegistration(MediaType mediaType, ResourceCodec codec) {
            this.mediaType = mediaType;
            this.codec = codec;

        }

        @Override
        public String toString() {
            return "[CodecRegistration: mediaType=" + mediaType + ", codec=" + codec + "]";
        }
    }
}