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.entity; 018 019import static org.apache.juneau.commons.utils.AssertionUtils.*; 020import static org.apache.juneau.commons.utils.IoUtils.*; 021import static org.apache.juneau.commons.utils.Utils.*; 022 023import java.io.*; 024import java.nio.charset.*; 025import java.util.function.*; 026 027import org.apache.juneau.commons.io.*; 028import org.apache.juneau.http.header.*; 029 030/** 031 * A self contained, repeatable entity that obtains its content from a {@link String}. 032 * 033 * <h5 class='section'>See Also:</h5><ul> 034 * <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/JuneauRestCommonBasics">juneau-rest-common Basics</a> 035 * </ul> 036 */ 037@SuppressWarnings("resource") 038public class StringEntity extends BasicHttpEntity { 039 private static final String EMPTY = ""; 040 private byte[] byteCache; 041 042 /** 043 * Constructor. 044 */ 045 public StringEntity() {} 046 047 /** 048 * Constructor. 049 * 050 * @param contentType The entity content type. 051 * @param content The entity contents. 052 */ 053 public StringEntity(ContentType contentType, String content) { 054 super(contentType, content); 055 } 056 057 /** 058 * Copy constructor. 059 * 060 * @param copyFrom The bean being copied. 061 */ 062 protected StringEntity(StringEntity copyFrom) { 063 super(copyFrom); 064 } 065 066 @Override /* Overridden from AbstractHttpEntity */ 067 public byte[] asBytes() throws IOException { 068 if (isCached() && byteCache == null) 069 byteCache = content().getBytes(getCharset()); 070 if (nn(byteCache)) 071 return byteCache; 072 return content().getBytes(getCharset()); 073 } 074 075 @Override /* Overridden from AbstractHttpEntity */ 076 public String asString() throws IOException { 077 return content(); 078 } 079 080 @Override 081 public StringEntity copy() { 082 return new StringEntity(this); 083 } 084 085 @Override /* Overridden from HttpEntity */ 086 public InputStream getContent() throws IOException { 087 if (isCached()) 088 return new ByteArrayInputStream(asBytes()); 089 return new ReaderInputStream(new StringReader(content()), getCharset()); 090 } 091 092 @Override /* Overridden from HttpEntity */ 093 public long getContentLength() { 094 if (isCached()) 095 return asSafeBytes().length; 096 long l = super.getContentLength(); 097 if (l != -1 || isSupplied()) 098 return l; 099 String s = content(); 100 if (getCharset() == UTF8) 101 for (var i = 0; i < s.length(); i++) 102 if (s.charAt(i) > 127) 103 return -1; 104 return s.length(); 105 } 106 107 @Override /* Overridden from HttpEntity */ 108 public boolean isRepeatable() { return true; } 109 110 @Override /* Overridden from HttpEntity */ 111 public boolean isStreaming() { return false; } 112 113 @Override /* Overridden from BasicHttpEntity */ 114 public StringEntity setCached() throws IOException { 115 super.setCached(); 116 return this; 117 } 118 119 @Override /* Overridden from BasicHttpEntity */ 120 public StringEntity setCharset(Charset value) { 121 super.setCharset(value); 122 return this; 123 } 124 125 @Override /* Overridden from BasicHttpEntity */ 126 public StringEntity setChunked() { 127 super.setChunked(); 128 return this; 129 } 130 131 @Override /* Overridden from BasicHttpEntity */ 132 public StringEntity setChunked(boolean value) { 133 super.setChunked(value); 134 return this; 135 } 136 137 @Override /* Overridden from BasicHttpEntity */ 138 public StringEntity setContent(Object value) { 139 super.setContent(value); 140 return this; 141 } 142 143 @Override /* Overridden from BasicHttpEntity */ 144 public StringEntity setContent(Supplier<?> value) { 145 super.setContent(value); 146 return this; 147 } 148 149 @Override /* Overridden from BasicHttpEntity */ 150 public StringEntity setContentEncoding(ContentEncoding value) { 151 super.setContentEncoding(value); 152 return this; 153 } 154 155 @Override /* Overridden from BasicHttpEntity */ 156 public StringEntity setContentEncoding(String value) { 157 super.setContentEncoding(value); 158 return this; 159 } 160 161 @Override /* Overridden from BasicHttpEntity */ 162 public StringEntity setContentLength(long value) { 163 super.setContentLength(value); 164 return this; 165 } 166 167 @Override /* Overridden from BasicHttpEntity */ 168 public StringEntity setContentType(ContentType value) { 169 super.setContentType(value); 170 return this; 171 } 172 173 @Override /* Overridden from BasicHttpEntity */ 174 public StringEntity setContentType(String value) { 175 super.setContentType(value); 176 return this; 177 } 178 179 @Override /* Overridden from BasicHttpEntity */ 180 public StringEntity setMaxLength(int value) { 181 super.setMaxLength(value); 182 return this; 183 } 184 185 @Override /* Overridden from BasicHttpEntity */ 186 public StringEntity setUnmodifiable() { 187 super.setUnmodifiable(); 188 return this; 189 } 190 191 @Override /* Overridden from HttpEntity */ 192 public void writeTo(OutputStream out) throws IOException { 193 assertArgNotNull("out", out); 194 if (isCached()) { 195 out.write(asBytes()); 196 } else { 197 var osw = new OutputStreamWriter(out, getCharset()); 198 osw.write(content()); 199 osw.flush(); 200 } 201 } 202 203 private String content() { 204 return contentOrElse(EMPTY); 205 } 206}