From 55d25f9f969a64511773e7d893fab420b44cf502 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Tue, 25 Feb 2025 14:36:12 -0800 Subject: [PATCH] GUACAMOLE-2036: Refactor away public constructor accepting internal char array. --- .../protocol/GuacamoleInstruction.java | 28 --------- .../guacamole/protocol/GuacamoleParser.java | 60 ++++++++++++++++++- 2 files changed, 59 insertions(+), 29 deletions(-) diff --git a/guacamole-common/src/main/java/org/apache/guacamole/protocol/GuacamoleInstruction.java b/guacamole-common/src/main/java/org/apache/guacamole/protocol/GuacamoleInstruction.java index fcce42b2a..2d6c7a136 100644 --- a/guacamole-common/src/main/java/org/apache/guacamole/protocol/GuacamoleInstruction.java +++ b/guacamole-common/src/main/java/org/apache/guacamole/protocol/GuacamoleInstruction.java @@ -93,34 +93,6 @@ public class GuacamoleInstruction { this.args = Collections.unmodifiableList(args); } - /** - * Creates a new GuacamoleInstruction having the given opcode, list of - * argument values, and underlying protocol representation. The list given - * will be used to back the internal list of arguments and the list - * returned by {@link #getArgs()}. The provided protocol representation - * will be used to back the internal protocol representation and values - * returned by {@link #toCharArray()} and {@link #toString()}. - *

- * Neither the provided argument list nor the provided protocol - * representation may be modified in any way after being provided to this - * constructor. Doing otherwise will result in undefined behavior. - * - * @param opcode - * The opcode of the instruction to create. - * - * @param args - * The list of argument values to provide in the new instruction, if - * any. - * - * @param raw - * The underlying representation of this instruction as would be sent - * over the network via the Guacamole protocol. - */ - public GuacamoleInstruction(String opcode, List args, char[] raw) { - this(opcode, args); - this.rawChars = raw; - } - /** * Returns the opcode associated with this GuacamoleInstruction. * diff --git a/guacamole-common/src/main/java/org/apache/guacamole/protocol/GuacamoleParser.java b/guacamole-common/src/main/java/org/apache/guacamole/protocol/GuacamoleParser.java index 378b471cc..dbbba2565 100644 --- a/guacamole-common/src/main/java/org/apache/guacamole/protocol/GuacamoleParser.java +++ b/guacamole-common/src/main/java/org/apache/guacamole/protocol/GuacamoleParser.java @@ -21,6 +21,7 @@ package org.apache.guacamole.protocol; import java.util.Arrays; import java.util.Iterator; +import java.util.List; import org.apache.guacamole.GuacamoleException; import org.apache.guacamole.GuacamoleServerException; @@ -120,6 +121,62 @@ public class GuacamoleParser implements Iterator { */ private int rawInstructionOffset = 0; + /** + * GuacamoleInstruction that efficiently exposes the originally parsed + * character buffer for calls to {@link #toString()} and {@link #toCharArray()} + * rather than regenerate the buffer from scratch. + */ + private static class ParsedGuacamoleInstruction extends GuacamoleInstruction { + + /** + * The original data parsed to produce this GuacamoleInstruction. + */ + private final char[] rawChars; + + /** + * A String containing the original data parsed to produce this + * GuacamoleInstruction. + */ + private String rawString = null; + + /** + * Creates a new GuacamoleInstruction that efficiently exposes the + * originally parsed character buffer rather than regenerating that + * buffer from scratch for {@link #toString()} and {@link #toCharArray()}. + * + * @param opcode + * The opcode of the instruction to create. + * + * @param args + * The list of argument values to provide in the new instruction, if + * any. + * + * @param raw + * The underlying representation of this instruction as would be sent + * over the network via the Guacamole protocol. + */ + public ParsedGuacamoleInstruction(String opcode, List args, char[] raw) { + super(opcode, args); + this.rawChars = raw; + } + + @Override + public String toString() { + + if (rawString == null) + rawString = new String(rawChars); + + return rawString; + + } + + @Override + public char[] toCharArray() { + return rawChars; + } + + } + /** * Appends data from the given buffer to the current instruction. * @@ -167,7 +224,8 @@ public class GuacamoleParser implements Iterator { // If the instruction is now complete, we're good to store the // parsed instruction for future retrieval via next() if (state == State.COMPLETE) { - parsedInstruction = new GuacamoleInstruction(elements[0], Arrays.asList(elements).subList(1, elementCount), + parsedInstruction = new ParsedGuacamoleInstruction(elements[0], + Arrays.asList(elements).subList(1, elementCount), Arrays.copyOf(rawInstruction, rawInstructionOffset)); rawInstructionOffset = 0; }