Skip to content

Commit

Permalink
Allow specifying charset when creating terminal client to support mul…
Browse files Browse the repository at this point in the history
…tiple charsets

Additionally move other utility methods to buffer (where they are better fit) and site to application package which provides better cohesion
  • Loading branch information
rabelenda-abstracta committed Jul 30, 2019
1 parent 8c95ab0 commit 398fd6d
Show file tree
Hide file tree
Showing 55 changed files with 399 additions and 388 deletions.
1 change: 1 addition & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
language: java
dist: trusty
jdk: oraclejdk8
cache:
directories:
Expand Down
84 changes: 84 additions & 0 deletions src/main/java/com/bytezone/dm3270/Charset.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
package com.bytezone.dm3270;

import com.bytezone.dm3270.buffers.Buffer;
import java.nio.charset.UnsupportedCharsetException;

public enum Charset {
CP1025,
CP1026,
CP1047,
CP1140,
CP1141,
CP1142,
CP1143,
CP1144,
CP1145,
CP1146,
CP1147,
CP1148,
CP1149,
CP1153,
CP1154,
CP1166,
CP1377,
CP850,
CP870,
CP930,
CP931,
CP935,
CP937,
CP939;

private char[] charsMapping;
private java.nio.charset.Charset charset;

public synchronized void load() throws UnsupportedCharsetException {
if (charset != null) {
return;
}
charset = java.nio.charset.Charset.forName(name());
byte[] baseBytes = new byte[256];
for (int i = 0; i < 256; i++) {
baseBytes[i] = (byte) i;
}
charsMapping = new String(baseBytes, charset).toCharArray();
}

public char getChar(byte value) {
return charsMapping[value & 0xFF];
}

public String getString(byte[] buffer) {
return new String(buffer, charset);
}

public String getString(byte[] buffer, int offset, int length) {
return new String(buffer,
offset + length > buffer.length ? buffer.length - offset - 1 : offset,
length, charset);
}

public String toHex(byte[] b) {
return toHex(b, 0, b.length);
}

public String toHex(byte[] b, int offset, int length) {
StringBuilder text = new StringBuilder();
for (int ptr = offset, max = offset + length; ptr < max; ptr += Buffer.HEX_LINE_SIZE) {
StringBuilder hexLine = new StringBuilder();
StringBuilder textLine = new StringBuilder();
for (int linePtr = 0; linePtr < Buffer.HEX_LINE_SIZE && ptr + linePtr < max; linePtr++) {
int val = b[ptr + linePtr] & 0xFF;
hexLine.append(String.format("%02X ", val));
if (val < 0x40 || val == 0xFF) {
textLine.append('.');
} else {
textLine.append(new String(b, ptr + linePtr, 1, charset));
}
}
text.append(String.format("%04X %-48s %s%n", ptr, hexLine.toString(), textLine.toString()));
}
return text.length() > 0 ? text.substring(0, text.length() - 1) : text.toString();
}

}
10 changes: 8 additions & 2 deletions src/main/java/com/bytezone/dm3270/TerminalClient.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import com.bytezone.dm3270.application.ConsolePane;
import com.bytezone.dm3270.application.KeyboardStatusListener;
import com.bytezone.dm3270.application.Site;
import com.bytezone.dm3270.display.Cursor;
import com.bytezone.dm3270.display.CursorMoveListener;
import com.bytezone.dm3270.display.Field;
Expand All @@ -10,7 +11,6 @@
import com.bytezone.dm3270.display.ScreenDimensions;
import com.bytezone.dm3270.display.ScreenPosition;
import com.bytezone.dm3270.streams.TelnetState;
import com.bytezone.dm3270.utilities.Site;
import java.awt.Point;
import java.util.Iterator;
import java.util.List;
Expand Down Expand Up @@ -38,9 +38,15 @@ public class TerminalClient {
* @param alternateScreenDimensions alternate screen dimensions in rows and columns
*/
public TerminalClient(int model, ScreenDimensions alternateScreenDimensions) {
this(model, alternateScreenDimensions, Charset.CP1047);
}

public TerminalClient(int model, ScreenDimensions alternateScreenDimensions, Charset charset) {
charset.load();
TelnetState telnetState = new TelnetState();
telnetState.setDoDeviceType(model);
screen = new Screen(new ScreenDimensions(24, 80), alternateScreenDimensions, telnetState);
screen = new Screen(new ScreenDimensions(24, 80), alternateScreenDimensions, telnetState,
charset);
}

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.bytezone.dm3270.application;

import com.bytezone.dm3270.ConnectionListener;
import com.bytezone.dm3270.buffers.Buffer;
import com.bytezone.dm3270.commands.Command;
import com.bytezone.dm3270.display.CursorMoveListener;
import com.bytezone.dm3270.display.Field;
Expand All @@ -11,8 +12,6 @@
import com.bytezone.dm3270.streams.TelnetListener;
import com.bytezone.dm3270.streams.TelnetState;
import com.bytezone.dm3270.streams.TerminalServer;
import com.bytezone.dm3270.utilities.Dm3270Utility;
import com.bytezone.dm3270.utilities.Site;
import javax.net.SocketFactory;

public class ConsolePane implements FieldChangeListener, CursorMoveListener,
Expand Down Expand Up @@ -68,10 +67,10 @@ private void sendAID(Command command) {
if (screen.isSscpLuData()) {
buffer[0] = 0x07;
}
Dm3270Utility.packUnsignedShort(telnetState.nextCommandHeaderSeq(), buffer, 3);
CommandHeader header = new CommandHeader(buffer);
Buffer.packUnsignedShort(telnetState.nextCommandHeaderSeq(), buffer, 3);
CommandHeader header = new CommandHeader(buffer, screen.getCharset());
TN3270ExtendedCommand extendedCommand = new TN3270ExtendedCommand(header, command,
telnetState);
telnetState, screen.getCharset());
telnetState.write(extendedCommand.getTelnetData());
} else {
telnetState.write(command.getTelnetData());
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.bytezone.dm3270.utilities;
package com.bytezone.dm3270.application;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package com.bytezone.dm3270.attributes;

import com.bytezone.dm3270.display.ScreenContext;

import java.util.Optional;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
Expand Down
36 changes: 36 additions & 0 deletions src/main/java/com/bytezone/dm3270/buffers/Buffer.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,42 @@

public interface Buffer {

int HEX_LINE_SIZE = 16;

static int unsignedShort(byte[] buffer, int offset) {
return (buffer[offset] & 0xFF) * 0x100 + (buffer[offset + 1] & 0xFF);
}

static int packUnsignedShort(int value, byte[] buffer, int offset) {
buffer[offset++] = (byte) ((value >> 8) & 0xFF);
buffer[offset++] = (byte) (value & 0xFF);
return offset;
}

static int unsignedLong(byte[] buffer, int offset) {
return (buffer[offset] & 0xFF) * 0x1000000 + (buffer[offset + 1] & 0xFF) * 0x10000
+ (buffer[offset + 2] & 0xFF) * 0x100 + (buffer[offset + 3] & 0xFF);
}

static String toHex(byte[] b, int offset, int length) {
StringBuilder text = new StringBuilder();
for (int ptr = offset, max = offset + length; ptr < max; ptr += HEX_LINE_SIZE) {
StringBuilder hexLine = new StringBuilder();
StringBuilder textLine = new StringBuilder();
for (int linePtr = 0; linePtr < HEX_LINE_SIZE && ptr + linePtr < max; linePtr++) {
int val = b[ptr + linePtr] & 0xFF;
hexLine.append(String.format("%02X ", val));
if (val < 0x20 || val >= 0xF0) {
textLine.append('.');
} else {
textLine.append(new String(b, ptr + linePtr, 1));
}
}
text.append(String.format("%04X %-48s %s%n", ptr, hexLine.toString(), textLine.toString()));
}
return text.length() > 0 ? text.substring(0, text.length() - 1) : text.toString();
}

byte[] getData();

byte[] getTelnetData();
Expand Down
12 changes: 8 additions & 4 deletions src/main/java/com/bytezone/dm3270/buffers/MultiBuffer.java
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
package com.bytezone.dm3270.buffers;

import com.bytezone.dm3270.Charset;
import com.bytezone.dm3270.display.Screen;
import com.bytezone.dm3270.utilities.Dm3270Utility;

import java.util.ArrayList;
import java.util.List;
import org.slf4j.Logger;
Expand All @@ -11,9 +10,14 @@
public class MultiBuffer implements Buffer {

private static final Logger LOG = LoggerFactory.getLogger(MultiBuffer.class);
private final Charset charset;

private List<Buffer> buffers = new ArrayList<>();

public MultiBuffer(Charset charset) {
this.charset = charset;
}

public void addBuffer(Buffer buffer) {
buffers.add(buffer);
}
Expand All @@ -23,11 +27,11 @@ public byte[] getData() {
byte[] data = new byte[size()];
int ptr = 0;
for (Buffer buffer : buffers) {
LOG.debug(Dm3270Utility.toHex(buffer.getData()));
LOG.debug(charset.toHex(buffer.getData()));
System.arraycopy(buffer.getData(), 0, data, ptr, buffer.size());
ptr += buffer.size();
}
LOG.debug(Dm3270Utility.toHex(data));
LOG.debug(charset.toHex(data));
return data;
}

Expand Down
6 changes: 3 additions & 3 deletions src/main/java/com/bytezone/dm3270/commands/AIDCommand.java
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
package com.bytezone.dm3270.commands;

import com.bytezone.dm3270.Charset;
import com.bytezone.dm3270.display.Cursor;
import com.bytezone.dm3270.display.Field;
import com.bytezone.dm3270.display.FieldManager;
import com.bytezone.dm3270.display.Screen;

import com.bytezone.dm3270.orders.BufferAddress;
import com.bytezone.dm3270.orders.BufferAddressSource;
import com.bytezone.dm3270.orders.Order;
Expand Down Expand Up @@ -74,7 +74,7 @@ public class AIDCommand extends Command implements BufferAddressSource, Iterable
private final List<Order> orders = new ArrayList<>();
private final List<Order> textOrders = new ArrayList<>();

public AIDCommand(byte[] buffer, int offset, int length) {
public AIDCommand(byte[] buffer, int offset, int length, Charset charset) {
super(buffer, offset, length); // copies buffer[offset:length] to data[]

keyCommand = data[0];
Expand All @@ -92,7 +92,7 @@ public AIDCommand(byte[] buffer, int offset, int length) {
ModifiedField currentAIDField = null;

while (ptr < length) {
Order order = Order.getOrder(data, ptr, length);
Order order = Order.getOrder(data, ptr, length, charset);
if (previousOrder != null && previousOrder.matchesPreviousOrder(order)) {
previousOrder.incrementDuplicates();
} else {
Expand Down
16 changes: 8 additions & 8 deletions src/main/java/com/bytezone/dm3270/commands/Command.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package com.bytezone.dm3270.commands;

import com.bytezone.dm3270.Charset;
import com.bytezone.dm3270.buffers.AbstractTN3270Command;
import com.bytezone.dm3270.utilities.Dm3270Utility;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

Expand Down Expand Up @@ -97,15 +97,15 @@ public Command() {
* used. A Short Read results in only the AID being sent inbound to the host.
*/

public static Command getCommand(byte[] buffer, int offset, int length) {
public static Command getCommand(byte[] buffer, int offset, int length, Charset charset) {
switch (buffer[offset]) {
case Command.WRITE_F1:
case Command.WRITE_01:
case Command.ERASE_WRITE_F5:
case Command.ERASE_WRITE_05:
case Command.ERASE_WRITE_ALTERNATE_7E:
case Command.ERASE_WRITE_ALTERNATE_0D:
return new WriteCommand(buffer, offset, length);
return new WriteCommand(buffer, offset, length, charset);

case Command.ERASE_ALL_UNPROTECTED_6F:
case Command.ERASE_ALL_UNPROTECTED_0F:
Expand All @@ -121,22 +121,22 @@ public static Command getCommand(byte[] buffer, int offset, int length) {

case Command.WRITE_STRUCTURED_FIELD_F3:
case Command.WRITE_STRUCTURED_FIELD_11:
return new WriteStructuredFieldCommand(buffer, offset, length);
return new WriteStructuredFieldCommand(buffer, offset, length, charset);

default:
LOG.warn("Unknown 3270 Command: {}\n{}", String.format("%02X", buffer[offset]),
Dm3270Utility.toHex(buffer, offset, length));
charset.toHex(buffer, offset, length));
return null;
}
}

public abstract String getName();

public static Command getReply(byte[] buffer, int offset, int length) {
public static Command getReply(byte[] buffer, int offset, int length, Charset charset) {
if (buffer[offset] == AIDCommand.AID_STRUCTURED_FIELD) {
return new ReadStructuredFieldCommand(buffer, offset, length);
return new ReadStructuredFieldCommand(buffer, offset, length, charset);
}
return new AIDCommand(buffer, offset, length);
return new AIDCommand(buffer, offset, length, charset);
}

}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.bytezone.dm3270.commands;

import com.bytezone.dm3270.Charset;
import com.bytezone.dm3270.display.Screen;
import com.bytezone.dm3270.structuredfields.StructuredField;
import org.slf4j.Logger;
Expand All @@ -8,11 +9,13 @@
public class ReadPartitionQuery extends Command {

private static final Logger LOG = LoggerFactory.getLogger(ReadPartitionQuery.class);
private final Charset charset;

private String typeName;

public ReadPartitionQuery(byte[] buffer, int offset, int length) {
public ReadPartitionQuery(byte[] buffer, int offset, int length, Charset charset) {
super(buffer, offset, length);
this.charset = charset;

assert data[0] == StructuredField.READ_PARTITION;
assert data[1] == (byte) 0xFF;
Expand All @@ -26,8 +29,7 @@ public void process(Screen screen) {

switch (data[2]) {
case (byte) 0x02:
setReply(
new ReadStructuredFieldCommand(screen.getTelnetState())); // build a QueryReply
setReply(new ReadStructuredFieldCommand(screen.getTelnetState(), charset));
typeName = "Read Partition (Query)";
break;

Expand All @@ -43,7 +45,7 @@ public void process(Screen screen) {

case 2:
setReply(
new ReadStructuredFieldCommand(screen.getTelnetState())); // build a QueryReply
new ReadStructuredFieldCommand(screen.getTelnetState(), charset));
typeName = "Read Partition (QueryList)";
break;

Expand Down
Loading

0 comments on commit 398fd6d

Please sign in to comment.