Add cli module

This commit is contained in:
Paul Schaub 2020-06-06 18:45:42 +02:00
parent 8092140fa0
commit 47a298af2f
Signed by: vanitasvitae
GPG Key ID: 62BEE9264BF17311
9 changed files with 317 additions and 2 deletions

2
cli/.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
/build
testcredentials.properties

46
cli/build.gradle Normal file
View File

@ -0,0 +1,46 @@
plugins {
id 'java'
id 'application'
}
group 'org.mercury_im'
version '1.0'
mainClassName = "org.mercury_im.messenger.cli.MercuryCli"
repositories {
mavenCentral()
}
// Add the generated folder to the source directories so that we can work with generated classes
// This is apparently necessary for use with requery.
sourceSets {
main.java.srcDirs += "${buildDir}/generated/sources/annotationProcessor/java/main/"
test.java.srcDirs += "${buildDir}/generated/sources/annotationProcessor/java/test/"
}
dependencies {
implementation project(':domain')
implementation project(':data')
implementation "io.requery:requery:$requeryVersion"
implementation "com.h2database:h2:1.4.200"
// RxJava2
implementation "io.reactivex.rxjava2:rxjava:$rxJava2Version"
// Dagger 2 for dependency injection
implementation "com.google.dagger:dagger:$daggerVersion"
annotationProcessor "com.google.dagger:dagger-compiler:$daggerVersion"
compileOnly "org.projectlombok:lombok:$lombokVersion"
annotationProcessor "org.projectlombok:lombok:$lombokVersion"
implementation 'org.igniterealtime.smack:smack-tcp'
implementation 'org.igniterealtime.smack:smack-java8-full'
testCompile group: 'junit', name: 'junit', version: '4.12'
}
run {
standardInput = System.in
}

View File

@ -0,0 +1,21 @@
package org.mercury_im.messenger.cli;
import java.io.Console;
public class ConsoleUserInterface implements UserInterface {
public static boolean isSupported() {
return System.console() != null;
}
@Override
public String readText() {
Console console = System.console();
return console.readLine();
}
@Override
public String readPassword() {
return new String(System.console().readPassword());
}
}

View File

@ -0,0 +1,132 @@
package org.mercury_im.messenger.cli;
import org.jivesoftware.smack.util.StringUtils;
import org.jxmpp.jid.DomainBareJid;
import org.jxmpp.jid.EntityBareJid;
import org.jxmpp.jid.impl.JidCreate;
import org.jxmpp.jid.parts.Localpart;
import org.jxmpp.stringprep.XmppStringprepException;
import org.mercury_im.messenger.cli.di.component.CliComponent;
import org.mercury_im.messenger.cli.di.component.DaggerCliComponent;
import org.mercury_im.messenger.core.Messenger;
import org.mercury_im.messenger.core.viewmodel.accounts.LoginViewModel;
import org.mercury_im.messenger.core.xmpp.MercuryConnection;
import java.util.List;
import javax.inject.Inject;
import io.reactivex.disposables.Disposable;
public class MercuryCli {
private final UserInterface userInterface;
Disposable connectionStateDisposable;
@Inject
Messenger messenger;
@Inject
LoginViewModel loginViewModel;
public static void main(String[] args) {
MercuryCli cli = new MercuryCli();
cli.loginDialog();
System.out.println("Login successful.");
cli.loop();
}
/**
* Create the Dependency Injection graph.
*/
public CliComponent createCliComponent() {
CliComponent cliComponent = DaggerCliComponent.builder()
.build();
cliComponent.inject(this);
return cliComponent;
}
public MercuryCli() {
createCliComponent();
userInterface = ConsoleUserInterface.isSupported() ? new ConsoleUserInterface() : new ScannerUserInterface();
//connectionStateDisposable = messenger.getConnectionCenter().observeConnectionPoolState().subscribe(System.out::println);
}
private void loginDialog() {
System.out.println("Format is 'Username'@'Service'.");
String username = promptForUsername();
DomainBareJid service = promptForServiceDomain();
String password = promptForPassword();
EntityBareJid jid = JidCreate.entityBareFrom(Localpart.formUnescapedOrNull(username), service);
loginViewModel.onLoginUsernameChanged(jid.toString());
loginViewModel.onLoginPasswordChanged(password);
loginViewModel.login();
}
private String promptForPassword() {
System.out.println("Enter password:");
String password = userInterface.readPassword();
if (StringUtils.isNullOrEmpty(password)) {
System.out.println("Password too short.");
return promptForPassword();
}
return password;
}
private DomainBareJid promptForServiceDomain() {
System.out.println("Enter service:");
String service = userInterface.readText();
try {
return JidCreate.domainBareFrom(service);
} catch (XmppStringprepException e) {
System.out.println("Invalid service domain.");
return promptForServiceDomain();
}
}
private String promptForUsername() {
System.out.println("Please enter username:");
String username = userInterface.readText();
try {
Localpart.from(username);
} catch (XmppStringprepException e) {
System.out.println("Invalid username.");
return promptForUsername();
}
return username;
}
private void loop() {
String input = userInterface.readText();
if (StringUtils.isNullOrEmpty(input)) {
loop();
return;
}
String[] command = input.split(" ");
switch (command[0]) {
case "/exit":
System.out.println("Shutting down.");
messenger.getConnectionManager().doShutdownAllConnections();
connectionStateDisposable.dispose();
return;
case "/contacts":
List<MercuryConnection> connectionList = messenger.getConnectionManager().getConnections();
break;
case "/msg":
break;
}
loop();
}
}

