Convert app module to Java (#488)
* app.Program: convert to Java * app.Main: convert to Java * app: remove scala dependencies * parent: remove scala dependencies
This commit is contained in:
parent
783402f745
commit
ee5a831e81
8 changed files with 112 additions and 190 deletions
10
app/pom.xml
10
app/pom.xml
|
@ -45,20 +45,10 @@
|
||||||
<groupId>net.kemitix.thorp</groupId>
|
<groupId>net.kemitix.thorp</groupId>
|
||||||
<artifactId>thorp-uishell</artifactId>
|
<artifactId>thorp-uishell</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<!-- scala -->
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.scala-lang</groupId>
|
|
||||||
<artifactId>scala-library</artifactId>
|
|
||||||
</dependency>
|
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
<plugins>
|
<plugins>
|
||||||
<plugin>
|
|
||||||
<groupId>net.alchim31.maven</groupId>
|
|
||||||
<artifactId>scala-maven-plugin</artifactId>
|
|
||||||
</plugin>
|
|
||||||
<plugin>
|
<plugin>
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
<artifactId>maven-assembly-plugin</artifactId>
|
<artifactId>maven-assembly-plugin</artifactId>
|
||||||
|
|
10
app/src/main/java/net/kemitix/thorp/Main.java
Normal file
10
app/src/main/java/net/kemitix/thorp/Main.java
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
package net.kemitix.thorp;
|
||||||
|
|
||||||
|
public class Main {
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
Program.run(args);
|
||||||
|
System.exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
100
app/src/main/java/net/kemitix/thorp/Program.java
Normal file
100
app/src/main/java/net/kemitix/thorp/Program.java
Normal file
|
@ -0,0 +1,100 @@
|
||||||
|
package net.kemitix.thorp;
|
||||||
|
|
||||||
|
import net.kemitix.thorp.cli.CliArgs;
|
||||||
|
import net.kemitix.thorp.config.*;
|
||||||
|
import net.kemitix.thorp.console.Console;
|
||||||
|
import net.kemitix.thorp.domain.Counters;
|
||||||
|
import net.kemitix.thorp.domain.RemoteObjects;
|
||||||
|
import net.kemitix.thorp.domain.StorageEvent;
|
||||||
|
import net.kemitix.thorp.domain.Terminal;
|
||||||
|
import net.kemitix.thorp.domain.channel.Channel;
|
||||||
|
import net.kemitix.thorp.domain.channel.Sink;
|
||||||
|
import net.kemitix.thorp.lib.Archive;
|
||||||
|
import net.kemitix.thorp.lib.LocalFileSystem;
|
||||||
|
import net.kemitix.thorp.lib.UnversionedMirrorArchive;
|
||||||
|
import net.kemitix.thorp.storage.Storage;
|
||||||
|
import net.kemitix.thorp.uishell.UIEvent;
|
||||||
|
import net.kemitix.thorp.uishell.UIShell;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
|
||||||
|
public interface Program {
|
||||||
|
|
||||||
|
String version = "1.1.0-SNAPSHOT";
|
||||||
|
String versionLabel = String.format("%sThrop v%s%s",
|
||||||
|
Terminal.white, version, Terminal.reset);
|
||||||
|
|
||||||
|
static void run(String[] args) {
|
||||||
|
try {
|
||||||
|
ConfigOptions configOptions = CliArgs.parse(args);
|
||||||
|
Configuration configuration = ConfigurationBuilder.buildConfig(configOptions);
|
||||||
|
Console.putStrLn(versionLabel);
|
||||||
|
if (!ConfigQuery.showVersion(configOptions)) {
|
||||||
|
executeWithUi(configuration);
|
||||||
|
}
|
||||||
|
} catch (ConfigValidationException e) {
|
||||||
|
Console.putStrLn(String.format(
|
||||||
|
"Configuration error: %s", e.getErrors()));
|
||||||
|
} catch (IOException e) {
|
||||||
|
Console.putStrLn(String.format(
|
||||||
|
"Error loading configuration: %s", e.getMessage()));
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
Console.putStrLn(String.format(
|
||||||
|
"Program interrupted: %s", e.getMessage()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void executeWithUi(Configuration configuration) throws InterruptedException {
|
||||||
|
Channel
|
||||||
|
.<UIEvent>create("ui")
|
||||||
|
.addListener(UIShell.listener(configuration))
|
||||||
|
.run(uiSink -> execute(configuration, uiSink))
|
||||||
|
.start()
|
||||||
|
.waitForShutdown();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void execute(Configuration configuration, Sink<UIEvent> uiSink) {
|
||||||
|
try {
|
||||||
|
uiSink.accept(UIEvent.showValidConfig());
|
||||||
|
RemoteObjects remoteObjects = Storage.getInstance().list(configuration.bucket, configuration.prefix);
|
||||||
|
Archive archive = UnversionedMirrorArchive.create();
|
||||||
|
List<StorageEvent> storageEvents = new ArrayList<>();
|
||||||
|
storageEvents.addAll(LocalFileSystem.scanCopyUpload(configuration, uiSink, remoteObjects, archive));
|
||||||
|
storageEvents.addAll(LocalFileSystem.scanDelete(configuration, uiSink, remoteObjects, archive));
|
||||||
|
Counters counters = countEvents(storageEvents);
|
||||||
|
uiSink.accept(UIEvent.showSummary(counters));
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
// do nothing
|
||||||
|
} finally {
|
||||||
|
Storage.getInstance().shutdown();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static Counters countEvents(List<StorageEvent> storageEvents) {
|
||||||
|
AtomicInteger uploads = new AtomicInteger();
|
||||||
|
AtomicInteger copies = new AtomicInteger();
|
||||||
|
AtomicInteger deletes = new AtomicInteger();
|
||||||
|
AtomicInteger errors = new AtomicInteger();
|
||||||
|
storageEvents.forEach(storageEvent -> {
|
||||||
|
if (storageEvent instanceof StorageEvent.UploadEvent) {
|
||||||
|
uploads.incrementAndGet();
|
||||||
|
} else if (storageEvent instanceof StorageEvent.CopyEvent) {
|
||||||
|
copies.incrementAndGet();
|
||||||
|
} else if (storageEvent instanceof StorageEvent.DeleteEvent) {
|
||||||
|
deletes.incrementAndGet();
|
||||||
|
} else if (storageEvent instanceof StorageEvent.ErrorEvent) {
|
||||||
|
errors.incrementAndGet();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return Counters.empty
|
||||||
|
.withUploaded(uploads.get())
|
||||||
|
.withCopied(copies.get())
|
||||||
|
.withDeleted(deletes.get())
|
||||||
|
.withErrors(errors.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -1,10 +0,0 @@
|
||||||
package net.kemitix.thorp
|
|
||||||
|
|
||||||
object Main {
|
|
||||||
|
|
||||||
def main(args: Array[String]): Unit = {
|
|
||||||
Program.run(args.toList)
|
|
||||||
System.exit(0)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,106 +0,0 @@
|
||||||
package net.kemitix.thorp
|
|
||||||
|
|
||||||
import net.kemitix.thorp.cli.CliArgs
|
|
||||||
import net.kemitix.thorp.config._
|
|
||||||
import net.kemitix.thorp.console._
|
|
||||||
import net.kemitix.thorp.domain.StorageEvent.{
|
|
||||||
CopyEvent,
|
|
||||||
DeleteEvent,
|
|
||||||
ErrorEvent,
|
|
||||||
UploadEvent
|
|
||||||
}
|
|
||||||
import net.kemitix.thorp.domain.channel.{Channel, Sink}
|
|
||||||
import net.kemitix.thorp.domain.{Counters, StorageEvent}
|
|
||||||
import net.kemitix.thorp.lib.{LocalFileSystem, UnversionedMirrorArchive}
|
|
||||||
import net.kemitix.thorp.storage.Storage
|
|
||||||
import net.kemitix.thorp.uishell.{UIEvent, UIShell}
|
|
||||||
|
|
||||||
import scala.io.AnsiColor.{RESET, WHITE}
|
|
||||||
import scala.jdk.CollectionConverters._
|
|
||||||
|
|
||||||
trait Program {
|
|
||||||
|
|
||||||
val version = "1.1.0-SNAPSHOT"
|
|
||||||
lazy val versionLabel = s"${WHITE}Thorp v$version$RESET"
|
|
||||||
|
|
||||||
def run(args: List[String]): Unit = {
|
|
||||||
val cli = CliArgs.parse(args.toArray)
|
|
||||||
val config = ConfigurationBuilder.buildConfig(cli)
|
|
||||||
Console.putStrLn(versionLabel)
|
|
||||||
if (!showVersion(cli)) {
|
|
||||||
executeWithUI(config)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private def showVersion: ConfigOptions => Boolean =
|
|
||||||
cli => ConfigQuery.showVersion(cli)
|
|
||||||
|
|
||||||
private def executeWithUI(configuration: Configuration): Unit = {
|
|
||||||
Channel
|
|
||||||
.create("ui")
|
|
||||||
.addListener(UIShell.listener(configuration))
|
|
||||||
.run(execute(configuration)(_))
|
|
||||||
.start()
|
|
||||||
.waitForShutdown()
|
|
||||||
}
|
|
||||||
|
|
||||||
private def execute(
|
|
||||||
configuration: Configuration
|
|
||||||
)(uiSink: Sink[UIEvent]): Unit = {
|
|
||||||
try {
|
|
||||||
showValidConfig(uiSink)
|
|
||||||
val remoteObjects =
|
|
||||||
fetchRemoteData(configuration, uiSink)
|
|
||||||
val archive = UnversionedMirrorArchive.create
|
|
||||||
val storageEvents = LocalFileSystem
|
|
||||||
.scanCopyUpload(configuration, uiSink, remoteObjects, archive)
|
|
||||||
val deleteEvents = LocalFileSystem
|
|
||||||
.scanDelete(configuration, uiSink, remoteObjects, archive)
|
|
||||||
showSummary(uiSink)(
|
|
||||||
(storageEvents.asScala ++ deleteEvents.asScala).toList
|
|
||||||
)
|
|
||||||
} finally {
|
|
||||||
Storage.getInstance().shutdown()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private def showValidConfig(uiSink: Sink[UIEvent]): Unit =
|
|
||||||
uiSink.accept(UIEvent.showValidConfig)
|
|
||||||
|
|
||||||
private def fetchRemoteData(configuration: Configuration,
|
|
||||||
uiSink: Sink[UIEvent]) = {
|
|
||||||
val bucket = configuration.bucket
|
|
||||||
val prefix = configuration.prefix
|
|
||||||
val objects = Storage.getInstance().list(bucket, prefix)
|
|
||||||
uiSink.accept(UIEvent.remoteDataFetched(objects.byKey.size))
|
|
||||||
objects
|
|
||||||
}
|
|
||||||
|
|
||||||
//TODO not called
|
|
||||||
private def logValidationErrors(throwable: Throwable) =
|
|
||||||
throwable match {
|
|
||||||
case validateError: ConfigValidationException =>
|
|
||||||
validateError.getErrors.asScala
|
|
||||||
.map(error => Console.putStrLn(s"- $error"))
|
|
||||||
}
|
|
||||||
|
|
||||||
private def showSummary(
|
|
||||||
uiSink: Sink[UIEvent]
|
|
||||||
)(events: Seq[StorageEvent]): Unit = {
|
|
||||||
val counters = events.foldLeft(Counters.empty)(countActivities)
|
|
||||||
uiSink.accept(UIEvent.showSummary(counters))
|
|
||||||
}
|
|
||||||
|
|
||||||
private def countActivities =
|
|
||||||
(counters: Counters, s3Action: StorageEvent) => {
|
|
||||||
s3Action match {
|
|
||||||
case _: UploadEvent => counters.incrementUploaded()
|
|
||||||
case _: CopyEvent => counters.incrementCopied()
|
|
||||||
case _: DeleteEvent => counters.incrementDeleted()
|
|
||||||
case _: ErrorEvent => counters.incrementErrors()
|
|
||||||
case _ => counters
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
object Program extends Program
|
|
Binary file not shown.
Before Width: | Height: | Size: 177 KiB After Width: | Height: | Size: 190 KiB |
|
@ -66,9 +66,10 @@ public class Terminal {
|
||||||
public static String enableAlternateBuffer = csi + "?1049h";
|
public static String enableAlternateBuffer = csi + "?1049h";
|
||||||
public static String disableAlternateBuffer = csi + "?1049l";
|
public static String disableAlternateBuffer = csi + "?1049l";
|
||||||
|
|
||||||
|
public static String reset = "\u001B[0m";
|
||||||
public static String red = "\u001B[31m";
|
public static String red = "\u001B[31m";
|
||||||
public static String green = "\u001B[32m";
|
public static String green = "\u001B[32m";
|
||||||
public static String reset = "\u001B[0m";
|
public static String white = "\u001B[37m";
|
||||||
|
|
||||||
private static Map<Integer, String> getSubBars() {
|
private static Map<Integer, String> getSubBars() {
|
||||||
Map<Integer, String> subBars = new HashMap<>();
|
Map<Integer, String> subBars = new HashMap<>();
|
||||||
|
|
|
@ -16,10 +16,8 @@
|
||||||
<packaging>pom</packaging>
|
<packaging>pom</packaging>
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
<scala-maven-plugin.version>4.4.0</scala-maven-plugin.version>
|
|
||||||
<tiles-maven-plugin.version>2.17</tiles-maven-plugin.version>
|
<tiles-maven-plugin.version>2.17</tiles-maven-plugin.version>
|
||||||
<kemitix-maven-tiles.version>2.7.0</kemitix-maven-tiles.version>
|
<kemitix-maven-tiles.version>2.7.0</kemitix-maven-tiles.version>
|
||||||
<scala-library.version>2.13.3</scala-library.version>
|
|
||||||
<lombok.version>1.18.12</lombok.version>
|
<lombok.version>1.18.12</lombok.version>
|
||||||
<mon.version>2.2.0</mon.version>
|
<mon.version>2.2.0</mon.version>
|
||||||
<junit.version>5.6.2</junit.version>
|
<junit.version>5.6.2</junit.version>
|
||||||
|
@ -111,71 +109,10 @@
|
||||||
<artifactId>assertj-core</artifactId>
|
<artifactId>assertj-core</artifactId>
|
||||||
<version>${assertj.version}</version>
|
<version>${assertj.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<!-- scala - scala -->
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.scala-lang</groupId>
|
|
||||||
<artifactId>scala-library</artifactId>
|
|
||||||
<version>${scala-library.version}</version>
|
|
||||||
</dependency>
|
|
||||||
<!-- scala - command line parsing -->
|
|
||||||
<dependency>
|
|
||||||
<groupId>com.github.scopt</groupId>
|
|
||||||
<artifactId>scopt_2.13</artifactId>
|
|
||||||
<version>4.0.0-RC2</version>
|
|
||||||
</dependency>
|
|
||||||
<!-- scala - test -->
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.scalatest</groupId>
|
|
||||||
<artifactId>scalatest_2.13</artifactId>
|
|
||||||
<version>3.0.8</version>
|
|
||||||
</dependency>
|
|
||||||
<dependency><!-- only used by storage-aws -->
|
|
||||||
<groupId>org.scalamock</groupId>
|
|
||||||
<artifactId>scalamock_2.13</artifactId>
|
|
||||||
<version>4.4.0</version>
|
|
||||||
</dependency>
|
|
||||||
</dependencies>
|
</dependencies>
|
||||||
</dependencyManagement>
|
</dependencyManagement>
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
<pluginManagement>
|
|
||||||
<plugins>
|
|
||||||
<plugin>
|
|
||||||
<groupId>net.alchim31.maven</groupId>
|
|
||||||
<artifactId>scala-maven-plugin</artifactId>
|
|
||||||
<version>${scala-maven-plugin.version}</version>
|
|
||||||
<configuration>
|
|
||||||
<args>
|
|
||||||
<arg>-Ywarn-unused:imports</arg>
|
|
||||||
<arg>-Xfatal-warnings</arg>
|
|
||||||
<arg>-feature</arg>
|
|
||||||
<arg>-deprecation</arg>
|
|
||||||
<arg>-unchecked</arg>
|
|
||||||
<arg>-language:postfixOps</arg>
|
|
||||||
<arg>-language:higherKinds</arg>
|
|
||||||
</args>
|
|
||||||
</configuration>
|
|
||||||
<executions>
|
|
||||||
<execution>
|
|
||||||
<id>scala-compile-first</id>
|
|
||||||
<phase>process-resources</phase>
|
|
||||||
<goals>
|
|
||||||
<goal>add-source</goal>
|
|
||||||
<goal>compile</goal>
|
|
||||||
</goals>
|
|
||||||
</execution>
|
|
||||||
<execution>
|
|
||||||
<id>scala-test-compile</id>
|
|
||||||
<phase>process-test-resources</phase>
|
|
||||||
<goals>
|
|
||||||
<goal>testCompile</goal>
|
|
||||||
</goals>
|
|
||||||
</execution>
|
|
||||||
</executions>
|
|
||||||
</plugin>
|
|
||||||
</plugins>
|
|
||||||
</pluginManagement>
|
|
||||||
<plugins>
|
<plugins>
|
||||||
<plugin>
|
<plugin>
|
||||||
<groupId>io.repaint.maven</groupId>
|
<groupId>io.repaint.maven</groupId>
|
||||||
|
|
Loading…
Reference in a new issue