001/* 002 * Copyright 2024 Revetware LLC. 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 * http://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 com.soklet.servlet.javax; 018 019import javax.annotation.Nonnull; 020import javax.annotation.Nullable; 021import javax.annotation.concurrent.NotThreadSafe; 022import java.io.PrintWriter; 023import java.io.Writer; 024import java.util.Locale; 025import java.util.function.Consumer; 026 027import static java.util.Objects.requireNonNull; 028 029/** 030 * @author <a href="https://www.revetkn.com">Mark Allen</a> 031 */ 032@NotThreadSafe 033public class SokletServletPrintWriter extends PrintWriter { 034 @Nonnull 035 private final Consumer<SokletServletPrintWriter> writeOccurredCallback; 036 @Nonnull 037 private final Consumer<SokletServletPrintWriter> writeFinalizedCallback; 038 @Nonnull 039 private Boolean writeFinalized = false; 040 041 public SokletServletPrintWriter(@Nonnull Writer writer) { 042 this(requireNonNull(writer), null, null); 043 } 044 045 public SokletServletPrintWriter(@Nonnull Writer writer, 046 @Nullable Consumer<SokletServletPrintWriter> writeOccurredCallback, 047 @Nullable Consumer<SokletServletPrintWriter> writeFinalizedCallback) { 048 super(requireNonNull(writer), true); 049 050 if (writeOccurredCallback == null) 051 writeOccurredCallback = (ignored) -> {}; 052 053 if (writeFinalizedCallback == null) 054 writeFinalizedCallback = (ignored) -> {}; 055 056 this.writeOccurredCallback = writeOccurredCallback; 057 this.writeFinalizedCallback = writeFinalizedCallback; 058 } 059 060 @Nonnull 061 protected Boolean getWriteFinalized() { 062 return this.writeFinalized; 063 } 064 065 protected void setWriteFinalized(@Nonnull Boolean writeFinalized) { 066 requireNonNull(writeFinalized); 067 this.writeFinalized = writeFinalized; 068 } 069 070 @Nonnull 071 protected Consumer<SokletServletPrintWriter> getWriteOccurredCallback() { 072 return this.writeOccurredCallback; 073 } 074 075 @Nonnull 076 protected Consumer<SokletServletPrintWriter> getWriteFinalizedCallback() { 077 return this.writeFinalizedCallback; 078 } 079 080// Implementation of PrintWriter methods below: 081 082 @Override 083 public void write(@Nonnull char[] buf, 084 int off, 085 int len) { 086 requireNonNull(buf); 087 088 super.write(buf, off, len); 089 super.flush(); 090 getWriteOccurredCallback().accept(this); 091 } 092 093 @Override 094 public void write(@Nonnull String s, 095 int off, 096 int len) { 097 requireNonNull(s); 098 099 super.write(s, off, len); 100 super.flush(); 101 getWriteOccurredCallback().accept(this); 102 } 103 104 @Override 105 public void write(int c) { 106 super.write(c); 107 super.flush(); 108 getWriteOccurredCallback().accept(this); 109 } 110 111 @Override 112 public void write(@Nonnull char[] buf) { 113 requireNonNull(buf); 114 115 super.write(buf); 116 super.flush(); 117 getWriteOccurredCallback().accept(this); 118 } 119 120 @Override 121 public void write(@Nonnull String s) { 122 requireNonNull(s); 123 124 super.write(s); 125 super.flush(); 126 getWriteOccurredCallback().accept(this); 127 } 128 129 @Override 130 public void print(boolean b) { 131 super.print(b); 132 super.flush(); 133 getWriteOccurredCallback().accept(this); 134 } 135 136 @Override 137 public void print(char c) { 138 super.print(c); 139 super.flush(); 140 getWriteOccurredCallback().accept(this); 141 } 142 143 @Override 144 public void print(int i) { 145 super.print(i); 146 super.flush(); 147 getWriteOccurredCallback().accept(this); 148 } 149 150 @Override 151 public void print(long l) { 152 super.print(l); 153 super.flush(); 154 getWriteOccurredCallback().accept(this); 155 } 156 157 @Override 158 public void print(float f) { 159 super.print(f); 160 super.flush(); 161 getWriteOccurredCallback().accept(this); 162 } 163 164 @Override 165 public void print(double d) { 166 super.print(d); 167 super.flush(); 168 getWriteOccurredCallback().accept(this); 169 } 170 171 @Override 172 public void print(@Nonnull char[] s) { 173 requireNonNull(s); 174 175 super.print(s); 176 super.flush(); 177 getWriteOccurredCallback().accept(this); 178 } 179 180 @Override 181 public void print(@Nullable String s) { 182 super.print(s); 183 super.flush(); 184 getWriteOccurredCallback().accept(this); 185 } 186 187 @Override 188 public void print(@Nullable Object obj) { 189 super.print(obj); 190 super.flush(); 191 getWriteOccurredCallback().accept(this); 192 } 193 194 @Override 195 public void println() { 196 super.println(); 197 super.flush(); 198 getWriteOccurredCallback().accept(this); 199 } 200 201 @Override 202 public void println(boolean x) { 203 super.println(x); 204 super.flush(); 205 getWriteOccurredCallback().accept(this); 206 } 207 208 @Override 209 public void println(char x) { 210 super.println(x); 211 super.flush(); 212 getWriteOccurredCallback().accept(this); 213 } 214 215 @Override 216 public void println(int x) { 217 super.println(x); 218 super.flush(); 219 getWriteOccurredCallback().accept(this); 220 } 221 222 @Override 223 public void println(long x) { 224 super.println(x); 225 super.flush(); 226 getWriteOccurredCallback().accept(this); 227 } 228 229 @Override 230 public void println(float x) { 231 super.println(x); 232 super.flush(); 233 getWriteOccurredCallback().accept(this); 234 } 235 236 @Override 237 public void println(double x) { 238 super.println(x); 239 super.flush(); 240 getWriteOccurredCallback().accept(this); 241 } 242 243 @Override 244 public void println(char[] x) { 245 requireNonNull(x); 246 247 super.println(x); 248 super.flush(); 249 getWriteOccurredCallback().accept(this); 250 } 251 252 @Override 253 public void println(@Nullable String x) { 254 super.println(x); 255 super.flush(); 256 getWriteOccurredCallback().accept(this); 257 } 258 259 @Override 260 public void println(@Nullable Object x) { 261 super.println(x); 262 super.flush(); 263 getWriteOccurredCallback().accept(this); 264 } 265 266 @Override 267 @Nonnull 268 public PrintWriter printf(@Nonnull String format, 269 @Nullable Object... args) { 270 requireNonNull(format); 271 272 PrintWriter printWriter = super.printf(format, args); 273 super.flush(); 274 getWriteOccurredCallback().accept(this); 275 return printWriter; 276 } 277 278 @Override 279 @Nonnull 280 public PrintWriter printf(@Nullable Locale l, 281 @Nonnull String format, 282 @Nullable Object... args) { 283 requireNonNull(format); 284 285 PrintWriter printWriter = super.printf(l, format, args); 286 super.flush(); 287 getWriteOccurredCallback().accept(this); 288 return printWriter; 289 } 290 291 @Override 292 @Nonnull 293 public PrintWriter format(@Nonnull String format, 294 @Nullable Object... args) { 295 requireNonNull(format); 296 297 PrintWriter printWriter = super.format(format, args); 298 super.flush(); 299 getWriteOccurredCallback().accept(this); 300 return printWriter; 301 } 302 303 @Override 304 @Nonnull 305 public PrintWriter format(@Nullable Locale l, 306 @Nonnull String format, 307 @Nullable Object... args) { 308 requireNonNull(format); 309 310 PrintWriter printWriter = super.format(l, format, args); 311 super.flush(); 312 getWriteOccurredCallback().accept(this); 313 return printWriter; 314 } 315 316 @Override 317 @Nonnull 318 public PrintWriter append(@Nullable CharSequence csq) { 319 PrintWriter printWriter = super.append(csq); 320 super.flush(); 321 getWriteOccurredCallback().accept(this); 322 return printWriter; 323 } 324 325 @Override 326 @Nonnull 327 public PrintWriter append(@Nullable CharSequence csq, 328 int start, 329 int end) { 330 PrintWriter printWriter = super.append(csq, start, end); 331 super.flush(); 332 getWriteOccurredCallback().accept(this); 333 return printWriter; 334 } 335 336 @Override 337 @Nonnull 338 public PrintWriter append(char c) { 339 PrintWriter printWriter = super.append(c); 340 super.flush(); 341 getWriteOccurredCallback().accept(this); 342 return printWriter; 343 } 344 345 @Override 346 public void flush() { 347 super.flush(); 348 349 if (!getWriteFinalized()) { 350 setWriteFinalized(true); 351 getWriteFinalizedCallback().accept(this); 352 } 353 } 354 355 @Override 356 public void close() { 357 super.flush(); 358 super.close(); 359 360 if (!getWriteFinalized()) { 361 setWriteFinalized(true); 362 getWriteFinalizedCallback().accept(this); 363 } 364 } 365}