001/* 002 * Copyright 2002-2018 the original author or authors. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * https://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017package org.springframework.core.io.buffer; 018 019import java.nio.ByteBuffer; 020import java.util.List; 021 022import io.netty.buffer.ByteBuf; 023import io.netty.buffer.ByteBufAllocator; 024import io.netty.buffer.CompositeByteBuf; 025import io.netty.buffer.Unpooled; 026 027import org.springframework.util.Assert; 028 029/** 030 * Implementation of the {@code DataBufferFactory} interface based on a 031 * Netty {@link ByteBufAllocator}. 032 * 033 * @author Arjen Poutsma 034 * @author Juergen Hoeller 035 * @since 5.0 036 * @see io.netty.buffer.PooledByteBufAllocator 037 * @see io.netty.buffer.UnpooledByteBufAllocator 038 */ 039public class NettyDataBufferFactory implements DataBufferFactory { 040 041 private final ByteBufAllocator byteBufAllocator; 042 043 044 /** 045 * Create a new {@code NettyDataBufferFactory} based on the given factory. 046 * @param byteBufAllocator the factory to use 047 * @see io.netty.buffer.PooledByteBufAllocator 048 * @see io.netty.buffer.UnpooledByteBufAllocator 049 */ 050 public NettyDataBufferFactory(ByteBufAllocator byteBufAllocator) { 051 Assert.notNull(byteBufAllocator, "ByteBufAllocator must not be null"); 052 this.byteBufAllocator = byteBufAllocator; 053 } 054 055 056 /** 057 * Return the {@code ByteBufAllocator} used by this factory. 058 */ 059 public ByteBufAllocator getByteBufAllocator() { 060 return this.byteBufAllocator; 061 } 062 063 @Override 064 public NettyDataBuffer allocateBuffer() { 065 ByteBuf byteBuf = this.byteBufAllocator.buffer(); 066 return new NettyDataBuffer(byteBuf, this); 067 } 068 069 @Override 070 public NettyDataBuffer allocateBuffer(int initialCapacity) { 071 ByteBuf byteBuf = this.byteBufAllocator.buffer(initialCapacity); 072 return new NettyDataBuffer(byteBuf, this); 073 } 074 075 @Override 076 public NettyDataBuffer wrap(ByteBuffer byteBuffer) { 077 ByteBuf byteBuf = Unpooled.wrappedBuffer(byteBuffer); 078 return new NettyDataBuffer(byteBuf, this); 079 } 080 081 @Override 082 public DataBuffer wrap(byte[] bytes) { 083 ByteBuf byteBuf = Unpooled.wrappedBuffer(bytes); 084 return new NettyDataBuffer(byteBuf, this); 085 } 086 087 /** 088 * Wrap the given Netty {@link ByteBuf} in a {@code NettyDataBuffer}. 089 * @param byteBuf the Netty byte buffer to wrap 090 * @return the wrapped buffer 091 */ 092 public NettyDataBuffer wrap(ByteBuf byteBuf) { 093 byteBuf.touch(); 094 return new NettyDataBuffer(byteBuf, this); 095 } 096 097 /** 098 * {@inheritDoc} 099 * <p>This implementation uses Netty's {@link CompositeByteBuf}. 100 */ 101 @Override 102 public DataBuffer join(List<? extends DataBuffer> dataBuffers) { 103 Assert.notEmpty(dataBuffers, "DataBuffer List must not be empty"); 104 int bufferCount = dataBuffers.size(); 105 if (bufferCount == 1) { 106 return dataBuffers.get(0); 107 } 108 CompositeByteBuf composite = this.byteBufAllocator.compositeBuffer(bufferCount); 109 for (DataBuffer dataBuffer : dataBuffers) { 110 Assert.isInstanceOf(NettyDataBuffer.class, dataBuffer); 111 composite.addComponent(true, ((NettyDataBuffer) dataBuffer).getNativeBuffer()); 112 } 113 return new NettyDataBuffer(composite, this); 114 } 115 116 /** 117 * Return the given Netty {@link DataBuffer} as a {@link ByteBuf}. 118 * <p>Returns the {@linkplain NettyDataBuffer#getNativeBuffer() native buffer} 119 * if {@code buffer} is a {@link NettyDataBuffer}; returns 120 * {@link Unpooled#wrappedBuffer(ByteBuffer)} otherwise. 121 * @param buffer the {@code DataBuffer} to return a {@code ByteBuf} for 122 * @return the netty {@code ByteBuf} 123 */ 124 public static ByteBuf toByteBuf(DataBuffer buffer) { 125 if (buffer instanceof NettyDataBuffer) { 126 return ((NettyDataBuffer) buffer).getNativeBuffer(); 127 } 128 else { 129 return Unpooled.wrappedBuffer(buffer.asByteBuffer()); 130 } 131 } 132 133 134 @Override 135 public String toString() { 136 return "NettyDataBufferFactory (" + this.byteBufAllocator + ")"; 137 } 138 139}