/* * Copyright 2015 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.http; import java.nio.charset.Charset; import java.util.HashMap; import java.util.Map; import java.util.Map.Entry; import org.jboss.netty.buffer.ChannelBuffer; import org.jboss.netty.handler.codec.http.HttpRequest; import org.springframework.http.MediaType; import org.springframework.integration.support.AbstractIntegrationMessageBuilder; import org.springframework.integration.support.DefaultMessageBuilderFactory; import org.springframework.integration.support.MessageBuilderFactory; import org.springframework.messaging.Message; import org.springframework.messaging.MessageHeaders; import org.springframework.messaging.converter.MessageConversionException; import org.springframework.messaging.converter.MessageConverter; import org.springframework.util.Assert; /** * Message converter (inbound only) to convert a Netty Http MessageEvent to * a Message. Returns null if the content is not readable. * * @author Mark Fisher * @author Jennifer Hickey * @author Gary Russell * @author Marius Bogoevici * @author Peter Rietzler */ public class NettyInboundMessageConverter implements MessageConverter { private final MessageBuilderFactory messageBuilderFactory; public NettyInboundMessageConverter() { this(new DefaultMessageBuilderFactory()); } public NettyInboundMessageConverter(MessageBuilderFactory messageBuilderFactory) { this.messageBuilderFactory = messageBuilderFactory; } @Override public Object fromMessage(Message<?> message, Class<?> targetClass) { throw new UnsupportedOperationException("This converter is for inbound messages only."); } @Override public Message<?> toMessage(Object payload, MessageHeaders header) { Assert.isInstanceOf(HttpRequest.class, payload); HttpRequest request = (HttpRequest) payload; ChannelBuffer content = request.getContent(); Charset charsetToUse = null; boolean binary = false; if (content.readable()) { Map<String, String> messageHeaders = new HashMap<String, String>(); for (Entry<String, String> entry : request.getHeaders()) { if (entry.getKey().equalsIgnoreCase("Content-Type")) { MediaType contentType = MediaType.parseMediaType(entry.getValue()); charsetToUse = contentType.getCharSet(); messageHeaders.put(MessageHeaders.CONTENT_TYPE, entry.getValue()); binary = MediaType.APPLICATION_OCTET_STREAM.equals(contentType); } else if (!entry.getKey().toUpperCase().startsWith("ACCEPT") && !entry.getKey().toUpperCase().equals("CONNECTION")) { messageHeaders.put(entry.getKey(), entry.getValue()); } } messageHeaders.put("requestPath", request.getUri()); messageHeaders.put("requestMethod", request.getMethod().toString()); addHeaders(messageHeaders, request); try { AbstractIntegrationMessageBuilder<?> builder; if (binary) { builder = this.messageBuilderFactory.withPayload(toByteArray(content)); } else { // ISO-8859-1 is the default http charset when not set charsetToUse = charsetToUse == null ? Charset.forName("ISO-8859-1") : charsetToUse; builder = this.messageBuilderFactory.withPayload(content.toString(charsetToUse)); } builder.copyHeaders(messageHeaders); return builder.build(); } catch (Exception ex) { throw new MessageConversionException("Failed to convert netty event to a Message", ex); } } else { return null; } } private byte[] toByteArray(ChannelBuffer content) { if (content.hasArray()) { return content.array(); } else { byte[] bytes = new byte[content.readableBytes()]; content.getBytes(0, bytes); return bytes; } } /** * Add additional headers. Default implementation adds none. * @param messageHeaders The headers that will be added to the message. * @param request The HttpRequest */ protected void addHeaders(Map<String, String> messageHeaders, HttpRequest request) { } }