From 66b9f27309ed91ddf4fe0dc4c5e1e7469e64ede2 Mon Sep 17 00:00:00 2001 From: Kaloyan Raev Date: Tue, 9 Jan 2018 12:59:58 +0200 Subject: [PATCH 1/5] Fixes #15: Implement GUI protocol for register account and login --- pom.xml | 5 + src/main/java/io/goobox/sync/storj/App.java | 5 + .../io/goobox/sync/storj/ipc/Command.java | 43 +++++++++ .../goobox/sync/storj/ipc/CommandResult.java | 29 ++++++ .../sync/storj/ipc/CreateAccountRequest.java | 94 +++++++++++++++++++ .../sync/storj/ipc/CreateAccountResult.java | 28 ++++++ .../goobox/sync/storj/ipc/LoginRequest.java | 91 ++++++++++++++++++ .../java/io/goobox/sync/storj/ipc/Status.java | 34 +++++++ .../io/goobox/sync/storj/ipc/StdinReader.java | 60 ++++++++++++ 9 files changed, 389 insertions(+) create mode 100644 src/main/java/io/goobox/sync/storj/ipc/Command.java create mode 100644 src/main/java/io/goobox/sync/storj/ipc/CommandResult.java create mode 100644 src/main/java/io/goobox/sync/storj/ipc/CreateAccountRequest.java create mode 100644 src/main/java/io/goobox/sync/storj/ipc/CreateAccountResult.java create mode 100644 src/main/java/io/goobox/sync/storj/ipc/LoginRequest.java create mode 100644 src/main/java/io/goobox/sync/storj/ipc/Status.java create mode 100644 src/main/java/io/goobox/sync/storj/ipc/StdinReader.java diff --git a/pom.xml b/pom.xml index 72b5272..215f7d2 100644 --- a/pom.xml +++ b/pom.xml @@ -99,6 +99,11 @@ commons-cli 1.4 + + com.google.code.gson + gson + 2.8.2 + junit junit diff --git a/src/main/java/io/goobox/sync/storj/App.java b/src/main/java/io/goobox/sync/storj/App.java index 9663236..8fce38a 100644 --- a/src/main/java/io/goobox/sync/storj/App.java +++ b/src/main/java/io/goobox/sync/storj/App.java @@ -41,6 +41,7 @@ import io.goobox.sync.common.systemtray.ShutdownListener; import io.goobox.sync.common.systemtray.SystemTrayHelper; import io.goobox.sync.storj.db.DB; +import io.goobox.sync.storj.ipc.StdinReader; import io.goobox.sync.storj.overlay.OverlayHelper; import io.storj.libstorj.Bucket; import io.storj.libstorj.CreateBucketCallback; @@ -61,6 +62,7 @@ public class App implements ShutdownListener { private TaskQueue tasks; private TaskExecutor taskExecutor; private FileWatcher fileWatcher; + private StdinReader stdinReader; public App() { this.syncDir = Utils.getSyncDir(); @@ -181,6 +183,9 @@ private void init() { storj.setConfigDirectory(StorjUtil.getStorjConfigDir().toFile()); storj.setDownloadDirectory(syncDir.toFile()); + stdinReader = new StdinReader(); + stdinReader.start(); + if (!checkAndCreateSyncDir()) { System.exit(1); } diff --git a/src/main/java/io/goobox/sync/storj/ipc/Command.java b/src/main/java/io/goobox/sync/storj/ipc/Command.java new file mode 100644 index 0000000..b9e025c --- /dev/null +++ b/src/main/java/io/goobox/sync/storj/ipc/Command.java @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2018 Kaloyan Raev + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package io.goobox.sync.storj.ipc; + +import java.util.Map; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class Command { + + private static final Logger logger = LoggerFactory.getLogger(Command.class); + + private String method; + private Map args; + + public CommandResult execute() { + if ("login".equals(method)) { + return new LoginRequest(args.get("email"), args.get("password"), args.get("encryptionKey")).execute(); + } else if ("createAccount".equals(method)) { + return new CreateAccountRequest(args.get("email"), args.get("password")).execute(); + } else { + String msg = "Invalid command method: " + method; + logger.error(msg); + return new CommandResult(Status.ERROR, msg); + } + } + +} diff --git a/src/main/java/io/goobox/sync/storj/ipc/CommandResult.java b/src/main/java/io/goobox/sync/storj/ipc/CommandResult.java new file mode 100644 index 0000000..c81b172 --- /dev/null +++ b/src/main/java/io/goobox/sync/storj/ipc/CommandResult.java @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2018 Kaloyan Raev + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package io.goobox.sync.storj.ipc; + +public class CommandResult { + + private String status; + private String message; + + public CommandResult(Status status, String message) { + this.status = status.toString(); + this.message = message; + } + +} diff --git a/src/main/java/io/goobox/sync/storj/ipc/CreateAccountRequest.java b/src/main/java/io/goobox/sync/storj/ipc/CreateAccountRequest.java new file mode 100644 index 0000000..8e7b084 --- /dev/null +++ b/src/main/java/io/goobox/sync/storj/ipc/CreateAccountRequest.java @@ -0,0 +1,94 @@ +/* + * Copyright (C) 2018 Kaloyan Raev + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package io.goobox.sync.storj.ipc; + +import java.util.concurrent.CountDownLatch; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import io.goobox.sync.storj.App; +import io.storj.libstorj.RegisterCallback; +import io.storj.libstorj.Storj; + +public class CreateAccountRequest { + + private static final Logger logger = LoggerFactory.getLogger(CreateAccountRequest.class); + + private String email; + private String password; + + public CreateAccountRequest(String email, String password) { + this.email = email; + this.password = password; + } + + public String getEmail() { + return email; + } + + public String getPassword() { + return password; + } + + public CommandResult execute() { + if (email == null) { + String msg = "Missing email argument"; + logger.error(msg); + return new CommandResult(Status.ERROR, msg); + } + + if (password == null) { + String msg = "Missing password argument"; + logger.error(msg); + return new CommandResult(Status.ERROR, msg); + } + + Storj storj = App.getInstance().getStorj(); + + final CountDownLatch latch = new CountDownLatch(1); + final String[] error = { null }; + + storj.register(email, password, new RegisterCallback() { + @Override + public void onConfirmationPending(String email) { + latch.countDown(); + } + + @Override + public void onError(String message) { + error[0] = message.substring(message.indexOf("Error: ") + 7); + latch.countDown(); + } + }); + + try { + latch.await(); + } catch (InterruptedException e) { + error[0] = "Interrupted"; + } + + if (error[0] != null) { + return new CreateAccountResult(Status.ERROR, error[0], null); + } + + String mnemonic = Storj.generateMnemonic(256); + + return new CreateAccountResult(Status.OK, null, mnemonic); + } + +} diff --git a/src/main/java/io/goobox/sync/storj/ipc/CreateAccountResult.java b/src/main/java/io/goobox/sync/storj/ipc/CreateAccountResult.java new file mode 100644 index 0000000..c96adb7 --- /dev/null +++ b/src/main/java/io/goobox/sync/storj/ipc/CreateAccountResult.java @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2018 Kaloyan Raev + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package io.goobox.sync.storj.ipc; + +public class CreateAccountResult extends CommandResult { + + private String encryptionKey; + + public CreateAccountResult(Status status, String message, String encryptionKey) { + super(status, message); + this.encryptionKey = encryptionKey; + } + +} diff --git a/src/main/java/io/goobox/sync/storj/ipc/LoginRequest.java b/src/main/java/io/goobox/sync/storj/ipc/LoginRequest.java new file mode 100644 index 0000000..68df637 --- /dev/null +++ b/src/main/java/io/goobox/sync/storj/ipc/LoginRequest.java @@ -0,0 +1,91 @@ +/* + * Copyright (C) 2018 Kaloyan Raev + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package io.goobox.sync.storj.ipc; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import io.goobox.sync.storj.App; +import io.storj.libstorj.Keys; +import io.storj.libstorj.Storj; + +public class LoginRequest { + + private static final Logger logger = LoggerFactory.getLogger(LoginRequest.class); + + private String email; + private String password; + private String encryptionKey; + + public LoginRequest(String email, String password, String encryptionKey) { + this.email = email; + this.password = password; + this.encryptionKey = encryptionKey; + } + + public String getEmail() { + return email; + } + + public String getPassword() { + return password; + } + + public String getEncryptionKey() { + return encryptionKey; + } + + public CommandResult execute() { + if (email == null) { + String msg = "Missing email argument"; + logger.error(msg); + return new CommandResult(Status.ERROR, msg); + } + + if (password == null) { + String msg = "Missing password argument"; + logger.error(msg); + return new CommandResult(Status.ERROR, msg); + } + + if (encryptionKey == null) { + String msg = "Missing encryptionKey argument"; + logger.error(msg); + return new CommandResult(Status.ERROR, msg); + } + + Storj storj = App.getInstance().getStorj(); + Keys keys = new Keys(email, password, encryptionKey); + + boolean result = storj.verifyKeys(email, password); + if (!result) { + String msg = "Email and password do not match"; + logger.error(msg); + return new CommandResult(Status.ERROR, msg); + } + + result = storj.importKeys(keys, ""); + if (!result) { + String msg = "Failed to write authentication file"; + logger.error(msg); + return new CommandResult(Status.ERROR, msg); + } + + return new CommandResult(Status.OK, null); + } + +} diff --git a/src/main/java/io/goobox/sync/storj/ipc/Status.java b/src/main/java/io/goobox/sync/storj/ipc/Status.java new file mode 100644 index 0000000..e6e8fdc --- /dev/null +++ b/src/main/java/io/goobox/sync/storj/ipc/Status.java @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2018 Kaloyan Raev + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package io.goobox.sync.storj.ipc; + +public enum Status { + + OK("ok"), ERROR("error"); + + private String str; + + private Status(String str) { + this.str = str; + } + + @Override + public String toString() { + return str; + } + +} diff --git a/src/main/java/io/goobox/sync/storj/ipc/StdinReader.java b/src/main/java/io/goobox/sync/storj/ipc/StdinReader.java new file mode 100644 index 0000000..723ff0d --- /dev/null +++ b/src/main/java/io/goobox/sync/storj/ipc/StdinReader.java @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2018 Kaloyan Raev + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package io.goobox.sync.storj.ipc; + +import java.util.Scanner; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.gson.Gson; +import com.google.gson.JsonSyntaxException; + +public class StdinReader extends Thread { + + private static final Logger logger = LoggerFactory.getLogger(StdinReader.class); + + @Override + public void run() { + Gson gson = new Gson(); + try (Scanner scanner = new Scanner(System.in)) { + while (true) { + String input = scanner.nextLine(); + logger.debug("Command input received: " + input); + + CommandResult result = null; + try { + Command cmd = gson.fromJson(input, Command.class); + if (cmd != null) { + result = cmd.execute(); + } + } catch (JsonSyntaxException e) { + String msg = "Invalid command input: " + input; + logger.error(msg, e); + result = new CommandResult(Status.ERROR, msg); + } + + if (result != null) { + String output = gson.toJson(result); + logger.debug("Command result sent: " + output); + System.out.println(output); + } + } + } + } + +} From f53a5f4373c9071266668c0eccf478ab57a27580 Mon Sep 17 00:00:00 2001 From: Kaloyan Raev Date: Tue, 9 Jan 2018 14:02:12 +0200 Subject: [PATCH 2/5] Replace output to stdout with logging --- src/main/java/io/goobox/sync/storj/App.java | 28 +++++++++---------- .../io/goobox/sync/storj/CheckStateTask.java | 19 ++++++++----- .../goobox/sync/storj/CreateCloudDirTask.java | 23 +++++++++------ .../goobox/sync/storj/CreateLocalDirTask.java | 11 ++++++-- .../sync/storj/DeleteCloudFileTask.java | 11 ++++++-- .../sync/storj/DeleteLocalFileTask.java | 13 +++++---- .../goobox/sync/storj/DownloadFileTask.java | 19 ++++++++----- .../io/goobox/sync/storj/FileWatcher.java | 18 ++++++------ .../java/io/goobox/sync/storj/SleepTask.java | 9 ++++-- .../io/goobox/sync/storj/UploadFileTask.java | 24 +++++++++------- .../io/goobox/sync/storj/db/SyncFile.java | 6 +++- .../io/goobox/sync/storj/ipc/StdinReader.java | 4 +-- .../sync/storj/overlay/OverlayHelper.java | 11 ++++++-- 13 files changed, 121 insertions(+), 75 deletions(-) diff --git a/src/main/java/io/goobox/sync/storj/App.java b/src/main/java/io/goobox/sync/storj/App.java index 8fce38a..3d3435f 100644 --- a/src/main/java/io/goobox/sync/storj/App.java +++ b/src/main/java/io/goobox/sync/storj/App.java @@ -97,7 +97,7 @@ public static void main(String[] args) { instance = new App(); } } catch (ParseException e) { - logger.error("Failed to parse command line options: {}", e.getMessage()); + logger.error("Failed to parse command line options", e); System.exit(1); } @@ -217,34 +217,34 @@ public void shutdown() { } private boolean checkAndCreateSyncDir() { - System.out.print("Checking if local Goobox sync folder exists... "); + logger.info("Checking if local Goobox sync folder exists"); return checkAndCreateFolder(getSyncDir()); } private boolean checkAndCreateDataDir() { - System.out.print("Checking if Goobox data folder exists... "); + logger.info("Checking if Goobox data folder exists"); return checkAndCreateFolder(Utils.getDataDir()); } private boolean checkAndCreateFolder(Path path) { if (Files.exists(path)) { - System.out.println("yes"); + logger.info("Folder exists"); return true; } else { - System.out.print("no. "); + logger.info("Folder does not exist"); try { Files.createDirectory(path); - System.out.println("Folder created."); + logger.info("Folder created"); return true; } catch (IOException e) { - System.out.println("Failed creating folder: " + e.getMessage()); + logger.error("Failed creating folder", e); return false; } } } private Bucket checkAndCreateCloudBucket() { - System.out.print("Checking if cloud Goobox bucket exists... "); + logger.info("Checking if cloud Goobox bucket exists"); final Bucket[] result = { null }; try { @@ -257,23 +257,23 @@ public void onBucketsReceived(Bucket[] buckets) { for (Bucket bucket : buckets) { if ("Goobox".equals(bucket.getName())) { result[0] = bucket; - System.out.println("yes"); + logger.info("Goobox bucket exists"); latch.countDown(); return; } } - System.out.print("no. "); + logger.info("Goobox bucket does not exist"); storj.createBucket("Goobox", new CreateBucketCallback() { @Override public void onError(String message) { - System.out.println("Failed creating cloud Goobox bucket."); + logger.error("Failed creating cloud Goobox bucket: {}", message); latch.countDown(); } @Override public void onBucketCreated(Bucket bucket) { - System.out.println("Cloud Goobox bucket created."); + logger.info("Cloud Goobox bucket created"); result[0] = bucket; latch.countDown(); } @@ -282,7 +282,7 @@ public void onBucketCreated(Bucket bucket) { @Override public void onError(String message) { - System.out.println(message); + logger.error(message); latch.countDown(); } }); @@ -295,7 +295,7 @@ public void onError(String message) { } } } catch (KeysNotFoundException e) { - System.out.println( + logger.error( "No keys found. Have your imported your keys using libstorj? Make sure you don't specify a passcode."); } catch (InterruptedException e) { // do nothing diff --git a/src/main/java/io/goobox/sync/storj/CheckStateTask.java b/src/main/java/io/goobox/sync/storj/CheckStateTask.java index 5e903b3..8651afc 100644 --- a/src/main/java/io/goobox/sync/storj/CheckStateTask.java +++ b/src/main/java/io/goobox/sync/storj/CheckStateTask.java @@ -26,6 +26,9 @@ import java.util.Deque; import java.util.List; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import io.goobox.sync.common.Utils; import io.goobox.sync.common.systemtray.SystemTrayHelper; import io.goobox.sync.storj.db.DB; @@ -38,6 +41,8 @@ public class CheckStateTask implements Runnable { + private static final Logger logger = LoggerFactory.getLogger(CheckStateTask.class); + private Bucket gooboxBucket; private TaskQueue tasks; @@ -50,11 +55,11 @@ public CheckStateTask() { public void run() { // check if there are local file operations in progress if (App.getInstance().getFileWatcher().isInProgress()) { - System.out.println("Skip checking for changes - local file operations in progress..."); + logger.info("Skip checking for changes - local file operations in progress"); return; } - System.out.println("Checking for changes..."); + logger.info("Checking for changes"); SystemTrayHelper.setSynchronizing(); OverlayHelper.getInstance().setSynchronizing(); @@ -77,7 +82,7 @@ public void onFilesReceived(File[] files) { @Override public void onError(String message) { - System.out.println(" " + message); + logger.error(message); // Try again tasks.add(CheckStateTask.this); } @@ -135,7 +140,7 @@ private void processFiles(File[] files) { } } } catch (ParseException e) { - e.printStackTrace(); + logger.error("Cannot parse timestamp", e); } } @@ -144,7 +149,7 @@ private void processFiles(File[] files) { localPaths.remove(localPath); } } catch (IOException e) { - e.printStackTrace(); + logger.error("I/O error", e); } } @@ -169,7 +174,7 @@ private void processFiles(File[] files) { } } } catch (IOException e) { - e.printStackTrace(); + logger.error("I/O error", e); } } } @@ -198,7 +203,7 @@ private List getLocalPaths() { paths.add(path); } } catch (IOException e) { - e.printStackTrace(); + logger.error("I/O error", e); } } diff --git a/src/main/java/io/goobox/sync/storj/CreateCloudDirTask.java b/src/main/java/io/goobox/sync/storj/CreateCloudDirTask.java index 434f600..551cd5f 100644 --- a/src/main/java/io/goobox/sync/storj/CreateCloudDirTask.java +++ b/src/main/java/io/goobox/sync/storj/CreateCloudDirTask.java @@ -21,6 +21,9 @@ import java.nio.file.Path; import java.util.concurrent.CountDownLatch; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import io.goobox.sync.storj.db.DB; import io.storj.libstorj.Bucket; import io.storj.libstorj.File; @@ -29,6 +32,8 @@ public class CreateCloudDirTask implements Runnable { + private static final Logger logger = LoggerFactory.getLogger(CreateCloudDirTask.class); + private Bucket bucket; private Path path; @@ -48,14 +53,14 @@ public void run() { } else { final Path tmp = createTempDirFile(); - System.out.println("Creating cloud directory " + dirName + "... "); + logger.info("Creating cloud directory {}", dirName); App.getInstance().getStorj().uploadFile(bucket, dirName, tmp.toString(), new UploadFileCallback() { @Override public void onProgress(String filePath, double progress, long uploadedBytes, long totalBytes) { String progressMessage = String.format(" %3d%% %15d/%d bytes", (int) (progress * 100), uploadedBytes, totalBytes); - System.out.println(progressMessage); + logger.info(progressMessage); } @Override @@ -66,7 +71,7 @@ public void onComplete(final String filePath, final File file) { DB.setSynced(file, path); DB.commit(); } catch (IOException e) { - e.printStackTrace(); + logger.error("I/O error", e); } } @@ -78,15 +83,15 @@ public void onError(String filePath, String message) { DB.setUploadFailed(path); DB.commit(); - System.out.println(" " + message); + logger.error(message); } catch (IOException e) { - e.printStackTrace(); + logger.error("I/O error", e); } } }); } } catch (IOException e) { - System.out.println("Failed creating temp file: " + e.getMessage()); + logger.error("Failed creating temp file", e); } catch (InterruptedException e) { // interrupted - stop execution return; @@ -114,8 +119,8 @@ public void onFilesReceived(File[] files) { @Override public void onError(String message) { - System.out.printf("Error checking if directory with name %s exists: %s. Trying again...\n", - dirName, message); + logger.error("Error checking if directory with name {} exists: {}. Trying again.", dirName, + message); latch.countDown(); } }); @@ -136,7 +141,7 @@ private void deleteTempDirFile(Path tmp) { try { Files.deleteIfExists(tmp); } catch (IOException e) { - System.out.println("Failed deleting temp file: " + e.getMessage()); + logger.error("Failed deleting temp file", e); } } diff --git a/src/main/java/io/goobox/sync/storj/CreateLocalDirTask.java b/src/main/java/io/goobox/sync/storj/CreateLocalDirTask.java index 94e9dbc..0967268 100644 --- a/src/main/java/io/goobox/sync/storj/CreateLocalDirTask.java +++ b/src/main/java/io/goobox/sync/storj/CreateLocalDirTask.java @@ -19,11 +19,16 @@ import java.nio.file.Files; import java.nio.file.Path; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import io.goobox.sync.storj.db.DB; import io.storj.libstorj.File; public class CreateLocalDirTask implements Runnable { + private static final Logger logger = LoggerFactory.getLogger(CreateLocalDirTask.class); + private File storjDir; public CreateLocalDirTask(File storjDir) { @@ -32,15 +37,15 @@ public CreateLocalDirTask(File storjDir) { @Override public void run() { - System.out.print("Creating local directory " + storjDir.getName() + "... "); + logger.info("Creating local directory {}", storjDir.getName()); try { Path localDir = Files.createDirectories(App.getInstance().getSyncDir().resolve(storjDir.getName())); - System.out.println("done"); + logger.info("Locla directory created"); DB.setSynced(storjDir, localDir); DB.commit(); } catch (Exception e) { - System.out.println(e.getMessage()); + logger.error("Failed creating local directory", e); } } diff --git a/src/main/java/io/goobox/sync/storj/DeleteCloudFileTask.java b/src/main/java/io/goobox/sync/storj/DeleteCloudFileTask.java index 7dbca13..48b3d5b 100644 --- a/src/main/java/io/goobox/sync/storj/DeleteCloudFileTask.java +++ b/src/main/java/io/goobox/sync/storj/DeleteCloudFileTask.java @@ -16,6 +16,9 @@ */ package io.goobox.sync.storj; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import io.goobox.sync.storj.db.DB; import io.storj.libstorj.Bucket; import io.storj.libstorj.DeleteFileCallback; @@ -23,6 +26,8 @@ public class DeleteCloudFileTask implements Runnable { + private static final Logger logger = LoggerFactory.getLogger(DeleteCloudFileTask.class); + private Bucket bucket; private File file; @@ -33,19 +38,19 @@ public DeleteCloudFileTask(Bucket bucket, File file) { @Override public void run() { - System.out.printf("Deleting cloud %s %s...\n", file.isDirectory() ? "directory" : "file", file.getName()); + logger.info("Deleting cloud {}", file.getName()); App.getInstance().getStorj().deleteFile(bucket, file, new DeleteFileCallback() { @Override public void onFileDeleted() { - System.out.println("done"); + logger.info("Cloud deletion successful"); DB.remove(file); DB.commit(); } @Override public void onError(String message) { - System.out.println("failed. " + message); + logger.error("Failed deleting on cloud: {}", message); } }); } diff --git a/src/main/java/io/goobox/sync/storj/DeleteLocalFileTask.java b/src/main/java/io/goobox/sync/storj/DeleteLocalFileTask.java index 8275bde..6162c0a 100644 --- a/src/main/java/io/goobox/sync/storj/DeleteLocalFileTask.java +++ b/src/main/java/io/goobox/sync/storj/DeleteLocalFileTask.java @@ -21,10 +21,15 @@ import java.nio.file.Files; import java.nio.file.Path; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import io.goobox.sync.storj.db.DB; public class DeleteLocalFileTask implements Runnable { + private static final Logger logger = LoggerFactory.getLogger(DeleteLocalFileTask.class); + private Path path; public DeleteLocalFileTask(Path path) { @@ -33,19 +38,17 @@ public DeleteLocalFileTask(Path path) { @Override public void run() { - System.out.printf("Deleting local %s %s...\n", - Files.isDirectory(path) ? "directory" : "file", - StorjUtil.getStorjName(path)); + logger.info("Deleting local {}", StorjUtil.getStorjName(path)); try { Files.deleteIfExists(path); DB.remove(path); deleteParentIfEmpty(); - System.out.println("done"); + logger.info("Local deletetion successful"); } catch (DirectoryNotEmptyException e) { DB.remove(path); } catch (Exception e) { - System.out.println(e.getMessage()); + logger.error("Failed deleting locally", e); } finally { DB.commit(); } diff --git a/src/main/java/io/goobox/sync/storj/DownloadFileTask.java b/src/main/java/io/goobox/sync/storj/DownloadFileTask.java index 732f277..c0fec15 100644 --- a/src/main/java/io/goobox/sync/storj/DownloadFileTask.java +++ b/src/main/java/io/goobox/sync/storj/DownloadFileTask.java @@ -21,6 +21,9 @@ import java.nio.file.Path; import java.nio.file.Paths; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import io.goobox.sync.storj.db.DB; import io.storj.libstorj.Bucket; import io.storj.libstorj.DownloadFileCallback; @@ -28,6 +31,8 @@ public class DownloadFileTask implements Runnable { + private static final Logger logger = LoggerFactory.getLogger(DownloadFileTask.class); + private Bucket bucket; private File file; @@ -38,12 +43,12 @@ public DownloadFileTask(Bucket bucket, File file) { @Override public void run() { - System.out.println("Downloading file " + file.getName() + "... "); + logger.info("Downloading file {}", file.getName()); try { Files.createDirectories(App.getInstance().getSyncDir().resolve(file.getName()).getParent()); } catch (IOException e) { - System.out.println("Failed creating parent directories: " + e.getMessage()); + logger.error("Failed creating parent directories", e); } App.getInstance().getStorj().downloadFile(bucket, file, new DownloadFileCallback() { @@ -51,7 +56,7 @@ public void run() { public void onProgress(String fileId, double progress, long downloadedBytes, long totalBytes) { String progressMessage = String.format(" %3d%% %15d/%d bytes", (int) (progress * 100), downloadedBytes, totalBytes); - System.out.println(progressMessage); + logger.info(progressMessage); } @Override @@ -59,9 +64,9 @@ public void onComplete(String fileId, String localPath) { try { DB.setSynced(file, Paths.get(localPath)); DB.commit(); - System.out.println(" done."); + logger.info("Download completed"); } catch (IOException e) { - e.printStackTrace(); + logger.error("I/O error", e); } } @@ -71,9 +76,9 @@ public void onError(String fileId, String message) { try { DB.setDownloadFailed(file, localPath); DB.commit(); - System.out.println(" " + message); + logger.error("Download failed: {}", message); } catch (IOException e) { - e.printStackTrace(); + logger.error("I/O error", e); } } }); diff --git a/src/main/java/io/goobox/sync/storj/FileWatcher.java b/src/main/java/io/goobox/sync/storj/FileWatcher.java index e31e7b1..7a5b513 100644 --- a/src/main/java/io/goobox/sync/storj/FileWatcher.java +++ b/src/main/java/io/goobox/sync/storj/FileWatcher.java @@ -25,11 +25,16 @@ import java.util.Timer; import java.util.TimerTask; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import io.methvin.watcher.DirectoryChangeEvent; import io.methvin.watcher.DirectoryChangeListener; import io.methvin.watcher.DirectoryWatcher; public class FileWatcher extends Thread implements DirectoryChangeListener { + + private static final Logger logger = LoggerFactory.getLogger(FileWatcher.class); private long lastEventTime; private Map copyInProgress = new HashMap<>(); @@ -78,7 +83,7 @@ public void run() { if (copyInProgress.isEmpty()) { // last file event was more than 3 seconds ago - fire a sync check lastEventTime = 0; - System.out.println("3 seconds after the last file event"); + logger.info("3 seconds after the last file event"); App.getInstance().getTaskQueue().add(new CheckStateTask()); App.getInstance().getTaskExecutor().interruptSleeping(); } @@ -86,8 +91,7 @@ public void run() { } }, 3000, 3000); } catch (IOException e) { - System.out.println("File watcher error: " + e.getMessage()); - e.printStackTrace(); + logger.error("File watcher error", e); } } @@ -95,11 +99,11 @@ public void run() { public synchronized void onEvent(final DirectoryChangeEvent event) { lastEventTime = System.currentTimeMillis(); + logger.debug("{} {} {} count: {}", lastEventTime, event.eventType(), event.path(), event.count()); + switch (event.eventType()) { case CREATE: case MODIFY: - // TODO System.out.println(lastEventTime + " CREATE " + event.path() + " - // count: " + event.count()); try { copyInProgress.put(event.path(), Files.size(event.path())); } catch (IOException e) { @@ -108,13 +112,9 @@ public synchronized void onEvent(final DirectoryChangeEvent event) { } break; case DELETE: - // TODO System.out.println(lastEventTime + " DELETE " + event.path() + " count: - // " + event.count()); copyInProgress.remove(event.path()); break; case OVERFLOW: - // TODO System.out.println(lastEventTime + " OVERFLOW " + event.path() + " - // count: " + event.count()); break; } } diff --git a/src/main/java/io/goobox/sync/storj/SleepTask.java b/src/main/java/io/goobox/sync/storj/SleepTask.java index fe4884d..a58a4c7 100644 --- a/src/main/java/io/goobox/sync/storj/SleepTask.java +++ b/src/main/java/io/goobox/sync/storj/SleepTask.java @@ -16,11 +16,16 @@ */ package io.goobox.sync.storj; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + public class SleepTask implements Runnable { + private static final Logger logger = LoggerFactory.getLogger(SleepTask.class); + @Override public synchronized void run() { - System.out.println("Sleeping for 1 minute..."); + logger.info("Sleeping for 1 minute"); try { wait(60000); } catch (InterruptedException e) { @@ -29,7 +34,7 @@ public synchronized void run() { } public synchronized void interrupt() { - System.out.println("Sleep interrupted"); + logger.info("Sleep interrupted"); notify(); } diff --git a/src/main/java/io/goobox/sync/storj/UploadFileTask.java b/src/main/java/io/goobox/sync/storj/UploadFileTask.java index ba2ccff..3528aa7 100644 --- a/src/main/java/io/goobox/sync/storj/UploadFileTask.java +++ b/src/main/java/io/goobox/sync/storj/UploadFileTask.java @@ -20,6 +20,9 @@ import java.nio.file.Path; import java.util.concurrent.CountDownLatch; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import io.goobox.sync.storj.db.DB; import io.storj.libstorj.Bucket; import io.storj.libstorj.DeleteFileCallback; @@ -29,6 +32,8 @@ public class UploadFileTask implements Runnable { + private static final Logger logger = LoggerFactory.getLogger(UploadFileTask.class); + private Bucket bucket; private Path path; private String fileName; @@ -48,14 +53,14 @@ public void run() { return; } - System.out.println("Uploading file " + fileName + "... "); + logger.info("Uploading file {}", fileName); App.getInstance().getStorj().uploadFile(bucket, fileName, path.toString(), new UploadFileCallback() { @Override public void onProgress(String filePath, double progress, long uploadedBytes, long totalBytes) { String progressMessage = String.format(" %3d%% %15d/%d bytes", (int) (progress * 100), uploadedBytes, totalBytes); - System.out.println(progressMessage); + logger.info(progressMessage); } @Override @@ -64,7 +69,7 @@ public void onComplete(final String filePath, final File file) { DB.setSynced(file, path); DB.commit(); } catch (IOException e) { - e.printStackTrace(); + logger.error("I/O error", e); } } @@ -73,9 +78,9 @@ public void onError(String filePath, String message) { try { DB.setUploadFailed(path); DB.commit(); - System.out.println(" " + message); + logger.error("Upload failed: {}", message); } catch (IOException e) { - e.printStackTrace(); + logger.error("I/O error", e); } } }); @@ -101,19 +106,19 @@ public void onFilesReceived(File[] files) { repeat[0] = false; latch.countDown(); } else { - System.out.print("Deleting old version of " + fileName + " on the cloud... "); + logger.info("Deleting old version of {} on the cloud", fileName); App.getInstance().getStorj().deleteFile(bucket, storjFile, new DeleteFileCallback() { @Override public void onFileDeleted() { - System.out.println("done"); + logger.info("Old version deleted"); repeat[0] = false; latch.countDown(); } @Override public void onError(String message) { - System.out.println(message + ". Trying again..."); + logger.error("Failed deleting old version: {}. Trying again.", message); latch.countDown(); } }); @@ -122,8 +127,7 @@ public void onError(String message) { @Override public void onError(String message) { - System.out.println(String.format("Error checking if file with name %s exists: %s. Trying again...", - fileName, message)); + logger.error("Error checking if file with name {} exists: {}. Trying again.", fileName, message); latch.countDown(); } }); diff --git a/src/main/java/io/goobox/sync/storj/db/SyncFile.java b/src/main/java/io/goobox/sync/storj/db/SyncFile.java index 832eccf..fb668ee 100644 --- a/src/main/java/io/goobox/sync/storj/db/SyncFile.java +++ b/src/main/java/io/goobox/sync/storj/db/SyncFile.java @@ -23,6 +23,8 @@ import java.text.ParseException; import org.dizitart.no2.objects.Id; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import io.goobox.sync.storj.StorjUtil; import io.storj.libstorj.File; @@ -30,6 +32,8 @@ @SuppressWarnings("serial") public class SyncFile implements Serializable { + private static final Logger logger = LoggerFactory.getLogger(SyncFile.class); + @Id private String name; @@ -106,7 +110,7 @@ public void setCloudData(File file) { try { setStorjCreatedTime(StorjUtil.getTime(file.getCreated())); } catch (ParseException e) { - e.printStackTrace(); + logger.error("Cannot parse timestamp", e); } setStorjSize(file.getSize()); } diff --git a/src/main/java/io/goobox/sync/storj/ipc/StdinReader.java b/src/main/java/io/goobox/sync/storj/ipc/StdinReader.java index 723ff0d..73bad0c 100644 --- a/src/main/java/io/goobox/sync/storj/ipc/StdinReader.java +++ b/src/main/java/io/goobox/sync/storj/ipc/StdinReader.java @@ -34,7 +34,7 @@ public void run() { try (Scanner scanner = new Scanner(System.in)) { while (true) { String input = scanner.nextLine(); - logger.debug("Command input received: " + input); + logger.debug("Command input received: {}", input); CommandResult result = null; try { @@ -50,7 +50,7 @@ public void run() { if (result != null) { String output = gson.toJson(result); - logger.debug("Command result sent: " + output); + logger.debug("Command result sent: {}", output); System.out.println(output); } } diff --git a/src/main/java/io/goobox/sync/storj/overlay/OverlayHelper.java b/src/main/java/io/goobox/sync/storj/overlay/OverlayHelper.java index 6f32892..93f45f7 100644 --- a/src/main/java/io/goobox/sync/storj/overlay/OverlayHelper.java +++ b/src/main/java/io/goobox/sync/storj/overlay/OverlayHelper.java @@ -25,6 +25,9 @@ import java.util.List; import java.util.stream.Stream; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import com.liferay.nativity.control.NativityControl; import com.liferay.nativity.control.NativityControlUtil; import com.liferay.nativity.modules.contextmenu.ContextMenuControlCallback; @@ -41,6 +44,8 @@ public class OverlayHelper implements FileIconControlCallback, ContextMenuControlCallback { + private static final Logger logger = LoggerFactory.getLogger(OverlayHelper.class); + private NativityControl nativityControl; private FileIconControl fileIconControl; @@ -118,7 +123,7 @@ private void init() { try { attr.setSystem(true); } catch (IOException e) { - e.printStackTrace(); + logger.error("Cannot set system folder", e); } fileIconControl = FileIconControlUtil.getFileIconControl(nativityControl, this); @@ -144,7 +149,7 @@ public int getIconForFile(String path) { .map(OverlayIcon::id) .reduce(OverlayIcon.NONE.id(), Integer::max); } catch (IOException e) { - e.printStackTrace(); + logger.error("Failed walking the file tree", e); } } return 0; @@ -157,7 +162,7 @@ public List getContextMenuItems(String[] paths) { ContextMenuAction contextMenuAction = new ContextMenuAction() { @Override public void onSelection(String[] paths) { - System.out.println("Context menu selection: " + String.join("; ", paths)); + logger.info("Context menu selection: {}", String.join("; ", paths)); } }; From 72c18941df0b268b4066fb6f83f7fb46fc1d7978 Mon Sep 17 00:00:00 2001 From: Kaloyan Raev Date: Tue, 9 Jan 2018 14:04:20 +0200 Subject: [PATCH 3/5] Bump version to 0.0.13 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 215f7d2..17a9626 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ io.goobox goobox-sync-storj - 0.0.12 + 0.0.13 jar Goobox sync app for Storj From ef7aa37bc2e582d88c164276aaee00821355e8a5 Mon Sep 17 00:00:00 2001 From: Kaloyan Raev Date: Tue, 9 Jan 2018 14:08:37 +0200 Subject: [PATCH 4/5] Upload completed log entry --- src/main/java/io/goobox/sync/storj/UploadFileTask.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/io/goobox/sync/storj/UploadFileTask.java b/src/main/java/io/goobox/sync/storj/UploadFileTask.java index 3528aa7..e26de1e 100644 --- a/src/main/java/io/goobox/sync/storj/UploadFileTask.java +++ b/src/main/java/io/goobox/sync/storj/UploadFileTask.java @@ -68,6 +68,7 @@ public void onComplete(final String filePath, final File file) { try { DB.setSynced(file, path); DB.commit(); + logger.info("Upload completed"); } catch (IOException e) { logger.error("I/O error", e); } From 9139194611c12a14e2f6ec1c976a1fb206342914 Mon Sep 17 00:00:00 2001 From: Kaloyan Raev Date: Tue, 9 Jan 2018 15:03:45 +0200 Subject: [PATCH 5/5] Store auth file in app data dir --- src/main/java/io/goobox/sync/storj/App.java | 20 ++++++++++--------- .../java/io/goobox/sync/storj/StorjUtil.java | 6 ------ 2 files changed, 11 insertions(+), 15 deletions(-) diff --git a/src/main/java/io/goobox/sync/storj/App.java b/src/main/java/io/goobox/sync/storj/App.java index 3d3435f..abaace7 100644 --- a/src/main/java/io/goobox/sync/storj/App.java +++ b/src/main/java/io/goobox/sync/storj/App.java @@ -180,7 +180,7 @@ private void init() { SystemTrayHelper.setShutdownListener(this); storj = new Storj(); - storj.setConfigDirectory(StorjUtil.getStorjConfigDir().toFile()); + storj.setConfigDirectory(Utils.getDataDir().toFile()); storj.setDownloadDirectory(syncDir.toFile()); stdinReader = new StdinReader(); @@ -247,10 +247,10 @@ private Bucket checkAndCreateCloudBucket() { logger.info("Checking if cloud Goobox bucket exists"); final Bucket[] result = { null }; - try { - while (result[0] == null) { - final CountDownLatch latch = new CountDownLatch(1); + while (result[0] == null) { + final CountDownLatch latch = new CountDownLatch(1); + try { storj.getBuckets(new GetBucketsCallback() { @Override public void onBucketsReceived(Bucket[] buckets) { @@ -286,19 +286,21 @@ public void onError(String message) { latch.countDown(); } }); + } catch (KeysNotFoundException e) { + logger.error("No keys found. Waiting for keys to be imported."); + latch.countDown(); + } + try { latch.await(); if (result[0] == null) { // error - wait 3 seconds before trying again Thread.sleep(3000); } + } catch (InterruptedException e) { + break; } - } catch (KeysNotFoundException e) { - logger.error( - "No keys found. Have your imported your keys using libstorj? Make sure you don't specify a passcode."); - } catch (InterruptedException e) { - // do nothing } return result[0]; diff --git a/src/main/java/io/goobox/sync/storj/StorjUtil.java b/src/main/java/io/goobox/sync/storj/StorjUtil.java index 0c609c3..95c76b2 100644 --- a/src/main/java/io/goobox/sync/storj/StorjUtil.java +++ b/src/main/java/io/goobox/sync/storj/StorjUtil.java @@ -23,14 +23,8 @@ import java.util.Date; import java.util.TimeZone; -import io.goobox.sync.common.Utils; - public class StorjUtil { - public static Path getStorjConfigDir() { - return Utils.getHomeDir().resolve(".storj"); - } - public static long getTime(String storjTimestamp) throws ParseException { SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"); sdf.setTimeZone(TimeZone.getTimeZone("UTC"));