1 /* 2 * ==================================================================== 3 * Licensed to the Apache Software Foundation (ASF) under one 4 * or more contributor license agreements. See the NOTICE file 5 * distributed with this work for additional information 6 * regarding copyright ownership. The ASF licenses this file 7 * to you under the Apache License, Version 2.0 (the 8 * "License"); you may not use this file except in compliance 9 * with the License. You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, 14 * software distributed under the License is distributed on an 15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 * KIND, either express or implied. See the License for the 17 * specific language governing permissions and limitations 18 * under the License. 19 * ==================================================================== 20 * 21 * This software consists of voluntary contributions made by many 22 * individuals on behalf of the Apache Software Foundation. For more 23 * information on the Apache Software Foundation, please see 24 * <http://www.apache.org/>. 25 * 26 */ 27 28 package org.apache.hc.core5.http.io.entity; 29 30 import java.io.ByteArrayInputStream; 31 import java.io.IOException; 32 import java.io.InputStream; 33 import java.io.OutputStream; 34 35 import org.apache.hc.core5.annotation.Contract; 36 import org.apache.hc.core5.annotation.ThreadingBehavior; 37 import org.apache.hc.core5.http.ContentType; 38 import org.apache.hc.core5.util.Args; 39 40 /** 41 * A self contained, repeatable entity that obtains its content from a byte array. 42 * <p> 43 * This class contains {@link ThreadingBehavior#IMMUTABLE_CONDITIONAL immutable attributes} but subclasses may contain 44 * additional immutable or mutable attributes. 45 * </p> 46 * 47 * @since 4.0 48 */ 49 @Contract(threading = ThreadingBehavior.IMMUTABLE_CONDITIONAL) 50 public class ByteArrayEntity extends AbstractHttpEntity { 51 52 private final byte[] buf; 53 private final int off, len; 54 55 /** 56 * Constructs a new instance with the given attributes kept as immutable. 57 * 58 * @param buf The message body contents as a byte array buffer. 59 * @param off The offset in the buffer of the first byte to read. 60 * @param len The maximum number of bytes to read from the buffer. 61 * @param contentType The content-type, may be null. 62 * @param contentEncoding The content encoding string, may be null. 63 * @param chunked Whether this entity should be chunked. 64 * @since 5.0 65 */ 66 public ByteArrayEntity( 67 final byte[] buf, final int off, final int len, final ContentType contentType, final String contentEncoding, 68 final boolean chunked) { 69 super(contentType, contentEncoding, chunked); 70 Args.notNull(buf, "Source byte array"); 71 Args.notNegative(off, "offset"); 72 Args.notNegative(len, "length"); 73 Args.notNegative(off + len, "off + len"); 74 Args.check(off <= buf.length, "off %s cannot be greater then b.length %s ", off, buf.length); 75 Args.check(off + len <= buf.length, "off + len %s cannot be less then b.length %s ", off + len, buf.length); 76 this.buf = buf; 77 this.off = off; 78 this.len = len; 79 } 80 81 /** 82 * Constructs a new instance with the given attributes kept as immutable. 83 * <p> 84 * The new instance: 85 * </p> 86 * <ul> 87 * <li>is not chunked.</li> 88 * </ul> 89 * 90 * @param buf The message body contents as a byte array buffer. 91 * @param off The offset in the buffer of the first byte to read. 92 * @param len The maximum number of bytes to read from the buffer. 93 * @param contentType The content-type, may be null. 94 * @param contentEncoding The content encoding string, may be null. 95 * @since 5.0 96 */ 97 public ByteArrayEntity( 98 final byte[] buf, final int off, final int len, final ContentType contentType, final String contentEncoding) { 99 this(buf, off, len, contentType, contentEncoding, false); 100 } 101 102 /** 103 * Constructs a new instance with the given attributes kept as immutable. 104 * <p> 105 * The new instance: 106 * </p> 107 * <ul> 108 * <li>starts reading it's contents at index 0 in the buffer.</li> 109 * <li>has the content length of the given buffer.</li> 110 * </ul> 111 * 112 * @param buf The message body contents as a byte array buffer. 113 * @param contentType The content-type, may be null. 114 * @param contentEncoding The content encoding string, may be null. 115 * @param chunked Whether this entity should be chunked. 116 * @since 5.0 117 */ 118 public ByteArrayEntity( 119 final byte[] buf, final ContentType contentType, final String contentEncoding, final boolean chunked) { 120 super(contentType, contentEncoding, chunked); 121 Args.notNull(buf, "Source byte array"); 122 this.buf = buf; 123 this.off = 0; 124 this.len = this.buf.length; 125 } 126 127 /** 128 * Constructs a new instance with the given attributes kept as immutable. 129 * <p> 130 * The new instance: 131 * </p> 132 * <ul> 133 * <li>is not chunked.</li> 134 * <li>starts reading it's contents at index 0 in the buffer.</li> 135 * <li>has the content length of the given buffer.</li> 136 * </ul> 137 * 138 * @param buf The message body contents as a byte array buffer. 139 * @param contentType The content-type, may be null. 140 * @param contentEncoding The content encoding string, may be null. 141 * @since 5.0 142 */ 143 public ByteArrayEntity(final byte[] buf, final ContentType contentType, final String contentEncoding) { 144 this(buf, contentType, contentEncoding, false); 145 } 146 147 /** 148 * Constructs a new instance with the given attributes kept as immutable. 149 * <p> 150 * The new instance: 151 * </p> 152 * <ul> 153 * <li>starts reading it's contents at index 0 in the buffer.</li> 154 * <li>has the content length of the given buffer.</li> 155 * <li>does not define a content encoding.</li> 156 * </ul> 157 * 158 * @param buf The message body contents as a byte array buffer. 159 * @param contentType The content-type, may be null. 160 * @param chunked Whether this entity should be chunked. 161 */ 162 public ByteArrayEntity(final byte[] buf, final ContentType contentType, final boolean chunked) { 163 this(buf, contentType, null, chunked); 164 } 165 166 /** 167 * Constructs a new instance with the given attributes kept as immutable. 168 * <p> 169 * The new instance: 170 * </p> 171 * <ul> 172 * <li>is not chunked.</li> 173 * <li>starts reading it's contents at index 0 in the buffer.</li> 174 * <li>has the content length of the given buffer.</li> 175 * <li>does not define a content encoding.</li> 176 * </ul> 177 * 178 * @param buf The message body contents as a byte array buffer. 179 * @param contentType The content-type, may be null. 180 */ 181 public ByteArrayEntity(final byte[] buf, final ContentType contentType) { 182 this(buf, contentType, null, false); 183 } 184 185 /** 186 * Constructs a new instance with the given attributes kept as immutable. 187 * <p> 188 * The new instance: 189 * </p> 190 * <ul> 191 * <li>does not define a content encoding.</li> 192 * </ul> 193 * 194 * @param buf The message body contents as a byte array buffer. 195 * @param off The offset in the buffer of the first byte to read. 196 * @param len The maximum number of bytes to read from the buffer. 197 * @param contentType The content-type, may be null. 198 * @param chunked Whether this entity should be chunked. 199 */ 200 public ByteArrayEntity( 201 final byte[] buf, final int off, final int len, final ContentType contentType, final boolean chunked) { 202 this(buf, off, len, contentType, null, chunked); 203 } 204 205 /** 206 * Constructs a new instance with the given attributes kept as immutable. 207 * <p> 208 * The new instance: 209 * </p> 210 * <ul> 211 * <li>is not chunked.</li> 212 * <li>does not define a content encoding.</li> 213 * </ul> 214 * 215 * @param buf The message body contents as a byte array buffer. 216 * @param off The offset in the buffer of the first byte to read. 217 * @param len The maximum number of bytes to read from the buffer. 218 * @param contentType The content-type, may be null. 219 * @since 5.0 220 */ 221 public ByteArrayEntity(final byte[] buf, final int off, final int len, final ContentType contentType) { 222 this(buf, off, len, contentType, null, false); 223 } 224 225 /** 226 * {@inheritDoc} 227 * <p> 228 * This implementation always returns {@code true}. 229 * </p> 230 */ 231 @Override 232 public final boolean isRepeatable() { 233 return true; 234 } 235 236 @Override 237 public final long getContentLength() { 238 return this.len; 239 } 240 241 @Override 242 public final InputStream getContent() { 243 return new ByteArrayInputStream(this.buf, this.off, this.len); 244 } 245 246 @Override 247 public final void writeTo(final OutputStream outStream) throws IOException { 248 Args.notNull(outStream, "Output stream"); 249 outStream.write(this.buf, this.off, this.len); 250 outStream.flush(); 251 } 252 253 /** 254 * {@inheritDoc} 255 * <p> 256 * This implementation always returns {@code false}. 257 * </p> 258 */ 259 @Override 260 public final boolean isStreaming() { 261 return false; 262 } 263 264 /** 265 * {@inheritDoc} 266 * <p> 267 * This implementation is a no-op. 268 * </p> 269 */ 270 @Override 271 public final void close() throws IOException { 272 } 273 274 }