GUACAMOLE-2036: Refactor away public constructor accepting internal char array.

This commit is contained in:
Michael Jumper
2025-02-25 14:36:12 -08:00
parent a672229dad
commit 55d25f9f96
2 changed files with 59 additions and 29 deletions

View File

@@ -93,34 +93,6 @@ public class GuacamoleInstruction {
this.args = Collections.unmodifiableList(args); 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()}.
* <p>
* 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<String> args, char[] raw) {
this(opcode, args);
this.rawChars = raw;
}
/** /**
* Returns the opcode associated with this GuacamoleInstruction. * Returns the opcode associated with this GuacamoleInstruction.
* *

View File

@@ -21,6 +21,7 @@ package org.apache.guacamole.protocol;
import java.util.Arrays; import java.util.Arrays;
import java.util.Iterator; import java.util.Iterator;
import java.util.List;
import org.apache.guacamole.GuacamoleException; import org.apache.guacamole.GuacamoleException;
import org.apache.guacamole.GuacamoleServerException; import org.apache.guacamole.GuacamoleServerException;
@@ -120,6 +121,62 @@ public class GuacamoleParser implements Iterator<GuacamoleInstruction> {
*/ */
private int rawInstructionOffset = 0; 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<String> 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. * Appends data from the given buffer to the current instruction.
* *
@@ -167,7 +224,8 @@ public class GuacamoleParser implements Iterator<GuacamoleInstruction> {
// If the instruction is now complete, we're good to store the // If the instruction is now complete, we're good to store the
// parsed instruction for future retrieval via next() // parsed instruction for future retrieval via next()
if (state == State.COMPLETE) { 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)); Arrays.copyOf(rawInstruction, rawInstructionOffset));
rawInstructionOffset = 0; rawInstructionOffset = 0;
} }