import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import java.io.BufferedWriter;
import java.io.File;
import java.io.IOException;
+import java.io.OutputStreamWriter;
+import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List;
+import java.util.function.Consumer;
+import java.util.stream.Collectors;
import static net.sourceforge.argparse4j.DefaultSettings.VERSION_0_9_0_DEFAULT_SETTINGS;
parser.addArgument("-u", "--username").help("Specify your phone number, that will be your identifier.");
var mut = parser.addMutuallyExclusiveGroup();
- mut.addArgument("--dbus").help("Make request via user dbus.").action(Arguments.storeTrue());
- mut.addArgument("--dbus-system").help("Make request via system dbus.").action(Arguments.storeTrue());
+ mut.addArgument("--dbus").dest("global-dbus").help("Make request via user dbus.").action(Arguments.storeTrue());
+ mut.addArgument("--dbus-system")
+ .dest("global-dbus-system")
+ .help("Make request via system dbus.")
+ .action(Arguments.storeTrue());
parser.addArgument("-o", "--output")
.help("Choose to output in plain text or JSON")
var outputType = outputTypeInput == null
? command.getSupportedOutputTypes().stream().findFirst().orElse(null)
: outputTypeInput;
+ var writer = new BufferedWriter(new OutputStreamWriter(System.out, Charset.defaultCharset()));
var outputWriter = outputType == null
? null
- : outputType == OutputType.JSON ? new JsonWriterImpl(System.out) : new PlainTextWriterImpl(System.out);
+ : outputType == OutputType.JSON ? new JsonWriterImpl(writer) : new PlainTextWriterImpl(writer);
if (outputWriter != null && !command.getSupportedOutputTypes().contains(outputType)) {
throw new UserErrorException("Command doesn't support output type " + outputType);
var username = ns.getString("username");
- final var useDbus = Boolean.TRUE.equals(ns.getBoolean("dbus"));
- final var useDbusSystem = Boolean.TRUE.equals(ns.getBoolean("dbus-system"));
+ final var useDbus = Boolean.TRUE.equals(ns.getBoolean("global-dbus"));
+ final var useDbusSystem = Boolean.TRUE.equals(ns.getBoolean("global-dbus-system"));
if (useDbus || useDbusSystem) {
// If username is null, it will connect to the default object path
initDbusClient(command, username, useDbusSystem, outputWriter);
final TrustNewIdentity trustNewIdentity
) throws CommandException {
final var managers = new ArrayList<Manager>();
- for (String u : usernames) {
- try {
- managers.add(loadManager(u, dataPath, serviceEnvironment, trustNewIdentity));
- } catch (CommandException e) {
- logger.warn("Ignoring {}: {}", u, e.getMessage());
- }
- }
-
- command.handleCommand(ns, managers, new SignalCreator() {
- @Override
- public ProvisioningManager getNewProvisioningManager() {
- return ProvisioningManager.init(dataPath, serviceEnvironment, BaseConfig.USER_AGENT);
- }
-
- @Override
- public RegistrationManager getNewRegistrationManager(String username) throws IOException {
- return RegistrationManager.init(username, dataPath, serviceEnvironment, BaseConfig.USER_AGENT);
+ try {
+ for (String u : usernames) {
+ try {
+ managers.add(loadManager(u, dataPath, serviceEnvironment, trustNewIdentity));
+ } catch (CommandException e) {
+ logger.warn("Ignoring {}: {}", u, e.getMessage());
+ }
}
- }, outputWriter);
- for (var m : managers) {
- try {
- m.close();
- } catch (IOException e) {
- logger.warn("Cleanup failed", e);
+ command.handleCommand(ns, new SignalCreator() {
+ private List<Consumer<Manager>> onManagerAddedHandlers = new ArrayList<>();
+
+ @Override
+ public List<String> getAccountNumbers() {
+ synchronized (managers) {
+ return managers.stream().map(Manager::getSelfNumber).collect(Collectors.toList());
+ }
+ }
+
+ @Override
+ public void addManager(final Manager m) {
+ synchronized (managers) {
+ if (!managers.contains(m)) {
+ managers.add(m);
+ for (final var handler : onManagerAddedHandlers) {
+ handler.accept(m);
+ }
+ }
+ }
+ }
+
+ @Override
+ public void addOnManagerAddedHandler(final Consumer<Manager> handler) {
+ onManagerAddedHandlers.add(handler);
+ }
+
+ @Override
+ public Manager getManager(final String phoneNumber) {
+ synchronized (managers) {
+ return managers.stream()
+ .filter(m -> m.getSelfNumber().equals(phoneNumber))
+ .findFirst()
+ .orElse(null);
+ }
+ }
+
+ @Override
+ public ProvisioningManager getNewProvisioningManager() {
+ return ProvisioningManager.init(dataPath, serviceEnvironment, BaseConfig.USER_AGENT);
+ }
+
+ @Override
+ public RegistrationManager getNewRegistrationManager(String username) throws IOException {
+ return RegistrationManager.init(username, dataPath, serviceEnvironment, BaseConfig.USER_AGENT);
+ }
+ }, outputWriter);
+ } finally {
+ synchronized (managers) {
+ for (var m : managers) {
+ try {
+ m.close();
+ } catch (IOException e) {
+ logger.warn("Cleanup failed", e);
+ }
+ }
+ managers.clear();
}
}
}
try {
manager.checkAccountState();
} catch (IOException e) {
+ try {
+ manager.close();
+ } catch (IOException ie) {
+ logger.warn("Failed to close broken account", ie);
+ }
throw new IOErrorException("Error while checking account " + username + ": " + e.getMessage(), e);
}
Command command, Signal ts, DBusConnection dBusConn, OutputWriter outputWriter
) throws CommandException {
if (command instanceof LocalCommand localCommand) {
- try {
- localCommand.handleCommand(ns, new DbusManagerImpl(ts, dBusConn), outputWriter);
+ try (final var m = new DbusManagerImpl(ts, dBusConn)) {
+ localCommand.handleCommand(ns, m, outputWriter);
} catch (UnsupportedOperationException e) {
throw new UserErrorException("Command is not yet implemented via dbus", e);
- } catch (DBusExecutionException e) {
+ } catch (IOException | DBusExecutionException e) {
throw new UnexpectedErrorException(e.getMessage(), e);
}
} else {