Solve - #87. Break LogPrinterGui
This commit is contained in:
parent
79c519b1f3
commit
1176ad9e83
32 changed files with 1348 additions and 738 deletions
|
@ -0,0 +1,102 @@
|
||||||
|
/*
|
||||||
|
Copyright 2019-2021 Dmitry Isaenko
|
||||||
|
|
||||||
|
This file is part of NS-USBloader.
|
||||||
|
|
||||||
|
NS-USBloader 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.
|
||||||
|
|
||||||
|
NS-USBloader 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 NS-USBloader. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package nsusbloader.Controllers;
|
||||||
|
|
||||||
|
import javafx.collections.ObservableList;
|
||||||
|
import javafx.fxml.FXML;
|
||||||
|
import javafx.fxml.Initializable;
|
||||||
|
import javafx.scene.control.ContextMenu;
|
||||||
|
import javafx.scene.control.ListCell;
|
||||||
|
import javafx.scene.control.ListView;
|
||||||
|
import javafx.scene.control.MenuItem;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.ResourceBundle;
|
||||||
|
|
||||||
|
public class BlockListViewController implements Initializable {
|
||||||
|
|
||||||
|
@FXML
|
||||||
|
private ListView<File> splitMergeListView;
|
||||||
|
private ObservableList<File> filesList;
|
||||||
|
|
||||||
|
private ResourceBundle resourceBundle;
|
||||||
|
|
||||||
|
private static class FileListCell extends ListCell<File>{
|
||||||
|
@Override
|
||||||
|
public void updateItem(File file, boolean isEmpty){
|
||||||
|
super.updateItem(file, isEmpty);
|
||||||
|
|
||||||
|
if (file == null || isEmpty){
|
||||||
|
setText(null);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
String fileName = file.getName();
|
||||||
|
setText(fileName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void initialize(URL url, ResourceBundle resourceBundle) {
|
||||||
|
this.resourceBundle = resourceBundle;
|
||||||
|
setFilesListView();
|
||||||
|
filesList = splitMergeListView.getItems();
|
||||||
|
}
|
||||||
|
private void setFilesListView(){
|
||||||
|
splitMergeListView.setCellFactory(fileListView -> {
|
||||||
|
ListCell<File> item = new FileListCell();
|
||||||
|
setContextMenuToItem(item);
|
||||||
|
return item;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private <T> void setContextMenuToItem(ListCell<T> item){
|
||||||
|
ContextMenu contextMenu = new ContextMenu();
|
||||||
|
MenuItem deleteMenuItem = new MenuItem(resourceBundle.getString("tab1_table_contextMenu_Btn_BtnDelete"));
|
||||||
|
deleteMenuItem.setOnAction(actionEvent -> {
|
||||||
|
filesList.remove(item.getItem());
|
||||||
|
splitMergeListView.refresh();
|
||||||
|
});
|
||||||
|
MenuItem deleteAllMenuItem = new MenuItem(resourceBundle.getString("tab1_table_contextMenu_Btn_DeleteAll"));
|
||||||
|
deleteAllMenuItem.setOnAction(actionEvent -> {
|
||||||
|
filesList.clear();
|
||||||
|
splitMergeListView.refresh();
|
||||||
|
});
|
||||||
|
contextMenu.getItems().addAll(deleteMenuItem, deleteAllMenuItem);
|
||||||
|
|
||||||
|
item.setContextMenu(contextMenu);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void add(File file){
|
||||||
|
if (filesList.contains(file))
|
||||||
|
return;
|
||||||
|
filesList.add(file);
|
||||||
|
}
|
||||||
|
public void addAll(List<File> files){
|
||||||
|
for (File file : files) {
|
||||||
|
add(file);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public ObservableList<File> getItems(){ return filesList; }
|
||||||
|
public void clear(){
|
||||||
|
filesList.clear();
|
||||||
|
splitMergeListView.refresh();
|
||||||
|
}
|
||||||
|
}
|
|
@ -46,7 +46,7 @@ public class NSLMainController implements Initializable {
|
||||||
private Tab GamesTabHolder, RCMTabHolder, SMTabHolder;
|
private Tab GamesTabHolder, RCMTabHolder, SMTabHolder;
|
||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
private GamesController GamesTabController; // Accessible from Mediator | todo: incapsulate
|
private GamesController GamesTabController;
|
||||||
@FXML
|
@FXML
|
||||||
private SettingsController SettingsTabController;
|
private SettingsController SettingsTabController;
|
||||||
@FXML
|
@FXML
|
||||||
|
@ -69,6 +69,12 @@ public class NSLMainController implements Initializable {
|
||||||
MediatorControl.getInstance().setController(this);
|
MediatorControl.getInstance().setController(this);
|
||||||
|
|
||||||
if (AppPreferences.getInstance().getAutoCheckUpdates()){
|
if (AppPreferences.getInstance().getAutoCheckUpdates()){
|
||||||
|
checkForUpdates();
|
||||||
|
}
|
||||||
|
|
||||||
|
openLastOpenedTab();
|
||||||
|
}
|
||||||
|
private void checkForUpdates(){
|
||||||
Task<List<String>> updTask = new UpdatesChecker();
|
Task<List<String>> updTask = new UpdatesChecker();
|
||||||
updTask.setOnSucceeded(event->{
|
updTask.setOnSucceeded(event->{
|
||||||
List<String> result = updTask.getValue();
|
List<String> result = updTask.getValue();
|
||||||
|
@ -89,10 +95,6 @@ public class NSLMainController implements Initializable {
|
||||||
updates.setDaemon(true);
|
updates.setDaemon(true);
|
||||||
updates.start();
|
updates.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
openLastOpenedTab();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get resources
|
* Get resources
|
||||||
* TODO: Find better solution; used in UsbCommunications() -> GL -> SelectFile command
|
* TODO: Find better solution; used in UsbCommunications() -> GL -> SelectFile command
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
*/
|
*/
|
||||||
package nsusbloader.Controllers;
|
package nsusbloader.Controllers;
|
||||||
|
|
||||||
|
import javafx.beans.binding.Bindings;
|
||||||
import javafx.fxml.FXML;
|
import javafx.fxml.FXML;
|
||||||
import javafx.fxml.Initializable;
|
import javafx.fxml.Initializable;
|
||||||
import javafx.scene.control.*;
|
import javafx.scene.control.*;
|
||||||
|
@ -33,11 +34,11 @@ import nsusbloader.MediatorControl;
|
||||||
import nsusbloader.ModelControllers.CancellableRunnable;
|
import nsusbloader.ModelControllers.CancellableRunnable;
|
||||||
import nsusbloader.NSLDataTypes.EModule;
|
import nsusbloader.NSLDataTypes.EModule;
|
||||||
import nsusbloader.ServiceWindow;
|
import nsusbloader.ServiceWindow;
|
||||||
import nsusbloader.Utilities.splitmerge.MergeTask;
|
import nsusbloader.Utilities.splitmerge.SplitMergeTaskExecutor;
|
||||||
import nsusbloader.Utilities.splitmerge.SplitTask;
|
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
|
import java.util.List;
|
||||||
import java.util.ResourceBundle;
|
import java.util.ResourceBundle;
|
||||||
|
|
||||||
public class SplitMergeController implements Initializable {
|
public class SplitMergeController implements Initializable {
|
||||||
|
@ -53,40 +54,39 @@ public class SplitMergeController implements Initializable {
|
||||||
changeSaveToBtn,
|
changeSaveToBtn,
|
||||||
convertBtn;
|
convertBtn;
|
||||||
@FXML
|
@FXML
|
||||||
private Label fileFolderLabelLbl,
|
private Label saveToPathLbl,
|
||||||
fileFolderActualPathLbl,
|
|
||||||
saveToPathLbl,
|
|
||||||
statusLbl;
|
statusLbl;
|
||||||
|
|
||||||
|
@FXML
|
||||||
|
private BlockListViewController BlockListViewController;
|
||||||
|
|
||||||
private ResourceBundle resourceBundle;
|
private ResourceBundle resourceBundle;
|
||||||
|
|
||||||
private Region convertRegion;
|
private Region convertRegion;
|
||||||
private Thread smThread;
|
private Thread smThread;
|
||||||
private CancellableRunnable smTask;
|
private Runnable smTask;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void initialize(URL url, ResourceBundle resourceBundle) {
|
public void initialize(URL url, ResourceBundle resourceBundle) {
|
||||||
this.resourceBundle = resourceBundle;
|
this.resourceBundle = resourceBundle;
|
||||||
|
|
||||||
convertRegion = new Region();
|
convertRegion = new Region();
|
||||||
convertBtn.setGraphic(convertRegion);
|
convertBtn.setGraphic(convertRegion);
|
||||||
|
convertBtn.disableProperty().bind(Bindings.isEmpty(BlockListViewController.getItems()));
|
||||||
|
|
||||||
splitRad.setOnAction((actionEvent -> {
|
splitRad.setOnAction((actionEvent -> {
|
||||||
statusLbl.setText("");
|
statusLbl.setText("");
|
||||||
convertRegion.getStyleClass().clear();
|
convertRegion.getStyleClass().clear();
|
||||||
convertRegion.getStyleClass().add("regionSplitToOne");
|
convertRegion.getStyleClass().add("regionSplitToOne");
|
||||||
fileFolderLabelLbl.setText(resourceBundle.getString("tabSplMrg_Txt_File"));
|
|
||||||
selectFileFolderBtn.setText(resourceBundle.getString("tabSplMrg_Btn_SelectFile"));
|
selectFileFolderBtn.setText(resourceBundle.getString("tabSplMrg_Btn_SelectFile"));
|
||||||
fileFolderActualPathLbl.setText("");
|
BlockListViewController.clear();
|
||||||
convertBtn.setDisable(true);
|
|
||||||
}));
|
}));
|
||||||
mergeRad.setOnAction((actionEvent -> {
|
mergeRad.setOnAction((actionEvent -> {
|
||||||
statusLbl.setText("");
|
statusLbl.setText("");
|
||||||
convertRegion.getStyleClass().clear();
|
convertRegion.getStyleClass().clear();
|
||||||
convertRegion.getStyleClass().add("regionOneToSplit");
|
convertRegion.getStyleClass().add("regionOneToSplit");
|
||||||
fileFolderLabelLbl.setText(resourceBundle.getString("tabSplMrg_Txt_Folder"));
|
|
||||||
selectFileFolderBtn.setText(resourceBundle.getString("tabSplMrg_Btn_SelectFolder"));
|
selectFileFolderBtn.setText(resourceBundle.getString("tabSplMrg_Btn_SelectFolder"));
|
||||||
fileFolderActualPathLbl.setText("");
|
BlockListViewController.clear();
|
||||||
convertBtn.setDisable(true);
|
|
||||||
}));
|
}));
|
||||||
|
|
||||||
if (AppPreferences.getInstance().getSplitMergeType() == 0)
|
if (AppPreferences.getInstance().getSplitMergeType() == 0)
|
||||||
|
@ -110,32 +110,27 @@ public class SplitMergeController implements Initializable {
|
||||||
|
|
||||||
selectFileFolderBtn.setOnAction(actionEvent -> {
|
selectFileFolderBtn.setOnAction(actionEvent -> {
|
||||||
statusLbl.setText("");
|
statusLbl.setText("");
|
||||||
|
List<File> alreadyAddedFiles = BlockListViewController.getItems();
|
||||||
if (splitRad.isSelected()) {
|
if (splitRad.isSelected()) {
|
||||||
FileChooser fc = new FileChooser();
|
FileChooser fc = new FileChooser();
|
||||||
fc.setTitle(resourceBundle.getString("tabSplMrg_Btn_SelectFile"));
|
fc.setTitle(resourceBundle.getString("tabSplMrg_Btn_SelectFile"));
|
||||||
if (! fileFolderActualPathLbl.getText().isEmpty()){
|
if (! alreadyAddedFiles.isEmpty()){
|
||||||
File temporaryFile = new File(fileFolderActualPathLbl.getText()).getParentFile();
|
String recentLocation = FilesHelper.getRealFolder(alreadyAddedFiles.get(0).getParentFile().getAbsolutePath());
|
||||||
if (temporaryFile != null && temporaryFile.exists())
|
fc.setInitialDirectory(new File(recentLocation));
|
||||||
fc.setInitialDirectory(temporaryFile);
|
|
||||||
else
|
|
||||||
fc.setInitialDirectory(new File(System.getProperty("user.home")));
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
fc.setInitialDirectory(new File(System.getProperty("user.home")));
|
fc.setInitialDirectory(new File(System.getProperty("user.home")));
|
||||||
File fileFile = fc.showOpenDialog(changeSaveToBtn.getScene().getWindow());
|
List<File> files = fc.showOpenMultipleDialog(changeSaveToBtn.getScene().getWindow());
|
||||||
if (fileFile == null)
|
if (files == null || files.isEmpty())
|
||||||
return;
|
return;
|
||||||
fileFolderActualPathLbl.setText(fileFile.getAbsolutePath());
|
this.BlockListViewController.addAll(files);
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
DirectoryChooser dc = new DirectoryChooser();
|
DirectoryChooser dc = new DirectoryChooser();
|
||||||
dc.setTitle(resourceBundle.getString("tabSplMrg_Btn_SelectFolder"));
|
dc.setTitle(resourceBundle.getString("tabSplMrg_Btn_SelectFolder"));
|
||||||
if (! fileFolderActualPathLbl.getText().isEmpty()){
|
if (! alreadyAddedFiles.isEmpty()){
|
||||||
File temporaryFile = new File(fileFolderActualPathLbl.getText());
|
String recentLocation = FilesHelper.getRealFolder(alreadyAddedFiles.get(0).getParentFile().getAbsolutePath());
|
||||||
if (temporaryFile.exists())
|
dc.setInitialDirectory(new File(recentLocation));
|
||||||
dc.setInitialDirectory(temporaryFile);
|
|
||||||
else
|
|
||||||
dc.setInitialDirectory(new File(System.getProperty("user.home")));
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
dc.setInitialDirectory(new File(System.getProperty("user.home")));
|
dc.setInitialDirectory(new File(System.getProperty("user.home")));
|
||||||
|
@ -143,9 +138,8 @@ public class SplitMergeController implements Initializable {
|
||||||
File folderFile = dc.showDialog(changeSaveToBtn.getScene().getWindow());
|
File folderFile = dc.showDialog(changeSaveToBtn.getScene().getWindow());
|
||||||
if (folderFile == null)
|
if (folderFile == null)
|
||||||
return;
|
return;
|
||||||
fileFolderActualPathLbl.setText(folderFile.getAbsolutePath());
|
this.BlockListViewController.add(folderFile);
|
||||||
}
|
}
|
||||||
convertBtn.setDisable(false);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
convertBtn.setOnAction(actionEvent -> setConvertBtnAction());
|
convertBtn.setOnAction(actionEvent -> setConvertBtnAction());
|
||||||
|
@ -192,7 +186,7 @@ public class SplitMergeController implements Initializable {
|
||||||
* */
|
* */
|
||||||
private void stopBtnAction(){
|
private void stopBtnAction(){
|
||||||
if (smThread != null && smThread.isAlive()) {
|
if (smThread != null && smThread.isAlive()) {
|
||||||
smTask.cancel();
|
smThread.interrupt();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
|
@ -209,9 +203,9 @@ public class SplitMergeController implements Initializable {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (splitRad.isSelected())
|
if (splitRad.isSelected())
|
||||||
smTask = new SplitTask(fileFolderActualPathLbl.getText(), saveToPathLbl.getText());
|
smTask = new SplitMergeTaskExecutor(true, BlockListViewController.getItems(), saveToPathLbl.getText());
|
||||||
else
|
else
|
||||||
smTask = new MergeTask(fileFolderActualPathLbl.getText(), saveToPathLbl.getText());
|
smTask = new SplitMergeTaskExecutor(false, BlockListViewController.getItems(), saveToPathLbl.getText());
|
||||||
smThread = new Thread(smTask);
|
smThread = new Thread(smTask);
|
||||||
smThread.setDaemon(true);
|
smThread.setDaemon(true);
|
||||||
smThread.start();
|
smThread.start();
|
||||||
|
@ -230,14 +224,16 @@ public class SplitMergeController implements Initializable {
|
||||||
* */
|
* */
|
||||||
@FXML
|
@FXML
|
||||||
private void handleDrop(DragEvent event) {
|
private void handleDrop(DragEvent event) {
|
||||||
File fileDrpd = event.getDragboard().getFiles().get(0);
|
List<File> files = event.getDragboard().getFiles();
|
||||||
|
File firstFile = files.get(0);
|
||||||
|
|
||||||
if (fileDrpd.isDirectory())
|
if (firstFile.isDirectory())
|
||||||
mergeRad.fire();
|
mergeRad.fire();
|
||||||
else
|
else
|
||||||
splitRad.fire();
|
splitRad.fire();
|
||||||
fileFolderActualPathLbl.setText(fileDrpd.getAbsolutePath());
|
|
||||||
convertBtn.setDisable(false);
|
this.BlockListViewController.addAll(files);
|
||||||
|
|
||||||
event.setDropCompleted(true);
|
event.setDropCompleted(true);
|
||||||
event.consume();
|
event.consume();
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,8 +26,8 @@ import java.io.File;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
|
||||||
public interface ILogPrinter {
|
public interface ILogPrinter {
|
||||||
void print(String message, EMsgType type);
|
void print(String message, EMsgType type) throws InterruptedException;
|
||||||
void updateProgress(Double value);
|
void updateProgress(Double value) throws InterruptedException;
|
||||||
void update(HashMap<String, File> nspMap, EFileStatus status);
|
void update(HashMap<String, File> nspMap, EFileStatus status);
|
||||||
void update(File file, EFileStatus status);
|
void update(File file, EFileStatus status);
|
||||||
void updateOneLinerStatus(boolean status);
|
void updateOneLinerStatus(boolean status);
|
||||||
|
|
|
@ -32,9 +32,11 @@ public class LogPrinterGui implements ILogPrinter {
|
||||||
private final MessagesConsumer msgConsumer;
|
private final MessagesConsumer msgConsumer;
|
||||||
private final BlockingQueue<String> msgQueue;
|
private final BlockingQueue<String> msgQueue;
|
||||||
private final BlockingQueue<Double> progressQueue;
|
private final BlockingQueue<Double> progressQueue;
|
||||||
private final HashMap<String, EFileStatus> statusMap; // BlockingQueue for literally one object. TODO: read more books ; replace to hashMap
|
private final HashMap<String, EFileStatus> statusMap;
|
||||||
private final AtomicBoolean oneLinerStatus;
|
private final AtomicBoolean oneLinerStatus;
|
||||||
|
|
||||||
|
/* TODO: Rewrite 'print()' implementation everywhere */
|
||||||
|
|
||||||
LogPrinterGui(EModule whoIsAsking){
|
LogPrinterGui(EModule whoIsAsking){
|
||||||
this.msgQueue = new LinkedBlockingQueue<>();
|
this.msgQueue = new LinkedBlockingQueue<>();
|
||||||
this.progressQueue = new LinkedBlockingQueue<>();
|
this.progressQueue = new LinkedBlockingQueue<>();
|
||||||
|
@ -47,8 +49,7 @@ public class LogPrinterGui implements ILogPrinter {
|
||||||
* This is what will print to textArea of the application.
|
* This is what will print to textArea of the application.
|
||||||
* */
|
* */
|
||||||
@Override
|
@Override
|
||||||
public void print(String message, EMsgType type){
|
public void print(String message, EMsgType type) throws InterruptedException{
|
||||||
try {
|
|
||||||
switch (type){
|
switch (type){
|
||||||
case PASS:
|
case PASS:
|
||||||
msgQueue.put("[ PASS ] "+message+"\n");
|
msgQueue.put("[ PASS ] "+message+"\n");
|
||||||
|
@ -66,20 +67,13 @@ public class LogPrinterGui implements ILogPrinter {
|
||||||
msgQueue.put(message);
|
msgQueue.put(message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (InterruptedException ie){
|
|
||||||
ie.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/**
|
/**
|
||||||
* Update progress for progress bar
|
* Update progress for progress bar
|
||||||
* */
|
* */
|
||||||
@Override
|
@Override
|
||||||
public void updateProgress(Double value) {
|
public void updateProgress(Double value) throws InterruptedException {
|
||||||
try {
|
|
||||||
progressQueue.put(value);
|
progressQueue.put(value);
|
||||||
}
|
}
|
||||||
catch (InterruptedException ignored){} // TODO: Do something with this
|
|
||||||
}
|
|
||||||
/**
|
/**
|
||||||
* When we're done - update status
|
* When we're done - update status
|
||||||
* */
|
* */
|
||||||
|
|
|
@ -42,7 +42,7 @@ public class MessagesConsumer extends AnimationTimer {
|
||||||
private final NSTableViewController tableViewController;
|
private final NSTableViewController tableViewController;
|
||||||
private final EModule appModuleType;
|
private final EModule appModuleType;
|
||||||
|
|
||||||
private AtomicBoolean oneLinerStatus;
|
private final AtomicBoolean oneLinerStatus;
|
||||||
|
|
||||||
private boolean isInterrupted;
|
private boolean isInterrupted;
|
||||||
|
|
||||||
|
@ -50,7 +50,7 @@ public class MessagesConsumer extends AnimationTimer {
|
||||||
BlockingQueue<String> msgQueue,
|
BlockingQueue<String> msgQueue,
|
||||||
BlockingQueue<Double> progressQueue,
|
BlockingQueue<Double> progressQueue,
|
||||||
HashMap<String, EFileStatus> statusMap,
|
HashMap<String, EFileStatus> statusMap,
|
||||||
AtomicBoolean oneLinerStatus) {
|
AtomicBoolean oneLinerStatus){
|
||||||
this.appModuleType = appModuleType;
|
this.appModuleType = appModuleType;
|
||||||
this.isInterrupted = false;
|
this.isInterrupted = false;
|
||||||
|
|
||||||
|
@ -72,15 +72,15 @@ public class MessagesConsumer extends AnimationTimer {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void handle(long l) {
|
public void handle(long l){
|
||||||
ArrayList<String> messages = new ArrayList<>();
|
ArrayList<String> messages = new ArrayList<>();
|
||||||
int msgRecieved = msgQueue.drainTo(messages);
|
int msgReceived = msgQueue.drainTo(messages);
|
||||||
if (msgRecieved > 0)
|
if (msgReceived > 0)
|
||||||
messages.forEach(logsArea::appendText);
|
messages.forEach(logsArea::appendText);
|
||||||
|
|
||||||
ArrayList<Double> progress = new ArrayList<>();
|
ArrayList<Double> progress = new ArrayList<>();
|
||||||
int progressRecieved = progressQueue.drainTo(progress);
|
int progressReceived = progressQueue.drainTo(progress);
|
||||||
if (progressRecieved > 0) {
|
if (progressReceived > 0) {
|
||||||
progress.forEach(prg -> {
|
progress.forEach(prg -> {
|
||||||
if (prg != 1.0)
|
if (prg != 1.0)
|
||||||
progressBar.setProgress(prg);
|
progressBar.setProgress(prg);
|
||||||
|
@ -89,7 +89,11 @@ public class MessagesConsumer extends AnimationTimer {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isInterrupted) { // It's safe 'cuz it's could't be interrupted while HashMap populating
|
if (isInterrupted) // It's safe 'cuz it's could't be interrupted while HashMap populating
|
||||||
|
updateElementsAndStop();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateElementsAndStop(){
|
||||||
MediatorControl.getInstance().setBgThreadActive(false, appModuleType);
|
MediatorControl.getInstance().setBgThreadActive(false, appModuleType);
|
||||||
progressBar.setProgress(0.0);
|
progressBar.setProgress(0.0);
|
||||||
|
|
||||||
|
@ -109,10 +113,8 @@ public class MessagesConsumer extends AnimationTimer {
|
||||||
MediatorControl.getInstance().getSplitMergeController().setOneLineStatus(oneLinerStatus.get());
|
MediatorControl.getInstance().getSplitMergeController().setOneLineStatus(oneLinerStatus.get());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.stop();
|
this.stop();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
public void interrupt(){
|
public void interrupt(){
|
||||||
this.isInterrupted = true;
|
this.isInterrupted = true;
|
||||||
|
|
|
@ -72,8 +72,8 @@ public class Rcm implements Runnable{
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
logPrinter.print("Selected: "+filePath, EMsgType.INFO);
|
print("Selected: "+filePath, EMsgType.INFO);
|
||||||
logPrinter.print("=============== RCM ===============", EMsgType.INFO);
|
print("=============== RCM ===============", EMsgType.INFO);
|
||||||
|
|
||||||
ECurrentOS ecurrentOS;
|
ECurrentOS ecurrentOS;
|
||||||
String realOsName = System.getProperty("os.name").toLowerCase().replace(" ", "");
|
String realOsName = System.getProperty("os.name").toLowerCase().replace(" ", "");
|
||||||
|
@ -85,11 +85,11 @@ public class Rcm implements Runnable{
|
||||||
ecurrentOS = ECurrentOS.lin;
|
ecurrentOS = ECurrentOS.lin;
|
||||||
else
|
else
|
||||||
ecurrentOS = ECurrentOS.unsupported;
|
ecurrentOS = ECurrentOS.unsupported;
|
||||||
logPrinter.print("Found your OS: "+System.getProperty("os.name"), EMsgType.PASS);
|
print("Found your OS: "+System.getProperty("os.name"), EMsgType.PASS);
|
||||||
|
|
||||||
if (! ecurrentOS.equals(ECurrentOS.mac)){
|
if (! ecurrentOS.equals(ECurrentOS.mac)){
|
||||||
if (! RcmSmash.isSupported()){
|
if (! RcmSmash.isSupported()){
|
||||||
logPrinter.print("Unfortunately your platform '"+System.getProperty("os.name")+
|
print("Unfortunately your platform '"+System.getProperty("os.name")+
|
||||||
"' of '"+System.getProperty("os.arch")+"' is not supported :("+
|
"' of '"+System.getProperty("os.arch")+"' is not supported :("+
|
||||||
"\n But you could file a bug with request."+
|
"\n But you could file a bug with request."+
|
||||||
"\n\n Nothing has been sent to NS. Execution stopped.", EMsgType.FAIL);
|
"\n\n Nothing has been sent to NS. Execution stopped.", EMsgType.FAIL);
|
||||||
|
@ -124,14 +124,14 @@ public class Rcm implements Runnable{
|
||||||
// Send payload
|
// Send payload
|
||||||
for (int i=0; i < fullPayload.length / 4096 ; i++){
|
for (int i=0; i < fullPayload.length / 4096 ; i++){
|
||||||
if (writeUsb(Arrays.copyOfRange(fullPayload, i*4096, (i+1)*4096))){
|
if (writeUsb(Arrays.copyOfRange(fullPayload, i*4096, (i+1)*4096))){
|
||||||
logPrinter.print("Failed to sent payload ["+i+"]"+
|
print("Failed to sent payload ["+i+"]"+
|
||||||
"\n\n Execution stopped.", EMsgType.FAIL);
|
"\n\n Execution stopped.", EMsgType.FAIL);
|
||||||
usbConnect.close();
|
usbConnect.close();
|
||||||
logPrinter.close();
|
logPrinter.close();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
logPrinter.print("Information sent to NS.", EMsgType.PASS);
|
print("Information sent to NS.", EMsgType.PASS);
|
||||||
|
|
||||||
if (ecurrentOS.equals(ECurrentOS.mac)){
|
if (ecurrentOS.equals(ECurrentOS.mac)){
|
||||||
if (smashMacOS()){
|
if (smashMacOS()){
|
||||||
|
@ -149,7 +149,7 @@ public class Rcm implements Runnable{
|
||||||
retval = RcmSmash.smashWindows();
|
retval = RcmSmash.smashWindows();
|
||||||
else {
|
else {
|
||||||
// ( ?_?)
|
// ( ?_?)
|
||||||
logPrinter.print("Failed to smash the stack since your OS is not supported. Please report this issue."+
|
print("Failed to smash the stack since your OS is not supported. Please report this issue."+
|
||||||
"\n\n Execution stopped and failed. And it's strange.", EMsgType.FAIL);
|
"\n\n Execution stopped and failed. And it's strange.", EMsgType.FAIL);
|
||||||
usbConnect.close();
|
usbConnect.close();
|
||||||
logPrinter.close();
|
logPrinter.close();
|
||||||
|
@ -157,18 +157,27 @@ public class Rcm implements Runnable{
|
||||||
}
|
}
|
||||||
|
|
||||||
if (retval != 0){
|
if (retval != 0){
|
||||||
logPrinter.print("Failed to smash the stack ("+retval+")"+
|
print("Failed to smash the stack ("+retval+")"+
|
||||||
"\n\n Execution stopped and failed.", EMsgType.FAIL);
|
"\n\n Execution stopped and failed.", EMsgType.FAIL);
|
||||||
usbConnect.close();
|
usbConnect.close();
|
||||||
logPrinter.close();
|
logPrinter.close();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
logPrinter.print(".:: Payload complete ::.", EMsgType.PASS);
|
print(".:: Payload complete ::.", EMsgType.PASS);
|
||||||
usbConnect.close();
|
usbConnect.close();
|
||||||
logPrinter.updateOneLinerStatus(true);
|
logPrinter.updateOneLinerStatus(true);
|
||||||
logPrinter.close();
|
logPrinter.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void print(String message, EMsgType type){
|
||||||
|
try {
|
||||||
|
logPrinter.print(message, type);
|
||||||
|
}
|
||||||
|
catch (InterruptedException intr){
|
||||||
|
intr.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* Prepare the 'big' or full-size byte-buffer that is actually is a payload that we're about to use.
|
* Prepare the 'big' or full-size byte-buffer that is actually is a payload that we're about to use.
|
||||||
* @return false for issues
|
* @return false for issues
|
||||||
|
@ -179,7 +188,7 @@ public class Rcm implements Runnable{
|
||||||
|
|
||||||
// 126296 b <- biggest size per CTCaer; 16384 selected randomly as minimum threshold. It's probably wrong.
|
// 126296 b <- biggest size per CTCaer; 16384 selected randomly as minimum threshold. It's probably wrong.
|
||||||
if (pldrFile.length() > 126296 || pldrFile.length() < 16384) {
|
if (pldrFile.length() > 126296 || pldrFile.length() < 16384) {
|
||||||
logPrinter.print("File size of this payload looks wired. It's "+pldrFile.length()+" bytes."+
|
print("File size of this payload looks wired. It's "+pldrFile.length()+" bytes."+
|
||||||
"\n 1. Double-check that you're using the right payload." +
|
"\n 1. Double-check that you're using the right payload." +
|
||||||
"\n 2. Please report this issue in case you're sure that you're doing everything right." +
|
"\n 2. Please report this issue in case you're sure that you're doing everything right." +
|
||||||
"\n\n Nothing has been sent to NS. Execution stopped.", EMsgType.FAIL);
|
"\n\n Nothing has been sent to NS. Execution stopped.", EMsgType.FAIL);
|
||||||
|
@ -194,7 +203,7 @@ public class Rcm implements Runnable{
|
||||||
totalSize += 4096;
|
totalSize += 4096;
|
||||||
// Double-check
|
// Double-check
|
||||||
if (totalSize > 0x30298){
|
if (totalSize > 0x30298){
|
||||||
logPrinter.print("File size of the payload is too big. Comparing to maximum size, it's greater to "+(totalSize - 0x30298)+" bytes!"+
|
print("File size of the payload is too big. Comparing to maximum size, it's greater to "+(totalSize - 0x30298)+" bytes!"+
|
||||||
"\n 1. Double-check that you're using the right payload." +
|
"\n 1. Double-check that you're using the right payload." +
|
||||||
"\n 2. Please report this issue in case you're sure that you're doing everything right." +
|
"\n 2. Please report this issue in case you're sure that you're doing everything right." +
|
||||||
"\n\n Nothing has been sent to NS. Execution stopped.", EMsgType.FAIL); // Occurs: never. I'm too lazy to check.
|
"\n\n Nothing has been sent to NS. Execution stopped.", EMsgType.FAIL); // Occurs: never. I'm too lazy to check.
|
||||||
|
@ -209,7 +218,7 @@ public class Rcm implements Runnable{
|
||||||
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(pldrFile));
|
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(pldrFile));
|
||||||
int readSize;
|
int readSize;
|
||||||
if ((readSize = bis.read(dataPldFile)) != pldFileSize){
|
if ((readSize = bis.read(dataPldFile)) != pldFileSize){
|
||||||
logPrinter.print("Failed to retrieve data from payload file." +
|
print("Failed to retrieve data from payload file." +
|
||||||
"\n Got only "+readSize+" bytes while "+pldFileSize+" expected." +
|
"\n Got only "+readSize+" bytes while "+pldFileSize+" expected." +
|
||||||
"\n\n Nothing has been sent to NS. Execution stopped.", EMsgType.FAIL);
|
"\n\n Nothing has been sent to NS. Execution stopped.", EMsgType.FAIL);
|
||||||
bis.close();
|
bis.close();
|
||||||
|
@ -218,7 +227,7 @@ public class Rcm implements Runnable{
|
||||||
bis.close();
|
bis.close();
|
||||||
}
|
}
|
||||||
catch (Exception e){
|
catch (Exception e){
|
||||||
logPrinter.print("Failed to retrieve data from payload file: " +e.getMessage()+
|
print("Failed to retrieve data from payload file: " +e.getMessage()+
|
||||||
"\n\n Nothing has been sent to NS. Execution stopped.", EMsgType.FAIL);
|
"\n\n Nothing has been sent to NS. Execution stopped.", EMsgType.FAIL);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -241,7 +250,7 @@ public class Rcm implements Runnable{
|
||||||
IntBuffer readBufTransferred = IntBuffer.allocate(1);
|
IntBuffer readBufTransferred = IntBuffer.allocate(1);
|
||||||
int result = LibUsb.bulkTransfer(handler, (byte) 0x81, readBuffer, readBufTransferred, 1000);
|
int result = LibUsb.bulkTransfer(handler, (byte) 0x81, readBuffer, readBufTransferred, 1000);
|
||||||
if (result != LibUsb.SUCCESS) {
|
if (result != LibUsb.SUCCESS) {
|
||||||
logPrinter.print("Unable to get device ID" +
|
print("Unable to get device ID" +
|
||||||
"\n\n Nothing has been sent to NS. Execution stopped.", EMsgType.FAIL);
|
"\n\n Nothing has been sent to NS. Execution stopped.", EMsgType.FAIL);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -251,7 +260,7 @@ public class Rcm implements Runnable{
|
||||||
StringBuilder idStrBld = new StringBuilder("Found device with ID: ");
|
StringBuilder idStrBld = new StringBuilder("Found device with ID: ");
|
||||||
for (byte b: receivedBytes)
|
for (byte b: receivedBytes)
|
||||||
idStrBld.append(String.format("%02x ", b));
|
idStrBld.append(String.format("%02x ", b));
|
||||||
logPrinter.print(idStrBld.toString(), EMsgType.PASS);
|
print(idStrBld.toString(), EMsgType.PASS);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
|
@ -269,13 +278,13 @@ public class Rcm implements Runnable{
|
||||||
if (writeBufTransferred.get() == 4096)
|
if (writeBufTransferred.get() == 4096)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
logPrinter.print("RCM Data transfer issue [write]" +
|
print("RCM Data transfer issue [write]" +
|
||||||
"\n Requested: " + message.length +
|
"\n Requested: " + message.length +
|
||||||
"\n Transferred: " + writeBufTransferred.get()+
|
"\n Transferred: " + writeBufTransferred.get()+
|
||||||
"\n\n Execution stopped.", EMsgType.FAIL);
|
"\n\n Execution stopped.", EMsgType.FAIL);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
logPrinter.print("RCM Data transfer issue [write]" +
|
print("RCM Data transfer issue [write]" +
|
||||||
"\n Returned: " + UsbErrorCodes.getErrCode(result) +
|
"\n Returned: " + UsbErrorCodes.getErrCode(result) +
|
||||||
"\n\n Execution stopped.", EMsgType.FAIL);
|
"\n\n Execution stopped.", EMsgType.FAIL);
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -38,8 +38,8 @@ public class NxdtTask extends CancellableRunnable {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
logPrinter.print("Save to location: "+ saveToLocation, EMsgType.INFO);
|
print("Save to location: "+ saveToLocation, EMsgType.INFO);
|
||||||
logPrinter.print("=============== nxdumptool ===============", EMsgType.INFO);
|
print("=============== nxdumptool ===============", EMsgType.INFO);
|
||||||
|
|
||||||
UsbConnect usbConnect = UsbConnect.connectHomebrewMode(logPrinter);
|
UsbConnect usbConnect = UsbConnect.connectHomebrewMode(logPrinter);
|
||||||
|
|
||||||
|
@ -54,13 +54,22 @@ public class NxdtTask extends CancellableRunnable {
|
||||||
new NxdtUsbAbi1(handler, logPrinter, saveToLocation, this);
|
new NxdtUsbAbi1(handler, logPrinter, saveToLocation, this);
|
||||||
}
|
}
|
||||||
catch (Exception e){
|
catch (Exception e){
|
||||||
logPrinter.print(e.getMessage(), EMsgType.FAIL);
|
print(e.getMessage(), EMsgType.FAIL);
|
||||||
}
|
}
|
||||||
|
|
||||||
logPrinter.print(".:: Complete ::.", EMsgType.PASS);
|
print(".:: Complete ::.", EMsgType.PASS);
|
||||||
|
|
||||||
usbConnect.close();
|
usbConnect.close();
|
||||||
logPrinter.updateOneLinerStatus(true);
|
logPrinter.updateOneLinerStatus(true);
|
||||||
logPrinter.close();
|
logPrinter.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void print(String message, EMsgType type){
|
||||||
|
try {
|
||||||
|
logPrinter.print(message, type);
|
||||||
|
}
|
||||||
|
catch (InterruptedException ie){
|
||||||
|
ie.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -119,7 +119,7 @@ class NxdtUsbAbi1 {
|
||||||
USBSTATUS_SUCCESS[9] = (byte)((endpointMaxPacketSize >> 8) & 0xFF);
|
USBSTATUS_SUCCESS[9] = (byte)((endpointMaxPacketSize >> 8) & 0xFF);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void readLoop(){
|
private void readLoop() throws InterruptedException{
|
||||||
logPrinter.print("Awaiting for handshake", EMsgType.INFO);
|
logPrinter.print("Awaiting for handshake", EMsgType.INFO);
|
||||||
try {
|
try {
|
||||||
byte[] directive;
|
byte[] directive;
|
||||||
|
@ -292,7 +292,7 @@ class NxdtUsbAbi1 {
|
||||||
return nspFile != null;
|
return nspFile != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private String getAbsoluteFilePath(String filename) throws Exception{
|
private String getAbsoluteFilePath(String filename) {
|
||||||
if (isRomFs(filename) && isWindows) // Since RomFS entry starts from '/' it should be replaced to '\'.
|
if (isRomFs(filename) && isWindows) // Since RomFS entry starts from '/' it should be replaced to '\'.
|
||||||
return saveToPath + filename.replaceAll("/", "\\\\");
|
return saveToPath + filename.replaceAll("/", "\\\\");
|
||||||
return saveToPath + filename;
|
return saveToPath + filename;
|
||||||
|
|
178
src/main/java/nsusbloader/Utilities/splitmerge/MergeSubTask.java
Normal file
178
src/main/java/nsusbloader/Utilities/splitmerge/MergeSubTask.java
Normal file
|
@ -0,0 +1,178 @@
|
||||||
|
/*
|
||||||
|
Copyright 2019-2021 Dmitry Isaenko
|
||||||
|
|
||||||
|
This file is part of NS-USBloader.
|
||||||
|
|
||||||
|
NS-USBloader 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.
|
||||||
|
|
||||||
|
NS-USBloader 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 NS-USBloader. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package nsusbloader.Utilities.splitmerge;
|
||||||
|
|
||||||
|
import nsusbloader.NSLDataTypes.EMsgType;
|
||||||
|
|
||||||
|
import java.io.*;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.concurrent.Callable;
|
||||||
|
|
||||||
|
public class MergeSubTask implements Callable<Boolean> {
|
||||||
|
private final int id;
|
||||||
|
private final String saveToPath;
|
||||||
|
private final MultithreadingPrintAdapter printAdapter;
|
||||||
|
private final File splitFile;
|
||||||
|
|
||||||
|
private File[] chunkFiles;
|
||||||
|
private long chunksTotalSize;
|
||||||
|
private File resultFile;
|
||||||
|
|
||||||
|
public MergeSubTask(int id, File splitFile, String saveToPath, MultithreadingPrintAdapter printAdapter){
|
||||||
|
this.id = id;
|
||||||
|
this.splitFile = splitFile;
|
||||||
|
this.saveToPath = saveToPath;
|
||||||
|
this.printAdapter = printAdapter;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Boolean call(){
|
||||||
|
try{
|
||||||
|
collectChunks();
|
||||||
|
validateChunks();
|
||||||
|
sortChunks();
|
||||||
|
calculateChunksSizeSum();
|
||||||
|
|
||||||
|
createFile();
|
||||||
|
mergeChunksToFile();
|
||||||
|
validateFile();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
catch (InterruptedException ie){
|
||||||
|
cleanup();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
catch (Exception e){
|
||||||
|
e.printStackTrace();
|
||||||
|
try {
|
||||||
|
printAdapter.print("["+id+"] "+e.getMessage(), EMsgType.FAIL);
|
||||||
|
}
|
||||||
|
catch (InterruptedException ignore) {}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void collectChunks(){
|
||||||
|
chunkFiles = splitFile.listFiles((file, s) -> s.matches("^[0-9][0-9]$"));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void validateChunks() throws Exception{
|
||||||
|
if (chunkFiles == null || chunkFiles.length == 0){
|
||||||
|
throw new Exception("Selected folder doesn't have any chunks. Nothing to do here.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void sortChunks(){
|
||||||
|
Arrays.sort(chunkFiles);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void calculateChunksSizeSum() throws InterruptedException{
|
||||||
|
StringBuilder builder = new StringBuilder("["+id+"] Next files will be merged in following order: ");
|
||||||
|
|
||||||
|
for (File cnk : chunkFiles){
|
||||||
|
builder.append(cnk.getName());
|
||||||
|
builder.append(" ");
|
||||||
|
chunksTotalSize += cnk.length();
|
||||||
|
}
|
||||||
|
printAdapter.print(builder.toString(), EMsgType.INFO);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void createFile() throws Exception{
|
||||||
|
final String splitFileName = splitFile.getName();
|
||||||
|
|
||||||
|
resultFile = new File(saveToPath+File.separator+"!_"+splitFileName);
|
||||||
|
|
||||||
|
for (int i = 0; i < 50 ; i++){
|
||||||
|
if (interrupted())
|
||||||
|
throw new InterruptedException();
|
||||||
|
|
||||||
|
if (resultFile.exists()){
|
||||||
|
printAdapter.print("["+id+"] Trying to create a good new file...", EMsgType.WARNING);
|
||||||
|
resultFile = new File(saveToPath+File.separator+"!_"+i+"_"+splitFileName);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
printAdapter.print("["+id+"] Save results to: "+resultFile.getAbsolutePath(), EMsgType.INFO);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
throw new Exception("Can't create new file.");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void mergeChunksToFile() throws Exception{
|
||||||
|
if ( interrupted())
|
||||||
|
throw new InterruptedException();
|
||||||
|
|
||||||
|
try(BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(resultFile))){
|
||||||
|
BufferedInputStream bis;
|
||||||
|
byte[] chunk;
|
||||||
|
int readBytesCnt;
|
||||||
|
|
||||||
|
printAdapter.reportFileSize(chunksTotalSize);
|
||||||
|
|
||||||
|
for (File chunkFile : chunkFiles){
|
||||||
|
bis = new BufferedInputStream(new FileInputStream(chunkFile));
|
||||||
|
while (true){
|
||||||
|
chunk = new byte[4194240];
|
||||||
|
readBytesCnt = bis.read(chunk);
|
||||||
|
|
||||||
|
if (readBytesCnt < 4194240){
|
||||||
|
if (readBytesCnt > 0)
|
||||||
|
bos.write(chunk, 0, readBytesCnt);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (interrupted())
|
||||||
|
throw new InterruptedException();
|
||||||
|
|
||||||
|
bos.write(chunk);
|
||||||
|
|
||||||
|
printAdapter.updateProgressBySize(readBytesCnt);
|
||||||
|
}
|
||||||
|
bis.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void validateFile() throws Exception{
|
||||||
|
if ( interrupted())
|
||||||
|
throw new Exception("Merge task interrupted!");
|
||||||
|
|
||||||
|
long resultFileSize = resultFile.length();
|
||||||
|
printAdapter.print("["+id+"] Total chunks size: " + chunksTotalSize
|
||||||
|
+"\n Merged file size: " + resultFileSize, EMsgType.INFO);
|
||||||
|
|
||||||
|
if (chunksTotalSize != resultFileSize)
|
||||||
|
throw new Exception("Sizes are different! Do NOT use this file for installations!");
|
||||||
|
|
||||||
|
printAdapter.print("["+id+"] Sizes are the same! Resulting file should be good!", EMsgType.PASS);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void cleanup(){
|
||||||
|
boolean isDeleted = resultFile.delete();
|
||||||
|
try {
|
||||||
|
printAdapter.print(
|
||||||
|
"[" + id + "] Merge task interrupted and file "
|
||||||
|
+ (isDeleted ? "deleted." : "is NOT deleted."), EMsgType.FAIL);
|
||||||
|
}
|
||||||
|
catch (InterruptedException ignore) {}
|
||||||
|
}
|
||||||
|
private boolean interrupted(){
|
||||||
|
return Thread.interrupted(); // NOTE: it's not isInterrupted(); And it's handled properly for now.
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,169 +0,0 @@
|
||||||
/*
|
|
||||||
Copyright 2019-2020 Dmitry Isaenko
|
|
||||||
|
|
||||||
This file is part of NS-USBloader.
|
|
||||||
|
|
||||||
NS-USBloader 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.
|
|
||||||
|
|
||||||
NS-USBloader 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 NS-USBloader. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
package nsusbloader.Utilities.splitmerge;
|
|
||||||
|
|
||||||
import nsusbloader.ModelControllers.CancellableRunnable;
|
|
||||||
import nsusbloader.ModelControllers.ILogPrinter;
|
|
||||||
import nsusbloader.ModelControllers.Log;
|
|
||||||
import nsusbloader.NSLDataTypes.EModule;
|
|
||||||
import nsusbloader.NSLDataTypes.EMsgType;
|
|
||||||
|
|
||||||
import java.io.*;
|
|
||||||
import java.util.Arrays;
|
|
||||||
|
|
||||||
public class MergeTask extends CancellableRunnable {
|
|
||||||
|
|
||||||
private final ILogPrinter logPrinter;
|
|
||||||
private final String saveToPath;
|
|
||||||
private final String filePath;
|
|
||||||
|
|
||||||
private File splitFile;
|
|
||||||
|
|
||||||
private File[] chunkFiles;
|
|
||||||
private long chunksTotalSize;
|
|
||||||
private File resultFile;
|
|
||||||
|
|
||||||
public MergeTask(String filePath, String saveToPath) {
|
|
||||||
this.filePath = filePath;
|
|
||||||
this.saveToPath = saveToPath;
|
|
||||||
logPrinter = Log.getPrinter(EModule.SPLIT_MERGE_TOOL);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
try {
|
|
||||||
logPrinter.print("Merge file: " + filePath, EMsgType.INFO);
|
|
||||||
splitFile = new File(filePath);
|
|
||||||
|
|
||||||
collectChunks();
|
|
||||||
validateChunks();
|
|
||||||
sortChunks();
|
|
||||||
calculateChunksSizeSum();
|
|
||||||
|
|
||||||
createFile();
|
|
||||||
mergeChunksToFile();
|
|
||||||
validateFile();
|
|
||||||
|
|
||||||
logPrinter.print(".:: Merge complete ::.", EMsgType.INFO);
|
|
||||||
logPrinter.updateOneLinerStatus(true);
|
|
||||||
logPrinter.close();
|
|
||||||
}
|
|
||||||
catch (Exception e){
|
|
||||||
logPrinter.print(e.getMessage(), EMsgType.FAIL);
|
|
||||||
logPrinter.updateOneLinerStatus(false);
|
|
||||||
logPrinter.close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void collectChunks(){
|
|
||||||
chunkFiles = splitFile.listFiles((file, s) -> s.matches("^[0-9][0-9]$"));
|
|
||||||
}
|
|
||||||
|
|
||||||
private void validateChunks() throws Exception{
|
|
||||||
if (chunkFiles == null || chunkFiles.length == 0){
|
|
||||||
throw new Exception("Selected folder doesn't have any chunks. Nothing to do here.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void sortChunks(){
|
|
||||||
Arrays.sort(chunkFiles);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void calculateChunksSizeSum(){
|
|
||||||
logPrinter.print("Next files will be merged in following order: ", EMsgType.INFO);
|
|
||||||
for (File cnk : chunkFiles){
|
|
||||||
logPrinter.print(" "+cnk.getName(), EMsgType.INFO);
|
|
||||||
chunksTotalSize += cnk.length();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void createFile() throws Exception{
|
|
||||||
final String splitFileName = splitFile.getName();
|
|
||||||
|
|
||||||
resultFile = new File(saveToPath+File.separator+"!_"+splitFileName);
|
|
||||||
|
|
||||||
for (int i = 0; i < 50 ; i++){
|
|
||||||
if (isCancelled()){
|
|
||||||
throw new InterruptedException("Split task interrupted!");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (resultFile.exists()){
|
|
||||||
logPrinter.print("Trying to create a good new file...", EMsgType.WARNING);
|
|
||||||
resultFile = new File(saveToPath+File.separator+"!_"+i+"_"+splitFileName);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
logPrinter.print("Save results to: "+resultFile.getAbsolutePath(), EMsgType.INFO);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
throw new Exception("Can't create new file.");
|
|
||||||
}
|
|
||||||
|
|
||||||
private void mergeChunksToFile() throws Exception{
|
|
||||||
double chunkPercent = (4194240.0 / (chunksTotalSize / 100.0) / 100.0);
|
|
||||||
long totalSizeCnt = 0;
|
|
||||||
|
|
||||||
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(resultFile));
|
|
||||||
|
|
||||||
BufferedInputStream bis;
|
|
||||||
byte[] chunk;
|
|
||||||
int readBytesCnt;
|
|
||||||
|
|
||||||
for (File chunkFile : chunkFiles){
|
|
||||||
bis = new BufferedInputStream(new FileInputStream(chunkFile));
|
|
||||||
while (true){
|
|
||||||
|
|
||||||
if (isCancelled()){
|
|
||||||
bos.close();
|
|
||||||
bis.close();
|
|
||||||
boolean isDeleted = resultFile.delete();
|
|
||||||
throw new InterruptedException("Merge task interrupted and file "
|
|
||||||
+ (isDeleted ? "deleted." : "is not deleted."));
|
|
||||||
}
|
|
||||||
|
|
||||||
chunk = new byte[4194240];
|
|
||||||
readBytesCnt = bis.read(chunk);
|
|
||||||
|
|
||||||
logPrinter.updateProgress(chunkPercent * totalSizeCnt);
|
|
||||||
totalSizeCnt++;
|
|
||||||
|
|
||||||
if (readBytesCnt < 4194240){
|
|
||||||
if (readBytesCnt > 0)
|
|
||||||
bos.write(chunk, 0, readBytesCnt);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
bos.write(chunk);
|
|
||||||
}
|
|
||||||
bis.close();
|
|
||||||
}
|
|
||||||
bos.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void validateFile() throws Exception{
|
|
||||||
long resultFileSize = resultFile.length();
|
|
||||||
logPrinter.print("Total chunks size: " + chunksTotalSize, EMsgType.INFO);
|
|
||||||
logPrinter.print("Merged file size: " + resultFileSize, EMsgType.INFO);
|
|
||||||
|
|
||||||
if (chunksTotalSize != resultFileSize)
|
|
||||||
throw new Exception("Sizes are different! Do NOT use this file for installations!");
|
|
||||||
|
|
||||||
logPrinter.print("Sizes are the same! Resulting file should be good!", EMsgType.PASS);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,44 @@
|
||||||
|
/*
|
||||||
|
Copyright 2019-2021 Dmitry Isaenko
|
||||||
|
|
||||||
|
This file is part of NS-USBloader.
|
||||||
|
|
||||||
|
NS-USBloader 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.
|
||||||
|
|
||||||
|
NS-USBloader 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 NS-USBloader. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package nsusbloader.Utilities.splitmerge;
|
||||||
|
|
||||||
|
import nsusbloader.ModelControllers.ILogPrinter;
|
||||||
|
import nsusbloader.NSLDataTypes.EMsgType;
|
||||||
|
|
||||||
|
public class MultithreadingPrintAdapter {
|
||||||
|
private final ILogPrinter printer;
|
||||||
|
private long totalFilesSize;
|
||||||
|
private long bytesComplete;
|
||||||
|
|
||||||
|
public MultithreadingPrintAdapter(ILogPrinter printer){
|
||||||
|
this.printer = printer;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void print(String message, EMsgType type) throws InterruptedException{
|
||||||
|
printer.print(message, type);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void reportFileSize(long fileSize){
|
||||||
|
totalFilesSize += fileSize;
|
||||||
|
}
|
||||||
|
public void updateProgressBySize(long chunkSize) throws InterruptedException{
|
||||||
|
bytesComplete += chunkSize;
|
||||||
|
printer.updateProgress((double) bytesComplete / (double) totalFilesSize);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,147 @@
|
||||||
|
/*
|
||||||
|
Copyright 2019-2020 Dmitry Isaenko
|
||||||
|
|
||||||
|
This file is part of NS-USBloader.
|
||||||
|
|
||||||
|
NS-USBloader 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.
|
||||||
|
|
||||||
|
NS-USBloader 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 NS-USBloader. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package nsusbloader.Utilities.splitmerge;
|
||||||
|
|
||||||
|
import nsusbloader.ModelControllers.ILogPrinter;
|
||||||
|
import nsusbloader.ModelControllers.Log;
|
||||||
|
import nsusbloader.NSLDataTypes.EModule;
|
||||||
|
import nsusbloader.NSLDataTypes.EMsgType;
|
||||||
|
|
||||||
|
import java.io.*;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.concurrent.*;
|
||||||
|
/*
|
||||||
|
* TODO: Kill this on application exit (?)
|
||||||
|
*/
|
||||||
|
public class SplitMergeTaskExecutor implements Runnable {
|
||||||
|
private final boolean isSplit;
|
||||||
|
private final List<File> files;
|
||||||
|
private final String saveToPath;
|
||||||
|
private final ILogPrinter logPrinter;
|
||||||
|
private final ExecutorService executorService;
|
||||||
|
|
||||||
|
private final MultithreadingPrintAdapter printAdapter;
|
||||||
|
|
||||||
|
public SplitMergeTaskExecutor(boolean isSplit, List<File> files, String saveToPath){
|
||||||
|
this.isSplit = isSplit;
|
||||||
|
this.files = files;
|
||||||
|
this.saveToPath = saveToPath;
|
||||||
|
this.logPrinter = Log.getPrinter(EModule.SPLIT_MERGE_TOOL);
|
||||||
|
this.executorService = Executors.newFixedThreadPool(
|
||||||
|
files.size(),
|
||||||
|
runnable -> {
|
||||||
|
Thread thread = new Thread(runnable);
|
||||||
|
thread.setDaemon(true);
|
||||||
|
return thread;
|
||||||
|
});
|
||||||
|
this.printAdapter = new MultithreadingPrintAdapter(logPrinter);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void run(){
|
||||||
|
try {
|
||||||
|
List<Future<Boolean>> futuresResults = executorService.invokeAll(getSubTasksCollection());
|
||||||
|
boolean onelinerResult = true;
|
||||||
|
for (Future<Boolean> future : futuresResults){
|
||||||
|
onelinerResult &= future.get();
|
||||||
|
}
|
||||||
|
executorService.shutdown();
|
||||||
|
logPrinter.updateOneLinerStatus(onelinerResult);
|
||||||
|
}
|
||||||
|
catch (InterruptedException ie){
|
||||||
|
//ie.printStackTrace();
|
||||||
|
executorService.shutdownNow();
|
||||||
|
boolean interruptedSuccessfully = false;
|
||||||
|
try {
|
||||||
|
interruptedSuccessfully = executorService.awaitTermination(20, TimeUnit.SECONDS);
|
||||||
|
}
|
||||||
|
catch (InterruptedException awaitInterrupt){
|
||||||
|
print("Force interrupting task...", EMsgType.WARNING);
|
||||||
|
}
|
||||||
|
logPrinter.updateOneLinerStatus(false);
|
||||||
|
print((
|
||||||
|
isSplit?
|
||||||
|
"Split tasks interrupted ":
|
||||||
|
"Merge tasks interrupted ")+
|
||||||
|
(interruptedSuccessfully?
|
||||||
|
"successfully":
|
||||||
|
"with some issues"), EMsgType.WARNING);
|
||||||
|
}
|
||||||
|
catch (Exception e){
|
||||||
|
logPrinter.updateOneLinerStatus(false);
|
||||||
|
print(
|
||||||
|
isSplit?
|
||||||
|
"Split task failed: ":
|
||||||
|
"Merge task failed: "+e.getMessage(), EMsgType.FAIL);
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
print(
|
||||||
|
isSplit?
|
||||||
|
".:: Split complete ::.":
|
||||||
|
".:: Merge complete ::.", EMsgType.INFO);
|
||||||
|
logPrinter.close();
|
||||||
|
}
|
||||||
|
private List<Callable<Boolean>> getSubTasksCollection() throws InterruptedException{
|
||||||
|
List<Callable<Boolean>> subTasks = new ArrayList<>();
|
||||||
|
StringBuilder stringBuilder = new StringBuilder();
|
||||||
|
|
||||||
|
// TODO: Optimize?
|
||||||
|
|
||||||
|
if (isSplit){
|
||||||
|
stringBuilder.append("Split files:\n");
|
||||||
|
for (int i = 0; i < files.size(); i++){
|
||||||
|
File file = files.get(i);
|
||||||
|
stringBuilder.append("[");
|
||||||
|
stringBuilder.append(i);
|
||||||
|
stringBuilder.append("] ");
|
||||||
|
stringBuilder.append(file.getName());
|
||||||
|
stringBuilder.append("\n");
|
||||||
|
Callable<Boolean> task = new SplitSubTask(i, file, saveToPath, printAdapter);
|
||||||
|
subTasks.add(task);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
stringBuilder.append("Merge files:\n");
|
||||||
|
for (int i = 0; i < files.size(); i++){
|
||||||
|
File file = files.get(i);
|
||||||
|
stringBuilder.append("[");
|
||||||
|
stringBuilder.append(i);
|
||||||
|
stringBuilder.append("] ");
|
||||||
|
stringBuilder.append(file.getName());
|
||||||
|
stringBuilder.append("\n");
|
||||||
|
Callable<Boolean> task = new MergeSubTask(i, file, saveToPath, printAdapter);
|
||||||
|
subTasks.add(task);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
logPrinter.print(stringBuilder.toString(), EMsgType.INFO);
|
||||||
|
|
||||||
|
return subTasks;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void print(String message, EMsgType type){
|
||||||
|
try {
|
||||||
|
logPrinter.print(message, type);
|
||||||
|
}
|
||||||
|
catch (InterruptedException ie){
|
||||||
|
ie.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
186
src/main/java/nsusbloader/Utilities/splitmerge/SplitSubTask.java
Normal file
186
src/main/java/nsusbloader/Utilities/splitmerge/SplitSubTask.java
Normal file
|
@ -0,0 +1,186 @@
|
||||||
|
/*
|
||||||
|
Copyright 2019-2021 Dmitry Isaenko
|
||||||
|
|
||||||
|
This file is part of NS-USBloader.
|
||||||
|
|
||||||
|
NS-USBloader 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.
|
||||||
|
|
||||||
|
NS-USBloader 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 NS-USBloader. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package nsusbloader.Utilities.splitmerge;
|
||||||
|
|
||||||
|
import nsusbloader.NSLDataTypes.EMsgType;
|
||||||
|
|
||||||
|
import java.io.*;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.concurrent.Callable;
|
||||||
|
import java.util.concurrent.ExecutionException;
|
||||||
|
|
||||||
|
public class SplitSubTask implements Callable<Boolean> {
|
||||||
|
private final int id;
|
||||||
|
private final String saveToPath;
|
||||||
|
|
||||||
|
private final File file;
|
||||||
|
private File splitFile;
|
||||||
|
private long originalFileLen;
|
||||||
|
private final MultithreadingPrintAdapter printAdapter;
|
||||||
|
|
||||||
|
SplitSubTask(int id, File file, String saveToPath, MultithreadingPrintAdapter printAdapter){
|
||||||
|
this.id = id;
|
||||||
|
this.file = file;
|
||||||
|
this.saveToPath = saveToPath;
|
||||||
|
this.printAdapter = printAdapter;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Boolean call(){
|
||||||
|
try {
|
||||||
|
createSplitFile();
|
||||||
|
splitFileToChunks();
|
||||||
|
validateSplitFile();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
catch (InterruptedException | ExecutionException ie){
|
||||||
|
ie.printStackTrace();
|
||||||
|
cleanup();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
catch (Exception e){
|
||||||
|
e.printStackTrace();
|
||||||
|
try {
|
||||||
|
printAdapter.print("["+id+"] "+e.getMessage(), EMsgType.FAIL);
|
||||||
|
}
|
||||||
|
catch (InterruptedException ignore) {}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void createSplitFile() throws Exception{
|
||||||
|
if ( interrupted())
|
||||||
|
throw new Exception("Split task interrupted!");
|
||||||
|
|
||||||
|
splitFile = new File(saveToPath+File.separator+"!_"+file.getName());
|
||||||
|
|
||||||
|
for (int i = 0; i < 50; i++){
|
||||||
|
if (splitFile.mkdirs()){
|
||||||
|
printAdapter.print("["+id+"] Save results to: "+splitFile.getAbsolutePath(), EMsgType.INFO);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (splitFile.exists()){
|
||||||
|
printAdapter.print("["+id+"] Trying to create a good new folder...", EMsgType.WARNING);
|
||||||
|
splitFile = new File(saveToPath+File.separator+"!_"+i+"_"+file.getName());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new Exception("Folder " + splitFile.getAbsolutePath()
|
||||||
|
+ " could not be created. Not enough rights or something like that?");
|
||||||
|
}
|
||||||
|
throw new Exception("Can't create new file.");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void splitFileToChunks() throws Exception{
|
||||||
|
try(BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file))){
|
||||||
|
long counter;
|
||||||
|
|
||||||
|
originalFileLen = file.length();
|
||||||
|
printAdapter.reportFileSize(originalFileLen);
|
||||||
|
|
||||||
|
byte[] chunk;
|
||||||
|
int readBytesCnt;
|
||||||
|
|
||||||
|
main_loop:
|
||||||
|
for (int i = 0; ; i++){
|
||||||
|
String pathname = splitFile.getAbsolutePath()+File.separator+String.format("%02d", i);
|
||||||
|
BufferedOutputStream fragmentBos = new BufferedOutputStream(new FileOutputStream(pathname));
|
||||||
|
|
||||||
|
counter = 0;
|
||||||
|
|
||||||
|
while (counter < 1024){ // 0xffff0000 total
|
||||||
|
chunk = new byte[4194240];
|
||||||
|
|
||||||
|
if ((readBytesCnt = bis.read(chunk)) < 4194240){
|
||||||
|
if (readBytesCnt > 0)
|
||||||
|
fragmentBos.write(chunk, 0, readBytesCnt);
|
||||||
|
fragmentBos.close();
|
||||||
|
printAdapter.updateProgressBySize(readBytesCnt);
|
||||||
|
break main_loop;
|
||||||
|
}
|
||||||
|
if (interrupted())
|
||||||
|
throw new InterruptedException();
|
||||||
|
|
||||||
|
fragmentBos.write(chunk);
|
||||||
|
counter++;
|
||||||
|
printAdapter.updateProgressBySize(readBytesCnt);
|
||||||
|
}
|
||||||
|
fragmentBos.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void validateSplitFile() throws Exception{
|
||||||
|
if (interrupted())
|
||||||
|
throw new Exception("Split task interrupted!");
|
||||||
|
|
||||||
|
printAdapter.print("["+id+"] Original file: "+splitFile.getAbsolutePath()+" (size: "+originalFileLen+")", EMsgType.INFO);
|
||||||
|
|
||||||
|
long totalChunksSize = 0;
|
||||||
|
File[] chunkFileArr = splitFile.listFiles();
|
||||||
|
|
||||||
|
if (chunkFileArr == null)
|
||||||
|
throw new Exception("Unable to check results. It means that something went wrong.");
|
||||||
|
|
||||||
|
Arrays.sort(chunkFileArr);
|
||||||
|
|
||||||
|
StringBuilder stringBuilder = new StringBuilder("["+id+"] Chunks");
|
||||||
|
|
||||||
|
for (File chunkFile : chunkFileArr) {
|
||||||
|
stringBuilder.append("\n");
|
||||||
|
stringBuilder.append(" ");
|
||||||
|
stringBuilder.append(chunkFile.getName());
|
||||||
|
stringBuilder.append(" size: ");
|
||||||
|
stringBuilder.append(chunkFile.length());
|
||||||
|
totalChunksSize += chunkFile.length();
|
||||||
|
}
|
||||||
|
stringBuilder.append("\n");
|
||||||
|
stringBuilder.append("Total chunks size: ");
|
||||||
|
stringBuilder.append(totalChunksSize);
|
||||||
|
|
||||||
|
printAdapter.print(stringBuilder.toString(), EMsgType.INFO);
|
||||||
|
|
||||||
|
if (originalFileLen != totalChunksSize)
|
||||||
|
throw new Exception("Sizes are different! Do NOT use this file for installations!");
|
||||||
|
|
||||||
|
printAdapter.print("["+id+"] Sizes are the same! Split file should be good!", EMsgType.PASS);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void cleanup(){
|
||||||
|
boolean isDeleted = splitFile.delete();
|
||||||
|
File[] chunksToDelete = splitFile.listFiles();
|
||||||
|
if (! isDeleted && chunksToDelete != null){
|
||||||
|
isDeleted = true;
|
||||||
|
for (File chunkFile : chunksToDelete)
|
||||||
|
isDeleted &= chunkFile.delete();
|
||||||
|
isDeleted &= splitFile.delete();
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
printAdapter.print(
|
||||||
|
"["+id+"] Split task interrupted and folder "
|
||||||
|
+ (isDeleted?"deleted.":"is NOT deleted.")
|
||||||
|
, EMsgType.FAIL);
|
||||||
|
}
|
||||||
|
catch (InterruptedException ignore) {}
|
||||||
|
}
|
||||||
|
private boolean interrupted(){
|
||||||
|
return Thread.interrupted(); // NOTE: it's not isInterrupted(); And it's handled properly for now.
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,173 +0,0 @@
|
||||||
/*
|
|
||||||
Copyright 2019-2020 Dmitry Isaenko
|
|
||||||
|
|
||||||
This file is part of NS-USBloader.
|
|
||||||
|
|
||||||
NS-USBloader 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.
|
|
||||||
|
|
||||||
NS-USBloader 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 NS-USBloader. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
package nsusbloader.Utilities.splitmerge;
|
|
||||||
|
|
||||||
import nsusbloader.ModelControllers.CancellableRunnable;
|
|
||||||
import nsusbloader.ModelControllers.ILogPrinter;
|
|
||||||
import nsusbloader.ModelControllers.Log;
|
|
||||||
import nsusbloader.NSLDataTypes.EModule;
|
|
||||||
import nsusbloader.NSLDataTypes.EMsgType;
|
|
||||||
|
|
||||||
import java.io.*;
|
|
||||||
import java.util.Arrays;
|
|
||||||
|
|
||||||
public class SplitTask extends CancellableRunnable {
|
|
||||||
|
|
||||||
private final ILogPrinter logPrinter;
|
|
||||||
private final String saveToPath;
|
|
||||||
private final String filePath;
|
|
||||||
|
|
||||||
private File file;
|
|
||||||
private File splitFile;
|
|
||||||
private long originalFileLen;
|
|
||||||
|
|
||||||
public SplitTask(String filePath, String saveToPath){
|
|
||||||
this.filePath = filePath;
|
|
||||||
this.saveToPath = saveToPath;
|
|
||||||
this.logPrinter = Log.getPrinter(EModule.SPLIT_MERGE_TOOL);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
try {
|
|
||||||
logPrinter.print("Split file: "+filePath, EMsgType.INFO);
|
|
||||||
this.file = new File(filePath);
|
|
||||||
|
|
||||||
createSplitFile();
|
|
||||||
splitFileToChunks();
|
|
||||||
validateSplitFile();
|
|
||||||
|
|
||||||
logPrinter.print(".:: Split complete ::.", EMsgType.INFO);
|
|
||||||
logPrinter.updateOneLinerStatus(true);
|
|
||||||
logPrinter.close();
|
|
||||||
}
|
|
||||||
catch (Exception e){
|
|
||||||
logPrinter.print(e.getMessage(), EMsgType.FAIL);
|
|
||||||
logPrinter.updateOneLinerStatus(false);
|
|
||||||
logPrinter.close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void createSplitFile() throws Exception{
|
|
||||||
splitFile = new File(saveToPath+File.separator+"!_"+file.getName());
|
|
||||||
|
|
||||||
for (int i = 0; i < 50 ; i++){
|
|
||||||
if (isCancelled()){
|
|
||||||
throw new InterruptedException("Split task interrupted!");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (splitFile.mkdir()){
|
|
||||||
logPrinter.print("Save results to: "+splitFile.getAbsolutePath(), EMsgType.INFO);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (splitFile.exists()){
|
|
||||||
logPrinter.print("Trying to create a good new folder...", EMsgType.WARNING);
|
|
||||||
splitFile = new File(saveToPath+File.separator+"!_"+i+"_"+file.getName());
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new Exception("Folder " + splitFile.getAbsolutePath()
|
|
||||||
+ " could not be created. Not enough rights or something like that?");
|
|
||||||
}
|
|
||||||
throw new Exception("Can't create new file.");
|
|
||||||
}
|
|
||||||
|
|
||||||
private void splitFileToChunks() throws Exception{
|
|
||||||
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file));
|
|
||||||
|
|
||||||
long counter;
|
|
||||||
|
|
||||||
originalFileLen = file.length();
|
|
||||||
|
|
||||||
double chunkPercent = (4194240.0 / (originalFileLen / 100.0) / 100.0);
|
|
||||||
long totalSizeCnt = 0;
|
|
||||||
|
|
||||||
byte[] chunk;
|
|
||||||
int readBytesCnt;
|
|
||||||
|
|
||||||
main_loop:
|
|
||||||
for (int i = 0; ; i++){
|
|
||||||
String pathname = splitFile.getAbsolutePath()+File.separator+String.format("%02d", i);
|
|
||||||
BufferedOutputStream fragmentBos = new BufferedOutputStream(new FileOutputStream(new File(pathname)));
|
|
||||||
|
|
||||||
counter = 0;
|
|
||||||
|
|
||||||
while (counter < 1024){ // 0xffff0000 total
|
|
||||||
|
|
||||||
if (isCancelled()){
|
|
||||||
fragmentBos.close();
|
|
||||||
bis.close();
|
|
||||||
boolean isDeleted = splitFile.delete();
|
|
||||||
File[] chunksToDelete = splitFile.listFiles();
|
|
||||||
if (! isDeleted && chunksToDelete != null){
|
|
||||||
isDeleted = true;
|
|
||||||
for (File chunkFile : chunksToDelete)
|
|
||||||
isDeleted &= chunkFile.delete();
|
|
||||||
isDeleted &= splitFile.delete();
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new InterruptedException("Split task interrupted and folder "
|
|
||||||
+ (isDeleted?"deleted.":"is not deleted."));
|
|
||||||
}
|
|
||||||
|
|
||||||
chunk = new byte[4194240];
|
|
||||||
|
|
||||||
if ((readBytesCnt = bis.read(chunk)) < 4194240){
|
|
||||||
if (readBytesCnt > 0)
|
|
||||||
fragmentBos.write(chunk, 0, readBytesCnt);
|
|
||||||
fragmentBos.close();
|
|
||||||
logPrinter.updateProgress(1.0);
|
|
||||||
break main_loop;
|
|
||||||
}
|
|
||||||
|
|
||||||
fragmentBos.write(chunk);
|
|
||||||
|
|
||||||
logPrinter.updateProgress(chunkPercent * totalSizeCnt);
|
|
||||||
counter++; // NOTE: here we have some redundancy of variables. It has to be fixed one day.
|
|
||||||
totalSizeCnt++;
|
|
||||||
}
|
|
||||||
fragmentBos.close();
|
|
||||||
}
|
|
||||||
bis.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void validateSplitFile() throws Exception{
|
|
||||||
logPrinter.print("Original file size: "+originalFileLen, EMsgType.INFO);
|
|
||||||
long totalChunksSize = 0;
|
|
||||||
File[] chunkFileArr = splitFile.listFiles();
|
|
||||||
|
|
||||||
if (chunkFileArr == null)
|
|
||||||
throw new Exception("Unable to check results. It means that something went wrong.");
|
|
||||||
|
|
||||||
Arrays.sort(chunkFileArr);
|
|
||||||
|
|
||||||
for (File chunkFile : chunkFileArr) {
|
|
||||||
logPrinter.print("Chunk " + chunkFile.getName() + " size: " + chunkFile.length(), EMsgType.INFO);
|
|
||||||
totalChunksSize += chunkFile.length();
|
|
||||||
}
|
|
||||||
|
|
||||||
logPrinter.print("Total chunks size: " + totalChunksSize, EMsgType.INFO);
|
|
||||||
|
|
||||||
if (originalFileLen != totalChunksSize)
|
|
||||||
throw new Exception("Sizes are different! Do NOT use this file for installations!");
|
|
||||||
|
|
||||||
logPrinter.print("Sizes are the same! Split file should be good!", EMsgType.PASS);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -18,8 +18,7 @@
|
||||||
*/
|
*/
|
||||||
package nsusbloader.cli;
|
package nsusbloader.cli;
|
||||||
|
|
||||||
import nsusbloader.Utilities.splitmerge.MergeTask;
|
import nsusbloader.Utilities.splitmerge.SplitMergeTaskExecutor;
|
||||||
import nsusbloader.Utilities.splitmerge.SplitTask;
|
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
@ -27,7 +26,7 @@ import java.util.List;
|
||||||
|
|
||||||
public class MergeCli {
|
public class MergeCli {
|
||||||
|
|
||||||
private String[] arguments;
|
private final String[] arguments;
|
||||||
private String saveTo;
|
private String saveTo;
|
||||||
private String[] splitFiles;
|
private String[] splitFiles;
|
||||||
|
|
||||||
|
@ -97,12 +96,20 @@ public class MergeCli {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void runBackend() throws InterruptedException{
|
private void runBackend() throws InterruptedException{
|
||||||
for (String filePath : splitFiles){
|
Runnable mergeTask = new SplitMergeTaskExecutor(
|
||||||
Runnable mergeTask = new MergeTask(filePath, saveTo);
|
false,
|
||||||
|
getFilesFromStrings(),
|
||||||
|
saveTo);
|
||||||
Thread thread = new Thread(mergeTask);
|
Thread thread = new Thread(mergeTask);
|
||||||
thread.setDaemon(true);
|
thread.setDaemon(true);
|
||||||
thread.start();
|
thread.start();
|
||||||
thread.join();
|
thread.join();
|
||||||
}
|
}
|
||||||
|
private List<File> getFilesFromStrings(){
|
||||||
|
ArrayList<File> realFiles = new ArrayList<>();
|
||||||
|
for (String splitFileString : splitFiles){
|
||||||
|
realFiles.add(new File(splitFileString));
|
||||||
|
}
|
||||||
|
return realFiles;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,16 +18,14 @@
|
||||||
*/
|
*/
|
||||||
package nsusbloader.cli;
|
package nsusbloader.cli;
|
||||||
|
|
||||||
import nsusbloader.Utilities.splitmerge.SplitTask;
|
import nsusbloader.Utilities.splitmerge.SplitMergeTaskExecutor;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.nio.file.Paths;
|
import java.util.*;
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
public class SplitCli {
|
public class SplitCli {
|
||||||
|
|
||||||
private String[] arguments;
|
private final String[] arguments;
|
||||||
private String saveTo;
|
private String saveTo;
|
||||||
private String[] files;
|
private String[] files;
|
||||||
|
|
||||||
|
@ -95,12 +93,20 @@ public class SplitCli {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void runBackend() throws InterruptedException{
|
private void runBackend() throws InterruptedException{
|
||||||
for (String filePath : files){
|
Runnable splitTasks = new SplitMergeTaskExecutor(
|
||||||
Runnable splitTaks = new SplitTask(filePath, saveTo);
|
true,
|
||||||
Thread thread = new Thread(splitTaks);
|
getFilesFromStrings(),
|
||||||
|
saveTo);
|
||||||
|
Thread thread = new Thread(splitTasks);
|
||||||
thread.setDaemon(true);
|
thread.setDaemon(true);
|
||||||
thread.start();
|
thread.start();
|
||||||
thread.join();
|
thread.join();
|
||||||
}
|
}
|
||||||
|
private List<File> getFilesFromStrings(){
|
||||||
|
ArrayList<File> realFiles = new ArrayList<>();
|
||||||
|
for (String fileString : files){
|
||||||
|
realFiles.add(new File(fileString));
|
||||||
|
}
|
||||||
|
return realFiles;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -90,7 +90,7 @@ public class NETCommunications extends CancellableRunnable {
|
||||||
if (! isValid || isCancelled() )
|
if (! isValid || isCancelled() )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
logPrinter.print("\tStart chain", EMsgType.INFO);
|
print("\tStart chain", EMsgType.INFO);
|
||||||
|
|
||||||
final String handshakeContent = buildHandshakeContent();
|
final String handshakeContent = buildHandshakeContent();
|
||||||
|
|
||||||
|
@ -102,11 +102,11 @@ public class NETCommunications extends CancellableRunnable {
|
||||||
|
|
||||||
// Check if we should serve requests
|
// Check if we should serve requests
|
||||||
if (this.doNotServe){
|
if (this.doNotServe){
|
||||||
logPrinter.print("List of files transferred. Replies won't be served.", EMsgType.PASS);
|
print("List of files transferred. Replies won't be served.", EMsgType.PASS);
|
||||||
close(EFileStatus.UNKNOWN);
|
close(EFileStatus.UNKNOWN);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
logPrinter.print("Initiation files list has been sent to NS.", EMsgType.PASS);
|
print("Initiation files list has been sent to NS.", EMsgType.PASS);
|
||||||
|
|
||||||
// Go transfer
|
// Go transfer
|
||||||
serveRequestsLoop();
|
serveRequestsLoop();
|
||||||
|
@ -142,7 +142,7 @@ public class NETCommunications extends CancellableRunnable {
|
||||||
handshakeSocket.close();
|
handshakeSocket.close();
|
||||||
}
|
}
|
||||||
catch (IOException uhe){
|
catch (IOException uhe){
|
||||||
logPrinter.print("Unable to connect to NS and send files list:\n "
|
print("Unable to connect to NS and send files list:\n "
|
||||||
+ uhe.getMessage(), EMsgType.FAIL);
|
+ uhe.getMessage(), EMsgType.FAIL);
|
||||||
close(EFileStatus.UNKNOWN);
|
close(EFileStatus.UNKNOWN);
|
||||||
return true;
|
return true;
|
||||||
|
@ -175,13 +175,13 @@ public class NETCommunications extends CancellableRunnable {
|
||||||
}
|
}
|
||||||
catch (Exception e){
|
catch (Exception e){
|
||||||
if (isCancelled())
|
if (isCancelled())
|
||||||
logPrinter.print("Interrupted by user.", EMsgType.INFO);
|
print("Interrupted by user.", EMsgType.INFO);
|
||||||
else
|
else
|
||||||
logPrinter.print(e.getMessage(), EMsgType.INFO);
|
print(e.getMessage(), EMsgType.INFO);
|
||||||
close(EFileStatus.UNKNOWN);
|
close(EFileStatus.UNKNOWN);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
logPrinter.print("All transfers complete", EMsgType.PASS);
|
print("All transfers complete", EMsgType.PASS);
|
||||||
close(EFileStatus.UPLOADED);
|
close(EFileStatus.UPLOADED);
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
|
@ -199,7 +199,7 @@ public class NETCommunications extends CancellableRunnable {
|
||||||
|
|
||||||
if (! files.containsKey(reqFileName)){
|
if (! files.containsKey(reqFileName)){
|
||||||
writeToSocket(NETPacket.getCode404());
|
writeToSocket(NETPacket.getCode404());
|
||||||
logPrinter.print("File "+reqFileName+" doesn't exists or have 0 size. Returning 404", EMsgType.FAIL);
|
print("File "+reqFileName+" doesn't exists or have 0 size. Returning 404", EMsgType.FAIL);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -208,13 +208,13 @@ public class NETCommunications extends CancellableRunnable {
|
||||||
|
|
||||||
if (! requestedFile.exists() || reqFileSize == 0){ // well.. tell 404 if file exists with 0 length is against standard, but saves time
|
if (! requestedFile.exists() || reqFileSize == 0){ // well.. tell 404 if file exists with 0 length is against standard, but saves time
|
||||||
writeToSocket(NETPacket.getCode404());
|
writeToSocket(NETPacket.getCode404());
|
||||||
logPrinter.print("File "+requestedFile.getName()+" doesn't exists or have 0 size. Returning 404", EMsgType.FAIL);
|
print("File "+requestedFile.getName()+" doesn't exists or have 0 size. Returning 404", EMsgType.FAIL);
|
||||||
logPrinter.update(requestedFile, EFileStatus.FAILED);
|
logPrinter.update(requestedFile, EFileStatus.FAILED);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (packet.get(0).startsWith("HEAD")){
|
if (packet.get(0).startsWith("HEAD")){
|
||||||
writeToSocket(NETPacket.getCode200(reqFileSize));
|
writeToSocket(NETPacket.getCode200(reqFileSize));
|
||||||
logPrinter.print("Replying for requested file: "+requestedFile.getName(), EMsgType.INFO);
|
print("Replying for requested file: "+requestedFile.getName(), EMsgType.INFO);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (packet.get(0).startsWith("GET")) {
|
if (packet.get(0).startsWith("GET")) {
|
||||||
|
@ -237,7 +237,7 @@ public class NETCommunications extends CancellableRunnable {
|
||||||
|
|
||||||
if (fromRange > toRange){ // If start bytes greater then end bytes
|
if (fromRange > toRange){ // If start bytes greater then end bytes
|
||||||
writeToSocket(NETPacket.getCode400());
|
writeToSocket(NETPacket.getCode400());
|
||||||
logPrinter.print("Requested range for "
|
print("Requested range for "
|
||||||
+ file.getName()
|
+ file.getName()
|
||||||
+ " is incorrect. Returning 400", EMsgType.FAIL);
|
+ " is incorrect. Returning 400", EMsgType.FAIL);
|
||||||
logPrinter.update(file, EFileStatus.FAILED);
|
logPrinter.update(file, EFileStatus.FAILED);
|
||||||
|
@ -254,7 +254,7 @@ public class NETCommunications extends CancellableRunnable {
|
||||||
|
|
||||||
if (rangeStr[1].isEmpty()) { // If Range not defined: like "Range: bytes=-"
|
if (rangeStr[1].isEmpty()) { // If Range not defined: like "Range: bytes=-"
|
||||||
writeToSocket(NETPacket.getCode400());
|
writeToSocket(NETPacket.getCode400());
|
||||||
logPrinter.print("Requested range for "
|
print("Requested range for "
|
||||||
+ file.getName()
|
+ file.getName()
|
||||||
+ " is incorrect (empty start & end). Returning 400", EMsgType.FAIL);
|
+ " is incorrect (empty start & end). Returning 400", EMsgType.FAIL);
|
||||||
logPrinter.update(file, EFileStatus.FAILED);
|
logPrinter.update(file, EFileStatus.FAILED);
|
||||||
|
@ -267,7 +267,7 @@ public class NETCommunications extends CancellableRunnable {
|
||||||
}
|
}
|
||||||
// If file smaller than 500 bytes
|
// If file smaller than 500 bytes
|
||||||
writeToSocket(NETPacket.getCode416());
|
writeToSocket(NETPacket.getCode416());
|
||||||
logPrinter.print("File size requested for "
|
print("File size requested for "
|
||||||
+ file.getName()
|
+ file.getName()
|
||||||
+ " while actual size of it: "
|
+ " while actual size of it: "
|
||||||
+ fileSize+". Returning 416", EMsgType.FAIL);
|
+ fileSize+". Returning 416", EMsgType.FAIL);
|
||||||
|
@ -275,7 +275,7 @@ public class NETCommunications extends CancellableRunnable {
|
||||||
}
|
}
|
||||||
catch (NumberFormatException nfe){
|
catch (NumberFormatException nfe){
|
||||||
writeToSocket(NETPacket.getCode400());
|
writeToSocket(NETPacket.getCode400());
|
||||||
logPrinter.print("Requested range for "
|
print("Requested range for "
|
||||||
+ file.getName()
|
+ file.getName()
|
||||||
+ " has incorrect format. Returning 400\n\t"
|
+ " has incorrect format. Returning 400\n\t"
|
||||||
+ nfe.getMessage(), EMsgType.FAIL);
|
+ nfe.getMessage(), EMsgType.FAIL);
|
||||||
|
@ -293,7 +293,7 @@ public class NETCommunications extends CancellableRunnable {
|
||||||
private void writeToSocket(String fileName, long start, long end) throws Exception{
|
private void writeToSocket(String fileName, long start, long end) throws Exception{
|
||||||
File file = files.get(fileName).getFile();
|
File file = files.get(fileName).getFile();
|
||||||
|
|
||||||
logPrinter.print("Reply to range: "+start+"-"+end, EMsgType.INFO);
|
print("Reply to range: "+start+"-"+end, EMsgType.INFO);
|
||||||
|
|
||||||
writeToSocket(NETPacket.getCode206(files.get(fileName).getSize(), start, end));
|
writeToSocket(NETPacket.getCode206(files.get(fileName).getSize(), start, end));
|
||||||
try{
|
try{
|
||||||
|
@ -379,11 +379,11 @@ public class NETCommunications extends CancellableRunnable {
|
||||||
try {
|
try {
|
||||||
if (serverSocket != null && ! serverSocket.isClosed()) {
|
if (serverSocket != null && ! serverSocket.isClosed()) {
|
||||||
serverSocket.close();
|
serverSocket.close();
|
||||||
logPrinter.print("Closing server socket.", EMsgType.PASS);
|
print("Closing server socket.", EMsgType.PASS);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (IOException ioe){
|
catch (IOException ioe){
|
||||||
logPrinter.print("Closing server socket failed. Sometimes it's not an issue.", EMsgType.WARNING);
|
print("Closing server socket failed. Sometimes it's not an issue.", EMsgType.WARNING);
|
||||||
}
|
}
|
||||||
|
|
||||||
HashMap<String, File> tempMap = new HashMap<>();
|
HashMap<String, File> tempMap = new HashMap<>();
|
||||||
|
@ -392,7 +392,15 @@ public class NETCommunications extends CancellableRunnable {
|
||||||
|
|
||||||
logPrinter.update(tempMap, status);
|
logPrinter.update(tempMap, status);
|
||||||
|
|
||||||
logPrinter.print("\tEnd chain", EMsgType.INFO);
|
print("\tEnd chain", EMsgType.INFO);
|
||||||
logPrinter.close();
|
logPrinter.close();
|
||||||
}
|
}
|
||||||
|
private void print(String message, EMsgType type){
|
||||||
|
try {
|
||||||
|
logPrinter.print(message, type);
|
||||||
|
}
|
||||||
|
catch (InterruptedException ie){
|
||||||
|
ie.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -55,15 +55,21 @@ public class NetworkSetupValidator {
|
||||||
resolvePort(hostPortNum);
|
resolvePort(hostPortNum);
|
||||||
}
|
}
|
||||||
catch (Exception e){
|
catch (Exception e){
|
||||||
|
try {
|
||||||
logPrinter.print(e.getMessage(), EMsgType.FAIL);
|
logPrinter.print(e.getMessage(), EMsgType.FAIL);
|
||||||
|
}
|
||||||
|
catch (InterruptedException ignore){}
|
||||||
valid = false;
|
valid = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
valid = true;
|
valid = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void validateFiles(List<File> filesList) {
|
private void validateFiles(List<File> filesList){
|
||||||
filesList.removeIf(f -> {
|
filesList.removeIf(this::validator);
|
||||||
|
}
|
||||||
|
private boolean validator(File f){
|
||||||
|
try {
|
||||||
if (f.isFile())
|
if (f.isFile())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
@ -76,24 +82,27 @@ public class NetworkSetupValidator {
|
||||||
|
|
||||||
Arrays.sort(subFiles, Comparator.comparingInt(file -> Integer.parseInt(file.getName())));
|
Arrays.sort(subFiles, Comparator.comparingInt(file -> Integer.parseInt(file.getName())));
|
||||||
|
|
||||||
for (int i = subFiles.length - 2; i > 0 ; i--){
|
for (int i = subFiles.length - 2; i > 0; i--) {
|
||||||
if (subFiles[i].length() != subFiles[i-1].length()) {
|
if (subFiles[i].length() != subFiles[i - 1].length()) {
|
||||||
logPrinter.print("NET: Exclude split file: "+f.getName()+
|
logPrinter.print("NET: Exclude split file: " + f.getName() +
|
||||||
"\n Chunk sizes of the split file are not the same, but has to be.", EMsgType.WARNING);
|
"\n Chunk sizes of the split file are not the same, but has to be.", EMsgType.WARNING);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
long firstFileLength = subFiles[0].length();
|
long firstFileLength = subFiles[0].length();
|
||||||
long lastFileLength = subFiles[subFiles.length-1].length();
|
long lastFileLength = subFiles[subFiles.length - 1].length();
|
||||||
|
|
||||||
if (lastFileLength > firstFileLength){
|
if (lastFileLength > firstFileLength) {
|
||||||
logPrinter.print("NET: Exclude split file: "+f.getName()+
|
logPrinter.print("NET: Exclude split file: " + f.getName() +
|
||||||
"\n Chunk sizes of the split file are not the same, but has to be.", EMsgType.WARNING);
|
"\n Chunk sizes of the split file are not the same, but has to be.", EMsgType.WARNING);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
});
|
}
|
||||||
|
catch (InterruptedException ie){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void encodeAndAddFilesToMap(List<File> filesList) throws UnsupportedEncodingException, FileNotFoundException {
|
private void encodeAndAddFilesToMap(List<File> filesList) throws UnsupportedEncodingException, FileNotFoundException {
|
||||||
|
@ -108,7 +117,7 @@ public class NetworkSetupValidator {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void resolveIp(String hostIPaddr) throws IOException{
|
private void resolveIp(String hostIPaddr) throws IOException, InterruptedException{
|
||||||
if (! hostIPaddr.isEmpty()){
|
if (! hostIPaddr.isEmpty()){
|
||||||
this.hostIP = hostIPaddr;
|
this.hostIP = hostIPaddr;
|
||||||
logPrinter.print("NET: Host IP defined as: " + hostIP, EMsgType.PASS);
|
logPrinter.print("NET: Host IP defined as: " + hostIP, EMsgType.PASS);
|
||||||
|
@ -124,7 +133,7 @@ public class NetworkSetupValidator {
|
||||||
throw new IOException("Try using 'Expert mode' and set IP manually. " + getAvaliableIpExamples());
|
throw new IOException("Try using 'Expert mode' and set IP manually. " + getAvaliableIpExamples());
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean findIpUsingHost(String host) {
|
private boolean findIpUsingHost(String host) throws InterruptedException{
|
||||||
try {
|
try {
|
||||||
Socket scoketK;
|
Socket scoketK;
|
||||||
scoketK = new Socket();
|
scoketK = new Socket();
|
||||||
|
|
|
@ -59,17 +59,17 @@ public class GoldLeaf_05 extends TransferModule {
|
||||||
this.task = task;
|
this.task = task;
|
||||||
status = EFileStatus.FAILED;
|
status = EFileStatus.FAILED;
|
||||||
|
|
||||||
logPrinter.print("============= GoldLeaf v0.5 =============\n" +
|
print("============= GoldLeaf v0.5 =============\n" +
|
||||||
" Only one file per time could be sent. In case you selected more the first one would be picked.", EMsgType.INFO);
|
" Only one file per time could be sent. In case you selected more the first one would be picked.", EMsgType.INFO);
|
||||||
if (nspMap.isEmpty()){
|
if (nspMap.isEmpty()){
|
||||||
logPrinter.print("For using this GoldLeaf version you have to add file to the table and select it for upload", EMsgType.INFO);
|
print("For using this GoldLeaf version you have to add file to the table and select it for upload", EMsgType.INFO);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
File nspFile = (File) nspMap.values().toArray()[0];
|
File nspFile = (File) nspMap.values().toArray()[0];
|
||||||
logPrinter.print("File for upload: "+nspFile.getAbsolutePath(), EMsgType.INFO);
|
print("File for upload: "+nspFile.getAbsolutePath(), EMsgType.INFO);
|
||||||
|
|
||||||
if (!nspFile.getName().toLowerCase().endsWith(".nsp")) {
|
if (!nspFile.getName().toLowerCase().endsWith(".nsp")) {
|
||||||
logPrinter.print("GL This file doesn't look like NSP", EMsgType.FAIL);
|
print("GL This file doesn't look like NSP", EMsgType.FAIL);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
PFSProvider pfsElement;
|
PFSProvider pfsElement;
|
||||||
|
@ -77,11 +77,11 @@ public class GoldLeaf_05 extends TransferModule {
|
||||||
pfsElement = new PFSProvider(nspFile, logPrinter);
|
pfsElement = new PFSProvider(nspFile, logPrinter);
|
||||||
}
|
}
|
||||||
catch (Exception e){
|
catch (Exception e){
|
||||||
logPrinter.print("GL File provided has incorrect structure and won't be uploaded\n\t"+e.getMessage(), EMsgType.FAIL);
|
print("GL File provided has incorrect structure and won't be uploaded\n\t"+e.getMessage(), EMsgType.FAIL);
|
||||||
status = EFileStatus.INCORRECT_FILE_FAILED;
|
status = EFileStatus.INCORRECT_FILE_FAILED;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
logPrinter.print("GL File structure validated and it will be uploaded", EMsgType.PASS);
|
print("GL File structure validated and it will be uploaded", EMsgType.PASS);
|
||||||
|
|
||||||
try{
|
try{
|
||||||
if (nspFile.isDirectory())
|
if (nspFile.isDirectory())
|
||||||
|
@ -90,7 +90,7 @@ public class GoldLeaf_05 extends TransferModule {
|
||||||
this.raf = new RandomAccessFile(nspFile, "r");
|
this.raf = new RandomAccessFile(nspFile, "r");
|
||||||
}
|
}
|
||||||
catch (IOException ioe){
|
catch (IOException ioe){
|
||||||
logPrinter.print("GL File not found\n\t"+ioe.getMessage(), EMsgType.FAIL);
|
print("GL File not found\n\t"+ioe.getMessage(), EMsgType.FAIL);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -99,15 +99,15 @@ public class GoldLeaf_05 extends TransferModule {
|
||||||
|
|
||||||
// Go connect to GoldLeaf
|
// Go connect to GoldLeaf
|
||||||
if (writeUsb(CMD_GLUC)) {
|
if (writeUsb(CMD_GLUC)) {
|
||||||
logPrinter.print("GL Initiating GoldLeaf connection [1/2]", EMsgType.FAIL);
|
print("GL Initiating GoldLeaf connection [1/2]", EMsgType.FAIL);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
logPrinter.print("GL Initiating GoldLeaf connection: [1/2]", EMsgType.PASS);
|
print("GL Initiating GoldLeaf connection: [1/2]", EMsgType.PASS);
|
||||||
if (writeUsb(CMD_ConnectionRequest)){
|
if (writeUsb(CMD_ConnectionRequest)){
|
||||||
logPrinter.print("GL Initiating GoldLeaf connection: [2/2]", EMsgType.FAIL);
|
print("GL Initiating GoldLeaf connection: [2/2]", EMsgType.FAIL);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
logPrinter.print("GL Initiating GoldLeaf connection: [2/2]", EMsgType.PASS);
|
print("GL Initiating GoldLeaf connection: [2/2]", EMsgType.PASS);
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
readByte = readUsb();
|
readByte = readUsb();
|
||||||
|
@ -143,7 +143,7 @@ public class GoldLeaf_05 extends TransferModule {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (Arrays.equals(readByte, CMD_Finish)) {
|
if (Arrays.equals(readByte, CMD_Finish)) {
|
||||||
logPrinter.print("GL Closing GoldLeaf connection: Transfer successful.", EMsgType.PASS);
|
print("GL Closing GoldLeaf connection: Transfer successful.", EMsgType.PASS);
|
||||||
status = EFileStatus.UPLOADED;
|
status = EFileStatus.UPLOADED;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -164,29 +164,29 @@ public class GoldLeaf_05 extends TransferModule {
|
||||||
* false if no issues
|
* false if no issues
|
||||||
* */
|
* */
|
||||||
private boolean handleConnectionResponse(PFSProvider pfsElement){
|
private boolean handleConnectionResponse(PFSProvider pfsElement){
|
||||||
logPrinter.print("GL 'ConnectionResponse' command:", EMsgType.INFO);
|
print("GL 'ConnectionResponse' command:", EMsgType.INFO);
|
||||||
if (writeUsb(CMD_GLUC)) {
|
if (writeUsb(CMD_GLUC)) {
|
||||||
logPrinter.print(" [1/4]", EMsgType.FAIL);
|
print(" [1/4]", EMsgType.FAIL);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
logPrinter.print(" [1/4]", EMsgType.PASS);
|
print(" [1/4]", EMsgType.PASS);
|
||||||
if (writeUsb(CMD_NSPName)) {
|
if (writeUsb(CMD_NSPName)) {
|
||||||
logPrinter.print(" [2/4]", EMsgType.FAIL);
|
print(" [2/4]", EMsgType.FAIL);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
logPrinter.print(" [2/4]", EMsgType.PASS);
|
print(" [2/4]", EMsgType.PASS);
|
||||||
|
|
||||||
if (writeUsb(pfsElement.getBytesNspFileNameLength())) {
|
if (writeUsb(pfsElement.getBytesNspFileNameLength())) {
|
||||||
logPrinter.print(" [3/4]", EMsgType.FAIL);
|
print(" [3/4]", EMsgType.FAIL);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
logPrinter.print(" [3/4]", EMsgType.PASS);
|
print(" [3/4]", EMsgType.PASS);
|
||||||
|
|
||||||
if (writeUsb(pfsElement.getBytesNspFileName())) {
|
if (writeUsb(pfsElement.getBytesNspFileName())) {
|
||||||
logPrinter.print(" [4/4]", EMsgType.FAIL);
|
print(" [4/4]", EMsgType.FAIL);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
logPrinter.print(" [4/4]", EMsgType.PASS);
|
print(" [4/4]", EMsgType.PASS);
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -196,50 +196,50 @@ public class GoldLeaf_05 extends TransferModule {
|
||||||
* false if no issues
|
* false if no issues
|
||||||
* */
|
* */
|
||||||
private boolean handleStart(PFSProvider pfsElement){
|
private boolean handleStart(PFSProvider pfsElement){
|
||||||
logPrinter.print("GL Handle 'Start' command:", EMsgType.INFO);
|
print("GL Handle 'Start' command:", EMsgType.INFO);
|
||||||
if (writeUsb(CMD_GLUC)) {
|
if (writeUsb(CMD_GLUC)) {
|
||||||
logPrinter.print(" [Prefix]", EMsgType.FAIL);
|
print(" [Prefix]", EMsgType.FAIL);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
logPrinter.print(" [Prefix]", EMsgType.PASS);
|
print(" [Prefix]", EMsgType.PASS);
|
||||||
|
|
||||||
if (writeUsb(CMD_NSPData)) {
|
if (writeUsb(CMD_NSPData)) {
|
||||||
logPrinter.print(" [Command]", EMsgType.FAIL);
|
print(" [Command]", EMsgType.FAIL);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
logPrinter.print(" [Command]", EMsgType.PASS);
|
print(" [Command]", EMsgType.PASS);
|
||||||
|
|
||||||
if (writeUsb(pfsElement.getBytesCountOfNca())) {
|
if (writeUsb(pfsElement.getBytesCountOfNca())) {
|
||||||
logPrinter.print(" [Sub-files count]", EMsgType.FAIL);
|
print(" [Sub-files count]", EMsgType.FAIL);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
logPrinter.print(" [Sub-files count]", EMsgType.PASS);
|
print(" [Sub-files count]", EMsgType.PASS);
|
||||||
|
|
||||||
int ncaCount = pfsElement.getIntCountOfNca();
|
int ncaCount = pfsElement.getIntCountOfNca();
|
||||||
logPrinter.print(" [Information for "+ncaCount+" sub-files]", EMsgType.INFO);
|
print(" [Information for "+ncaCount+" sub-files]", EMsgType.INFO);
|
||||||
for (int i = 0; i < ncaCount; i++){
|
for (int i = 0; i < ncaCount; i++){
|
||||||
logPrinter.print("File #"+i, EMsgType.INFO);
|
print("File #"+i, EMsgType.INFO);
|
||||||
if (writeUsb(pfsElement.getNca(i).getNcaFileNameLength())) {
|
if (writeUsb(pfsElement.getNca(i).getNcaFileNameLength())) {
|
||||||
logPrinter.print(" [1/4] Name length", EMsgType.FAIL);
|
print(" [1/4] Name length", EMsgType.FAIL);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
logPrinter.print(" [1/4] Name length", EMsgType.PASS);
|
print(" [1/4] Name length", EMsgType.PASS);
|
||||||
|
|
||||||
if (writeUsb(pfsElement.getNca(i).getNcaFileName())) {
|
if (writeUsb(pfsElement.getNca(i).getNcaFileName())) {
|
||||||
logPrinter.print(" [2/4] Name", EMsgType.FAIL);
|
print(" [2/4] Name", EMsgType.FAIL);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
logPrinter.print(" [2/4] Name", EMsgType.PASS);
|
print(" [2/4] Name", EMsgType.PASS);
|
||||||
if (writeUsb(ByteBuffer.allocate(8).order(ByteOrder.LITTLE_ENDIAN).putLong(pfsElement.getBodySize()+pfsElement.getNca(i).getNcaOffset()).array())) { // offset. real.
|
if (writeUsb(ByteBuffer.allocate(8).order(ByteOrder.LITTLE_ENDIAN).putLong(pfsElement.getBodySize()+pfsElement.getNca(i).getNcaOffset()).array())) { // offset. real.
|
||||||
logPrinter.print(" [3/4] Offset", EMsgType.FAIL);
|
print(" [3/4] Offset", EMsgType.FAIL);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
logPrinter.print(" [3/4] Offset", EMsgType.PASS);
|
print(" [3/4] Offset", EMsgType.PASS);
|
||||||
if (writeUsb(ByteBuffer.allocate(8).order(ByteOrder.LITTLE_ENDIAN).putLong(pfsElement.getNca(i).getNcaSize()).array())) { // size
|
if (writeUsb(ByteBuffer.allocate(8).order(ByteOrder.LITTLE_ENDIAN).putLong(pfsElement.getNca(i).getNcaSize()).array())) { // size
|
||||||
logPrinter.print(" [4/4] Size", EMsgType.FAIL);
|
print(" [4/4] Size", EMsgType.FAIL);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
logPrinter.print(" [4/4] Size", EMsgType.PASS);
|
print(" [4/4] Size", EMsgType.PASS);
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -254,18 +254,18 @@ public class GoldLeaf_05 extends TransferModule {
|
||||||
int requestedNcaID;
|
int requestedNcaID;
|
||||||
|
|
||||||
if (isItRawRequest) {
|
if (isItRawRequest) {
|
||||||
logPrinter.print("GL Handle 'Content' command", EMsgType.INFO);
|
print("GL Handle 'Content' command", EMsgType.INFO);
|
||||||
byte[] readByte = readUsb();
|
byte[] readByte = readUsb();
|
||||||
if (readByte == null || readByte.length != 4) {
|
if (readByte == null || readByte.length != 4) {
|
||||||
logPrinter.print(" [Read requested ID]", EMsgType.FAIL);
|
print(" [Read requested ID]", EMsgType.FAIL);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
requestedNcaID = ByteBuffer.wrap(readByte).order(ByteOrder.LITTLE_ENDIAN).getInt();
|
requestedNcaID = ByteBuffer.wrap(readByte).order(ByteOrder.LITTLE_ENDIAN).getInt();
|
||||||
logPrinter.print(" [Read requested ID = "+requestedNcaID+" ]", EMsgType.PASS);
|
print(" [Read requested ID = "+requestedNcaID+" ]", EMsgType.PASS);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
requestedNcaID = pfsElement.getNcaTicketID();
|
requestedNcaID = pfsElement.getNcaTicketID();
|
||||||
logPrinter.print("GL Handle 'Ticket' command (ID = "+requestedNcaID+" )", EMsgType.INFO);
|
print("GL Handle 'Ticket' command (ID = "+requestedNcaID+" )", EMsgType.INFO);
|
||||||
}
|
}
|
||||||
|
|
||||||
long realNcaOffset = pfsElement.getNca(requestedNcaID).getNcaOffset()+pfsElement.getBodySize();
|
long realNcaOffset = pfsElement.getNca(requestedNcaID).getNcaOffset()+pfsElement.getBodySize();
|
||||||
|
@ -317,8 +317,8 @@ public class GoldLeaf_05 extends TransferModule {
|
||||||
logPrinter.updateProgress(1.0);
|
logPrinter.updateProgress(1.0);
|
||||||
//-----------------------------------------/
|
//-----------------------------------------/
|
||||||
}
|
}
|
||||||
catch (IOException ioe){
|
catch (IOException | InterruptedException ioe){
|
||||||
logPrinter.print("GL Failed to read NCA ID "+requestedNcaID+". IO Exception:\n "+ioe.getMessage(), EMsgType.FAIL);
|
print("GL Failed to read NCA ID "+requestedNcaID+". Exception:\n "+ioe.getMessage(), EMsgType.FAIL);
|
||||||
ioe.printStackTrace();
|
ioe.printStackTrace();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -345,18 +345,18 @@ public class GoldLeaf_05 extends TransferModule {
|
||||||
if (writeBufTransferred.get() == message.length)
|
if (writeBufTransferred.get() == message.length)
|
||||||
return false;
|
return false;
|
||||||
else {
|
else {
|
||||||
logPrinter.print("GL Data transfer issue [write]\n Requested: "+message.length+"\n Transferred: "+writeBufTransferred.get(), EMsgType.FAIL);
|
print("GL Data transfer issue [write]\n Requested: "+message.length+"\n Transferred: "+writeBufTransferred.get(), EMsgType.FAIL);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
case LibUsb.ERROR_TIMEOUT:
|
case LibUsb.ERROR_TIMEOUT:
|
||||||
continue;
|
continue;
|
||||||
default:
|
default:
|
||||||
logPrinter.print("GL Data transfer issue [write]\n Returned: "+ UsbErrorCodes.getErrCode(result), EMsgType.FAIL);
|
print("GL Data transfer issue [write]\n Returned: "+ UsbErrorCodes.getErrCode(result), EMsgType.FAIL);
|
||||||
logPrinter.print("GL Execution stopped", EMsgType.FAIL);
|
print("GL Execution stopped", EMsgType.FAIL);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
logPrinter.print("GL Execution interrupted", EMsgType.INFO);
|
print("GL Execution interrupted", EMsgType.INFO);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
|
@ -382,12 +382,12 @@ public class GoldLeaf_05 extends TransferModule {
|
||||||
case LibUsb.ERROR_TIMEOUT:
|
case LibUsb.ERROR_TIMEOUT:
|
||||||
continue;
|
continue;
|
||||||
default:
|
default:
|
||||||
logPrinter.print("GL Data transfer issue [read]\n Returned: " + UsbErrorCodes.getErrCode(result), EMsgType.FAIL);
|
print("GL Data transfer issue [read]\n Returned: " + UsbErrorCodes.getErrCode(result), EMsgType.FAIL);
|
||||||
logPrinter.print("GL Execution stopped", EMsgType.FAIL);
|
print("GL Execution stopped", EMsgType.FAIL);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
logPrinter.print("GL Execution interrupted", EMsgType.INFO);
|
print("GL Execution interrupted", EMsgType.INFO);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -69,7 +69,11 @@ class GoldLeaf_07 extends TransferModule {
|
||||||
// For using in CMD_SelectFile with SPEC:/ prefix
|
// For using in CMD_SelectFile with SPEC:/ prefix
|
||||||
private File selectedFile;
|
private File selectedFile;
|
||||||
|
|
||||||
GoldLeaf_07(DeviceHandle handler, LinkedHashMap<String, File> nspMap, CancellableRunnable task, ILogPrinter logPrinter, boolean nspFilter){
|
GoldLeaf_07(DeviceHandle handler,
|
||||||
|
LinkedHashMap<String, File> nspMap,
|
||||||
|
CancellableRunnable task,
|
||||||
|
ILogPrinter logPrinter,
|
||||||
|
boolean nspFilter){
|
||||||
super(handler, nspMap, task, logPrinter);
|
super(handler, nspMap, task, logPrinter);
|
||||||
|
|
||||||
final byte CMD_GetDriveCount = 0x00;
|
final byte CMD_GetDriveCount = 0x00;
|
||||||
|
@ -93,7 +97,7 @@ class GoldLeaf_07 extends TransferModule {
|
||||||
|
|
||||||
this.nspFilterForGl = nspFilter;
|
this.nspFilterForGl = nspFilter;
|
||||||
|
|
||||||
logPrinter.print("============= GoldLeaf v0.7.x =============\n\t" +
|
print("============= GoldLeaf v0.7.x =============\n\t" +
|
||||||
"VIRT:/ equals files added into the application\n\t" +
|
"VIRT:/ equals files added into the application\n\t" +
|
||||||
"HOME:/ equals "
|
"HOME:/ equals "
|
||||||
+System.getProperty("user.home"), EMsgType.INFO);
|
+System.getProperty("user.home"), EMsgType.INFO);
|
||||||
|
@ -260,7 +264,7 @@ class GoldLeaf_07 extends TransferModule {
|
||||||
byte[] drivesCnt = intToArrLE(2); //2
|
byte[] drivesCnt = intToArrLE(2); //2
|
||||||
// Write count of drives
|
// Write count of drives
|
||||||
if (writeGL_PASS(drivesCnt)) {
|
if (writeGL_PASS(drivesCnt)) {
|
||||||
logPrinter.print("GL Handle 'ListDrives' command", EMsgType.FAIL);
|
print("GL Handle 'ListDrives' command", EMsgType.FAIL);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
@ -316,7 +320,7 @@ class GoldLeaf_07 extends TransferModule {
|
||||||
command.add(totalSize);
|
command.add(totalSize);
|
||||||
|
|
||||||
if (writeGL_PASS(command)) {
|
if (writeGL_PASS(command)) {
|
||||||
logPrinter.print("GL Handle 'GetDriveInfo' command", EMsgType.FAIL);
|
print("GL Handle 'GetDriveInfo' command", EMsgType.FAIL);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -332,7 +336,7 @@ class GoldLeaf_07 extends TransferModule {
|
||||||
byte[] specialPathCnt = intToArrLE(0);
|
byte[] specialPathCnt = intToArrLE(0);
|
||||||
// Write count of special paths
|
// Write count of special paths
|
||||||
if (writeGL_PASS(specialPathCnt)) {
|
if (writeGL_PASS(specialPathCnt)) {
|
||||||
logPrinter.print("GL Handle 'SpecialPathCount' command", EMsgType.FAIL);
|
print("GL Handle 'SpecialPathCount' command", EMsgType.FAIL);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
@ -354,13 +358,13 @@ class GoldLeaf_07 extends TransferModule {
|
||||||
if (path.equals("VIRT:/")) {
|
if (path.equals("VIRT:/")) {
|
||||||
if (isGetDirectoryCount){
|
if (isGetDirectoryCount){
|
||||||
if (writeGL_PASS()) {
|
if (writeGL_PASS()) {
|
||||||
logPrinter.print("GL Handle 'GetDirectoryCount' command", EMsgType.FAIL);
|
print("GL Handle 'GetDirectoryCount' command", EMsgType.FAIL);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (writeGL_PASS(intToArrLE(nspMap.size()))) {
|
if (writeGL_PASS(intToArrLE(nspMap.size()))) {
|
||||||
logPrinter.print("GL Handle 'GetFileCount' command Count = "+nspMap.size(), EMsgType.FAIL);
|
print("GL Handle 'GetFileCount' command Count = "+nspMap.size(), EMsgType.FAIL);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -401,7 +405,7 @@ class GoldLeaf_07 extends TransferModule {
|
||||||
// If somehow there are no folders, let's say 0;
|
// If somehow there are no folders, let's say 0;
|
||||||
if (filesOrDirs == null){
|
if (filesOrDirs == null){
|
||||||
if (writeGL_PASS()) {
|
if (writeGL_PASS()) {
|
||||||
logPrinter.print("GL Handle 'GetDirectoryOrFileCount' command", EMsgType.FAIL);
|
print("GL Handle 'GetDirectoryOrFileCount' command", EMsgType.FAIL);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
@ -415,20 +419,20 @@ class GoldLeaf_07 extends TransferModule {
|
||||||
this.recentFiles = filesOrDirs;
|
this.recentFiles = filesOrDirs;
|
||||||
// Otherwise, let's tell how may folders are in there
|
// Otherwise, let's tell how may folders are in there
|
||||||
if (writeGL_PASS(intToArrLE(filesOrDirs.length))) {
|
if (writeGL_PASS(intToArrLE(filesOrDirs.length))) {
|
||||||
logPrinter.print("GL Handle 'GetDirectoryOrFileCount' command", EMsgType.FAIL);
|
print("GL Handle 'GetDirectoryOrFileCount' command", EMsgType.FAIL);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (path.startsWith("SPEC:/")){
|
else if (path.startsWith("SPEC:/")){
|
||||||
if (isGetDirectoryCount){ // If dir request then 0 dirs
|
if (isGetDirectoryCount){ // If dir request then 0 dirs
|
||||||
if (writeGL_PASS()) {
|
if (writeGL_PASS()) {
|
||||||
logPrinter.print("GL Handle 'GetDirectoryCount' command", EMsgType.FAIL);
|
print("GL Handle 'GetDirectoryCount' command", EMsgType.FAIL);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (selectedFile != null){ // Else it's file request, if we have selected then we will report 1.
|
else if (selectedFile != null){ // Else it's file request, if we have selected then we will report 1.
|
||||||
if (writeGL_PASS(intToArrLE(1))) {
|
if (writeGL_PASS(intToArrLE(1))) {
|
||||||
logPrinter.print("GL Handle 'GetFileCount' command Count = 1", EMsgType.FAIL);
|
print("GL Handle 'GetFileCount' command Count = 1", EMsgType.FAIL);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -482,7 +486,7 @@ class GoldLeaf_07 extends TransferModule {
|
||||||
// return proxyGetDirFile(true);
|
// return proxyGetDirFile(true);
|
||||||
|
|
||||||
if (writeGL_PASS(command)) {
|
if (writeGL_PASS(command)) {
|
||||||
logPrinter.print("GL Handle 'GetDirectory' command.", EMsgType.FAIL);
|
print("GL Handle 'GetDirectory' command.", EMsgType.FAIL);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
@ -539,7 +543,7 @@ class GoldLeaf_07 extends TransferModule {
|
||||||
//if (proxyForGL) // TODO: NOTE: PROXY TAILS
|
//if (proxyForGL) // TODO: NOTE: PROXY TAILS
|
||||||
// return proxyGetDirFile(false);
|
// return proxyGetDirFile(false);
|
||||||
if (writeGL_PASS(command)) {
|
if (writeGL_PASS(command)) {
|
||||||
logPrinter.print("GL Handle 'GetFile' command.", EMsgType.FAIL);
|
print("GL Handle 'GetFile' command.", EMsgType.FAIL);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
@ -550,7 +554,7 @@ class GoldLeaf_07 extends TransferModule {
|
||||||
command.add(intToArrLE(fileNameBytes.length / 2)); // since GL 0.7
|
command.add(intToArrLE(fileNameBytes.length / 2)); // since GL 0.7
|
||||||
command.add(fileNameBytes);
|
command.add(fileNameBytes);
|
||||||
if (writeGL_PASS(command)) {
|
if (writeGL_PASS(command)) {
|
||||||
logPrinter.print("GL Handle 'GetFile' command.", EMsgType.FAIL);
|
print("GL Handle 'GetFile' command.", EMsgType.FAIL);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
@ -562,7 +566,7 @@ class GoldLeaf_07 extends TransferModule {
|
||||||
command.add(intToArrLE(fileNameBytes.length / 2)); // since GL 0.7
|
command.add(intToArrLE(fileNameBytes.length / 2)); // since GL 0.7
|
||||||
command.add(fileNameBytes);
|
command.add(fileNameBytes);
|
||||||
if (writeGL_PASS(command)) {
|
if (writeGL_PASS(command)) {
|
||||||
logPrinter.print("GL Handle 'GetFile' command.", EMsgType.FAIL);
|
print("GL Handle 'GetFile' command.", EMsgType.FAIL);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
@ -593,7 +597,7 @@ class GoldLeaf_07 extends TransferModule {
|
||||||
command.add(longToArrLE(fileDirElement.length()));
|
command.add(longToArrLE(fileDirElement.length()));
|
||||||
}
|
}
|
||||||
if (writeGL_PASS(command)) {
|
if (writeGL_PASS(command)) {
|
||||||
logPrinter.print("GL Handle 'StatPath' command.", EMsgType.FAIL);
|
print("GL Handle 'StatPath' command.", EMsgType.FAIL);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
@ -610,7 +614,7 @@ class GoldLeaf_07 extends TransferModule {
|
||||||
command.add(longToArrLE(nspMap.get(filePath).length())); // YES, THIS IS LONG!
|
command.add(longToArrLE(nspMap.get(filePath).length())); // YES, THIS IS LONG!
|
||||||
|
|
||||||
if (writeGL_PASS(command)) {
|
if (writeGL_PASS(command)) {
|
||||||
logPrinter.print("GL Handle 'StatPath' command.", EMsgType.FAIL);
|
print("GL Handle 'StatPath' command.", EMsgType.FAIL);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
@ -623,7 +627,7 @@ class GoldLeaf_07 extends TransferModule {
|
||||||
command.add(GL_OBJ_TYPE_FILE);
|
command.add(GL_OBJ_TYPE_FILE);
|
||||||
command.add(longToArrLE(selectedFile.length()));
|
command.add(longToArrLE(selectedFile.length()));
|
||||||
if (writeGL_PASS(command)) {
|
if (writeGL_PASS(command)) {
|
||||||
logPrinter.print("GL Handle 'StatPath' command.", EMsgType.FAIL);
|
print("GL Handle 'StatPath' command.", EMsgType.FAIL);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
@ -651,7 +655,7 @@ class GoldLeaf_07 extends TransferModule {
|
||||||
try {
|
try {
|
||||||
if (currentFile.renameTo(newFile)){
|
if (currentFile.renameTo(newFile)){
|
||||||
if (writeGL_PASS()) {
|
if (writeGL_PASS()) {
|
||||||
logPrinter.print("GL Handle 'Rename' command.", EMsgType.FAIL);
|
print("GL Handle 'Rename' command.", EMsgType.FAIL);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
@ -676,7 +680,7 @@ class GoldLeaf_07 extends TransferModule {
|
||||||
try {
|
try {
|
||||||
if (fileToDel.delete()){
|
if (fileToDel.delete()){
|
||||||
if (writeGL_PASS()) {
|
if (writeGL_PASS()) {
|
||||||
logPrinter.print("GL Handle 'Rename' command.", EMsgType.FAIL);
|
print("GL Handle 'Rename' command.", EMsgType.FAIL);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
@ -714,10 +718,10 @@ class GoldLeaf_07 extends TransferModule {
|
||||||
}
|
}
|
||||||
if (result){
|
if (result){
|
||||||
if (writeGL_PASS()) {
|
if (writeGL_PASS()) {
|
||||||
logPrinter.print("GL Handle 'Create' command.", EMsgType.FAIL);
|
print("GL Handle 'Create' command.", EMsgType.FAIL);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
//logPrinter.print("GL Handle 'Create' command.", EMsgType.PASS);
|
//print("GL Handle 'Create' command.", EMsgType.PASS);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -802,12 +806,12 @@ class GoldLeaf_07 extends TransferModule {
|
||||||
"\n Received: " + bytesRead);
|
"\n Received: " + bytesRead);
|
||||||
// Let's tell as a command about our result.
|
// Let's tell as a command about our result.
|
||||||
if (writeGL_PASS(longToArrLE(size))) {
|
if (writeGL_PASS(longToArrLE(size))) {
|
||||||
logPrinter.print("GL Handle 'ReadFile' command [CMD]", EMsgType.FAIL);
|
print("GL Handle 'ReadFile' command [CMD]", EMsgType.FAIL);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
// Let's bypass bytes we read total
|
// Let's bypass bytes we read total
|
||||||
if (writeToUsb(chunk)) {
|
if (writeToUsb(chunk)) {
|
||||||
logPrinter.print("GL Handle 'ReadFile' command", EMsgType.FAIL);
|
print("GL Handle 'ReadFile' command", EMsgType.FAIL);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
@ -822,12 +826,12 @@ class GoldLeaf_07 extends TransferModule {
|
||||||
return writeGL_FAIL("GL Handle 'ReadFile' command [CMD] Requested = "+size+" Read from file = "+bytesRead);
|
return writeGL_FAIL("GL Handle 'ReadFile' command [CMD] Requested = "+size+" Read from file = "+bytesRead);
|
||||||
// Let's tell as a command about our result.
|
// Let's tell as a command about our result.
|
||||||
if (writeGL_PASS(longToArrLE(size))) {
|
if (writeGL_PASS(longToArrLE(size))) {
|
||||||
logPrinter.print("GL Handle 'ReadFile' command [CMD]", EMsgType.FAIL);
|
print("GL Handle 'ReadFile' command [CMD]", EMsgType.FAIL);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
// Let's bypass bytes we read total
|
// Let's bypass bytes we read total
|
||||||
if (writeToUsb(chunk)) {
|
if (writeToUsb(chunk)) {
|
||||||
logPrinter.print("GL Handle 'ReadFile' command", EMsgType.FAIL);
|
print("GL Handle 'ReadFile' command", EMsgType.FAIL);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
@ -839,14 +843,14 @@ class GoldLeaf_07 extends TransferModule {
|
||||||
}
|
}
|
||||||
catch (NullPointerException ignored){}
|
catch (NullPointerException ignored){}
|
||||||
catch (IOException ioe_){
|
catch (IOException ioe_){
|
||||||
logPrinter.print("GL Handle 'ReadFile' command: unable to close: "+openReadFileNameAndPath+"\n\t"+ioe_.getMessage(), EMsgType.WARNING);
|
print("GL Handle 'ReadFile' command: unable to close: "+openReadFileNameAndPath+"\n\t"+ioe_.getMessage(), EMsgType.WARNING);
|
||||||
}
|
}
|
||||||
try{
|
try{
|
||||||
splitReader.close();
|
splitReader.close();
|
||||||
}
|
}
|
||||||
catch (NullPointerException ignored){}
|
catch (NullPointerException ignored){}
|
||||||
catch (IOException ioe_){
|
catch (IOException ioe_){
|
||||||
logPrinter.print("GL Handle 'ReadFile' command: unable to close: "+openReadFileNameAndPath+"\n\t"+ioe_.getMessage(), EMsgType.WARNING);
|
print("GL Handle 'ReadFile' command: unable to close: "+openReadFileNameAndPath+"\n\t"+ioe_.getMessage(), EMsgType.WARNING);
|
||||||
}
|
}
|
||||||
openReadFileNameAndPath = null;
|
openReadFileNameAndPath = null;
|
||||||
randAccessFile = null;
|
randAccessFile = null;
|
||||||
|
@ -888,7 +892,7 @@ class GoldLeaf_07 extends TransferModule {
|
||||||
byte[] transferredData;
|
byte[] transferredData;
|
||||||
|
|
||||||
if ((transferredData = readGL_file()) == null){
|
if ((transferredData = readGL_file()) == null){
|
||||||
logPrinter.print("GL Handle 'WriteFile' command [1/1]", EMsgType.FAIL);
|
print("GL Handle 'WriteFile' command [1/1]", EMsgType.FAIL);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
try{
|
try{
|
||||||
|
@ -899,7 +903,7 @@ class GoldLeaf_07 extends TransferModule {
|
||||||
}
|
}
|
||||||
// Report we're good
|
// Report we're good
|
||||||
if (writeGL_PASS()) {
|
if (writeGL_PASS()) {
|
||||||
logPrinter.print("GL Handle 'WriteFile' command", EMsgType.FAIL);
|
print("GL Handle 'WriteFile' command", EMsgType.FAIL);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
@ -926,7 +930,7 @@ class GoldLeaf_07 extends TransferModule {
|
||||||
command.add(intToArrLE(selectedFileNameBytes.length / 2)); // since GL 0.7
|
command.add(intToArrLE(selectedFileNameBytes.length / 2)); // since GL 0.7
|
||||||
command.add(selectedFileNameBytes);
|
command.add(selectedFileNameBytes);
|
||||||
if (writeGL_PASS(command)) {
|
if (writeGL_PASS(command)) {
|
||||||
logPrinter.print("GL Handle 'SelectFile' command", EMsgType.FAIL);
|
print("GL Handle 'SelectFile' command", EMsgType.FAIL);
|
||||||
this.selectedFile = null;
|
this.selectedFile = null;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -1006,13 +1010,13 @@ class GoldLeaf_07 extends TransferModule {
|
||||||
closeOpenedReadFilesGl(); // Could be a problem if GL glitches and slow down process. Or if user has extra-slow SD card. TODO: refactor
|
closeOpenedReadFilesGl(); // Could be a problem if GL glitches and slow down process. Or if user has extra-slow SD card. TODO: refactor
|
||||||
continue;
|
continue;
|
||||||
default:
|
default:
|
||||||
logPrinter.print("GL Data transfer issue [read]\n Returned: " +
|
print("GL Data transfer issue [read]\n Returned: " +
|
||||||
UsbErrorCodes.getErrCode(result) +
|
UsbErrorCodes.getErrCode(result) +
|
||||||
"\n GL Execution stopped", EMsgType.FAIL);
|
"\n GL Execution stopped", EMsgType.FAIL);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
logPrinter.print("GL Execution interrupted", EMsgType.INFO);
|
print("GL Execution interrupted", EMsgType.INFO);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
private byte[] readGL_file(){
|
private byte[] readGL_file(){
|
||||||
|
@ -1035,13 +1039,13 @@ class GoldLeaf_07 extends TransferModule {
|
||||||
case LibUsb.ERROR_TIMEOUT:
|
case LibUsb.ERROR_TIMEOUT:
|
||||||
continue;
|
continue;
|
||||||
default:
|
default:
|
||||||
logPrinter.print("GL Data transfer issue [read]\n Returned: " +
|
print("GL Data transfer issue [read]\n Returned: " +
|
||||||
UsbErrorCodes.getErrCode(result) +
|
UsbErrorCodes.getErrCode(result) +
|
||||||
"\n GL Execution stopped", EMsgType.FAIL);
|
"\n GL Execution stopped", EMsgType.FAIL);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
logPrinter.print("GL Execution interrupted", EMsgType.INFO);
|
print("GL Execution interrupted", EMsgType.INFO);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
|
@ -1066,10 +1070,10 @@ class GoldLeaf_07 extends TransferModule {
|
||||||
|
|
||||||
private boolean writeGL_FAIL(String reportToUImsg){
|
private boolean writeGL_FAIL(String reportToUImsg){
|
||||||
if (writeToUsb(Arrays.copyOf(CMD_GLCO_FAILURE, 4096))){
|
if (writeToUsb(Arrays.copyOf(CMD_GLCO_FAILURE, 4096))){
|
||||||
logPrinter.print(reportToUImsg, EMsgType.WARNING);
|
print(reportToUImsg, EMsgType.WARNING);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
logPrinter.print(reportToUImsg, EMsgType.FAIL);
|
print(reportToUImsg, EMsgType.FAIL);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
|
@ -1091,7 +1095,7 @@ class GoldLeaf_07 extends TransferModule {
|
||||||
if (writeBufTransferred.get() == message.length)
|
if (writeBufTransferred.get() == message.length)
|
||||||
return false;
|
return false;
|
||||||
else {
|
else {
|
||||||
logPrinter.print("GL Data transfer issue [write]\n Requested: " +
|
print("GL Data transfer issue [write]\n Requested: " +
|
||||||
message.length +
|
message.length +
|
||||||
"\n Transferred: " +
|
"\n Transferred: " +
|
||||||
writeBufTransferred.get(), EMsgType.FAIL);
|
writeBufTransferred.get(), EMsgType.FAIL);
|
||||||
|
@ -1100,13 +1104,13 @@ class GoldLeaf_07 extends TransferModule {
|
||||||
case LibUsb.ERROR_TIMEOUT:
|
case LibUsb.ERROR_TIMEOUT:
|
||||||
continue;
|
continue;
|
||||||
default:
|
default:
|
||||||
logPrinter.print("GL Data transfer issue [write]\n Returned: " +
|
print("GL Data transfer issue [write]\n Returned: " +
|
||||||
UsbErrorCodes.getErrCode(result) +
|
UsbErrorCodes.getErrCode(result) +
|
||||||
"\n GL Execution stopped", EMsgType.FAIL);
|
"\n GL Execution stopped", EMsgType.FAIL);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
logPrinter.print("GL Execution interrupted", EMsgType.INFO);
|
print("GL Execution interrupted", EMsgType.INFO);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -103,7 +103,7 @@ class GoldLeaf_08 extends TransferModule {
|
||||||
|
|
||||||
this.nspFilterForGl = nspFilter;
|
this.nspFilterForGl = nspFilter;
|
||||||
|
|
||||||
logPrinter.print("============= GoldLeaf v0.8 =============\n\t" +
|
print("============= GoldLeaf v0.8 =============\n\t" +
|
||||||
"VIRT:/ equals files added into the application\n\t" +
|
"VIRT:/ equals files added into the application\n\t" +
|
||||||
"HOME:/ equals "
|
"HOME:/ equals "
|
||||||
+System.getProperty("user.home"), EMsgType.INFO);
|
+System.getProperty("user.home"), EMsgType.INFO);
|
||||||
|
@ -273,7 +273,7 @@ class GoldLeaf_08 extends TransferModule {
|
||||||
* */
|
* */
|
||||||
private boolean startOrEndFile(){
|
private boolean startOrEndFile(){
|
||||||
if (writeGL_PASS()){
|
if (writeGL_PASS()){
|
||||||
logPrinter.print("GL Handle 'StartFile' command", EMsgType.FAIL);
|
print("GL Handle 'StartFile' command", EMsgType.FAIL);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
@ -288,7 +288,7 @@ class GoldLeaf_08 extends TransferModule {
|
||||||
byte[] drivesCnt = intToArrLE(2); //2
|
byte[] drivesCnt = intToArrLE(2); //2
|
||||||
// Write count of drives
|
// Write count of drives
|
||||||
if (writeGL_PASS(drivesCnt)) {
|
if (writeGL_PASS(drivesCnt)) {
|
||||||
logPrinter.print("GL Handle 'ListDrives' command", EMsgType.FAIL);
|
print("GL Handle 'ListDrives' command", EMsgType.FAIL);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
@ -344,7 +344,7 @@ class GoldLeaf_08 extends TransferModule {
|
||||||
command.add(totalSize);
|
command.add(totalSize);
|
||||||
|
|
||||||
if (writeGL_PASS(command)) {
|
if (writeGL_PASS(command)) {
|
||||||
logPrinter.print("GL Handle 'GetDriveInfo' command", EMsgType.FAIL);
|
print("GL Handle 'GetDriveInfo' command", EMsgType.FAIL);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -360,7 +360,7 @@ class GoldLeaf_08 extends TransferModule {
|
||||||
byte[] specialPathCnt = intToArrLE(0);
|
byte[] specialPathCnt = intToArrLE(0);
|
||||||
// Write count of special paths
|
// Write count of special paths
|
||||||
if (writeGL_PASS(specialPathCnt)) {
|
if (writeGL_PASS(specialPathCnt)) {
|
||||||
logPrinter.print("GL Handle 'SpecialPathCount' command", EMsgType.FAIL);
|
print("GL Handle 'SpecialPathCount' command", EMsgType.FAIL);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
@ -382,13 +382,13 @@ class GoldLeaf_08 extends TransferModule {
|
||||||
if (path.equals("VIRT:/")) {
|
if (path.equals("VIRT:/")) {
|
||||||
if (isGetDirectoryCount){
|
if (isGetDirectoryCount){
|
||||||
if (writeGL_PASS()) {
|
if (writeGL_PASS()) {
|
||||||
logPrinter.print("GL Handle 'GetDirectoryCount' command", EMsgType.FAIL);
|
print("GL Handle 'GetDirectoryCount' command", EMsgType.FAIL);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (writeGL_PASS(intToArrLE(nspMap.size()))) {
|
if (writeGL_PASS(intToArrLE(nspMap.size()))) {
|
||||||
logPrinter.print("GL Handle 'GetFileCount' command Count = "+nspMap.size(), EMsgType.FAIL);
|
print("GL Handle 'GetFileCount' command Count = "+nspMap.size(), EMsgType.FAIL);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -429,7 +429,7 @@ class GoldLeaf_08 extends TransferModule {
|
||||||
// If somehow there are no folders, let's say 0;
|
// If somehow there are no folders, let's say 0;
|
||||||
if (filesOrDirs == null){
|
if (filesOrDirs == null){
|
||||||
if (writeGL_PASS()) {
|
if (writeGL_PASS()) {
|
||||||
logPrinter.print("GL Handle 'GetDirectoryOrFileCount' command", EMsgType.FAIL);
|
print("GL Handle 'GetDirectoryOrFileCount' command", EMsgType.FAIL);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
@ -443,20 +443,20 @@ class GoldLeaf_08 extends TransferModule {
|
||||||
this.recentFiles = filesOrDirs;
|
this.recentFiles = filesOrDirs;
|
||||||
// Otherwise, let's tell how may folders are in there
|
// Otherwise, let's tell how may folders are in there
|
||||||
if (writeGL_PASS(intToArrLE(filesOrDirs.length))) {
|
if (writeGL_PASS(intToArrLE(filesOrDirs.length))) {
|
||||||
logPrinter.print("GL Handle 'GetDirectoryOrFileCount' command", EMsgType.FAIL);
|
print("GL Handle 'GetDirectoryOrFileCount' command", EMsgType.FAIL);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (path.startsWith("SPEC:/")){
|
else if (path.startsWith("SPEC:/")){
|
||||||
if (isGetDirectoryCount){ // If dir request then 0 dirs
|
if (isGetDirectoryCount){ // If dir request then 0 dirs
|
||||||
if (writeGL_PASS()) {
|
if (writeGL_PASS()) {
|
||||||
logPrinter.print("GL Handle 'GetDirectoryCount' command", EMsgType.FAIL);
|
print("GL Handle 'GetDirectoryCount' command", EMsgType.FAIL);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (selectedFile != null){ // Else it's file request, if we have selected then we will report 1.
|
else if (selectedFile != null){ // Else it's file request, if we have selected then we will report 1.
|
||||||
if (writeGL_PASS(intToArrLE(1))) {
|
if (writeGL_PASS(intToArrLE(1))) {
|
||||||
logPrinter.print("GL Handle 'GetFileCount' command Count = 1", EMsgType.FAIL);
|
print("GL Handle 'GetFileCount' command Count = 1", EMsgType.FAIL);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -510,7 +510,7 @@ class GoldLeaf_08 extends TransferModule {
|
||||||
// return proxyGetDirFile(true);
|
// return proxyGetDirFile(true);
|
||||||
|
|
||||||
if (writeGL_PASS(command)) {
|
if (writeGL_PASS(command)) {
|
||||||
logPrinter.print("GL Handle 'GetDirectory' command.", EMsgType.FAIL);
|
print("GL Handle 'GetDirectory' command.", EMsgType.FAIL);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
@ -567,7 +567,7 @@ class GoldLeaf_08 extends TransferModule {
|
||||||
//if (proxyForGL) // TODO: NOTE: PROXY TAILS
|
//if (proxyForGL) // TODO: NOTE: PROXY TAILS
|
||||||
// return proxyGetDirFile(false);
|
// return proxyGetDirFile(false);
|
||||||
if (writeGL_PASS(command)) {
|
if (writeGL_PASS(command)) {
|
||||||
logPrinter.print("GL Handle 'GetFile' command.", EMsgType.FAIL);
|
print("GL Handle 'GetFile' command.", EMsgType.FAIL);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
@ -578,7 +578,7 @@ class GoldLeaf_08 extends TransferModule {
|
||||||
command.add(intToArrLE(fileNameBytes.length / 2)); // since GL 0.7
|
command.add(intToArrLE(fileNameBytes.length / 2)); // since GL 0.7
|
||||||
command.add(fileNameBytes);
|
command.add(fileNameBytes);
|
||||||
if (writeGL_PASS(command)) {
|
if (writeGL_PASS(command)) {
|
||||||
logPrinter.print("GL Handle 'GetFile' command.", EMsgType.FAIL);
|
print("GL Handle 'GetFile' command.", EMsgType.FAIL);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
@ -590,7 +590,7 @@ class GoldLeaf_08 extends TransferModule {
|
||||||
command.add(intToArrLE(fileNameBytes.length / 2)); // since GL 0.7
|
command.add(intToArrLE(fileNameBytes.length / 2)); // since GL 0.7
|
||||||
command.add(fileNameBytes);
|
command.add(fileNameBytes);
|
||||||
if (writeGL_PASS(command)) {
|
if (writeGL_PASS(command)) {
|
||||||
logPrinter.print("GL Handle 'GetFile' command.", EMsgType.FAIL);
|
print("GL Handle 'GetFile' command.", EMsgType.FAIL);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
@ -621,7 +621,7 @@ class GoldLeaf_08 extends TransferModule {
|
||||||
command.add(longToArrLE(fileDirElement.length()));
|
command.add(longToArrLE(fileDirElement.length()));
|
||||||
}
|
}
|
||||||
if (writeGL_PASS(command)) {
|
if (writeGL_PASS(command)) {
|
||||||
logPrinter.print("GL Handle 'StatPath' command.", EMsgType.FAIL);
|
print("GL Handle 'StatPath' command.", EMsgType.FAIL);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
@ -638,7 +638,7 @@ class GoldLeaf_08 extends TransferModule {
|
||||||
command.add(longToArrLE(nspMap.get(filePath).length())); // YES, THIS IS LONG!
|
command.add(longToArrLE(nspMap.get(filePath).length())); // YES, THIS IS LONG!
|
||||||
|
|
||||||
if (writeGL_PASS(command)) {
|
if (writeGL_PASS(command)) {
|
||||||
logPrinter.print("GL Handle 'StatPath' command.", EMsgType.FAIL);
|
print("GL Handle 'StatPath' command.", EMsgType.FAIL);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
@ -651,7 +651,7 @@ class GoldLeaf_08 extends TransferModule {
|
||||||
command.add(GL_OBJ_TYPE_FILE);
|
command.add(GL_OBJ_TYPE_FILE);
|
||||||
command.add(longToArrLE(selectedFile.length()));
|
command.add(longToArrLE(selectedFile.length()));
|
||||||
if (writeGL_PASS(command)) {
|
if (writeGL_PASS(command)) {
|
||||||
logPrinter.print("GL Handle 'StatPath' command.", EMsgType.FAIL);
|
print("GL Handle 'StatPath' command.", EMsgType.FAIL);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
@ -679,7 +679,7 @@ class GoldLeaf_08 extends TransferModule {
|
||||||
try {
|
try {
|
||||||
if (currentFile.renameTo(newFile)){
|
if (currentFile.renameTo(newFile)){
|
||||||
if (writeGL_PASS()) {
|
if (writeGL_PASS()) {
|
||||||
logPrinter.print("GL Handle 'Rename' command.", EMsgType.FAIL);
|
print("GL Handle 'Rename' command.", EMsgType.FAIL);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
@ -704,7 +704,7 @@ class GoldLeaf_08 extends TransferModule {
|
||||||
try {
|
try {
|
||||||
if (fileToDel.delete()){
|
if (fileToDel.delete()){
|
||||||
if (writeGL_PASS()) {
|
if (writeGL_PASS()) {
|
||||||
logPrinter.print("GL Handle 'Rename' command.", EMsgType.FAIL);
|
print("GL Handle 'Rename' command.", EMsgType.FAIL);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
@ -742,10 +742,10 @@ class GoldLeaf_08 extends TransferModule {
|
||||||
}
|
}
|
||||||
if (result){
|
if (result){
|
||||||
if (writeGL_PASS()) {
|
if (writeGL_PASS()) {
|
||||||
logPrinter.print("GL Handle 'Create' command.", EMsgType.FAIL);
|
print("GL Handle 'Create' command.", EMsgType.FAIL);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
//logPrinter.print("GL Handle 'Create' command.", EMsgType.PASS);
|
//print("GL Handle 'Create' command.", EMsgType.PASS);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -830,12 +830,12 @@ class GoldLeaf_08 extends TransferModule {
|
||||||
"\n Received: " + bytesRead);
|
"\n Received: " + bytesRead);
|
||||||
// Let's tell as a command about our result.
|
// Let's tell as a command about our result.
|
||||||
if (writeGL_PASS(longToArrLE(size))) {
|
if (writeGL_PASS(longToArrLE(size))) {
|
||||||
logPrinter.print("GL Handle 'ReadFile' command [CMD]", EMsgType.FAIL);
|
print("GL Handle 'ReadFile' command [CMD]", EMsgType.FAIL);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
// Let's bypass bytes we read total
|
// Let's bypass bytes we read total
|
||||||
if (writeToUsb(chunk)) {
|
if (writeToUsb(chunk)) {
|
||||||
logPrinter.print("GL Handle 'ReadFile' command", EMsgType.FAIL);
|
print("GL Handle 'ReadFile' command", EMsgType.FAIL);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
@ -850,12 +850,12 @@ class GoldLeaf_08 extends TransferModule {
|
||||||
return writeGL_FAIL("GL Handle 'ReadFile' command [CMD] Requested = "+size+" Read from file = "+bytesRead);
|
return writeGL_FAIL("GL Handle 'ReadFile' command [CMD] Requested = "+size+" Read from file = "+bytesRead);
|
||||||
// Let's tell as a command about our result.
|
// Let's tell as a command about our result.
|
||||||
if (writeGL_PASS(longToArrLE(size))) {
|
if (writeGL_PASS(longToArrLE(size))) {
|
||||||
logPrinter.print("GL Handle 'ReadFile' command [CMD]", EMsgType.FAIL);
|
print("GL Handle 'ReadFile' command [CMD]", EMsgType.FAIL);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
// Let's bypass bytes we read total
|
// Let's bypass bytes we read total
|
||||||
if (writeToUsb(chunk)) {
|
if (writeToUsb(chunk)) {
|
||||||
logPrinter.print("GL Handle 'ReadFile' command", EMsgType.FAIL);
|
print("GL Handle 'ReadFile' command", EMsgType.FAIL);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
@ -867,14 +867,14 @@ class GoldLeaf_08 extends TransferModule {
|
||||||
}
|
}
|
||||||
catch (NullPointerException ignored){}
|
catch (NullPointerException ignored){}
|
||||||
catch (IOException ioe_){
|
catch (IOException ioe_){
|
||||||
logPrinter.print("GL Handle 'ReadFile' command: unable to close: "+openReadFileNameAndPath+"\n\t"+ioe_.getMessage(), EMsgType.WARNING);
|
print("GL Handle 'ReadFile' command: unable to close: "+openReadFileNameAndPath+"\n\t"+ioe_.getMessage(), EMsgType.WARNING);
|
||||||
}
|
}
|
||||||
try{
|
try{
|
||||||
splitReader.close();
|
splitReader.close();
|
||||||
}
|
}
|
||||||
catch (NullPointerException ignored){}
|
catch (NullPointerException ignored){}
|
||||||
catch (IOException ioe_){
|
catch (IOException ioe_){
|
||||||
logPrinter.print("GL Handle 'ReadFile' command: unable to close: "+openReadFileNameAndPath+"\n\t"+ioe_.getMessage(), EMsgType.WARNING);
|
print("GL Handle 'ReadFile' command: unable to close: "+openReadFileNameAndPath+"\n\t"+ioe_.getMessage(), EMsgType.WARNING);
|
||||||
}
|
}
|
||||||
openReadFileNameAndPath = null;
|
openReadFileNameAndPath = null;
|
||||||
randAccessFile = null;
|
randAccessFile = null;
|
||||||
|
@ -916,7 +916,7 @@ class GoldLeaf_08 extends TransferModule {
|
||||||
byte[] transferredData;
|
byte[] transferredData;
|
||||||
|
|
||||||
if ((transferredData = readGL_file()) == null){
|
if ((transferredData = readGL_file()) == null){
|
||||||
logPrinter.print("GL Handle 'WriteFile' command [1/1]", EMsgType.FAIL);
|
print("GL Handle 'WriteFile' command [1/1]", EMsgType.FAIL);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
try{
|
try{
|
||||||
|
@ -927,7 +927,7 @@ class GoldLeaf_08 extends TransferModule {
|
||||||
}
|
}
|
||||||
// Report we're good
|
// Report we're good
|
||||||
if (writeGL_PASS()) {
|
if (writeGL_PASS()) {
|
||||||
logPrinter.print("GL Handle 'WriteFile' command", EMsgType.FAIL);
|
print("GL Handle 'WriteFile' command", EMsgType.FAIL);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
@ -957,7 +957,7 @@ class GoldLeaf_08 extends TransferModule {
|
||||||
command.add(intToArrLE(selectedFileNameBytes.length / 2)); // since GL 0.7
|
command.add(intToArrLE(selectedFileNameBytes.length / 2)); // since GL 0.7
|
||||||
command.add(selectedFileNameBytes);
|
command.add(selectedFileNameBytes);
|
||||||
if (writeGL_PASS(command)) {
|
if (writeGL_PASS(command)) {
|
||||||
logPrinter.print("GL Handle 'SelectFile' command", EMsgType.FAIL);
|
print("GL Handle 'SelectFile' command", EMsgType.FAIL);
|
||||||
this.selectedFile = null;
|
this.selectedFile = null;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -1033,13 +1033,13 @@ class GoldLeaf_08 extends TransferModule {
|
||||||
closeOpenedReadFilesGl(); // Could be a problem if GL glitches and slow down process. Or if user has extra-slow SD card. TODO: refactor
|
closeOpenedReadFilesGl(); // Could be a problem if GL glitches and slow down process. Or if user has extra-slow SD card. TODO: refactor
|
||||||
continue;
|
continue;
|
||||||
default:
|
default:
|
||||||
logPrinter.print("GL Data transfer issue [read]\n Returned: " +
|
print("GL Data transfer issue [read]\n Returned: " +
|
||||||
UsbErrorCodes.getErrCode(result) +
|
UsbErrorCodes.getErrCode(result) +
|
||||||
"\n GL Execution stopped", EMsgType.FAIL);
|
"\n GL Execution stopped", EMsgType.FAIL);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
logPrinter.print("GL Execution interrupted", EMsgType.INFO);
|
print("GL Execution interrupted", EMsgType.INFO);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
private byte[] readGL_file(){
|
private byte[] readGL_file(){
|
||||||
|
@ -1060,13 +1060,13 @@ class GoldLeaf_08 extends TransferModule {
|
||||||
case LibUsb.ERROR_TIMEOUT:
|
case LibUsb.ERROR_TIMEOUT:
|
||||||
continue;
|
continue;
|
||||||
default:
|
default:
|
||||||
logPrinter.print("GL Data transfer issue [read]\n Returned: " +
|
print("GL Data transfer issue [read]\n Returned: " +
|
||||||
UsbErrorCodes.getErrCode(result) +
|
UsbErrorCodes.getErrCode(result) +
|
||||||
"\n GL Execution stopped", EMsgType.FAIL);
|
"\n GL Execution stopped", EMsgType.FAIL);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
logPrinter.print("GL Execution interrupted", EMsgType.INFO);
|
print("GL Execution interrupted", EMsgType.INFO);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
|
@ -1091,10 +1091,10 @@ class GoldLeaf_08 extends TransferModule {
|
||||||
|
|
||||||
private boolean writeGL_FAIL(String reportToUImsg){
|
private boolean writeGL_FAIL(String reportToUImsg){
|
||||||
if (writeToUsb(Arrays.copyOf(CMD_GLCO_FAILURE, 4096))){
|
if (writeToUsb(Arrays.copyOf(CMD_GLCO_FAILURE, 4096))){
|
||||||
logPrinter.print(reportToUImsg, EMsgType.WARNING);
|
print(reportToUImsg, EMsgType.WARNING);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
logPrinter.print(reportToUImsg, EMsgType.FAIL);
|
print(reportToUImsg, EMsgType.FAIL);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
|
@ -1116,7 +1116,7 @@ class GoldLeaf_08 extends TransferModule {
|
||||||
if (writeBufTransferred.get() == message.length)
|
if (writeBufTransferred.get() == message.length)
|
||||||
return false;
|
return false;
|
||||||
else {
|
else {
|
||||||
logPrinter.print("GL Data transfer issue [write]\n Requested: " +
|
print("GL Data transfer issue [write]\n Requested: " +
|
||||||
message.length +
|
message.length +
|
||||||
"\n Transferred: "+writeBufTransferred.get(), EMsgType.FAIL);
|
"\n Transferred: "+writeBufTransferred.get(), EMsgType.FAIL);
|
||||||
return true;
|
return true;
|
||||||
|
@ -1124,13 +1124,13 @@ class GoldLeaf_08 extends TransferModule {
|
||||||
case LibUsb.ERROR_TIMEOUT:
|
case LibUsb.ERROR_TIMEOUT:
|
||||||
continue;
|
continue;
|
||||||
default:
|
default:
|
||||||
logPrinter.print("GL Data transfer issue [write]\n Returned: " +
|
print("GL Data transfer issue [write]\n Returned: " +
|
||||||
UsbErrorCodes.getErrCode(result) +
|
UsbErrorCodes.getErrCode(result) +
|
||||||
"\n GL Execution stopped", EMsgType.FAIL);
|
"\n GL Execution stopped", EMsgType.FAIL);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
logPrinter.print("GL Execution interrupted", EMsgType.INFO);
|
print("GL Execution interrupted", EMsgType.INFO);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -50,7 +50,7 @@ class TinFoil extends TransferModule {
|
||||||
|
|
||||||
TinFoil(DeviceHandle handler, LinkedHashMap<String, File> nspMap, CancellableRunnable task, ILogPrinter logPrinter){
|
TinFoil(DeviceHandle handler, LinkedHashMap<String, File> nspMap, CancellableRunnable task, ILogPrinter logPrinter){
|
||||||
super(handler, nspMap, task, logPrinter);
|
super(handler, nspMap, task, logPrinter);
|
||||||
logPrinter.print("============= Tinfoil =============", EMsgType.INFO);
|
print("============= Tinfoil =============", EMsgType.INFO);
|
||||||
|
|
||||||
if (! sendListOfFiles())
|
if (! sendListOfFiles())
|
||||||
return;
|
return;
|
||||||
|
@ -69,25 +69,25 @@ class TinFoil extends TransferModule {
|
||||||
byte[] padding = new byte[8];
|
byte[] padding = new byte[8];
|
||||||
|
|
||||||
if (writeUsb(TUL0)) {
|
if (writeUsb(TUL0)) {
|
||||||
logPrinter.print("TF Send list of files: handshake [1/4]", EMsgType.FAIL);
|
print("TF Send list of files: handshake [1/4]", EMsgType.FAIL);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (writeUsb(nspListNamesSize)) { // size of the list we can transfer
|
if (writeUsb(nspListNamesSize)) { // size of the list we can transfer
|
||||||
logPrinter.print("TF Send list of files: list length [2/4]", EMsgType.FAIL);
|
print("TF Send list of files: list length [2/4]", EMsgType.FAIL);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (writeUsb(padding)) {
|
if (writeUsb(padding)) {
|
||||||
logPrinter.print("TF Send list of files: padding [3/4]", EMsgType.FAIL);
|
print("TF Send list of files: padding [3/4]", EMsgType.FAIL);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (writeUsb(nspListNames)) {
|
if (writeUsb(nspListNames)) {
|
||||||
logPrinter.print("TF Send list of files: list itself [4/4]", EMsgType.FAIL);
|
print("TF Send list of files: list itself [4/4]", EMsgType.FAIL);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
logPrinter.print("TF Send list of files complete.", EMsgType.PASS);
|
print("TF Send list of files complete.", EMsgType.PASS);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -114,7 +114,7 @@ class TinFoil extends TransferModule {
|
||||||
* After we sent commands to NS, this chain starts
|
* After we sent commands to NS, this chain starts
|
||||||
* */
|
* */
|
||||||
private boolean proceedCommands(){
|
private boolean proceedCommands(){
|
||||||
logPrinter.print("TF Awaiting for NS commands.", EMsgType.INFO);
|
print("TF Awaiting for NS commands.", EMsgType.INFO);
|
||||||
try{
|
try{
|
||||||
byte[] deviceReply;
|
byte[] deviceReply;
|
||||||
byte command;
|
byte command;
|
||||||
|
@ -127,18 +127,18 @@ class TinFoil extends TransferModule {
|
||||||
|
|
||||||
switch (command){
|
switch (command){
|
||||||
case CMD_EXIT:
|
case CMD_EXIT:
|
||||||
logPrinter.print("TF Transfer complete.", EMsgType.PASS);
|
print("TF Transfer complete.", EMsgType.PASS);
|
||||||
return true;
|
return true;
|
||||||
case CMD_FILE_RANGE_DEFAULT:
|
case CMD_FILE_RANGE_DEFAULT:
|
||||||
case CMD_FILE_RANGE_ALTERNATIVE:
|
case CMD_FILE_RANGE_ALTERNATIVE:
|
||||||
//logPrinter.print("TF Received 'FILE RANGE' command [0x0"+command+"].", EMsgType.PASS);
|
//print("TF Received 'FILE RANGE' command [0x0"+command+"].", EMsgType.PASS);
|
||||||
if (fileRangeCmd())
|
if (fileRangeCmd())
|
||||||
return false; // catches exception
|
return false; // catches exception
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception e){
|
catch (Exception e){
|
||||||
logPrinter.print(e.getMessage(), EMsgType.INFO);
|
print(e.getMessage(), EMsgType.INFO);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -169,7 +169,7 @@ class TinFoil extends TransferModule {
|
||||||
|
|
||||||
String nspFileName = new String(receivedArray, StandardCharsets.UTF_8);
|
String nspFileName = new String(receivedArray, StandardCharsets.UTF_8);
|
||||||
|
|
||||||
logPrinter.print(String.format("TF Reply to: %s" +
|
print(String.format("TF Reply to: %s" +
|
||||||
"\n Offset: %-20d 0x%x" +
|
"\n Offset: %-20d 0x%x" +
|
||||||
"\n Size: %-20d 0x%x",
|
"\n Size: %-20d 0x%x",
|
||||||
nspFileName,
|
nspFileName,
|
||||||
|
@ -188,28 +188,28 @@ class TinFoil extends TransferModule {
|
||||||
else
|
else
|
||||||
sendNormalFile(nspFile, size, offset);
|
sendNormalFile(nspFile, size, offset);
|
||||||
} catch (IOException ioe){
|
} catch (IOException ioe){
|
||||||
logPrinter.print("TF IOException:\n "+ioe.getMessage(), EMsgType.FAIL);
|
print("TF IOException:\n "+ioe.getMessage(), EMsgType.FAIL);
|
||||||
ioe.printStackTrace();
|
ioe.printStackTrace();
|
||||||
return true;
|
return true;
|
||||||
} catch (ArithmeticException ae){
|
} catch (ArithmeticException ae){
|
||||||
logPrinter.print("TF ArithmeticException (can't cast 'offset end' - 'offsets current' to 'integer'):" +
|
print("TF ArithmeticException (can't cast 'offset end' - 'offsets current' to 'integer'):" +
|
||||||
"\n "+ae.getMessage(), EMsgType.FAIL);
|
"\n "+ae.getMessage(), EMsgType.FAIL);
|
||||||
ae.printStackTrace();
|
ae.printStackTrace();
|
||||||
return true;
|
return true;
|
||||||
} catch (NullPointerException npe){
|
} catch (NullPointerException npe){
|
||||||
logPrinter.print("TF NullPointerException (in some moment application didn't find something. Something important.):" +
|
print("TF NullPointerException (in some moment application didn't find something. Something important.):" +
|
||||||
"\n "+npe.getMessage(), EMsgType.FAIL);
|
"\n "+npe.getMessage(), EMsgType.FAIL);
|
||||||
npe.printStackTrace();
|
npe.printStackTrace();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
catch (Exception defe){
|
catch (Exception defe){
|
||||||
logPrinter.print(defe.getMessage(), EMsgType.FAIL);
|
print(defe.getMessage(), EMsgType.FAIL);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void sendSplitFile(File nspFile, long size, long offset) throws IOException, NullPointerException, ArithmeticException {
|
void sendSplitFile(File nspFile, long size, long offset) throws Exception {
|
||||||
byte[] readBuffer;
|
byte[] readBuffer;
|
||||||
long currentOffset = 0;
|
long currentOffset = 0;
|
||||||
int chunk = 8388608; // = 8Mb;
|
int chunk = 8388608; // = 8Mb;
|
||||||
|
@ -237,7 +237,7 @@ class TinFoil extends TransferModule {
|
||||||
logPrinter.updateProgress(1.0);
|
logPrinter.updateProgress(1.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void sendNormalFile(File nspFile, long size, long offset) throws IOException, NullPointerException, ArithmeticException {
|
void sendNormalFile(File nspFile, long size, long offset) throws Exception {
|
||||||
byte[] readBuffer;
|
byte[] readBuffer;
|
||||||
long currentOffset = 0;
|
long currentOffset = 0;
|
||||||
int chunk = 8388608;
|
int chunk = 8388608;
|
||||||
|
@ -278,17 +278,17 @@ class TinFoil extends TransferModule {
|
||||||
final byte[] twelveZeroBytes = new byte[12];
|
final byte[] twelveZeroBytes = new byte[12];
|
||||||
|
|
||||||
if (writeUsb(standardReplyBytes)){ // Send integer value of '1' in Little-endian format.
|
if (writeUsb(standardReplyBytes)){ // Send integer value of '1' in Little-endian format.
|
||||||
logPrinter.print("TF Sending response failed [1/3]", EMsgType.FAIL);
|
print("TF Sending response failed [1/3]", EMsgType.FAIL);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(writeUsb(sizeAsBytes)) { // Send EXACTLY what has been received
|
if(writeUsb(sizeAsBytes)) { // Send EXACTLY what has been received
|
||||||
logPrinter.print("TF Sending response failed [2/3]", EMsgType.FAIL);
|
print("TF Sending response failed [2/3]", EMsgType.FAIL);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(writeUsb(twelveZeroBytes)) { // kinda another one padding
|
if(writeUsb(twelveZeroBytes)) { // kinda another one padding
|
||||||
logPrinter.print("TF Sending response failed [3/3]", EMsgType.FAIL);
|
print("TF Sending response failed [3/3]", EMsgType.FAIL);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
@ -308,7 +308,7 @@ class TinFoil extends TransferModule {
|
||||||
while (! task.isCancelled() ) {
|
while (! task.isCancelled() ) {
|
||||||
/*
|
/*
|
||||||
if (varVar != 0)
|
if (varVar != 0)
|
||||||
logPrinter.print("writeUsb() retry cnt: "+varVar, EMsgType.INFO); //NOTE: DEBUG
|
print("writeUsb() retry cnt: "+varVar, EMsgType.INFO); //NOTE: DEBUG
|
||||||
varVar++;
|
varVar++;
|
||||||
*/
|
*/
|
||||||
result = LibUsb.bulkTransfer(handlerNS, (byte) 0x01, writeBuffer, writeBufTransferred, 5050); // last one is TIMEOUT. 0 stands for unlimited. Endpoint OUT = 0x01
|
result = LibUsb.bulkTransfer(handlerNS, (byte) 0x01, writeBuffer, writeBufTransferred, 5050); // last one is TIMEOUT. 0 stands for unlimited. Endpoint OUT = 0x01
|
||||||
|
@ -317,7 +317,7 @@ class TinFoil extends TransferModule {
|
||||||
case LibUsb.SUCCESS:
|
case LibUsb.SUCCESS:
|
||||||
if (writeBufTransferred.get() == message.length)
|
if (writeBufTransferred.get() == message.length)
|
||||||
return false;
|
return false;
|
||||||
logPrinter.print("TF Data transfer issue [write]" +
|
print("TF Data transfer issue [write]" +
|
||||||
"\n Requested: "+message.length+
|
"\n Requested: "+message.length+
|
||||||
"\n Transferred: "+writeBufTransferred.get(), EMsgType.FAIL);
|
"\n Transferred: "+writeBufTransferred.get(), EMsgType.FAIL);
|
||||||
return true;
|
return true;
|
||||||
|
@ -326,13 +326,13 @@ class TinFoil extends TransferModule {
|
||||||
//writeBufTransferred.clear(); // MUST BE HERE IF WE 'GET()' IT
|
//writeBufTransferred.clear(); // MUST BE HERE IF WE 'GET()' IT
|
||||||
continue;
|
continue;
|
||||||
default:
|
default:
|
||||||
logPrinter.print("TF Data transfer issue [write]" +
|
print("TF Data transfer issue [write]" +
|
||||||
"\n Returned: "+ UsbErrorCodes.getErrCode(result) +
|
"\n Returned: "+ UsbErrorCodes.getErrCode(result) +
|
||||||
"\n (execution stopped)", EMsgType.FAIL);
|
"\n (execution stopped)", EMsgType.FAIL);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
logPrinter.print("TF Execution interrupted", EMsgType.INFO);
|
print("TF Execution interrupted", EMsgType.INFO);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -51,7 +51,7 @@ public abstract class TransferModule {
|
||||||
File[] subFiles = f.listFiles((file, name) -> name.matches("[0-9]{2}"));
|
File[] subFiles = f.listFiles((file, name) -> name.matches("[0-9]{2}"));
|
||||||
|
|
||||||
if (subFiles == null || subFiles.length == 0) {
|
if (subFiles == null || subFiles.length == 0) {
|
||||||
logPrinter.print("TransferModule: Exclude folder: " + f.getName(), EMsgType.WARNING);
|
print("TransferModule: Exclude folder: " + f.getName(), EMsgType.WARNING);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -59,7 +59,7 @@ public abstract class TransferModule {
|
||||||
|
|
||||||
for (int i = subFiles.length - 2; i > 0 ; i--){
|
for (int i = subFiles.length - 2; i > 0 ; i--){
|
||||||
if (subFiles[i].length() != subFiles[i-1].length()) {
|
if (subFiles[i].length() != subFiles[i-1].length()) {
|
||||||
logPrinter.print("TransferModule: Exclude split file: "+f.getName()+
|
print("TransferModule: Exclude split file: "+f.getName()+
|
||||||
"\n Chunk sizes of the split file are not the same, but has to be.", EMsgType.WARNING);
|
"\n Chunk sizes of the split file are not the same, but has to be.", EMsgType.WARNING);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -69,7 +69,7 @@ public abstract class TransferModule {
|
||||||
long lastFileLength = subFiles[subFiles.length-1].length();
|
long lastFileLength = subFiles[subFiles.length-1].length();
|
||||||
|
|
||||||
if (lastFileLength > firstFileLength){
|
if (lastFileLength > firstFileLength){
|
||||||
logPrinter.print("TransferModule: Exclude split file: "+f.getName()+
|
print("TransferModule: Exclude split file: "+f.getName()+
|
||||||
"\n Chunk sizes of the split file are not the same, but has to be.", EMsgType.WARNING);
|
"\n Chunk sizes of the split file are not the same, but has to be.", EMsgType.WARNING);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -77,4 +77,13 @@ public abstract class TransferModule {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
public EFileStatus getStatus(){ return status; }
|
public EFileStatus getStatus(){ return status; }
|
||||||
|
|
||||||
|
void print(String message, EMsgType type){
|
||||||
|
try {
|
||||||
|
logPrinter.print(message, type);
|
||||||
|
}
|
||||||
|
catch (InterruptedException ie){
|
||||||
|
ie.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,7 +49,7 @@ public class UsbCommunications extends CancellableRunnable {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
logPrinter.print("\tStart", EMsgType.INFO);
|
print("\tStart", EMsgType.INFO);
|
||||||
|
|
||||||
UsbConnect usbConnect = UsbConnect.connectHomebrewMode(logPrinter);
|
UsbConnect usbConnect = UsbConnect.connectHomebrewMode(logPrinter);
|
||||||
|
|
||||||
|
@ -87,7 +87,15 @@ public class UsbCommunications extends CancellableRunnable {
|
||||||
*/
|
*/
|
||||||
private void close(EFileStatus status){
|
private void close(EFileStatus status){
|
||||||
logPrinter.update(nspMap, status);
|
logPrinter.update(nspMap, status);
|
||||||
logPrinter.print("\tEnd", EMsgType.INFO);
|
print("\tEnd", EMsgType.INFO);
|
||||||
logPrinter.close();
|
logPrinter.close();
|
||||||
}
|
}
|
||||||
|
private void print(String message, EMsgType type){
|
||||||
|
try {
|
||||||
|
logPrinter.print(message, type);
|
||||||
|
}
|
||||||
|
catch (InterruptedException ie){
|
||||||
|
ie.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -65,7 +65,10 @@ public class UsbConnect {
|
||||||
usbConnect.connected = true;
|
usbConnect.connected = true;
|
||||||
}
|
}
|
||||||
catch (Exception e){
|
catch (Exception e){
|
||||||
|
try {
|
||||||
logPrinter.print(e.getMessage(), EMsgType.FAIL);
|
logPrinter.print(e.getMessage(), EMsgType.FAIL);
|
||||||
|
}
|
||||||
|
catch (InterruptedException ignore){}
|
||||||
usbConnect.close();
|
usbConnect.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -89,7 +92,10 @@ public class UsbConnect {
|
||||||
}
|
}
|
||||||
catch (Exception e){
|
catch (Exception e){
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
|
try {
|
||||||
logPrinter.print(e.getMessage(), EMsgType.FAIL);
|
logPrinter.print(e.getMessage(), EMsgType.FAIL);
|
||||||
|
}
|
||||||
|
catch (InterruptedException ignore){}
|
||||||
usbConnect.close();
|
usbConnect.close();
|
||||||
}
|
}
|
||||||
return usbConnect;
|
return usbConnect;
|
||||||
|
@ -100,7 +106,7 @@ public class UsbConnect {
|
||||||
private UsbConnect(ILogPrinter logPrinter){
|
private UsbConnect(ILogPrinter logPrinter){
|
||||||
this.logPrinter = logPrinter;
|
this.logPrinter = logPrinter;
|
||||||
this.connected = false;
|
this.connected = false;
|
||||||
};
|
}
|
||||||
|
|
||||||
private void createContextAndInitLibUSB() throws Exception{
|
private void createContextAndInitLibUSB() throws Exception{
|
||||||
// Creating Context required by libusb. Optional? Consider removing.
|
// Creating Context required by libusb. Optional? Consider removing.
|
||||||
|
@ -178,7 +184,7 @@ public class UsbConnect {
|
||||||
// Actually, there are no drivers in Linux kernel which uses this device.
|
// Actually, there are no drivers in Linux kernel which uses this device.
|
||||||
returningValue = LibUsb.setAutoDetachKernelDriver(handlerNS, true);
|
returningValue = LibUsb.setAutoDetachKernelDriver(handlerNS, true);
|
||||||
if (returningValue != LibUsb.SUCCESS)
|
if (returningValue != LibUsb.SUCCESS)
|
||||||
logPrinter.print("Skip kernel driver attach & detach ("+UsbErrorCodes.getErrCode(returningValue)+")", EMsgType.INFO);
|
print("Skip kernel driver attach & detach ("+UsbErrorCodes.getErrCode(returningValue)+")", EMsgType.INFO);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -230,7 +236,7 @@ public class UsbConnect {
|
||||||
returningValue = LibUsb.releaseInterface(handlerNS, DEFAULT_INTERFACE);
|
returningValue = LibUsb.releaseInterface(handlerNS, DEFAULT_INTERFACE);
|
||||||
|
|
||||||
if (returningValue != LibUsb.SUCCESS) {
|
if (returningValue != LibUsb.SUCCESS) {
|
||||||
logPrinter.print("Release interface failure: " +
|
print("Release interface failure: " +
|
||||||
UsbErrorCodes.getErrCode(returningValue) +
|
UsbErrorCodes.getErrCode(returningValue) +
|
||||||
" (sometimes it's not an issue)", EMsgType.WARNING);
|
" (sometimes it's not an issue)", EMsgType.WARNING);
|
||||||
}
|
}
|
||||||
|
@ -241,4 +247,13 @@ public class UsbConnect {
|
||||||
if (contextNS != null)
|
if (contextNS != null)
|
||||||
LibUsb.exit(contextNS);
|
LibUsb.exit(contextNS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void print(String message, EMsgType type){
|
||||||
|
try {
|
||||||
|
logPrinter.print(message, type);
|
||||||
|
}
|
||||||
|
catch (InterruptedException ie){
|
||||||
|
ie.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
10
src/main/resources/BlockListView.fxml
Normal file
10
src/main/resources/BlockListView.fxml
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
|
||||||
|
<?import javafx.scene.control.ListView?>
|
||||||
|
<?import javafx.scene.layout.AnchorPane?>
|
||||||
|
|
||||||
|
<AnchorPane xmlns="http://javafx.com/javafx/8.0.141" xmlns:fx="http://javafx.com/fxml/1" fx:controller="nsusbloader.Controllers.BlockListViewController">
|
||||||
|
<children>
|
||||||
|
<ListView fx:id="splitMergeListView" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0" />
|
||||||
|
</children>
|
||||||
|
</AnchorPane>
|
|
@ -42,7 +42,10 @@
|
||||||
</GridPane>
|
</GridPane>
|
||||||
</children>
|
</children>
|
||||||
</VBox>
|
</VBox>
|
||||||
<VBox fillWidth="false" spacing="5.0">
|
<HBox spacing="15.0" VBox.vgrow="ALWAYS">
|
||||||
|
<children>
|
||||||
|
<fx:include fx:id="BlockListView" source="BlockListView.fxml" HBox.hgrow="ALWAYS" VBox.vgrow="ALWAYS" />
|
||||||
|
<VBox spacing="5.0">
|
||||||
<children>
|
<children>
|
||||||
<RadioButton fx:id="splitRad" contentDisplay="TOP" mnemonicParsing="false" text="%tabSplMrg_RadioBtn_Split">
|
<RadioButton fx:id="splitRad" contentDisplay="TOP" mnemonicParsing="false" text="%tabSplMrg_RadioBtn_Split">
|
||||||
<toggleGroup>
|
<toggleGroup>
|
||||||
|
@ -50,47 +53,14 @@
|
||||||
</toggleGroup>
|
</toggleGroup>
|
||||||
</RadioButton>
|
</RadioButton>
|
||||||
<RadioButton fx:id="mergeRad" contentDisplay="TOP" mnemonicParsing="false" text="%tabSplMrg_RadioBtn_Merge" toggleGroup="$splitMergeTogGrp" />
|
<RadioButton fx:id="mergeRad" contentDisplay="TOP" mnemonicParsing="false" text="%tabSplMrg_RadioBtn_Merge" toggleGroup="$splitMergeTogGrp" />
|
||||||
</children>
|
<Button fx:id="selectFileFolderBtn" contentDisplay="TOP" mnemonicParsing="false">
|
||||||
<VBox.margin>
|
<VBox.margin>
|
||||||
<Insets left="15.0" right="15.0" />
|
<Insets bottom="10.0" />
|
||||||
</VBox.margin>
|
</VBox.margin>
|
||||||
</VBox>
|
</Button>
|
||||||
<VBox spacing="5.0">
|
|
||||||
<children>
|
|
||||||
<HBox>
|
|
||||||
<children>
|
|
||||||
<Label fx:id="fileFolderLabelLbl" />
|
|
||||||
<Label fx:id="fileFolderActualPathLbl" />
|
|
||||||
</children>
|
|
||||||
</HBox>
|
|
||||||
<Button fx:id="selectFileFolderBtn" contentDisplay="TOP" mnemonicParsing="false" />
|
|
||||||
</children>
|
|
||||||
<VBox.margin>
|
|
||||||
<Insets left="15.0" right="15.0" />
|
|
||||||
</VBox.margin>
|
|
||||||
</VBox>
|
|
||||||
<VBox spacing="5.0">
|
|
||||||
<children>
|
|
||||||
<HBox>
|
|
||||||
<children>
|
|
||||||
<Label text="%tabSplMrg_Lbl_SaveToLocation" />
|
<Label text="%tabSplMrg_Lbl_SaveToLocation" />
|
||||||
<Label fx:id="saveToPathLbl" />
|
<Label fx:id="saveToPathLbl" maxWidth="200.0" textOverrun="CENTER_WORD_ELLIPSIS" />
|
||||||
</children>
|
|
||||||
</HBox>
|
|
||||||
<Button fx:id="changeSaveToBtn" contentDisplay="TOP" mnemonicParsing="false" text="%tabSplMrg_Btn_ChangeSaveToLocation" />
|
<Button fx:id="changeSaveToBtn" contentDisplay="TOP" mnemonicParsing="false" text="%tabSplMrg_Btn_ChangeSaveToLocation" />
|
||||||
</children>
|
|
||||||
<VBox.margin>
|
|
||||||
<Insets left="15.0" right="15.0" />
|
|
||||||
</VBox.margin>
|
|
||||||
</VBox>
|
|
||||||
<HBox alignment="CENTER">
|
|
||||||
<children>
|
|
||||||
<Label fx:id="statusLbl" />
|
|
||||||
</children>
|
|
||||||
<VBox.margin>
|
|
||||||
<Insets left="15.0" right="15.0" />
|
|
||||||
</VBox.margin>
|
|
||||||
</HBox>
|
|
||||||
<Pane VBox.vgrow="ALWAYS" />
|
<Pane VBox.vgrow="ALWAYS" />
|
||||||
<VBox>
|
<VBox>
|
||||||
<children>
|
<children>
|
||||||
|
@ -101,6 +71,21 @@
|
||||||
</HBox>
|
</HBox>
|
||||||
</children>
|
</children>
|
||||||
</VBox>
|
</VBox>
|
||||||
|
</children>
|
||||||
|
</VBox>
|
||||||
|
</children>
|
||||||
|
<VBox.margin>
|
||||||
|
<Insets left="15.0" right="15.0" />
|
||||||
|
</VBox.margin>
|
||||||
|
</HBox>
|
||||||
|
<HBox alignment="CENTER">
|
||||||
|
<children>
|
||||||
|
<Label fx:id="statusLbl" />
|
||||||
|
</children>
|
||||||
|
<VBox.margin>
|
||||||
|
<Insets left="15.0" right="15.0" />
|
||||||
|
</VBox.margin>
|
||||||
|
</HBox>
|
||||||
<padding>
|
<padding>
|
||||||
<Insets bottom="5.0" left="5.0" right="5.0" top="5.0" />
|
<Insets bottom="5.0" left="5.0" right="5.0" top="5.0" />
|
||||||
</padding>
|
</padding>
|
||||||
|
|
|
@ -205,6 +205,7 @@
|
||||||
.table-view .table-cell{
|
.table-view .table-cell{
|
||||||
-fx-text-fill: #f7fafa;
|
-fx-text-fill: #f7fafa;
|
||||||
}
|
}
|
||||||
|
|
||||||
.table-row-cell, .table-row-cell:selected, .table-row-cell:filled:selected{
|
.table-row-cell, .table-row-cell:selected, .table-row-cell:filled:selected{
|
||||||
-fx-background-color: -fx-table-cell-border-color, #424242;
|
-fx-background-color: -fx-table-cell-border-color, #424242;
|
||||||
-fx-background-insets: 0, 0 0 1 0;
|
-fx-background-insets: 0, 0 0 1 0;
|
||||||
|
@ -223,7 +224,35 @@
|
||||||
-fx-padding: 0.0em; /* 0 */
|
-fx-padding: 0.0em; /* 0 */
|
||||||
-fx-table-cell-border-color: #6d8484;
|
-fx-table-cell-border-color: #6d8484;
|
||||||
}
|
}
|
||||||
// -========================== Context menu =====================-
|
/* -========================== ListView =====================- */
|
||||||
|
.list-view {
|
||||||
|
-fx-background-color: #4f4f4f;
|
||||||
|
-fx-background-position: center;
|
||||||
|
-fx-background-repeat: no-repeat;
|
||||||
|
-fx-background-radius: 3;
|
||||||
|
-fx-border-color: #00ffc9;
|
||||||
|
-fx-border-radius: 3;
|
||||||
|
-fx-border-width: 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.list-cell, .list-cell:selected, .list-cell:filled:selected{
|
||||||
|
-fx-background-color: -fx-table-cell-border-color, #424242;
|
||||||
|
-fx-background-insets: 0, 0 0 1 0;
|
||||||
|
-fx-table-cell-border-color: #6d8484;
|
||||||
|
}
|
||||||
|
.list-cell:odd, .list-cell:odd:selected, .list-cell:odd:filled:selected{
|
||||||
|
-fx-background-color: -fx-table-cell-border-color, #4f4f4f;
|
||||||
|
-fx-background-insets: 0, 0 0 1 0;
|
||||||
|
-fx-table-cell-border-color: #6d8484;
|
||||||
|
}
|
||||||
|
|
||||||
|
.list-cell .text, .list-cell:odd .text{
|
||||||
|
-fx-fill: #f7fafa;
|
||||||
|
}
|
||||||
|
.list-cell:filled:selected .text, .list-cell:odd:filled:selected .text{
|
||||||
|
-fx-fill: #08f3ff;
|
||||||
|
}
|
||||||
|
/* -========================== Context menu =====================- */
|
||||||
.context-menu {
|
.context-menu {
|
||||||
-fx-background-color: #2d2d2d;
|
-fx-background-color: #2d2d2d;
|
||||||
-fx-cursor: hand;
|
-fx-cursor: hand;
|
||||||
|
@ -234,7 +263,7 @@
|
||||||
.context-menu .menu-item:focused .label {
|
.context-menu .menu-item:focused .label {
|
||||||
-fx-text-fill: white;
|
-fx-text-fill: white;
|
||||||
}
|
}
|
||||||
// -========================== Text Field =====================-
|
/* -========================== Text Field =====================- */
|
||||||
.text-field {
|
.text-field {
|
||||||
-fx-prompt-text-fill: #40596c;
|
-fx-prompt-text-fill: #40596c;
|
||||||
-fx-border-color: #289de8;
|
-fx-border-color: #289de8;
|
||||||
|
|
|
@ -242,6 +242,35 @@
|
||||||
-fx-padding: 0.0em; /* 0 */
|
-fx-padding: 0.0em; /* 0 */
|
||||||
-fx-table-cell-border-color: #b0b0b0;
|
-fx-table-cell-border-color: #b0b0b0;
|
||||||
}
|
}
|
||||||
|
/* -========================== ListView =====================- */
|
||||||
|
.list-view {
|
||||||
|
-fx-background-color: #fefefe;
|
||||||
|
-fx-background-position: center;
|
||||||
|
-fx-background-repeat: no-repeat;
|
||||||
|
-fx-background-radius: 3;
|
||||||
|
-fx-border-color: #06b9bb;
|
||||||
|
-fx-border-radius: 3;
|
||||||
|
-fx-border-width: 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.list-cell, .list-cell:selected, .list-cell:filled:selected{
|
||||||
|
-fx-background-color: -fx-table-cell-border-color, #ebfffe;
|
||||||
|
-fx-background-insets: 0, 0 0 1 0;
|
||||||
|
-fx-table-cell-border-color: #b0b0b0;
|
||||||
|
}
|
||||||
|
.list-cell:odd, .list-cell:odd:selected, .list-cell:odd:filled:selected{
|
||||||
|
-fx-background-color: -fx-table-cell-border-color, #fefefe;
|
||||||
|
-fx-background-insets: 0, 0 0 1 0;
|
||||||
|
-fx-table-cell-border-color: #b0b0b0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.list-cell .text, .list-cell:odd .text{
|
||||||
|
-fx-fill: #2c2c2c;
|
||||||
|
}
|
||||||
|
.list-cell:filled:selected .text, .list-cell:odd:filled:selected .text{
|
||||||
|
-fx-fill: #2c2c2c;
|
||||||
|
-fx-font-weight: bold
|
||||||
|
}
|
||||||
/* -========================= Separator ===================- */
|
/* -========================= Separator ===================- */
|
||||||
.separator *.line {
|
.separator *.line {
|
||||||
-fx-border-style: solid;
|
-fx-border-style: solid;
|
||||||
|
|
86
src/test/java/nsusbloader/com/usb/MergeTest.java
Normal file
86
src/test/java/nsusbloader/com/usb/MergeTest.java
Normal file
|
@ -0,0 +1,86 @@
|
||||||
|
package nsusbloader.com.usb;
|
||||||
|
|
||||||
|
import nsusbloader.NSLMain;
|
||||||
|
import nsusbloader.Utilities.splitmerge.SplitMergeTaskExecutor;
|
||||||
|
import org.junit.jupiter.api.*;
|
||||||
|
import org.junit.jupiter.api.io.TempDir;
|
||||||
|
|
||||||
|
import java.io.BufferedOutputStream;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileOutputStream;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.nio.file.Paths;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
|
public class MergeTest {
|
||||||
|
private List<File> files;
|
||||||
|
@TempDir
|
||||||
|
File testFilesLocation;
|
||||||
|
@TempDir
|
||||||
|
File saveToPath;
|
||||||
|
|
||||||
|
static Random random;
|
||||||
|
|
||||||
|
@BeforeAll
|
||||||
|
static void init(){
|
||||||
|
NSLMain.isCli = true;
|
||||||
|
MergeTest.random = new Random();
|
||||||
|
}
|
||||||
|
|
||||||
|
void makeSplittedFiles() throws Exception{
|
||||||
|
String parentLocation = testFilesLocation.getAbsolutePath();
|
||||||
|
this.files = new ArrayList<>();
|
||||||
|
for (int i = 0; i < 7; i++) {
|
||||||
|
files.add(createSplitFile(parentLocation, "TestFile4Merge_" + i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
File createSplitFile(String parent, String name) throws Exception{
|
||||||
|
Path file = Paths.get(parent, name);
|
||||||
|
File newlyCreatedSplitFile = Files.createDirectory(file).toFile();
|
||||||
|
|
||||||
|
Assertions.assertTrue(newlyCreatedSplitFile.exists());
|
||||||
|
Assertions.assertTrue(newlyCreatedSplitFile.canRead());
|
||||||
|
Assertions.assertTrue(newlyCreatedSplitFile.canWrite());
|
||||||
|
|
||||||
|
int chunksCount = random.nextInt(6 + 1) + 1; // At min = 1, max = 6
|
||||||
|
populateSplittedFile(newlyCreatedSplitFile, chunksCount);
|
||||||
|
|
||||||
|
return newlyCreatedSplitFile;
|
||||||
|
}
|
||||||
|
void populateSplittedFile(File splitFileContainer, int chunksCount) throws Exception{
|
||||||
|
int chunkSize = random.nextInt(8192 + 1) + 8192; // At min = 8192, max = 8192*2
|
||||||
|
|
||||||
|
for (int i = 0; i < chunksCount; i++){
|
||||||
|
File chunkFile = new File(splitFileContainer, String.format("%02d", i));
|
||||||
|
try (BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(chunkFile))){
|
||||||
|
byte[] zero = new byte[chunkSize];
|
||||||
|
bos.write(zero);
|
||||||
|
}
|
||||||
|
|
||||||
|
Assertions.assertTrue(chunkFile.exists());
|
||||||
|
Assertions.assertTrue(chunkFile.canRead());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@DisplayName("Test test-files location for merge")
|
||||||
|
@Test
|
||||||
|
void testTempLocation(){
|
||||||
|
Assertions.assertTrue(testFilesLocation.isDirectory());
|
||||||
|
}
|
||||||
|
|
||||||
|
// @Disabled("Current test is not ready")
|
||||||
|
@DisplayName("Test merge functionality")
|
||||||
|
//@Timeout(value = 60000, unit = TimeUnit.MILLISECONDS)
|
||||||
|
@Test
|
||||||
|
void testMerge() throws Exception{
|
||||||
|
makeSplittedFiles();
|
||||||
|
SplitMergeTaskExecutor splitMergeTaskExecutor = new SplitMergeTaskExecutor(false, files, saveToPath.getAbsolutePath());
|
||||||
|
Thread thread = new Thread(splitMergeTaskExecutor);
|
||||||
|
thread.setDaemon(true);
|
||||||
|
thread.start();
|
||||||
|
thread.join();
|
||||||
|
}
|
||||||
|
}
|
78
src/test/java/nsusbloader/com/usb/SplitTest.java
Normal file
78
src/test/java/nsusbloader/com/usb/SplitTest.java
Normal file
|
@ -0,0 +1,78 @@
|
||||||
|
package nsusbloader.com.usb;
|
||||||
|
|
||||||
|
import nsusbloader.NSLMain;
|
||||||
|
import nsusbloader.Utilities.splitmerge.SplitMergeTaskExecutor;
|
||||||
|
import org.junit.jupiter.api.*;
|
||||||
|
import org.junit.jupiter.api.io.TempDir;
|
||||||
|
|
||||||
|
import java.io.BufferedOutputStream;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileOutputStream;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.nio.file.Paths;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
|
class SplitTest {
|
||||||
|
private List<File> files;
|
||||||
|
@TempDir
|
||||||
|
File testFilesLocation;
|
||||||
|
@TempDir
|
||||||
|
File saveToPath;
|
||||||
|
|
||||||
|
static Random random;
|
||||||
|
|
||||||
|
@BeforeAll
|
||||||
|
static void init(){
|
||||||
|
NSLMain.isCli = true;
|
||||||
|
SplitTest.random = new Random();
|
||||||
|
}
|
||||||
|
|
||||||
|
void makeRegularFiles() throws Exception {
|
||||||
|
String parentLocation = testFilesLocation.getAbsolutePath();
|
||||||
|
Assertions.assertTrue(Files.exists(Paths.get(parentLocation)));
|
||||||
|
this.files = new ArrayList<>();
|
||||||
|
for (int i = 0; i < 7; i++) {
|
||||||
|
files.add(createRegularFile(parentLocation, "TestFile4Split_" + i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
File createRegularFile(String parent, String name) throws Exception{
|
||||||
|
Path file = Paths.get(parent, name);
|
||||||
|
File newlyCreatedFile = Files.createFile(file).toFile();
|
||||||
|
|
||||||
|
Assertions.assertTrue(newlyCreatedFile.exists());
|
||||||
|
Assertions.assertTrue(newlyCreatedFile.canRead());
|
||||||
|
Assertions.assertTrue(newlyCreatedFile.canWrite());
|
||||||
|
|
||||||
|
int randomValue = random.nextInt(8192 + 1) + 8192; // At min = 8192, max = 8192*2
|
||||||
|
fulfillFile(newlyCreatedFile, randomValue);
|
||||||
|
|
||||||
|
return newlyCreatedFile;
|
||||||
|
}
|
||||||
|
void fulfillFile(File file, int fileSize) throws Exception{
|
||||||
|
try (BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(file))){
|
||||||
|
byte[] zero = new byte[fileSize];
|
||||||
|
bos.write(zero);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@DisplayName("Test test-files location for split")
|
||||||
|
@Test
|
||||||
|
void testTempLocation(){
|
||||||
|
Assertions.assertTrue(testFilesLocation.isDirectory());
|
||||||
|
}
|
||||||
|
|
||||||
|
@DisplayName("Test split functionality")
|
||||||
|
//@Timeout(value = 60000, unit = TimeUnit.MILLISECONDS)
|
||||||
|
@Test
|
||||||
|
void testSplit() throws Exception{
|
||||||
|
makeRegularFiles();
|
||||||
|
SplitMergeTaskExecutor splitMergeTaskExecutor = new SplitMergeTaskExecutor(true, files, saveToPath.getAbsolutePath());
|
||||||
|
Thread thread = new Thread(splitMergeTaskExecutor);
|
||||||
|
thread.setDaemon(true);
|
||||||
|
thread.start();
|
||||||
|
thread.join();
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue