All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.bytezone.dm3270.TerminalClient Maven / Gradle / Ivy

Go to download

This is a trimmed down version of https://github.com/dmolony/dm3270 to be used as TN3270 client library

There is a newer version: 0.9.1
Show newest version
package com.bytezone.dm3270;

import com.bytezone.dm3270.application.ConsolePane;
import com.bytezone.dm3270.application.KeyboardStatusListener;
import com.bytezone.dm3270.display.Cursor;
import com.bytezone.dm3270.display.CursorMoveListener;
import com.bytezone.dm3270.display.Field;
import com.bytezone.dm3270.display.Screen;
import com.bytezone.dm3270.display.ScreenChangeListener;
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.List;
import java.util.Optional;
import javax.net.SocketFactory;

/**
 * Client to connect to TN3270 terminal servers.
 * 

* This class provides a facade to ease usage of dm3270 to java clients. */ public class TerminalClient { private boolean usesExtended3270; private final Screen screen; private ConsolePane consolePane; private SocketFactory socketFactory = SocketFactory.getDefault(); private ConnectionListener connectionListener; private int connectionTimeoutMillis; /** * Creates a new terminal client with given model and screen dimensions. * * @param model model of the terminal. Known values are 2,3,4 and 5 * @param screenDimensions dimensions in rows and columns */ public TerminalClient(int model, ScreenDimensions screenDimensions) { TelnetState telnetState = new TelnetState(); telnetState.setDoDeviceType(model); screen = new Screen(screenDimensions, null, telnetState); } /** * Sets whether the emulated terminal supports extended protocol or not. * * @param usesExtended3270 set true to support extended protocol, and false if not. By default is * false. */ public void setUsesExtended3270(boolean usesExtended3270) { this.usesExtended3270 = usesExtended3270; } /** * Allows setting the {@link SocketFactory} to be used to create sockets which allows using SSL * sockets. * * @param socketFactory the {@link SocketFactory} to use. If non is specified {@link * SocketFactory#getDefault()} will be used. */ public void setSocketFactory(SocketFactory socketFactory) { this.socketFactory = socketFactory; } /** * Sets the timeout for the socket connection. * * @param connectionTimeoutMillis Number of millis to wait for a connection to be established * before it fails. If not specified no timeout (same as 0 value) will be applied. */ public void setConnectionTimeoutMillis(int connectionTimeoutMillis) { this.connectionTimeoutMillis = connectionTimeoutMillis; } /** * Sets a class to handle general exception handler. * * @param connectionListener a class to handle exceptions. If none is provided then exceptions * stack trace will be printed to error output. */ public void setConnectionListener(ConnectionListener connectionListener) { this.connectionListener = connectionListener; } /** * Connect to a terminal server. * * @param host host name of the terminal server. * @param port port where the terminal server is listening for connections. */ public void connect(String host, int port) { screen.lockKeyboard("connect"); consolePane = new ConsolePane(screen, new Site(host, port, usesExtended3270), socketFactory); consolePane.setConnectionTimeoutMillis(connectionTimeoutMillis); consolePane.setConnectionListener(connectionListener); consolePane.connect(); } /** * Set the text of a field in the screen. * * @param row row number where to set the field text. First row is 1. * @param column column number where to set the field text. First column is 1. * @param text the text to set on the field. */ public void setFieldTextByCoord(int row, int column, String text) { int linearPosition = (row - 1) * screen.getScreenDimensions().columns + column - 1; if (screen.getFieldManager().getFields().isEmpty()) { screen.setPositionText(linearPosition, text); } else { Field field = screen.getFieldManager() .getFieldAt(linearPosition) .orElseThrow( () -> new IllegalArgumentException("Invalid field position " + row + "," + column)); screen.setFieldText(field, text); } screen.getScreenCursor().moveTo(linearPosition + text.length()); } public void setFieldTextByLabel(String lbl, String text) { Field field = findFieldPositionByLabel(lbl); if (field == null) { throw new IllegalArgumentException("Invalid field label: " + lbl); } screen.setFieldText(field, text); screen.getScreenCursor().moveTo(field.getFirstLocation() + text.length()); } private Field findFieldPositionByLabel(String label) { Field labelField = findLabelField(label); return (labelField != null) ? labelField.getNextUnprotectedField() : null; } private Field findLabelField(String label) { String screenText = getScreenText(); int pos = 0; Field fallbackLabelField = null; while (pos != -1) { pos = screenText.indexOf(label, pos); if (pos != -1) { Field field = screen.getFieldManager().getFieldAt(pos).orElse(null); if (field != null) { if (field.isProtected()) { return field; } else { if (fallbackLabelField == null) { fallbackLabelField = field; } pos++; } } else { pos++; } } } return fallbackLabelField; } /** * Send an Action ID. * * This method is usually used to send Enter after setting text fields, or to send some other keys * (like F1). * * @param aid Action ID to send. For example Enter. * @param name Name of the action sent. */ public void sendAID(byte aid, String name) { consolePane.sendAID(aid, name); } /** * Gets the screen text. * * @return The screen text with newlines separating each row. */ public String getScreenText() { StringBuilder text = new StringBuilder(); int pos = 0; boolean visible = true; for (ScreenPosition sp : screen.getPen()) { if (sp.isStartField()) { visible = sp.getStartFieldAttribute().isVisible(); } text.append(visible ? sp.getCharString() : " "); if (++pos % screen.getScreenDimensions().columns == 0) { text.append("\n"); } } return text.toString(); } /** * Gets the list of all fields (protected and unprotected) that compose the screen. * * @return The list of fields that compose the screen. Fields are not only positions where input * is expected, but also parts of the screen which are not meant to be modified or even visible. */ public List getFields() { return screen.getFieldManager().getFields(); } /** * Adding a {@link ScreenChangeListener} to the terminal emulator. * * @param listener The listener to be notified when changes on the screen happen. */ public void addScreenChangeListener(ScreenChangeListener listener) { screen.getFieldManager().addScreenChangeListener(listener); } /** * Remove a {@link ScreenChangeListener} from the terminal emulator. * * @param listener Listener to be removed from notifications. */ public void removeScreenChangeListener(ScreenChangeListener listener) { screen.getFieldManager().removeScreenChangeListener(listener); } /** * Allows checking if keyboard has been locked (no input can be sent) by the terminal server. * * @return True if the keyboard is currently locked, false otherwise. */ public boolean isKeyboardLocked() { return screen.isKeyboardLocked(); } /** * Add a {@link KeyboardStatusListener} to the terminal emulator. * * @param listener the listener to be notified when the status (locked/unlocked) of the keyboard * has changed. */ public void addKeyboardStatusListener(KeyboardStatusListener listener) { screen.addKeyboardStatusChangeListener(listener); } /** * Remove a {@link KeyboardStatusListener} from the terminal emulator. * * @param listener the listener to be removed from notifications. */ public void removeKeyboardStatusListener(KeyboardStatusListener listener) { screen.removeKeyboardStatusChangeListener(listener); } /** * Gets the status of the alarm. * * Prefer using resetAlarm so it is properly reset when checking value. Use this operation only if * you are implementing some tracing or debugging and don't want to change the alarm flag status. */ public boolean isAlarmOn() { return screen.isAlarmOn(); } /** * Allows resetting and getting the status of the alarm triggered by the terminal server. * * @return True if the alarm has sounded, false otherwise. */ public boolean resetAlarm() { return screen.resetAlarm(); } /** * Get the screen dimensions of the terminal emulator screen. * * @return Allows getting the number of rows and columns used by the terminal emulator. */ public ScreenDimensions getScreenDimensions() { return screen.getScreenDimensions(); } /** * Get the position of the cursor in the screen. * * @return The position of the cursor in the screen (x contains the column and y the row). If the * cursor is not visible then empty value is returned. */ public Optional getCursorPosition() { Cursor cursor = screen.getScreenCursor(); int location = cursor.getLocation(); int columns = screen.getScreenDimensions().columns; return cursor.isVisible() ? Optional.of(new Point(location % columns + 1, location / columns + 1)) : Optional.empty(); } /** * Add a {@link CursorMoveListener} to the terminal emulator. * * @param listener listener to be notified when the cursor is moved by terminal server. */ public void addCursorMoveListener(CursorMoveListener listener) { screen.getScreenCursor().addCursorMoveListener(listener); } /** * Remove a {@link CursorMoveListener} from the terminal emulator. * * @param listener listener to be remove from notificaitons. */ public void removeCursorMoveListener(CursorMoveListener listener) { screen.getScreenCursor().removeCursorMoveListener(listener); } /** * Disconnect the terminal emulator from the server. * * @throws InterruptedException thrown when the disconnect is interrupted. */ public void disconnect() throws InterruptedException { consolePane.disconnect(); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy