org.springframework.cloud.aws.messaging.endpoint.NotificationMessageHandlerMethodArgumentResolver.java Source code

Java tutorial

Introduction

Here is the source code for org.springframework.cloud.aws.messaging.endpoint.NotificationMessageHandlerMethodArgumentResolver.java

Source

/*
 * Copyright 2013-2014 the original author or authors.
 *
 * 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 org.springframework.cloud.aws.messaging.endpoint;

import com.fasterxml.jackson.databind.JsonNode;
import org.springframework.cloud.aws.messaging.config.annotation.NotificationMessage;
import org.springframework.core.MethodParameter;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpInputMessage;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.util.StringUtils;
import org.springframework.web.util.WebUtils;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.Charset;
import java.util.Arrays;
import java.util.List;

/**
 * @author Agim Emruli
 */
public class NotificationMessageHandlerMethodArgumentResolver
        extends AbstractNotificationMessageHandlerMethodArgumentResolver {

    private final List<HttpMessageConverter<?>> messageConverter;

    public NotificationMessageHandlerMethodArgumentResolver() {
        this(Arrays.<HttpMessageConverter<?>>asList(new MappingJackson2HttpMessageConverter(),
                new StringHttpMessageConverter()));
    }

    public NotificationMessageHandlerMethodArgumentResolver(List<HttpMessageConverter<?>> messageConverter) {
        this.messageConverter = messageConverter;
    }

    @Override
    public boolean supportsParameter(MethodParameter parameter) {
        return (parameter.hasParameterAnnotation(NotificationMessage.class));
    }

    @Override
    @SuppressWarnings({ "unchecked", "rawtypes" })
    protected Object doResolveArgumentFromNotificationMessage(JsonNode content, HttpInputMessage request,
            Class<?> parameterType) {
        if (!"Notification".equals(content.get("Type").asText())) {
            throw new IllegalArgumentException(
                    "@NotificationMessage annotated parameters are only allowed for method that receive a notification message.");
        }

        MediaType mediaType = getMediaType(content);
        String messageContent = content.findPath("Message").asText();

        for (HttpMessageConverter<?> converter : this.messageConverter) {
            if (converter.canRead(parameterType, mediaType)) {
                try {
                    return converter.read((Class) parameterType,
                            new ByteArrayHttpInputMessage(messageContent, mediaType, request));
                } catch (Exception e) {
                    throw new HttpMessageNotReadableException(
                            "Error converting notification message with payload:" + messageContent, e);
                }
            }
        }

        throw new HttpMessageNotReadableException(
                "Error converting notification message with payload:" + messageContent);
    }

    private static MediaType getMediaType(JsonNode content) {
        JsonNode contentTypeNode = content.findPath("MessageAttributes").findPath("contentType");
        if (contentTypeNode.isObject()) {
            String contentType = contentTypeNode.findPath("Value").asText();
            if (StringUtils.hasText(contentType)) {
                return MediaType.parseMediaType(contentType);
            }
        }

        return MediaType.TEXT_PLAIN;
    }

    private static class ByteArrayHttpInputMessage implements HttpInputMessage {

        private final String content;
        private final MediaType mediaType;
        private final HttpInputMessage request;

        private ByteArrayHttpInputMessage(String content, MediaType mediaType, HttpInputMessage request) {
            this.content = content;
            this.mediaType = mediaType;
            this.request = request;
        }

        @Override
        public InputStream getBody() throws IOException {
            return new ByteArrayInputStream(this.content.getBytes(getCharset()));
        }

        private Charset getCharset() {
            return this.mediaType.getCharSet() != null ? this.mediaType.getCharSet()
                    : Charset.forName(WebUtils.DEFAULT_CHARACTER_ENCODING);
        }

        @Override
        public HttpHeaders getHeaders() {
            return this.request.getHeaders();
        }
    }
}