type(type).fromJson(data);
+ }
}
diff --git a/avaje-jex/src/main/java/io/avaje/jex/http/Context.java b/avaje-jex/src/main/java/io/avaje/jex/http/Context.java
index 5644b9a7..6ecb1e44 100644
--- a/avaje-jex/src/main/java/io/avaje/jex/http/Context.java
+++ b/avaje-jex/src/main/java/io/avaje/jex/http/Context.java
@@ -531,6 +531,14 @@ default String userAgent() {
return header(Constants.USER_AGENT);
}
+ /** Writes Nothing. */
+ void writeEmpty(int statusCode);
+
+ /** Writes Nothing. */
+ default void writeEmpty(HttpStatus statusCode) {
+ writeEmpty(statusCode.status());
+ }
+
/**
* Writes the given bytes directly to the response.
*
diff --git a/avaje-jex/src/main/java/io/avaje/jex/spi/JsonService.java b/avaje-jex/src/main/java/io/avaje/jex/spi/JsonService.java
index bab6d9f0..2325bd2d 100644
--- a/avaje-jex/src/main/java/io/avaje/jex/spi/JsonService.java
+++ b/avaje-jex/src/main/java/io/avaje/jex/spi/JsonService.java
@@ -35,10 +35,19 @@ public non-sealed interface JsonService extends JexExtension {
String toJsonString(Object bean);
/**
- * Deserializes a json input stream and deserializes it into a Java object of the specified type.
+ * **Read a Java Object from JSON string**
+ *
+ * Deserializes a Java object from a JSON string
*
* @param type the Type object of the desired type
* @param is the input stream containing the JSON data
+ * @return the serialized JSON string
+ */
+ T fromJson(Type type, String string);
+
+ /**
+ * Deserializes a json input stream and deserializes it into a Java object of the specified type.
+ *
* @return the deserialized object
*/
T fromJson(Type type, InputStream is);
diff --git a/pom.xml b/pom.xml
index 6cca2ec0..89b7fb8b 100644
--- a/pom.xml
+++ b/pom.xml
@@ -47,6 +47,7 @@
avaje-jex-static-content
avaje-jex-test
avaje-jex-ssl
+ avaje-jex-websockets
From afc15aef313501a59e5187a014819696d27c6881 Mon Sep 17 00:00:00 2001
From: Josiah Noel <32279667+SentryMan@users.noreply.github.com>
Date: Thu, 4 Sep 2025 01:36:37 -0400
Subject: [PATCH 2/4] will of D
---
.../jex/websocket/{JexWebSocket.java => DWebSocket.java} | 4 ++--
...bSocketExchangeHandler.java => DWebSocketHandler.java} | 8 ++++----
.../main/java/io/avaje/jex/websocket/WebSocketPlugin.java | 2 +-
.../main/java/io/avaje/jex/websocket/internal/Util.java | 8 --------
.../jex/websocket/internal/EchoWebSocketHandler.java | 8 +++++++-
.../avaje/jex/websocket/internal/WebSocketClientUtil.java | 1 +
6 files changed, 15 insertions(+), 16 deletions(-)
rename avaje-jex-websockets/src/main/java/io/avaje/jex/websocket/{JexWebSocket.java => DWebSocket.java} (93%)
rename avaje-jex-websockets/src/main/java/io/avaje/jex/websocket/{WebSocketExchangeHandler.java => DWebSocketHandler.java} (50%)
diff --git a/avaje-jex-websockets/src/main/java/io/avaje/jex/websocket/JexWebSocket.java b/avaje-jex-websockets/src/main/java/io/avaje/jex/websocket/DWebSocket.java
similarity index 93%
rename from avaje-jex-websockets/src/main/java/io/avaje/jex/websocket/JexWebSocket.java
rename to avaje-jex-websockets/src/main/java/io/avaje/jex/websocket/DWebSocket.java
index 649dfa63..f66b3f1d 100644
--- a/avaje-jex-websockets/src/main/java/io/avaje/jex/websocket/JexWebSocket.java
+++ b/avaje-jex-websockets/src/main/java/io/avaje/jex/websocket/DWebSocket.java
@@ -10,12 +10,12 @@
import io.avaje.jex.websocket.exception.CloseCode;
import io.avaje.jex.websocket.internal.AbstractWebSocket;
-class JexWebSocket extends AbstractWebSocket {
+class DWebSocket extends AbstractWebSocket {
private final WebSocketListener listener;
private final Context ctx;
- JexWebSocket(Context ctx, WebSocketListener listener) {
+ DWebSocket(Context ctx, WebSocketListener listener) {
super(ctx.exchange());
this.listener = listener;
this.ctx = ctx;
diff --git a/avaje-jex-websockets/src/main/java/io/avaje/jex/websocket/WebSocketExchangeHandler.java b/avaje-jex-websockets/src/main/java/io/avaje/jex/websocket/DWebSocketHandler.java
similarity index 50%
rename from avaje-jex-websockets/src/main/java/io/avaje/jex/websocket/WebSocketExchangeHandler.java
rename to avaje-jex-websockets/src/main/java/io/avaje/jex/websocket/DWebSocketHandler.java
index fd7e3b66..4a05476a 100644
--- a/avaje-jex-websockets/src/main/java/io/avaje/jex/websocket/WebSocketExchangeHandler.java
+++ b/avaje-jex-websockets/src/main/java/io/avaje/jex/websocket/DWebSocketHandler.java
@@ -3,17 +3,17 @@
import io.avaje.jex.http.Context;
import io.avaje.jex.websocket.internal.WebSocketHandler;
-class WebSocketExchangeHandler extends WebSocketHandler {
+class DWebSocketHandler extends WebSocketHandler {
private final WebSocketListener listener;
- WebSocketExchangeHandler(WebSocketListener listener) {
+ DWebSocketHandler(WebSocketListener listener) {
this.listener = listener;
}
@Override
- protected JexWebSocket openWebSocket(Context exchange) {
+ protected DWebSocket openWebSocket(Context exchange) {
- return new JexWebSocket(exchange, listener);
+ return new DWebSocket(exchange, listener);
}
}
diff --git a/avaje-jex-websockets/src/main/java/io/avaje/jex/websocket/WebSocketPlugin.java b/avaje-jex-websockets/src/main/java/io/avaje/jex/websocket/WebSocketPlugin.java
index 105feabf..f8dd6512 100644
--- a/avaje-jex-websockets/src/main/java/io/avaje/jex/websocket/WebSocketPlugin.java
+++ b/avaje-jex-websockets/src/main/java/io/avaje/jex/websocket/WebSocketPlugin.java
@@ -13,7 +13,7 @@ public class WebSocketPlugin implements JexPlugin {
private final List handlers = new ArrayList<>();
public WebSocketPlugin ws(String path, WebSocketListener listener, Role... roles) {
- handlers.add(r -> r.get(path, new WebSocketExchangeHandler(listener), roles));
+ handlers.add(r -> r.get(path, new DWebSocketHandler(listener), roles));
return this;
}
diff --git a/avaje-jex-websockets/src/main/java/io/avaje/jex/websocket/internal/Util.java b/avaje-jex-websockets/src/main/java/io/avaje/jex/websocket/internal/Util.java
index 6133b464..a5a168d2 100644
--- a/avaje-jex-websockets/src/main/java/io/avaje/jex/websocket/internal/Util.java
+++ b/avaje-jex-websockets/src/main/java/io/avaje/jex/websocket/internal/Util.java
@@ -40,21 +40,13 @@
class Util {
public static final String HEADER_UPGRADE = "Upgrade";
-
public static final String HEADER_UPGRADE_VALUE = "websocket";
-
public static final String HEADER_CONNECTION = "Connection";
-
public static final String HEADER_WEBSOCKET_VERSION = "sec-websocket-version";
-
public static final String HEADER_WEBSOCKET_VERSION_VALUE = "13";
-
public static final String HEADER_WEBSOCKET_KEY = "sec-websocket-key";
-
public static final String HEADER_WEBSOCKET_ACCEPT = "sec-websocket-accept";
-
public static final String HEADER_WEBSOCKET_PROTOCOL = "sec-websocket-protocol";
-
private static final String WEBSOCKET_KEY_MAGIC = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
public static String makeAcceptKey(String key) throws NoSuchAlgorithmException {
diff --git a/avaje-jex-websockets/src/test/java/io/avaje/jex/websocket/internal/EchoWebSocketHandler.java b/avaje-jex-websockets/src/test/java/io/avaje/jex/websocket/internal/EchoWebSocketHandler.java
index ca048aae..62d166d0 100644
--- a/avaje-jex-websockets/src/test/java/io/avaje/jex/websocket/internal/EchoWebSocketHandler.java
+++ b/avaje-jex-websockets/src/test/java/io/avaje/jex/websocket/internal/EchoWebSocketHandler.java
@@ -1,6 +1,7 @@
package io.avaje.jex.websocket.internal;
import io.avaje.jex.websocket.WebSocketListener;
+import io.avaje.jex.websocket.WsContext.WsError;
import io.avaje.jex.websocket.WsContext.WsMessage;
public class EchoWebSocketHandler implements WebSocketListener {
@@ -15,6 +16,11 @@ public void onMessage(WsMessage message) {
sb = new StringBuilder();
message.send(msg);
}
- message.closeSession();
+ // message.closeSession();
+ }
+
+ @Override
+ public void onError(WsError wsError) {
+ wsError.error().printStackTrace();
}
}
diff --git a/avaje-jex-websockets/src/test/java/io/avaje/jex/websocket/internal/WebSocketClientUtil.java b/avaje-jex-websockets/src/test/java/io/avaje/jex/websocket/internal/WebSocketClientUtil.java
index cbc1b50b..f1c5fbe7 100644
--- a/avaje-jex-websockets/src/test/java/io/avaje/jex/websocket/internal/WebSocketClientUtil.java
+++ b/avaje-jex-websockets/src/test/java/io/avaje/jex/websocket/internal/WebSocketClientUtil.java
@@ -54,6 +54,7 @@ public void onError(WebSocket webSocket, Throwable error) {
if (onCloseCallback != null) {
onCloseCallback.run();
}
+ error.printStackTrace();
}
@Override
From 96cf358514aa02e3f55ec34b51ce60b2faa6e652 Mon Sep 17 00:00:00 2001
From: Josiah Noel <32279667+SentryMan@users.noreply.github.com>
Date: Thu, 4 Sep 2025 15:25:22 -0400
Subject: [PATCH 3/4] builder
---
.../avaje/jex/websocket/ListenerBuilder.java | 132 ++++++++++++++++++
.../jex/websocket/WebSocketListener.java | 66 +++++++++
.../avaje/jex/websocket/WebSocketPlugin.java | 12 +-
.../io/avaje/jex/websocket/WsContext.java | 9 ++
.../internal/EchoWebSocketHandler.java | 3 +-
.../jex/websocket/internal/WebSocketTest.java | 3 +-
6 files changed, 219 insertions(+), 6 deletions(-)
create mode 100644 avaje-jex-websockets/src/main/java/io/avaje/jex/websocket/ListenerBuilder.java
diff --git a/avaje-jex-websockets/src/main/java/io/avaje/jex/websocket/ListenerBuilder.java b/avaje-jex-websockets/src/main/java/io/avaje/jex/websocket/ListenerBuilder.java
new file mode 100644
index 00000000..8e37750f
--- /dev/null
+++ b/avaje-jex-websockets/src/main/java/io/avaje/jex/websocket/ListenerBuilder.java
@@ -0,0 +1,132 @@
+package io.avaje.jex.websocket;
+
+import java.util.function.Consumer;
+
+import io.avaje.jex.websocket.WsContext.WsBinaryMessage;
+import io.avaje.jex.websocket.WsContext.WsClose;
+import io.avaje.jex.websocket.WsContext.WsError;
+import io.avaje.jex.websocket.WsContext.WsMessage;
+import io.avaje.jex.websocket.WsContext.WsOpen;
+import io.avaje.jex.websocket.WsContext.WsPong;
+
+/** A builder for creating a {@link WebSocketListener} with specific event handlers. */
+class ListenerBuilder implements WebSocketListener.Builder {
+ private Consumer onOpen;
+ private Consumer onMessage;
+ private Consumer onBinaryMessage;
+ private Consumer onClose;
+ private Consumer onPong;
+ private Consumer onError;
+
+ /**
+ * Set the handler for the WebSocket open event.
+ *
+ * @param handler Consumer for {@link WsOpen}
+ * @return this builder
+ */
+ @Override
+ public ListenerBuilder onOpen(Consumer handler) {
+ this.onOpen = handler;
+ return this;
+ }
+
+ /**
+ * Set the handler for the WebSocket text message event.
+ *
+ * @param handler Consumer for {@link WsMessage}
+ * @return this builder
+ */
+ @Override
+ public ListenerBuilder onMessage(Consumer handler) {
+ this.onMessage = handler;
+ return this;
+ }
+
+ /**
+ * Set the handler for the WebSocket binary message event.
+ *
+ * @param handler Consumer for {@link WsBinaryMessage}
+ * @return this builder
+ */
+ @Override
+ public ListenerBuilder onBinaryMessage(Consumer handler) {
+ this.onBinaryMessage = handler;
+ return this;
+ }
+
+ /**
+ * Set the handler for the WebSocket close event.
+ *
+ * @param handler Consumer for {@link WsClose}
+ * @return this builder
+ */
+ @Override
+ public ListenerBuilder onClose(Consumer handler) {
+ this.onClose = handler;
+ return this;
+ }
+
+ /**
+ * Set the handler for the WebSocket pong event.
+ *
+ * @param handler Consumer for {@link WsPong}
+ * @return this builder
+ */
+ @Override
+ public ListenerBuilder onPong(Consumer handler) {
+ this.onPong = handler;
+ return this;
+ }
+
+ /**
+ * Set the handler for the WebSocket error event.
+ *
+ * @param handler Consumer for {@link WsError}
+ * @return this builder
+ */
+ @Override
+ public ListenerBuilder onError(Consumer handler) {
+ this.onError = handler;
+ return this;
+ }
+
+ /**
+ * Build a {@link WebSocketListener} implementation using the configured handlers.
+ *
+ * @return a new {@link WebSocketListener} instance
+ */
+ @Override
+ public WebSocketListener build() {
+ return new WebSocketListener() {
+ @Override
+ public void onOpen(WsOpen wsOpen) {
+ if (onOpen != null) onOpen.accept(wsOpen);
+ }
+
+ @Override
+ public void onMessage(WsMessage message) {
+ if (onMessage != null) onMessage.accept(message);
+ }
+
+ @Override
+ public void onBinaryMessage(WsBinaryMessage binaryPayload) {
+ if (onBinaryMessage != null) onBinaryMessage.accept(binaryPayload);
+ }
+
+ @Override
+ public void onClose(WsClose wsClose) {
+ if (onClose != null) onClose.accept(wsClose);
+ }
+
+ @Override
+ public void onPong(WsPong wsPong) {
+ if (onPong != null) onPong.accept(wsPong);
+ }
+
+ @Override
+ public void onError(WsError wsError) {
+ if (onError != null) onError.accept(wsError);
+ }
+ };
+ }
+}
diff --git a/avaje-jex-websockets/src/main/java/io/avaje/jex/websocket/WebSocketListener.java b/avaje-jex-websockets/src/main/java/io/avaje/jex/websocket/WebSocketListener.java
index 9b6870f7..c11d0dd4 100644
--- a/avaje-jex-websockets/src/main/java/io/avaje/jex/websocket/WebSocketListener.java
+++ b/avaje-jex-websockets/src/main/java/io/avaje/jex/websocket/WebSocketListener.java
@@ -1,5 +1,7 @@
package io.avaje.jex.websocket;
+import java.util.function.Consumer;
+
import io.avaje.jex.websocket.WsContext.WsBinaryMessage;
import io.avaje.jex.websocket.WsContext.WsClose;
import io.avaje.jex.websocket.WsContext.WsError;
@@ -12,6 +14,16 @@
* log.
*/
public interface WebSocketListener {
+
+ /**
+ * Create a builder for a WebSocketListener.
+ *
+ * @return the builder
+ */
+ static Builder builder() {
+ return new ListenerBuilder();
+ }
+
/**
* Called when a binary message is received.
*
@@ -53,4 +65,58 @@ default void onPong(WsPong wsPong) {}
* @param wsError the error
*/
default void onError(WsError wsError) {}
+
+ interface Builder {
+
+ /**
+ * Set the handler for the WebSocket open event.
+ *
+ * @param handler Consumer for {@link WsOpen}
+ * @return this builder
+ */
+ Builder onOpen(Consumer handler);
+
+ /**
+ * Set the handler for the WebSocket text message event.
+ *
+ * @param handler Consumer for {@link WsMessage}
+ * @return this builder
+ */
+ Builder onMessage(Consumer handler);
+
+ /**
+ * Set the handler for the WebSocket binary message event.
+ *
+ * @param handler Consumer for {@link WsBinaryMessage}
+ * @return this builder
+ */
+ Builder onBinaryMessage(Consumer handler);
+
+ /**
+ * Set the handler for the WebSocket close event.
+ *
+ * @param handler Consumer for {@link WsClose}
+ * @return this builder
+ */
+ Builder onClose(Consumer handler);
+
+ /**
+ * Set the handler for the WebSocket pong event.
+ *
+ * @param handler Consumer for {@link WsPong}
+ * @return this builder
+ */
+ Builder onPong(Consumer handler);
+
+ /**
+ * Set the handler for the WebSocket error event.
+ *
+ * @param handler Consumer for {@link WsError}
+ * @return this builder
+ */
+ Builder onError(Consumer handler);
+
+ /** Build the WebSocketListener. */
+ WebSocketListener build();
+ }
}
diff --git a/avaje-jex-websockets/src/main/java/io/avaje/jex/websocket/WebSocketPlugin.java b/avaje-jex-websockets/src/main/java/io/avaje/jex/websocket/WebSocketPlugin.java
index f8dd6512..06070a78 100644
--- a/avaje-jex-websockets/src/main/java/io/avaje/jex/websocket/WebSocketPlugin.java
+++ b/avaje-jex-websockets/src/main/java/io/avaje/jex/websocket/WebSocketPlugin.java
@@ -2,15 +2,23 @@
import java.util.ArrayList;
import java.util.List;
+import java.util.function.Consumer;
import io.avaje.jex.Jex;
-import io.avaje.jex.Routing;
+import io.avaje.jex.Routing.HttpService;
import io.avaje.jex.security.Role;
import io.avaje.jex.spi.JexPlugin;
+import io.avaje.jex.websocket.WebSocketListener.Builder;
public class WebSocketPlugin implements JexPlugin {
- private final List handlers = new ArrayList<>();
+ private final List handlers = new ArrayList<>();
+
+ public WebSocketPlugin ws(String path, Consumer consumer, Role... roles) {
+ var builder = WebSocketListener.builder();
+ consumer.accept(builder);
+ return ws(path, builder.build(), roles);
+ }
public WebSocketPlugin ws(String path, WebSocketListener listener, Role... roles) {
handlers.add(r -> r.get(path, new DWebSocketHandler(listener), roles));
diff --git a/avaje-jex-websockets/src/main/java/io/avaje/jex/websocket/WsContext.java b/avaje-jex-websockets/src/main/java/io/avaje/jex/websocket/WsContext.java
index 52f22a42..319eb3e9 100644
--- a/avaje-jex-websockets/src/main/java/io/avaje/jex/websocket/WsContext.java
+++ b/avaje-jex-websockets/src/main/java/io/avaje/jex/websocket/WsContext.java
@@ -143,6 +143,15 @@ public abstract static sealed class WsMessageCtx extends WsContext {
public WebSocketFrame wsFrame() {
return wsFrame;
}
+
+ /**
+ * Indicates if this frame is the final fragment in a message.
+ *
+ * @return true if final fragment, false otherwise
+ */
+ public boolean isFin() {
+ return wsFrame.isFin();
+ }
}
public static final class WsBinaryMessage extends WsMessageCtx {
diff --git a/avaje-jex-websockets/src/test/java/io/avaje/jex/websocket/internal/EchoWebSocketHandler.java b/avaje-jex-websockets/src/test/java/io/avaje/jex/websocket/internal/EchoWebSocketHandler.java
index 62d166d0..4679ab25 100644
--- a/avaje-jex-websockets/src/test/java/io/avaje/jex/websocket/internal/EchoWebSocketHandler.java
+++ b/avaje-jex-websockets/src/test/java/io/avaje/jex/websocket/internal/EchoWebSocketHandler.java
@@ -11,12 +11,11 @@ public class EchoWebSocketHandler implements WebSocketListener {
@Override
public void onMessage(WsMessage message) {
sb.append(message.message());
- if (message.wsFrame().isFin()) {
+ if (message.isFin()) {
String msg = sb.toString();
sb = new StringBuilder();
message.send(msg);
}
- // message.closeSession();
}
@Override
diff --git a/avaje-jex-websockets/src/test/java/io/avaje/jex/websocket/internal/WebSocketTest.java b/avaje-jex-websockets/src/test/java/io/avaje/jex/websocket/internal/WebSocketTest.java
index e488e78d..bdaa034f 100644
--- a/avaje-jex-websockets/src/test/java/io/avaje/jex/websocket/internal/WebSocketTest.java
+++ b/avaje-jex-websockets/src/test/java/io/avaje/jex/websocket/internal/WebSocketTest.java
@@ -2,7 +2,6 @@
import static org.junit.jupiter.api.Assertions.fail;
-import java.io.IOException;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.logging.ConsoleHandler;
@@ -29,7 +28,7 @@ public class WebSocketTest {
TestPair server;
@BeforeEach
- public void setUp() throws IOException {
+ void setUp() {
var jex = Jex.create();
From 214bb03545d17f6e55a370bd96b638ff3801fe74 Mon Sep 17 00:00:00 2001
From: Josiah Noel <32279667+SentryMan@users.noreply.github.com>
Date: Sun, 14 Sep 2025 22:32:00 -0400
Subject: [PATCH 4/4] remove write from interface
---
.../java/io/avaje/jex/websocket/WebSocketFrame.java | 10 ----------
.../jex/websocket/internal/AbstractWebSocket.java | 2 +-
.../java/io/avaje/jex/websocket/internal/WSFrame.java | 4 +---
3 files changed, 2 insertions(+), 14 deletions(-)
diff --git a/avaje-jex-websockets/src/main/java/io/avaje/jex/websocket/WebSocketFrame.java b/avaje-jex-websockets/src/main/java/io/avaje/jex/websocket/WebSocketFrame.java
index 39b57f10..84bed8e3 100644
--- a/avaje-jex-websockets/src/main/java/io/avaje/jex/websocket/WebSocketFrame.java
+++ b/avaje-jex-websockets/src/main/java/io/avaje/jex/websocket/WebSocketFrame.java
@@ -1,7 +1,5 @@
package io.avaje.jex.websocket;
-import java.io.IOException;
-import java.io.OutputStream;
import java.util.Arrays;
import java.util.Map;
import java.util.stream.Collectors;
@@ -54,14 +52,6 @@ public interface WebSocketFrame {
*/
boolean isMasked();
- /**
- * Writes the frame to the given output stream in WebSocket frame format.
- *
- * @param out the output stream to write to
- * @throws IOException if an I/O error occurs
- */
- void write(OutputStream out) throws IOException;
-
/** WebSocket opcodes */
public enum OpCode {
CONTINUATION(0),
diff --git a/avaje-jex-websockets/src/main/java/io/avaje/jex/websocket/internal/AbstractWebSocket.java b/avaje-jex-websockets/src/main/java/io/avaje/jex/websocket/internal/AbstractWebSocket.java
index b84b0b5b..85e0cf77 100644
--- a/avaje-jex-websockets/src/main/java/io/avaje/jex/websocket/internal/AbstractWebSocket.java
+++ b/avaje-jex-websockets/src/main/java/io/avaje/jex/websocket/internal/AbstractWebSocket.java
@@ -248,7 +248,7 @@ public void send(String payload) {
sendFrame(new WSFrame(OpCode.TEXT, true, payload));
}
- public void sendFrame(WebSocketFrame frame) {
+ public void sendFrame(WSFrame frame) {
lock.lock();
try {
onFrameSent(frame);
diff --git a/avaje-jex-websockets/src/main/java/io/avaje/jex/websocket/internal/WSFrame.java b/avaje-jex-websockets/src/main/java/io/avaje/jex/websocket/internal/WSFrame.java
index 2b3218a3..f41d4134 100644
--- a/avaje-jex-websockets/src/main/java/io/avaje/jex/websocket/internal/WSFrame.java
+++ b/avaje-jex-websockets/src/main/java/io/avaje/jex/websocket/internal/WSFrame.java
@@ -346,9 +346,7 @@ public String toString() {
}
// ------------------------------------------------------------------------
-
- @Override
- public void write(OutputStream out) throws IOException {
+ void write(OutputStream out) throws IOException {
byte header = 0;
if (this.fin) {
header |= 0x80;