001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.apache.juneau.http.classic.entity; 018 019import static org.apache.juneau.commons.utils.Shorts.*; 020 021import java.io.*; 022 023import org.apache.juneau.http.*; 024import org.apache.juneau.http.classic.header.*; 025 026/** 027 * A repeatable entity that obtains its content from a byte array. 028 * 029 * <h5 class='section'>See Also:</h5><ul> 030 * <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/JuneauRestCommon">juneau-rest-common</a> 031 * </ul> 032 */ 033@SuppressWarnings({ 034 "java:S1192", // Duplicated literals (argument/property names) read more clearly inline than as constants 035 "resource" // Resource management handled externally 036}) 037public class ByteArrayEntity extends BasicHttpEntity<ByteArrayEntity> { 038 039 private static final byte[] EMPTY = {}; 040 041 /** 042 * Constructor. 043 */ 044 public ByteArrayEntity() {} 045 046 /** 047 * Constructor. 048 * 049 * @param contentType The entity content type. Can be <jk>null</jk> to omit an explicit <c>Content-Type</c> header. 050 * @param contents The entity contents. Can be <jk>null</jk> (treated as an empty byte array). 051 */ 052 public ByteArrayEntity(ContentType contentType, byte[] contents) { 053 super(contentType, contents); 054 } 055 056 /** 057 * Copy constructor. 058 * 059 * @param copyFrom The bean being copied. Must not be <jk>null</jk>. 060 */ 061 protected ByteArrayEntity(ByteArrayEntity copyFrom) { 062 super(copyFrom); 063 } 064 065 @Override /* Overridden from AbstractHttpEntity */ 066 public byte[] asBytes() throws IOException { 067 return cp(content()); 068 } 069 070 @Override /* Overridden from AbstractHttpEntity */ 071 public String asString() throws IOException { 072 return new String(content(), getCharset()); 073 } 074 075 @Override /* Overridden from BasicHttpEntity */ 076 public ByteArrayEntity copy() { 077 return new ByteArrayEntity(this); 078 } 079 080 @Override /* Overridden from HttpEntity */ 081 public InputStream getContent() throws IOException { return new ByteArrayInputStream(content()); } 082 083 @Override /* Overridden from HttpEntity */ 084 public long getContentLength() { return isSupplied() ? super.getContentLength() : content().length; } 085 086 @Override /* Overridden from HttpEntity */ 087 public boolean isRepeatable() { return true; } 088 089 @Override /* Overridden from BasicHttpEntity */ 090 public ByteArrayEntity unmodifiable() { 091 return this instanceof UnmodifiableBean ? this : new Unmodifiable(this); 092 } 093 094 @Override /* Overridden from HttpEntity */ 095 public void writeTo(OutputStream out) throws IOException { 096 reqnn("out", out); 097 out.write(content()); 098 } 099 100 @Override /* Overridden from Object */ 101 public boolean equals(Object o) { 102 // Leaf-type gate: keeps this entity from comparing equal to a different leaf with equal base content, while 103 // preserving content equality (ByteArrayEntity.Unmodifiable IS-A ByteArrayEntity, so bean.equals(bean.unmodifiable()) holds). 104 // This leaf adds no equality-relevant state of its own; base content is compared via super.equals(...). 105 return o instanceof ByteArrayEntity && super.equals(o); 106 } 107 108 @Override /* Overridden from Object */ 109 public int hashCode() { 110 // Fold in the leaf type so distinct leaves land in different buckets; stable across ByteArrayEntity and its 111 // Unmodifiable snapshot (both report ByteArrayEntity.class), keeping the equals/hashCode contract intact. 112 return h(ByteArrayEntity.class, super.hashCode()); 113 } 114 115 private byte[] content() { 116 return contentOrElse(EMPTY); 117 } 118 119 /** 120 * Unmodifiable point-in-time snapshot of the enclosing {@link ByteArrayEntity}. 121 * 122 * <p> 123 * Its only behavioral override is {@link #modify(Runnable)}, which throws — because all mutation is funneled through 124 * {@code modify(...)}, this single override freezes the entire mutation surface. 125 */ 126 public static class Unmodifiable extends ByteArrayEntity implements UnmodifiableBean { 127 128 /** 129 * Constructor. 130 * 131 * @param copyFrom The entity to snapshot. Must not be <jk>null</jk>. 132 */ 133 @SuppressWarnings({ 134 "java:S1699" // Paradigm intentionally calls the overridable freeze() from the ctor to deep-freeze sub-beans. 135 }) 136 protected Unmodifiable(ByteArrayEntity copyFrom) { 137 super(copyFrom); 138 freeze(); 139 } 140 141 @Override /* Overridden from BasicHttpEntity */ 142 protected ByteArrayEntity modify(Runnable mutation) { 143 throw uoex("Bean is unmodifiable."); 144 } 145 } 146}