org.springframework.integration.stomp.support.StompHeaderMapper.java Source code

Java tutorial

Introduction

Here is the source code for org.springframework.integration.stomp.support.StompHeaderMapper.java

Source

/*
 * Copyright 2015-2016 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.integration.stomp.support;

import java.text.MessageFormat;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import org.springframework.http.MediaType;
import org.springframework.integration.mapping.HeaderMapper;
import org.springframework.messaging.MessageHeaders;
import org.springframework.messaging.simp.stomp.StompHeaderAccessor;
import org.springframework.messaging.simp.stomp.StompHeaders;
import org.springframework.util.Assert;
import org.springframework.util.MimeType;
import org.springframework.util.MultiValueMap;
import org.springframework.util.PatternMatchUtils;
import org.springframework.util.StringUtils;

/**
 * The STOMP {@link HeaderMapper} implementation.
 *
 * @author Artem Bilan
 * @since 4.2
 * @see StompHeaders
 */
public class StompHeaderMapper implements HeaderMapper<StompHeaders> {

    private static final Log logger = LogFactory.getLog(StompHeaderMapper.class);

    public static final String STOMP_INBOUND_HEADER_NAME_PATTERN = "STOMP_INBOUND_HEADERS";

    public static final String STOMP_OUTBOUND_HEADER_NAME_PATTERN = "STOMP_OUTBOUND_HEADERS";

    private static final String[] STOMP_INBOUND_HEADER_NAMES = new String[] { StompHeaders.CONTENT_LENGTH,
            StompHeaders.CONTENT_TYPE, StompHeaders.MESSAGE_ID, StompHeaders.RECEIPT_ID,
            StompHeaders.SUBSCRIPTION, };

    private final static List<String> STOMP_INBOUND_HEADER_NAMES_LIST = Arrays
            .<String>asList(STOMP_INBOUND_HEADER_NAMES);

    private static final String[] STOMP_OUTBOUND_HEADER_NAMES = new String[] { StompHeaders.CONTENT_LENGTH,
            StompHeaders.CONTENT_TYPE, StompHeaders.DESTINATION, StompHeaders.RECEIPT,
            IntegrationStompHeaders.DESTINATION, IntegrationStompHeaders.RECEIPT };

    private final static List<String> STOMP_OUTBOUND_HEADER_NAMES_LIST = Arrays
            .<String>asList(STOMP_OUTBOUND_HEADER_NAMES);

    private volatile String[] inboundHeaderNames = STOMP_INBOUND_HEADER_NAMES;

    private volatile String[] outboundHeaderNames = STOMP_OUTBOUND_HEADER_NAMES;

    public void setInboundHeaderNames(String[] inboundHeaderNames) { //NOSONAR - false positive
        Assert.notNull(inboundHeaderNames, "'inboundHeaderNames' must not be null.");
        Assert.noNullElements(inboundHeaderNames, "'inboundHeaderNames' must not contains null elements.");
        Arrays.sort(inboundHeaderNames);
        if (!Arrays.equals(STOMP_INBOUND_HEADER_NAMES, inboundHeaderNames)) {
            this.inboundHeaderNames = inboundHeaderNames;
        }
    }

    public void setOutboundHeaderNames(String[] outboundHeaderNames) { //NOSONAR - false positive
        Assert.notNull(outboundHeaderNames, "'outboundHeaderNames' must not be null.");
        Assert.noNullElements(outboundHeaderNames, "'outboundHeaderNames' must not contains null elements.");
        Arrays.sort(outboundHeaderNames);
        if (!Arrays.equals(STOMP_OUTBOUND_HEADER_NAMES, outboundHeaderNames)) {
            this.outboundHeaderNames = outboundHeaderNames;
        }
    }

    @Override
    @SuppressWarnings("unchecked")
    public void fromHeaders(MessageHeaders headers, StompHeaders target) {
        for (Map.Entry<String, Object> entry : headers.entrySet()) {
            String name = entry.getKey();
            if (shouldMapHeader(name, this.outboundHeaderNames)) {
                Object value = entry.getValue();
                if (value != null) {
                    setStompHeader(target, name, value);
                }
            } else if (StompHeaderAccessor.NATIVE_HEADERS.equals(name)) {
                MultiValueMap<String, String> multiValueMap = headers.get(StompHeaderAccessor.NATIVE_HEADERS,
                        MultiValueMap.class);
                for (Map.Entry<String, List<String>> entry1 : multiValueMap.entrySet()) {
                    name = entry1.getKey();
                    if (shouldMapHeader(name, this.outboundHeaderNames)) {
                        String value = entry1.getValue().get(0);
                        if (StringUtils.hasText(value)) {
                            setStompHeader(target, name, value);
                        }
                    }
                }
            }
        }
    }

    private void setStompHeader(StompHeaders target, String name, Object value) {
        if (StompHeaders.CONTENT_LENGTH.equals(name)) {
            if (value instanceof Number) {
                target.setContentLength(((Number) value).longValue());
            } else if (value instanceof String) {
                target.setContentLength(Long.parseLong((String) value));
            } else {
                Class<?> clazz = (value != null) ? value.getClass() : null;
                throw new IllegalArgumentException(
                        "Expected Number or String value for 'content-length' header value, but received: "
                                + clazz);
            }
        } else if (StompHeaders.CONTENT_TYPE.equals(name) || MessageHeaders.CONTENT_TYPE.equals(name)) {
            MimeType contentType = target.getContentType();
            if (contentType == null || StompHeaders.CONTENT_TYPE.equals(name)) {
                if (value instanceof MediaType) {
                    target.setContentType((MediaType) value);
                } else if (value instanceof String) {
                    target.setContentType(MediaType.parseMediaType((String) value));
                } else {
                    Class<?> clazz = (value != null) ? value.getClass() : null;
                    throw new IllegalArgumentException(
                            "Expected MediaType or String value for 'content-type' header value, but received: "
                                    + clazz);
                }
            }
        } else if (StompHeaders.DESTINATION.equals(name) || IntegrationStompHeaders.DESTINATION.equals(name)) {
            if (value instanceof String) {
                target.setDestination((String) value);
            } else {
                Class<?> clazz = (value != null) ? value.getClass() : null;
                throw new IllegalArgumentException(
                        "Expected String value for 'destination' header value, but received: " + clazz);
            }
        } else if (StompHeaders.RECEIPT.equals(name) || IntegrationStompHeaders.RECEIPT.equals(name)) {
            if (value instanceof String) {
                target.setReceipt((String) value);
            } else {
                Class<?> clazz = (value != null) ? value.getClass() : null;
                throw new IllegalArgumentException(
                        "Expected String value for 'receipt' header value, but received: " + clazz);
            }
        } else {
            if (value instanceof String) {
                target.set(name, (String) value);
            } else {
                Class<?> clazz = (value != null) ? value.getClass() : null;
                throw new IllegalArgumentException(
                        "Expected String value for any generic STOMP header value, but received: " + clazz);
            }
        }
    }

    @Override
    public Map<String, Object> toHeaders(StompHeaders source) {
        Map<String, Object> target = new HashMap<String, Object>();
        for (String name : source.keySet()) {
            if (shouldMapHeader(name, this.inboundHeaderNames)) {
                if (StompHeaders.CONTENT_TYPE.equals(name)) {
                    target.put(MessageHeaders.CONTENT_TYPE, source.getContentType());
                } else {
                    String key = name;
                    if (IntegrationStompHeaders.HEADERS.contains(name)) {
                        key = IntegrationStompHeaders.PREFIX + name;
                    }
                    target.put(key, source.getFirst(name));
                }
            }
        }
        return target;
    }

    private boolean shouldMapHeader(String headerName, String[] patterns) {
        if (patterns != null && patterns.length > 0) {
            for (String pattern : patterns) {
                if (PatternMatchUtils.simpleMatch(pattern, headerName)) {
                    if (logger.isDebugEnabled()) {
                        logger.debug(MessageFormat.format("headerName=[{0}] WILL be mapped, matched pattern={1}",
                                headerName, pattern));
                    }
                    return true;
                } else if (STOMP_INBOUND_HEADER_NAME_PATTERN.equals(pattern)
                        && STOMP_INBOUND_HEADER_NAMES_LIST.contains(headerName)) {
                    if (logger.isDebugEnabled()) {
                        logger.debug(MessageFormat.format("headerName=[{0}] WILL be mapped, matched pattern={1}",
                                headerName, pattern));
                    }
                    return true;
                } else if (STOMP_OUTBOUND_HEADER_NAME_PATTERN.equals(pattern)
                        && (STOMP_OUTBOUND_HEADER_NAMES_LIST.contains(headerName)
                                || MessageHeaders.CONTENT_TYPE.equals(headerName))) {
                    if (logger.isDebugEnabled()) {
                        logger.debug(MessageFormat.format("headerName=[{0}] WILL be mapped, matched pattern={1}",
                                headerName, pattern));
                    }
                    return true;
                }
            }
        }
        if (logger.isDebugEnabled()) {
            logger.debug(MessageFormat.format("headerName=[{0}] WILL NOT be mapped", headerName));
        }
        return false;
    }

}