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 org.springframework.util.Assert; 023 024/** 025 * Default implementation of the {@code DataBufferFactory} interface. Allows for 026 * specification of the default initial capacity at construction time, as well 027 * as whether heap-based or direct buffers are to be preferred. 028 * 029 * @author Arjen Poutsma 030 * @since 5.0 031 */ 032public class DefaultDataBufferFactory implements DataBufferFactory { 033 034 /** 035 * The default capacity when none is specified. 036 * @see #DefaultDataBufferFactory() 037 * @see #DefaultDataBufferFactory(boolean) 038 */ 039 public static final int DEFAULT_INITIAL_CAPACITY = 256; 040 041 042 private final boolean preferDirect; 043 044 private final int defaultInitialCapacity; 045 046 047 /** 048 * Creates a new {@code DefaultDataBufferFactory} with default settings. 049 */ 050 public DefaultDataBufferFactory() { 051 this(false); 052 } 053 054 /** 055 * Creates a new {@code DefaultDataBufferFactory}, indicating whether direct 056 * buffers should be created by {@link #allocateBuffer()} and 057 * {@link #allocateBuffer(int)}. 058 * @param preferDirect {@code true} if direct buffers are to be preferred; 059 * {@code false} otherwise 060 */ 061 public DefaultDataBufferFactory(boolean preferDirect) { 062 this(preferDirect, DEFAULT_INITIAL_CAPACITY); 063 } 064 065 /** 066 * Creates a new {@code DefaultDataBufferFactory}, indicating whether direct 067 * buffers should be created by {@link #allocateBuffer()} and 068 * {@link #allocateBuffer(int)}, and what the capacity is to be used for 069 * {@link #allocateBuffer()}. 070 * @param preferDirect {@code true} if direct buffers are to be preferred; 071 * {@code false} otherwise 072 */ 073 public DefaultDataBufferFactory(boolean preferDirect, int defaultInitialCapacity) { 074 Assert.isTrue(defaultInitialCapacity > 0, "'defaultInitialCapacity' should be larger than 0"); 075 this.preferDirect = preferDirect; 076 this.defaultInitialCapacity = defaultInitialCapacity; 077 } 078 079 080 @Override 081 public DefaultDataBuffer allocateBuffer() { 082 return allocateBuffer(this.defaultInitialCapacity); 083 } 084 085 @Override 086 public DefaultDataBuffer allocateBuffer(int initialCapacity) { 087 ByteBuffer byteBuffer = (this.preferDirect ? 088 ByteBuffer.allocateDirect(initialCapacity) : 089 ByteBuffer.allocate(initialCapacity)); 090 return DefaultDataBuffer.fromEmptyByteBuffer(this, byteBuffer); 091 } 092 093 @Override 094 public DefaultDataBuffer wrap(ByteBuffer byteBuffer) { 095 return DefaultDataBuffer.fromFilledByteBuffer(this, byteBuffer.slice()); 096 } 097 098 @Override 099 public DefaultDataBuffer wrap(byte[] bytes) { 100 return DefaultDataBuffer.fromFilledByteBuffer(this, ByteBuffer.wrap(bytes)); 101 } 102 103 /** 104 * {@inheritDoc} 105 * <p>This implementation creates a single {@link DefaultDataBuffer} 106 * to contain the data in {@code dataBuffers}. 107 */ 108 @Override 109 public DefaultDataBuffer join(List<? extends DataBuffer> dataBuffers) { 110 Assert.notEmpty(dataBuffers, "DataBuffer List must not be empty"); 111 int capacity = dataBuffers.stream().mapToInt(DataBuffer::readableByteCount).sum(); 112 DefaultDataBuffer result = allocateBuffer(capacity); 113 dataBuffers.forEach(result::write); 114 dataBuffers.forEach(DataBufferUtils::release); 115 return result; 116 } 117 118 119 @Override 120 public String toString() { 121 return "DefaultDataBufferFactory (preferDirect=" + this.preferDirect + ")"; 122 } 123 124}