001/* 002 * Copyright 2024-2025 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.jakarta; 018 019import jakarta.servlet.ReadListener; 020import jakarta.servlet.ServletInputStream; 021 022import javax.annotation.Nonnull; 023import javax.annotation.concurrent.NotThreadSafe; 024import java.io.IOException; 025import java.io.InputStream; 026 027import static java.lang.String.format; 028import static java.util.Objects.requireNonNull; 029 030/** 031 * Soklet integration implementation of {@link ServletInputStream}. 032 * 033 * @author <a href="https://www.revetkn.com">Mark Allen</a> 034 */ 035@NotThreadSafe 036public final class SokletServletInputStream extends ServletInputStream { 037 @Nonnull 038 private final InputStream inputStream; 039 @Nonnull 040 private Boolean finished; 041 042 @Nonnull 043 public static SokletServletInputStream withInputStream(@Nonnull InputStream inputStream) { 044 requireNonNull(inputStream); 045 return new SokletServletInputStream(inputStream); 046 } 047 048 private SokletServletInputStream(@Nonnull InputStream inputStream) { 049 super(); 050 requireNonNull(inputStream); 051 052 this.inputStream = inputStream; 053 this.finished = false; 054 } 055 056 @Nonnull 057 protected InputStream getInputStream() { 058 return this.inputStream; 059 } 060 061 @Nonnull 062 protected Boolean getFinished() { 063 return this.finished; 064 } 065 066 protected void setFinished(@Nonnull Boolean finished) { 067 requireNonNull(finished); 068 this.finished = finished; 069 } 070 071 // Implementation of ServletInputStream methods below: 072 073 @Override 074 public boolean isFinished() { 075 return getFinished(); 076 } 077 078 @Override 079 public boolean isReady() { 080 return true; 081 } 082 083 @Override 084 public int available() throws IOException { 085 return getInputStream().available(); 086 } 087 088 @Override 089 public void close() throws IOException { 090 super.close(); 091 getInputStream().close(); 092 } 093 094 @Override 095 public void setReadListener(@Nonnull ReadListener readListener) { 096 requireNonNull(readListener); 097 throw new IllegalStateException(format("%s functionality is not supported", ReadListener.class.getSimpleName())); 098 } 099 100 @Override 101 public int read() throws IOException { 102 int data = getInputStream().read(); 103 104 if (data == -1) 105 setFinished(true); 106 107 return data; 108 } 109}