blob: 1204bfc40b6bd45136a4f7bad16c673c96b921a2 [file] [log] [blame] [edit]
/*
* 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);
}
}