View File

@ -0,0 +1,18 @@
package org.mercury_im.messenger.cli;
import java.util.Scanner;
public class ScannerUserInterface implements UserInterface {
private final Scanner scanner = new Scanner(System.in);
@Override
public String readText() {
return scanner.nextLine();
}
@Override
public String readPassword() {
return scanner.nextLine();
}
}

View File

@ -0,0 +1,8 @@
package org.mercury_im.messenger.cli;
public interface UserInterface {
String readText();
String readPassword();
}

View File

@ -0,0 +1,22 @@
package org.mercury_im.messenger.cli.di.component;
import org.mercury_im.messenger.cli.MercuryCli;
import org.mercury_im.messenger.cli.di.module.CliPersistenceModule;
import org.mercury_im.messenger.core.di.module.ViewModelModule;
import org.mercury_im.messenger.data.di.RepositoryModule;
import javax.inject.Singleton;
import dagger.Component;
@Singleton
@Component(
modules = {
CliPersistenceModule.class,
RepositoryModule.class,
ViewModelModule.class
})
public interface CliComponent {
void inject(MercuryCli mercuryCli);
}

View File

@ -0,0 +1,66 @@
package org.mercury_im.messenger.cli.di.module;
import org.h2.jdbcx.JdbcDataSource;
import org.mercury_im.messenger.core.util.ThreadUtils;
import org.mercury_im.messenger.data.model.Models;
import java.util.concurrent.Executors;
import javax.inject.Named;
import javax.inject.Singleton;
import dagger.Module;
import dagger.Provides;
import io.reactivex.Scheduler;
import io.reactivex.schedulers.Schedulers;
import io.requery.Persistable;
import io.requery.cache.EmptyEntityCache;
import io.requery.reactivex.ReactiveEntityStore;
import io.requery.reactivex.ReactiveSupport;
import io.requery.sql.Configuration;
import io.requery.sql.ConfigurationBuilder;
import io.requery.sql.EntityDataStore;
import io.requery.sql.SchemaModifier;
import io.requery.sql.TableCreationMode;
@Module
public class CliPersistenceModule {
private static Scheduler scheduler = Schedulers.newThread();
@Provides
@Singleton
static ReactiveEntityStore<Persistable> provideDatabase() {
JdbcDataSource dataSource = new JdbcDataSource();
dataSource.setUrl("jdbc:h2:~/mercury_req_db");
dataSource.setUser("sa");
dataSource.setPassword("sa");
// override onUpgrade to handle migrating to a new version
Configuration configuration = new ConfigurationBuilder(dataSource, Models.DEFAULT)
.useDefaultLogging()
.setEntityCache(new EmptyEntityCache())
.setWriteExecutor(Executors.newSingleThreadExecutor())
.build();
SchemaModifier tables = new SchemaModifier(configuration);
tables.createTables(TableCreationMode.DROP_CREATE);
System.out.println(tables.createTablesString(TableCreationMode.DROP_CREATE));
return ReactiveSupport.toReactiveStore(new EntityDataStore<>(configuration));
}
@Provides
@Named(value = ThreadUtils.SCHEDULER_IO)
@Singleton
static Scheduler provideDatabaseThread() {
return Schedulers.io();
}
@Provides
@Named(value = ThreadUtils.SCHEDULER_UI)
@Singleton
static Scheduler providerUIThread() {
return scheduler;
}
}

View File

@ -1,7 +1,7 @@
include ':entity',
':data',
':domain',
':app'
// ':core-old'
':app',
':cli'
includeBuild 'libs/Smack'