| /* |
| * libbrlapi - A library providing access to braille terminals for applications. |
| * |
| * Copyright (C) 2006-2023 by |
| * Samuel Thibault <Samuel.Thibault@ens-lyon.org> |
| * Sébastien Hinderer <Sebastien.Hinderer@ens-lyon.org> |
| * |
| * libbrlapi comes with ABSOLUTELY NO WARRANTY. |
| * |
| * This is free software, placed under the terms of the |
| * GNU Lesser General Public License, as published by the Free Software |
| * Foundation; either version 2.1 of the License, or (at your option) any |
| * later version. Please see the file LICENSE-LGPL for details. |
| * |
| * Web Page: http://brltty.app/ |
| * |
| * This software is maintained by Dave Mielke <dave@mielke.cc>. |
| */ |
| |
| package org.a11y.brlapi; |
| |
| import java.io.InterruptedIOException; |
| |
| public abstract class Client extends Program { |
| protected abstract void runClient (Connection connection) |
| throws ProgramException; |
| |
| private final ConnectionSettings connectionSettings = new ConnectionSettings(); |
| |
| public final Client setServerHost (String host) throws SyntaxException { |
| try { |
| connectionSettings.setServerHost(host); |
| } catch (IllegalArgumentException exception) { |
| throw new SyntaxException(exception.getMessage()); |
| } |
| |
| return this; |
| } |
| |
| public final Client setAuthenticationScheme (String scheme) throws SyntaxException { |
| try { |
| connectionSettings.setAuthenticationScheme(scheme); |
| } catch (IllegalArgumentException exception) { |
| throw new SyntaxException(exception.getMessage()); |
| } |
| |
| return this; |
| } |
| |
| protected Client (String... arguments) { |
| super(arguments); |
| |
| addOption("server", |
| (operands) -> { |
| setServerHost(operands[0]); |
| }, |
| "host specification" |
| ); |
| |
| addOption("authentication", |
| (operands) -> { |
| setAuthenticationScheme(operands[0]); |
| }, |
| "scheme" |
| ); |
| } |
| |
| @Override |
| protected void extendUsageSummary (StringBuilder usage) { |
| super.extendUsageSummary(usage); |
| |
| usage.append('\n') |
| .append("The default server host is ") |
| .append(ConnectionSettings.DEFAULT_SERVER_HOST) |
| .append(". ") |
| |
| .append("The format of a host specification is ") |
| .append(USAGE_OPTIONAL_BEGIN) |
| .append("host") |
| .append(USAGE_OPTIONAL_END) |
| .append(USAGE_OPTIONAL_BEGIN) |
| .append(ConnectionSettings.HOST_PORT_SEPARATOR).append("port") |
| .append(USAGE_OPTIONAL_END) |
| .append(". ") |
| |
| .append("The host component may be either a host name or an IPV4 address") |
| .append(" - if not specified, a local socket is used. ") |
| |
| .append("The port component must be an integer within the range ") |
| .append(ConnectionSettings.MINIMUM_PORT_NUMBER) |
| .append(" through ") |
| .append(ConnectionSettings.MAXIMUM_PORT_NUMBER) |
| .append(" - if not specified, ") |
| .append(ConnectionSettings.DEFAULT_PORT_NUMBER) |
| .append(" is assumed. ") |
| ; |
| |
| usage.append('\n') |
| .append("The default authentication scheme is ") |
| .append(ConnectionSettings.DEFAULT_AUTHENTICATION_SCHEME) |
| .append(". ") |
| |
| .append("The format of a scheme specification is name") |
| .append(USAGE_OPTIONAL_BEGIN) |
| .append(ConnectionSettings.AUTHENTICATION_OPERAND_PREFIX).append("operand") |
| .append(USAGE_OPTIONAL_END) |
| .append(". ") |
| |
| .append("More than one scheme, separated by ") |
| .append(ConnectionSettings.AUTHENTICATION_SCHEME_SEPARATOR) |
| .append(", may be specified. ") |
| |
| .append("The following schemes are supported:") |
| .append("\n ").append(ConnectionSettings.AUTHENTICATION_SCHEME_KEYFILE) |
| .append(ConnectionSettings.AUTHENTICATION_OPERAND_PREFIX).append("path") |
| .append("\n ").append(ConnectionSettings.AUTHENTICATION_SCHEME_NONE) |
| ; |
| } |
| |
| protected interface ClientTask { |
| public void run (Connection connection) throws ProgramException; |
| } |
| |
| private final Client connect (ClientTask task) throws ProgramException { |
| try { |
| Connection connection = new Connection(connectionSettings); |
| |
| try { |
| task.run(connection); |
| } finally { |
| connection.close(); |
| connection = null; |
| } |
| } catch (LostConnectionException exception) { |
| throw new ExternalException("connection lost"); |
| } catch (APIError error) { |
| throw new ExternalException(("API error: " + error)); |
| } catch (APIException exception) { |
| throw new ExternalException(("API exception: " + exception)); |
| } |
| |
| return this; |
| } |
| |
| public final boolean pause (Connection connection, int milliseconds) { |
| try { |
| connection.pause(milliseconds); |
| return true; |
| } catch (InterruptedIOException exception) { |
| return false; |
| } |
| } |
| |
| @Override |
| protected final void runProgram () throws ProgramException { |
| connect( |
| (connection) -> { |
| runClient(connection); |
| } |
| ); |
| } |
| |
| protected final Parameter getParameter (Connection connection, String name) |
| throws SemanticException |
| { |
| Parameter parameter = connection.getParameters().get(name); |
| if (parameter != null) return parameter; |
| throw new SemanticException("unknown parameter: %s", name); |
| } |
| |
| protected interface TtyModeTask { |
| public void run (Connection connection) throws ProgramException; |
| } |
| |
| protected final Client ttyMode (Connection connection, String driver, TtyModeTask task, int... path) |
| throws ProgramException |
| { |
| try { |
| connection.enterTtyModeWithPath(driver, path); |
| |
| try { |
| task.run(connection); |
| } finally { |
| if (!connection.isUnusable()) connection.leaveTtyMode(); |
| } |
| } catch (APIError error) { |
| throw new ProgramException(("tty mode error: " + error)); |
| } |
| |
| return this; |
| } |
| |
| protected final Client ttyMode (Connection connection, boolean keys, TtyModeTask task, int... path) |
| throws ProgramException |
| { |
| return ttyMode(connection, (keys? connection.getDriverName(): null), task, path); |
| } |
| |
| protected interface RawModeTask { |
| public void run (Connection connection) throws ProgramException; |
| } |
| |
| protected final Client rawMode (Connection connection, String driver, RawModeTask task) |
| throws ProgramException |
| { |
| try { |
| connection.enterRawMode(driver); |
| |
| try { |
| task.run(connection); |
| } finally { |
| if (!connection.isUnusable()) connection.leaveRawMode(); |
| } |
| } catch (APIError error) { |
| throw new ProgramException(("raw mode error: " + error)); |
| } |
| |
| return this; |
| } |
| |
| protected final Client rawMode (Connection connection, RawModeTask task) |
| throws ProgramException |
| { |
| return rawMode(connection, connection.getDriverName(), task); |
| } |
| } |