org.springframework.integration.x.bus.MessageBusSupport.java Source code

Java tutorial

Introduction

Here is the source code for org.springframework.integration.x.bus.MessageBusSupport.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.integration.x.bus;

import static org.springframework.http.MediaType.ALL;
import static org.springframework.http.MediaType.APPLICATION_OCTET_STREAM;
import static org.springframework.http.MediaType.APPLICATION_OCTET_STREAM_VALUE;
import static org.springframework.http.MediaType.TEXT_PLAIN;
import static org.springframework.http.MediaType.TEXT_PLAIN_VALUE;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;

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

import org.springframework.context.Lifecycle;
import org.springframework.http.MediaType;
import org.springframework.integration.support.MessageBuilder;
import org.springframework.integration.x.bus.serializer.MultiTypeCodec;
import org.springframework.integration.x.bus.serializer.SerializationException;
import org.springframework.messaging.Message;
import org.springframework.messaging.MessageChannel;
import org.springframework.messaging.MessageHeaders;
import org.springframework.messaging.converter.ContentTypeResolver;
import org.springframework.util.AlternativeJdkIdGenerator;
import org.springframework.util.Assert;
import org.springframework.util.IdGenerator;
import org.springframework.util.MimeType;

/**
 * @author David Turanski
 * @author Gary Russell
 */
public abstract class MessageBusSupport implements MessageBus {

    protected final Log logger = LogFactory.getLog(getClass());

    private volatile MultiTypeCodec<Object> codec;

    private final ContentTypeResolver contentTypeResolver = new StringConvertingContentTypeResolver();

    protected static final String ORIGINAL_CONTENT_TYPE_HEADER = "originalContentType";

    protected static final List<MediaType> MEDIATYPES_MEDIATYPE_ALL = Collections.singletonList(MediaType.ALL);

    private final List<Binding> bindings = Collections.synchronizedList(new ArrayList<Binding>());

    private final IdGenerator idGenerator = new AlternativeJdkIdGenerator();

    public void setCodec(MultiTypeCodec<Object> codec) {
        this.codec = codec;
    }

    protected IdGenerator getIdGenerator() {
        return idGenerator;
    }

    @Override
    public void unbindConsumers(String name) {
        deleteBindings("inbound." + name);
    }

    @Override
    public void unbindProducers(String name) {
        deleteBindings("outbound." + name);
    }

    @Override
    public void unbindConsumer(String name, MessageChannel channel) {
        deleteBinding("inbound." + name, channel);
    }

    @Override
    public void unbindProducer(String name, MessageChannel channel) {
        deleteBinding("outbound." + name, channel);
    }

    protected void addBinding(Binding binding) {
        this.bindings.add(binding);
    }

    protected void deleteBindings(String name) {
        Assert.hasText(name, "a valid name is required to remove bindings");
        synchronized (this.bindings) {
            Iterator<Binding> iterator = this.bindings.iterator();
            while (iterator.hasNext()) {
                Binding binding = iterator.next();
                if (binding.getEndpoint().getComponentName().equals(name)) {
                    binding.stop();
                    iterator.remove();
                }
            }
        }
    }

    protected void deleteBinding(String name, MessageChannel channel) {
        Assert.hasText(name, "a valid name is required to remove a binding");
        Assert.notNull(channel, "a valid channel is required to remove a binding");
        synchronized (this.bindings) {
            Iterator<Binding> iterator = this.bindings.iterator();
            while (iterator.hasNext()) {
                Binding binding = iterator.next();
                if (binding.getChannel().equals(channel) && binding.getEndpoint().getComponentName().equals(name)) {
                    binding.stop();
                    iterator.remove();
                    return;
                }
            }
        }
    }

    protected void stopBindings() {
        for (Lifecycle bean : this.bindings) {
            try {
                bean.stop();
            } catch (Exception e) {
                if (logger.isWarnEnabled()) {
                    logger.warn("failed to stop adapter", e);
                }
            }
        }
    }

    // TODO: Performs serialization currently no transformation
    protected final Message<?> serializePayloadIfNecessary(Message<?> message, MediaType to) {
        Object originalPayload = message.getPayload();
        Object originalContentType = message.getHeaders().get(MessageHeaders.CONTENT_TYPE);
        Object contentType = originalContentType;
        if (to.equals(ALL)) {
            return message;
        } else if (to.equals(APPLICATION_OCTET_STREAM)) {
            contentType = resolveContentType(originalPayload);
            Object payload = serializePayloadIfNecessary(originalPayload);
            MessageBuilder<Object> messageBuilder = MessageBuilder.withPayload(payload)
                    .copyHeaders(message.getHeaders()).setHeader(MessageHeaders.CONTENT_TYPE, contentType);
            if (originalContentType != null) {
                messageBuilder.setHeader(ORIGINAL_CONTENT_TYPE_HEADER, originalContentType);
            }
            return messageBuilder.build();
        } else {
            throw new IllegalArgumentException("'to' can only be 'ALL' or 'APPLICATION_OCTET_STREAM'");
        }
    }

    private byte[] serializePayloadIfNecessary(Object originalPayload) {
        if (originalPayload instanceof byte[]) {
            return (byte[]) originalPayload;
        } else {
            ByteArrayOutputStream bos = new ByteArrayOutputStream();
            try {
                if (originalPayload instanceof String) {
                    return ((String) originalPayload).getBytes("UTF-8");
                }
                this.codec.serialize(originalPayload, bos);
                return bos.toByteArray();
            } catch (IOException e) {
                throw new SerializationException(
                        "unable to serialize payload [" + originalPayload.getClass().getName() + "]", e);
            }
        }
    }

    protected final Message<?> deserializePayloadIfNecessary(Message<?> message) {
        Message<?> messageToSend = message;
        Object originalPayload = message.getPayload();
        MimeType contentType = contentTypeResolver.resolve(message.getHeaders());
        Object payload = deserializePayload(originalPayload, contentType);
        if (payload != null) {
            MessageBuilder<Object> transformed = MessageBuilder.withPayload(payload)
                    .copyHeaders(message.getHeaders());
            Object originalContentType = message.getHeaders().get(ORIGINAL_CONTENT_TYPE_HEADER);
            transformed.setHeader(MessageHeaders.CONTENT_TYPE, originalContentType);
            transformed.setHeader(ORIGINAL_CONTENT_TYPE_HEADER, null);
            messageToSend = transformed.build();
        }
        return messageToSend;
    }

    private Object deserializePayload(Object payload, MimeType contentType) {
        if (payload instanceof byte[]) {
            if (APPLICATION_OCTET_STREAM.equals(contentType)) {
                return payload;
            } else {
                return deserializePayload((byte[]) payload, contentType);
            }
        }
        return payload;
    }

    private Object deserializePayload(byte[] bytes, MimeType contentType) {
        Class<?> targetType = null;
        try {
            if (contentType.equals(TEXT_PLAIN)) {
                return new String(bytes, "UTF-8");
            }
            targetType = Class.forName(contentType.getParameter("type"));

            return codec.deserialize(bytes, targetType);
        } catch (ClassNotFoundException e) {
            throw new SerializationException("unable to deserialize [" + targetType + "]. Class not found.", e);
        } catch (IOException e) {
            throw new SerializationException("unable to deserialize [" + targetType + "]", e);
        }

    }

    private String resolveContentType(Object originalPayload) {
        if (originalPayload instanceof byte[]) {
            return APPLICATION_OCTET_STREAM_VALUE;
        }
        if (originalPayload instanceof String) {
            return TEXT_PLAIN_VALUE;
        }
        return "application/x-java-object;type=" + originalPayload.getClass().getName();
    }

}