Compare commits
2 commits
79c519b1f3
...
2a3bdd949f
Author | SHA1 | Date | |
---|---|---|---|
|
2a3bdd949f | ||
|
1176ad9e83 |
33 changed files with 1360 additions and 750 deletions
24
pom.xml
24
pom.xml
|
@ -60,28 +60,28 @@
|
|||
<dependency>
|
||||
<groupId>org.openjfx</groupId>
|
||||
<artifactId>javafx-controls</artifactId>
|
||||
<version>11</version>
|
||||
<version>16</version>
|
||||
<classifier>linux</classifier>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.openjfx</groupId>
|
||||
<artifactId>javafx-media</artifactId>
|
||||
<version>11</version>
|
||||
<version>16</version>
|
||||
<classifier>linux</classifier>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.openjfx</groupId>
|
||||
<artifactId>javafx-fxml</artifactId>
|
||||
<version>11</version>
|
||||
<version>16</version>
|
||||
<classifier>linux</classifier>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.openjfx</groupId>
|
||||
<artifactId>javafx-graphics</artifactId>
|
||||
<version>11</version>
|
||||
<version>16</version>
|
||||
<classifier>linux</classifier>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
|
@ -89,28 +89,28 @@
|
|||
<dependency>
|
||||
<groupId>org.openjfx</groupId>
|
||||
<artifactId>javafx-controls</artifactId>
|
||||
<version>11</version>
|
||||
<version>16</version>
|
||||
<classifier>win</classifier>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.openjfx</groupId>
|
||||
<artifactId>javafx-media</artifactId>
|
||||
<version>11</version>
|
||||
<version>16</version>
|
||||
<classifier>win</classifier>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.openjfx</groupId>
|
||||
<artifactId>javafx-fxml</artifactId>
|
||||
<version>11</version>
|
||||
<version>16</version>
|
||||
<classifier>win</classifier>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.openjfx</groupId>
|
||||
<artifactId>javafx-graphics</artifactId>
|
||||
<version>11</version>
|
||||
<version>16</version>
|
||||
<classifier>win</classifier>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
|
@ -118,28 +118,28 @@
|
|||
<dependency>
|
||||
<groupId>org.openjfx</groupId>
|
||||
<artifactId>javafx-controls</artifactId>
|
||||
<version>11</version>
|
||||
<version>16</version>
|
||||
<classifier>mac</classifier>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.openjfx</groupId>
|
||||
<artifactId>javafx-media</artifactId>
|
||||
<version>11</version>
|
||||
<version>16</version>
|
||||
<classifier>mac</classifier>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.openjfx</groupId>
|
||||
<artifactId>javafx-fxml</artifactId>
|
||||
<version>11</version>
|
||||
<version>16</version>
|
||||
<classifier>mac</classifier>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.openjfx</groupId>
|
||||
<artifactId>javafx-graphics</artifactId>
|
||||
<version>11</version>
|
||||
<version>16</version>
|
||||
<classifier>mac</classifier>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
|
|
|
@ -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;
|
||||
|
||||
@FXML
|
||||
private GamesController GamesTabController; // Accessible from Mediator | todo: incapsulate
|
||||
private GamesController GamesTabController;
|
||||
@FXML
|
||||
private SettingsController SettingsTabController;
|
||||
@FXML
|
||||
|
@ -69,6 +69,12 @@ public class NSLMainController implements Initializable {
|
|||
MediatorControl.getInstance().setController(this);
|
||||
|
||||
if (AppPreferences.getInstance().getAutoCheckUpdates()){
|
||||
checkForUpdates();
|
||||
}
|
||||
|
||||
openLastOpenedTab();
|
||||
}
|
||||
private void checkForUpdates(){
|
||||
Task<List<String>> updTask = new UpdatesChecker();
|
||||
updTask.setOnSucceeded(event->{
|
||||
List<String> result = updTask.getValue();
|
||||
|
@ -89,10 +95,6 @@ public class NSLMainController implements Initializable {
|
|||
updates.setDaemon(true);
|
||||
updates.start();
|
||||
}
|
||||
|
||||
openLastOpenedTab();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get resources
|
||||
* TODO: Find better solution; used in UsbCommunications() -> GL -> SelectFile command
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
*/
|
||||
package nsusbloader.Controllers;
|
||||
|
||||
import javafx.beans.binding.Bindings;
|
||||
import javafx.fxml.FXML;
|
||||
import javafx.fxml.Initializable;
|
||||
import javafx.scene.control.*;
|
||||
|
@ -33,11 +34,11 @@ import nsusbloader.MediatorControl;
|
|||
import nsusbloader.ModelControllers.CancellableRunnable;
|
||||
import nsusbloader.NSLDataTypes.EModule;
|
||||
import nsusbloader.ServiceWindow;
|
||||
import nsusbloader.Utilities.splitmerge.MergeTask;
|
||||
import nsusbloader.Utilities.splitmerge.SplitTask;
|
||||
import nsusbloader.Utilities.splitmerge.SplitMergeTaskExecutor;
|
||||
|
||||
import java.io.File;
|
||||
import java.net.URL;
|
||||
import java.util.List;
|
||||
import java.util.ResourceBundle;
|
||||
|
||||
public class SplitMergeController implements Initializable {
|
||||
|
@ -53,40 +54,39 @@ public class SplitMergeController implements Initializable {
|
|||
changeSaveToBtn,
|
||||
convertBtn;
|
||||
@FXML
|
||||
private Label fileFolderLabelLbl,
|
||||
fileFolderActualPathLbl,
|
||||
saveToPathLbl,
|
||||
private Label saveToPathLbl,
|
||||
statusLbl;
|
||||
|
||||
@FXML
|
||||
private BlockListViewController BlockListViewController;
|
||||
|
||||
private ResourceBundle resourceBundle;
|
||||
|
||||
private Region convertRegion;
|
||||
private Thread smThread;
|
||||
private CancellableRunnable smTask;
|
||||
private Runnable smTask;
|
||||
|
||||
@Override
|
||||
public void initialize(URL url, ResourceBundle resourceBundle) {
|
||||
this.resourceBundle = resourceBundle;
|
||||
|
||||
convertRegion = new Region();
|
||||
convertBtn.setGraphic(convertRegion);
|
||||
convertBtn.disableProperty().bind(Bindings.isEmpty(BlockListViewController.getItems()));
|
||||
|
||||
splitRad.setOnAction((actionEvent -> {
|
||||
statusLbl.setText("");
|
||||
convertRegion.getStyleClass().clear();
|
||||
convertRegion.getStyleClass().add("regionSplitToOne");
|
||||
fileFolderLabelLbl.setText(resourceBundle.getString("tabSplMrg_Txt_File"));
|
||||
selectFileFolderBtn.setText(resourceBundle.getString("tabSplMrg_Btn_SelectFile"));
|
||||
fileFolderActualPathLbl.setText("");
|
||||
convertBtn.setDisable(true);
|
||||
BlockListViewController.clear();
|
||||
}));
|
||||
mergeRad.setOnAction((actionEvent -> {
|
||||
statusLbl.setText("");
|
||||
convertRegion.getStyleClass().clear();
|
||||
convertRegion.getStyleClass().add("regionOneToSplit");
|
||||
fileFolderLabelLbl.setText(resourceBundle.getString("tabSplMrg_Txt_Folder"));
|
||||
selectFileFolderBtn.setText(resourceBundle.getString("tabSplMrg_Btn_SelectFolder"));
|
||||
fileFolderActualPathLbl.setText("");
|
||||
convertBtn.setDisable(true);
|
||||
BlockListViewController.clear();
|
||||
}));
|
||||
|
||||
if (AppPreferences.getInstance().getSplitMergeType() == 0)
|
||||
|
@ -110,32 +110,27 @@ public class SplitMergeController implements Initializable {
|
|||
|
||||
selectFileFolderBtn.setOnAction(actionEvent -> {
|
||||
statusLbl.setText("");
|
||||
List<File> alreadyAddedFiles = BlockListViewController.getItems();
|
||||
if (splitRad.isSelected()) {
|
||||
FileChooser fc = new FileChooser();
|
||||
fc.setTitle(resourceBundle.getString("tabSplMrg_Btn_SelectFile"));
|
||||
if (! fileFolderActualPathLbl.getText().isEmpty()){
|
||||
File temporaryFile = new File(fileFolderActualPathLbl.getText()).getParentFile();
|
||||
if (temporaryFile != null && temporaryFile.exists())
|
||||
fc.setInitialDirectory(temporaryFile);
|
||||
else
|
||||
fc.setInitialDirectory(new File(System.getProperty("user.home")));
|
||||
if (! alreadyAddedFiles.isEmpty()){
|
||||
String recentLocation = FilesHelper.getRealFolder(alreadyAddedFiles.get(0).getParentFile().getAbsolutePath());
|
||||
fc.setInitialDirectory(new File(recentLocation));
|
||||
}
|
||||
else
|
||||
fc.setInitialDirectory(new File(System.getProperty("user.home")));
|
||||
File fileFile = fc.showOpenDialog(changeSaveToBtn.getScene().getWindow());
|
||||
if (fileFile == null)
|
||||
List<File> files = fc.showOpenMultipleDialog(changeSaveToBtn.getScene().getWindow());
|
||||
if (files == null || files.isEmpty())
|
||||
return;
|
||||
fileFolderActualPathLbl.setText(fileFile.getAbsolutePath());
|
||||
this.BlockListViewController.addAll(files);
|
||||
}
|
||||
else{
|
||||
DirectoryChooser dc = new DirectoryChooser();
|
||||
dc.setTitle(resourceBundle.getString("tabSplMrg_Btn_SelectFolder"));
|
||||
if (! fileFolderActualPathLbl.getText().isEmpty()){
|
||||
File temporaryFile = new File(fileFolderActualPathLbl.getText());
|
||||
if (temporaryFile.exists())
|
||||
dc.setInitialDirectory(temporaryFile);
|
||||
else
|
||||
dc.setInitialDirectory(new File(System.getProperty("user.home")));
|
||||
if (! alreadyAddedFiles.isEmpty()){
|
||||
String recentLocation = FilesHelper.getRealFolder(alreadyAddedFiles.get(0).getParentFile().getAbsolutePath());
|
||||
dc.setInitialDirectory(new File(recentLocation));
|
||||
}
|
||||
else
|
||||
dc.setInitialDirectory(new File(System.getProperty("user.home")));
|
||||
|
@ -143,9 +138,8 @@ public class SplitMergeController implements Initializable {
|
|||
File folderFile = dc.showDialog(changeSaveToBtn.getScene().getWindow());
|
||||
if (folderFile == null)
|
||||
return;
|
||||
fileFolderActualPathLbl.setText(folderFile.getAbsolutePath());
|
||||
this.BlockListViewController.add(folderFile);
|
||||
}
|
||||
convertBtn.setDisable(false);
|
||||
});
|
||||
|
||||
convertBtn.setOnAction(actionEvent -> setConvertBtnAction());
|
||||
|
@ -192,7 +186,7 @@ public class SplitMergeController implements Initializable {
|
|||
* */
|
||||
private void stopBtnAction(){
|
||||
if (smThread != null && smThread.isAlive()) {
|
||||
smTask.cancel();
|
||||
smThread.interrupt();
|
||||
}
|
||||
}
|
||||
/**
|
||||
|
@ -209,9 +203,9 @@ public class SplitMergeController implements Initializable {
|
|||
}
|
||||
|
||||
if (splitRad.isSelected())
|
||||
smTask = new SplitTask(fileFolderActualPathLbl.getText(), saveToPathLbl.getText());
|
||||
smTask = new SplitMergeTaskExecutor(true, BlockListViewController.getItems(), saveToPathLbl.getText());
|
||||
else
|
||||
smTask = new MergeTask(fileFolderActualPathLbl.getText(), saveToPathLbl.getText());
|
||||
smTask = new SplitMergeTaskExecutor(false, BlockListViewController.getItems(), saveToPathLbl.getText());
|
||||
smThread = new Thread(smTask);
|
||||
smThread.setDaemon(true);
|
||||
smThread.start();
|
||||
|
@ -230,14 +224,16 @@ public class SplitMergeController implements Initializable {
|
|||
* */
|
||||
@FXML
|
||||
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();
|
||||
else
|
||||
splitRad.fire();
|
||||
fileFolderActualPathLbl.setText(fileDrpd.getAbsolutePath());
|
||||
convertBtn.setDisable(false);
|
||||
|
||||
this.BlockListViewController.addAll(files);
|
||||
|
||||
event.setDropCompleted(true);
|
||||
event.consume();
|
||||
}
|
||||
|
|
|
@ -26,8 +26,8 @@ import java.io.File;
|
|||
import java.util.HashMap;
|
||||
|
||||
public interface ILogPrinter {
|
||||
void print(String message, EMsgType type);
|
||||
void updateProgress(Double value);
|
||||
void print(String message, EMsgType type) throws InterruptedException;
|
||||
void updateProgress(Double value) throws InterruptedException;
|
||||
void update(HashMap<String, File> nspMap, EFileStatus status);
|
||||
void update(File file, EFileStatus status);
|
||||
void updateOneLinerStatus(boolean status);
|
||||
|
|
|
@ -32,9 +32,11 @@ public class LogPrinterGui implements ILogPrinter {
|
|||
private final MessagesConsumer msgConsumer;
|
||||
private final BlockingQueue<String> msgQueue;
|
||||
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;
|
||||
|
||||
/* TODO: Rewrite 'print()' implementation everywhere */
|
||||
|
||||
LogPrinterGui(EModule whoIsAsking){
|
||||
this.msgQueue = 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.
|
||||
* */
|
||||
@Override
|
||||
public void print(String message, EMsgType type){
|
||||
try {
|
||||
public void print(String message, EMsgType type) throws InterruptedException{
|
||||
switch (type){
|
||||
case PASS:
|
||||
msgQueue.put("[ PASS ] "+message+"\n");
|
||||
|
@ -66,20 +67,13 @@ public class LogPrinterGui implements ILogPrinter {
|
|||
msgQueue.put(message);
|
||||
}
|
||||
}
|
||||
catch (InterruptedException ie){
|
||||
ie.printStackTrace();
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Update progress for progress bar
|
||||
* */
|
||||
@Override
|
||||
public void updateProgress(Double value) {
|
||||
try {
|
||||
public void updateProgress(Double value) throws InterruptedException {
|
||||
progressQueue.put(value);
|
||||
}
|
||||
catch (InterruptedException ignored){} // TODO: Do something with this
|
||||
}
|
||||
/**
|
||||
* When we're done - update status
|
||||
* */
|
||||
|
|
|
@ -42,7 +42,7 @@ public class MessagesConsumer extends AnimationTimer {
|
|||
private final NSTableViewController tableViewController;
|
||||
private final EModule appModuleType;
|
||||
|
||||
private AtomicBoolean oneLinerStatus;
|
||||
private final AtomicBoolean oneLinerStatus;
|
||||
|
||||
private boolean isInterrupted;
|
||||
|
||||
|
@ -74,13 +74,13 @@ public class MessagesConsumer extends AnimationTimer {
|
|||
@Override
|
||||
public void handle(long l){
|
||||
ArrayList<String> messages = new ArrayList<>();
|
||||
int msgRecieved = msgQueue.drainTo(messages);
|
||||
if (msgRecieved > 0)
|
||||
int msgReceived = msgQueue.drainTo(messages);
|
||||
if (msgReceived > 0)
|
||||
messages.forEach(logsArea::appendText);
|
||||
|
||||
ArrayList<Double> progress = new ArrayList<>();
|
||||
int progressRecieved = progressQueue.drainTo(progress);
|
||||
if (progressRecieved > 0) {
|
||||
int progressReceived = progressQueue.drainTo(progress);
|
||||
if (progressReceived > 0) {
|
||||
progress.forEach(prg -> {
|
||||
if (prg != 1.0)
|
||||
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);
|
||||
progressBar.setProgress(0.0);
|
||||
|
||||
|
@ -109,10 +113,8 @@ public class MessagesConsumer extends AnimationTimer {
|
|||
MediatorControl.getInstance().getSplitMergeController().setOneLineStatus(oneLinerStatus.get());
|
||||
break;
|
||||
}
|
||||
|
||||
this.stop();
|
||||
}
|
||||
}
|
||||
|
||||
public void interrupt(){
|
||||
this.isInterrupted = true;
|
||||
|
|
|
@ -72,8 +72,8 @@ public class Rcm implements Runnable{
|
|||
|
||||
@Override
|
||||
public void run() {
|
||||
logPrinter.print("Selected: "+filePath, EMsgType.INFO);
|
||||
logPrinter.print("=============== RCM ===============", EMsgType.INFO);
|
||||
print("Selected: "+filePath, EMsgType.INFO);
|
||||
print("=============== RCM ===============", EMsgType.INFO);
|
||||
|
||||
ECurrentOS ecurrentOS;
|
||||
String realOsName = System.getProperty("os.name").toLowerCase().replace(" ", "");
|
||||
|
@ -85,11 +85,11 @@ public class Rcm implements Runnable{
|
|||
ecurrentOS = ECurrentOS.lin;
|
||||
else
|
||||
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 (! 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 :("+
|
||||
"\n But you could file a bug with request."+
|
||||
"\n\n Nothing has been sent to NS. Execution stopped.", EMsgType.FAIL);
|
||||
|
@ -124,14 +124,14 @@ public class Rcm implements Runnable{
|
|||
// Send payload
|
||||
for (int i=0; i < fullPayload.length / 4096 ; i++){
|
||||
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);
|
||||
usbConnect.close();
|
||||
logPrinter.close();
|
||||
return;
|
||||
}
|
||||
}
|
||||
logPrinter.print("Information sent to NS.", EMsgType.PASS);
|
||||
print("Information sent to NS.", EMsgType.PASS);
|
||||
|
||||
if (ecurrentOS.equals(ECurrentOS.mac)){
|
||||
if (smashMacOS()){
|
||||
|
@ -149,7 +149,7 @@ public class Rcm implements Runnable{
|
|||
retval = RcmSmash.smashWindows();
|
||||
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);
|
||||
usbConnect.close();
|
||||
logPrinter.close();
|
||||
|
@ -157,18 +157,27 @@ public class Rcm implements Runnable{
|
|||
}
|
||||
|
||||
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);
|
||||
usbConnect.close();
|
||||
logPrinter.close();
|
||||
return;
|
||||
}
|
||||
}
|
||||
logPrinter.print(".:: Payload complete ::.", EMsgType.PASS);
|
||||
print(".:: Payload complete ::.", EMsgType.PASS);
|
||||
usbConnect.close();
|
||||
logPrinter.updateOneLinerStatus(true);
|
||||
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.
|
||||
* @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.
|
||||
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 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);
|
||||
|
@ -194,7 +203,7 @@ public class Rcm implements Runnable{
|
|||
totalSize += 4096;
|
||||
// Double-check
|
||||
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 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.
|
||||
|
@ -209,7 +218,7 @@ public class Rcm implements Runnable{
|
|||
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(pldrFile));
|
||||
int readSize;
|
||||
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\n Nothing has been sent to NS. Execution stopped.", EMsgType.FAIL);
|
||||
bis.close();
|
||||
|
@ -218,7 +227,7 @@ public class Rcm implements Runnable{
|
|||
bis.close();
|
||||
}
|
||||
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);
|
||||
return true;
|
||||
}
|
||||
|
@ -241,7 +250,7 @@ public class Rcm implements Runnable{
|
|||
IntBuffer readBufTransferred = IntBuffer.allocate(1);
|
||||
int result = LibUsb.bulkTransfer(handler, (byte) 0x81, readBuffer, readBufTransferred, 1000);
|
||||
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);
|
||||
return true;
|
||||
}
|
||||
|
@ -251,7 +260,7 @@ public class Rcm implements Runnable{
|
|||
StringBuilder idStrBld = new StringBuilder("Found device with ID: ");
|
||||
for (byte b: receivedBytes)
|
||||
idStrBld.append(String.format("%02x ", b));
|
||||
logPrinter.print(idStrBld.toString(), EMsgType.PASS);
|
||||
print(idStrBld.toString(), EMsgType.PASS);
|
||||
return false;
|
||||
}
|
||||
/**
|
||||
|
@ -269,13 +278,13 @@ public class Rcm implements Runnable{
|
|||
if (writeBufTransferred.get() == 4096)
|
||||
return false;
|
||||
|
||||
logPrinter.print("RCM Data transfer issue [write]" +
|
||||
print("RCM Data transfer issue [write]" +
|
||||
"\n Requested: " + message.length +
|
||||
"\n Transferred: " + writeBufTransferred.get()+
|
||||
"\n\n Execution stopped.", EMsgType.FAIL);
|
||||
return true;
|
||||
}
|
||||
logPrinter.print("RCM Data transfer issue [write]" +
|
||||
print("RCM Data transfer issue [write]" +
|
||||
"\n Returned: " + UsbErrorCodes.getErrCode(result) +
|
||||
"\n\n Execution stopped.", EMsgType.FAIL);
|
||||
return true;
|
||||
|
|
|
@ -38,8 +38,8 @@ public class NxdtTask extends CancellableRunnable {
|
|||
|
||||
@Override
|
||||
public void run() {
|
||||
logPrinter.print("Save to location: "+ saveToLocation, EMsgType.INFO);
|
||||
logPrinter.print("=============== nxdumptool ===============", EMsgType.INFO);
|
||||
print("Save to location: "+ saveToLocation, EMsgType.INFO);
|
||||
print("=============== nxdumptool ===============", EMsgType.INFO);
|
||||
|
||||
UsbConnect usbConnect = UsbConnect.connectHomebrewMode(logPrinter);
|
||||
|
||||
|
@ -54,13 +54,22 @@ public class NxdtTask extends CancellableRunnable {
|
|||
new NxdtUsbAbi1(handler, logPrinter, saveToLocation, this);
|
||||
}
|
||||
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();
|
||||
logPrinter.updateOneLinerStatus(true);
|
||||
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);
|
||||
}
|
||||
|
||||
private void readLoop(){
|
||||
private void readLoop() throws InterruptedException{
|
||||
logPrinter.print("Awaiting for handshake", EMsgType.INFO);
|
||||
try {
|
||||
byte[] directive;
|
||||
|
@ -292,7 +292,7 @@ class NxdtUsbAbi1 {
|
|||
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 '\'.
|
||||
return saveToPath + filename.replaceAll("/", "\\\\");
|
||||
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;
|
||||
|
||||
import nsusbloader.Utilities.splitmerge.MergeTask;
|
||||
import nsusbloader.Utilities.splitmerge.SplitTask;
|
||||
import nsusbloader.Utilities.splitmerge.SplitMergeTaskExecutor;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
|
@ -27,7 +26,7 @@ import java.util.List;
|
|||
|
||||
public class MergeCli {
|
||||
|
||||
private String[] arguments;
|
||||
private final String[] arguments;
|
||||
private String saveTo;
|
||||
private String[] splitFiles;
|
||||
|
||||
|
@ -97,12 +96,20 @@ public class MergeCli {
|
|||
}
|
||||
|
||||
private void runBackend() throws InterruptedException{
|
||||
for (String filePath : splitFiles){
|
||||
Runnable mergeTask = new MergeTask(filePath, saveTo);
|
||||
Runnable mergeTask = new SplitMergeTaskExecutor(
|
||||
false,
|
||||
getFilesFromStrings(),
|
||||
saveTo);
|
||||
Thread thread = new Thread(mergeTask);
|
||||
thread.setDaemon(true);
|
||||
thread.start();
|
||||
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;
|
||||
|
||||
import nsusbloader.Utilities.splitmerge.SplitTask;
|
||||
import nsusbloader.Utilities.splitmerge.SplitMergeTaskExecutor;
|
||||
|
||||
import java.io.File;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.*;
|
||||
|
||||
public class SplitCli {
|
||||
|
||||
private String[] arguments;
|
||||
private final String[] arguments;
|
||||
private String saveTo;
|
||||
private String[] files;
|
||||
|
||||
|
@ -95,12 +93,20 @@ public class SplitCli {
|
|||
}
|
||||
|
||||
private void runBackend() throws InterruptedException{
|
||||
for (String filePath : files){
|
||||
Runnable splitTaks = new SplitTask(filePath, saveTo);
|
||||
Thread thread = new Thread(splitTaks);
|
||||
Runnable splitTasks = new SplitMergeTaskExecutor(
|
||||
true,
|
||||
getFilesFromStrings(),
|
||||
saveTo);
|
||||
Thread thread = new Thread(splitTasks);
|
||||
thread.setDaemon(true);
|
||||
thread.start();
|
||||
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() )
|
||||
return;
|
||||
|
||||
logPrinter.print("\tStart chain", EMsgType.INFO);
|
||||
print("\tStart chain", EMsgType.INFO);
|
||||
|
||||
final String handshakeContent = buildHandshakeContent();
|
||||
|
||||
|
@ -102,11 +102,11 @@ public class NETCommunications extends CancellableRunnable {
|
|||
|
||||
// Check if we should serve requests
|
||||
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);
|
||||
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
|
||||
serveRequestsLoop();
|
||||
|
@ -142,7 +142,7 @@ public class NETCommunications extends CancellableRunnable {
|
|||
handshakeSocket.close();
|
||||
}
|
||||
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);
|
||||
close(EFileStatus.UNKNOWN);
|
||||
return true;
|
||||
|
@ -175,13 +175,13 @@ public class NETCommunications extends CancellableRunnable {
|
|||
}
|
||||
catch (Exception e){
|
||||
if (isCancelled())
|
||||
logPrinter.print("Interrupted by user.", EMsgType.INFO);
|
||||
print("Interrupted by user.", EMsgType.INFO);
|
||||
else
|
||||
logPrinter.print(e.getMessage(), EMsgType.INFO);
|
||||
print(e.getMessage(), EMsgType.INFO);
|
||||
close(EFileStatus.UNKNOWN);
|
||||
return;
|
||||
}
|
||||
logPrinter.print("All transfers complete", EMsgType.PASS);
|
||||
print("All transfers complete", EMsgType.PASS);
|
||||
close(EFileStatus.UPLOADED);
|
||||
}
|
||||
/**
|
||||
|
@ -199,7 +199,7 @@ public class NETCommunications extends CancellableRunnable {
|
|||
|
||||
if (! files.containsKey(reqFileName)){
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
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);
|
||||
return;
|
||||
}
|
||||
if (packet.get(0).startsWith("HEAD")){
|
||||
writeToSocket(NETPacket.getCode200(reqFileSize));
|
||||
logPrinter.print("Replying for requested file: "+requestedFile.getName(), EMsgType.INFO);
|
||||
print("Replying for requested file: "+requestedFile.getName(), EMsgType.INFO);
|
||||
return;
|
||||
}
|
||||
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
|
||||
writeToSocket(NETPacket.getCode400());
|
||||
logPrinter.print("Requested range for "
|
||||
print("Requested range for "
|
||||
+ file.getName()
|
||||
+ " is incorrect. Returning 400", EMsgType.FAIL);
|
||||
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=-"
|
||||
writeToSocket(NETPacket.getCode400());
|
||||
logPrinter.print("Requested range for "
|
||||
print("Requested range for "
|
||||
+ file.getName()
|
||||
+ " is incorrect (empty start & end). Returning 400", EMsgType.FAIL);
|
||||
logPrinter.update(file, EFileStatus.FAILED);
|
||||
|
@ -267,7 +267,7 @@ public class NETCommunications extends CancellableRunnable {
|
|||
}
|
||||
// If file smaller than 500 bytes
|
||||
writeToSocket(NETPacket.getCode416());
|
||||
logPrinter.print("File size requested for "
|
||||
print("File size requested for "
|
||||
+ file.getName()
|
||||
+ " while actual size of it: "
|
||||
+ fileSize+". Returning 416", EMsgType.FAIL);
|
||||
|
@ -275,7 +275,7 @@ public class NETCommunications extends CancellableRunnable {
|
|||
}
|
||||
catch (NumberFormatException nfe){
|
||||
writeToSocket(NETPacket.getCode400());
|
||||
logPrinter.print("Requested range for "
|
||||
print("Requested range for "
|
||||
+ file.getName()
|
||||
+ " has incorrect format. Returning 400\n\t"
|
||||
+ nfe.getMessage(), EMsgType.FAIL);
|
||||
|
@ -293,7 +293,7 @@ public class NETCommunications extends CancellableRunnable {
|
|||
private void writeToSocket(String fileName, long start, long end) throws Exception{
|
||||
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));
|
||||
try{
|
||||
|
@ -379,11 +379,11 @@ public class NETCommunications extends CancellableRunnable {
|
|||
try {
|
||||
if (serverSocket != null && ! serverSocket.isClosed()) {
|
||||
serverSocket.close();
|
||||
logPrinter.print("Closing server socket.", EMsgType.PASS);
|
||||
print("Closing server socket.", EMsgType.PASS);
|
||||
}
|
||||
}
|
||||
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<>();
|
||||
|
@ -392,7 +392,15 @@ public class NETCommunications extends CancellableRunnable {
|
|||
|
||||
logPrinter.update(tempMap, status);
|
||||
|
||||
logPrinter.print("\tEnd chain", EMsgType.INFO);
|
||||
print("\tEnd chain", EMsgType.INFO);
|
||||
logPrinter.close();
|
||||
}
|
||||
private void print(String message, EMsgType type){
|
||||
try {
|
||||
logPrinter.print(message, type);
|
||||
}
|
||||
catch (InterruptedException ie){
|
||||
ie.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -55,7 +55,10 @@ public class NetworkSetupValidator {
|
|||
resolvePort(hostPortNum);
|
||||
}
|
||||
catch (Exception e){
|
||||
try {
|
||||
logPrinter.print(e.getMessage(), EMsgType.FAIL);
|
||||
}
|
||||
catch (InterruptedException ignore){}
|
||||
valid = false;
|
||||
return;
|
||||
}
|
||||
|
@ -63,7 +66,10 @@ public class NetworkSetupValidator {
|
|||
}
|
||||
|
||||
private void validateFiles(List<File> filesList){
|
||||
filesList.removeIf(f -> {
|
||||
filesList.removeIf(this::validator);
|
||||
}
|
||||
private boolean validator(File f){
|
||||
try {
|
||||
if (f.isFile())
|
||||
return false;
|
||||
|
||||
|
@ -93,7 +99,10 @@ public class NetworkSetupValidator {
|
|||
return true;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
}
|
||||
catch (InterruptedException ie){
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
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()){
|
||||
this.hostIP = hostIPaddr;
|
||||
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());
|
||||
}
|
||||
|
||||
private boolean findIpUsingHost(String host) {
|
||||
private boolean findIpUsingHost(String host) throws InterruptedException{
|
||||
try {
|
||||
Socket scoketK;
|
||||
scoketK = new Socket();
|
||||
|
|
|
@ -59,17 +59,17 @@ public class GoldLeaf_05 extends TransferModule {
|
|||
this.task = task;
|
||||
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);
|
||||
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;
|
||||
}
|
||||
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")) {
|
||||
logPrinter.print("GL This file doesn't look like NSP", EMsgType.FAIL);
|
||||
print("GL This file doesn't look like NSP", EMsgType.FAIL);
|
||||
return;
|
||||
}
|
||||
PFSProvider pfsElement;
|
||||
|
@ -77,11 +77,11 @@ public class GoldLeaf_05 extends TransferModule {
|
|||
pfsElement = new PFSProvider(nspFile, logPrinter);
|
||||
}
|
||||
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;
|
||||
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{
|
||||
if (nspFile.isDirectory())
|
||||
|
@ -90,7 +90,7 @@ public class GoldLeaf_05 extends TransferModule {
|
|||
this.raf = new RandomAccessFile(nspFile, "r");
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -99,15 +99,15 @@ public class GoldLeaf_05 extends TransferModule {
|
|||
|
||||
// Go connect to GoldLeaf
|
||||
if (writeUsb(CMD_GLUC)) {
|
||||
logPrinter.print("GL Initiating GoldLeaf connection [1/2]", EMsgType.FAIL);
|
||||
print("GL Initiating GoldLeaf connection [1/2]", EMsgType.FAIL);
|
||||
return;
|
||||
}
|
||||
logPrinter.print("GL Initiating GoldLeaf connection: [1/2]", EMsgType.PASS);
|
||||
print("GL Initiating GoldLeaf connection: [1/2]", EMsgType.PASS);
|
||||
if (writeUsb(CMD_ConnectionRequest)){
|
||||
logPrinter.print("GL Initiating GoldLeaf connection: [2/2]", EMsgType.FAIL);
|
||||
print("GL Initiating GoldLeaf connection: [2/2]", EMsgType.FAIL);
|
||||
return;
|
||||
}
|
||||
logPrinter.print("GL Initiating GoldLeaf connection: [2/2]", EMsgType.PASS);
|
||||
print("GL Initiating GoldLeaf connection: [2/2]", EMsgType.PASS);
|
||||
|
||||
while (true) {
|
||||
readByte = readUsb();
|
||||
|
@ -143,7 +143,7 @@ public class GoldLeaf_05 extends TransferModule {
|
|||
continue;
|
||||
}
|
||||
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;
|
||||
break;
|
||||
}
|
||||
|
@ -164,29 +164,29 @@ public class GoldLeaf_05 extends TransferModule {
|
|||
* false if no issues
|
||||
* */
|
||||
private boolean handleConnectionResponse(PFSProvider pfsElement){
|
||||
logPrinter.print("GL 'ConnectionResponse' command:", EMsgType.INFO);
|
||||
print("GL 'ConnectionResponse' command:", EMsgType.INFO);
|
||||
if (writeUsb(CMD_GLUC)) {
|
||||
logPrinter.print(" [1/4]", EMsgType.FAIL);
|
||||
print(" [1/4]", EMsgType.FAIL);
|
||||
return true;
|
||||
}
|
||||
logPrinter.print(" [1/4]", EMsgType.PASS);
|
||||
print(" [1/4]", EMsgType.PASS);
|
||||
if (writeUsb(CMD_NSPName)) {
|
||||
logPrinter.print(" [2/4]", EMsgType.FAIL);
|
||||
print(" [2/4]", EMsgType.FAIL);
|
||||
return true;
|
||||
}
|
||||
logPrinter.print(" [2/4]", EMsgType.PASS);
|
||||
print(" [2/4]", EMsgType.PASS);
|
||||
|
||||
if (writeUsb(pfsElement.getBytesNspFileNameLength())) {
|
||||
logPrinter.print(" [3/4]", EMsgType.FAIL);
|
||||
print(" [3/4]", EMsgType.FAIL);
|
||||
return true;
|
||||
}
|
||||
logPrinter.print(" [3/4]", EMsgType.PASS);
|
||||
print(" [3/4]", EMsgType.PASS);
|
||||
|
||||
if (writeUsb(pfsElement.getBytesNspFileName())) {
|
||||
logPrinter.print(" [4/4]", EMsgType.FAIL);
|
||||
print(" [4/4]", EMsgType.FAIL);
|
||||
return true;
|
||||
}
|
||||
logPrinter.print(" [4/4]", EMsgType.PASS);
|
||||
print(" [4/4]", EMsgType.PASS);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
@ -196,50 +196,50 @@ public class GoldLeaf_05 extends TransferModule {
|
|||
* false if no issues
|
||||
* */
|
||||
private boolean handleStart(PFSProvider pfsElement){
|
||||
logPrinter.print("GL Handle 'Start' command:", EMsgType.INFO);
|
||||
print("GL Handle 'Start' command:", EMsgType.INFO);
|
||||
if (writeUsb(CMD_GLUC)) {
|
||||
logPrinter.print(" [Prefix]", EMsgType.FAIL);
|
||||
print(" [Prefix]", EMsgType.FAIL);
|
||||
return true;
|
||||
}
|
||||
logPrinter.print(" [Prefix]", EMsgType.PASS);
|
||||
print(" [Prefix]", EMsgType.PASS);
|
||||
|
||||
if (writeUsb(CMD_NSPData)) {
|
||||
logPrinter.print(" [Command]", EMsgType.FAIL);
|
||||
print(" [Command]", EMsgType.FAIL);
|
||||
return true;
|
||||
}
|
||||
logPrinter.print(" [Command]", EMsgType.PASS);
|
||||
print(" [Command]", EMsgType.PASS);
|
||||
|
||||
if (writeUsb(pfsElement.getBytesCountOfNca())) {
|
||||
logPrinter.print(" [Sub-files count]", EMsgType.FAIL);
|
||||
print(" [Sub-files count]", EMsgType.FAIL);
|
||||
return true;
|
||||
}
|
||||
logPrinter.print(" [Sub-files count]", EMsgType.PASS);
|
||||
print(" [Sub-files count]", EMsgType.PASS);
|
||||
|
||||
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++){
|
||||
logPrinter.print("File #"+i, EMsgType.INFO);
|
||||
print("File #"+i, EMsgType.INFO);
|
||||
if (writeUsb(pfsElement.getNca(i).getNcaFileNameLength())) {
|
||||
logPrinter.print(" [1/4] Name length", EMsgType.FAIL);
|
||||
print(" [1/4] Name length", EMsgType.FAIL);
|
||||
return true;
|
||||
}
|
||||
logPrinter.print(" [1/4] Name length", EMsgType.PASS);
|
||||
print(" [1/4] Name length", EMsgType.PASS);
|
||||
|
||||
if (writeUsb(pfsElement.getNca(i).getNcaFileName())) {
|
||||
logPrinter.print(" [2/4] Name", EMsgType.FAIL);
|
||||
print(" [2/4] Name", EMsgType.FAIL);
|
||||
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.
|
||||
logPrinter.print(" [3/4] Offset", EMsgType.FAIL);
|
||||
print(" [3/4] Offset", EMsgType.FAIL);
|
||||
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
|
||||
logPrinter.print(" [4/4] Size", EMsgType.FAIL);
|
||||
print(" [4/4] Size", EMsgType.FAIL);
|
||||
return true;
|
||||
}
|
||||
logPrinter.print(" [4/4] Size", EMsgType.PASS);
|
||||
print(" [4/4] Size", EMsgType.PASS);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@ -254,18 +254,18 @@ public class GoldLeaf_05 extends TransferModule {
|
|||
int requestedNcaID;
|
||||
|
||||
if (isItRawRequest) {
|
||||
logPrinter.print("GL Handle 'Content' command", EMsgType.INFO);
|
||||
print("GL Handle 'Content' command", EMsgType.INFO);
|
||||
byte[] readByte = readUsb();
|
||||
if (readByte == null || readByte.length != 4) {
|
||||
logPrinter.print(" [Read requested ID]", EMsgType.FAIL);
|
||||
print(" [Read requested ID]", EMsgType.FAIL);
|
||||
return true;
|
||||
}
|
||||
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 {
|
||||
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();
|
||||
|
@ -317,8 +317,8 @@ public class GoldLeaf_05 extends TransferModule {
|
|||
logPrinter.updateProgress(1.0);
|
||||
//-----------------------------------------/
|
||||
}
|
||||
catch (IOException ioe){
|
||||
logPrinter.print("GL Failed to read NCA ID "+requestedNcaID+". IO Exception:\n "+ioe.getMessage(), EMsgType.FAIL);
|
||||
catch (IOException | InterruptedException ioe){
|
||||
print("GL Failed to read NCA ID "+requestedNcaID+". Exception:\n "+ioe.getMessage(), EMsgType.FAIL);
|
||||
ioe.printStackTrace();
|
||||
return true;
|
||||
}
|
||||
|
@ -345,18 +345,18 @@ public class GoldLeaf_05 extends TransferModule {
|
|||
if (writeBufTransferred.get() == message.length)
|
||||
return false;
|
||||
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;
|
||||
}
|
||||
case LibUsb.ERROR_TIMEOUT:
|
||||
continue;
|
||||
default:
|
||||
logPrinter.print("GL Data transfer issue [write]\n Returned: "+ UsbErrorCodes.getErrCode(result), EMsgType.FAIL);
|
||||
logPrinter.print("GL Execution stopped", EMsgType.FAIL);
|
||||
print("GL Data transfer issue [write]\n Returned: "+ UsbErrorCodes.getErrCode(result), EMsgType.FAIL);
|
||||
print("GL Execution stopped", EMsgType.FAIL);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
logPrinter.print("GL Execution interrupted", EMsgType.INFO);
|
||||
print("GL Execution interrupted", EMsgType.INFO);
|
||||
return true;
|
||||
}
|
||||
/**
|
||||
|
@ -382,12 +382,12 @@ public class GoldLeaf_05 extends TransferModule {
|
|||
case LibUsb.ERROR_TIMEOUT:
|
||||
continue;
|
||||
default:
|
||||
logPrinter.print("GL Data transfer issue [read]\n Returned: " + UsbErrorCodes.getErrCode(result), EMsgType.FAIL);
|
||||
logPrinter.print("GL Execution stopped", EMsgType.FAIL);
|
||||
print("GL Data transfer issue [read]\n Returned: " + UsbErrorCodes.getErrCode(result), EMsgType.FAIL);
|
||||
print("GL Execution stopped", EMsgType.FAIL);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
logPrinter.print("GL Execution interrupted", EMsgType.INFO);
|
||||
print("GL Execution interrupted", EMsgType.INFO);
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -69,7 +69,11 @@ class GoldLeaf_07 extends TransferModule {
|
|||
// For using in CMD_SelectFile with SPEC:/ prefix
|
||||
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);
|
||||
|
||||
final byte CMD_GetDriveCount = 0x00;
|
||||
|
@ -93,7 +97,7 @@ class GoldLeaf_07 extends TransferModule {
|
|||
|
||||
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" +
|
||||
"HOME:/ equals "
|
||||
+System.getProperty("user.home"), EMsgType.INFO);
|
||||
|
@ -260,7 +264,7 @@ class GoldLeaf_07 extends TransferModule {
|
|||
byte[] drivesCnt = intToArrLE(2); //2
|
||||
// Write count of drives
|
||||
if (writeGL_PASS(drivesCnt)) {
|
||||
logPrinter.print("GL Handle 'ListDrives' command", EMsgType.FAIL);
|
||||
print("GL Handle 'ListDrives' command", EMsgType.FAIL);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
@ -316,7 +320,7 @@ class GoldLeaf_07 extends TransferModule {
|
|||
command.add(totalSize);
|
||||
|
||||
if (writeGL_PASS(command)) {
|
||||
logPrinter.print("GL Handle 'GetDriveInfo' command", EMsgType.FAIL);
|
||||
print("GL Handle 'GetDriveInfo' command", EMsgType.FAIL);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -332,7 +336,7 @@ class GoldLeaf_07 extends TransferModule {
|
|||
byte[] specialPathCnt = intToArrLE(0);
|
||||
// Write count of special paths
|
||||
if (writeGL_PASS(specialPathCnt)) {
|
||||
logPrinter.print("GL Handle 'SpecialPathCount' command", EMsgType.FAIL);
|
||||
print("GL Handle 'SpecialPathCount' command", EMsgType.FAIL);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
@ -354,13 +358,13 @@ class GoldLeaf_07 extends TransferModule {
|
|||
if (path.equals("VIRT:/")) {
|
||||
if (isGetDirectoryCount){
|
||||
if (writeGL_PASS()) {
|
||||
logPrinter.print("GL Handle 'GetDirectoryCount' command", EMsgType.FAIL);
|
||||
print("GL Handle 'GetDirectoryCount' command", EMsgType.FAIL);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else {
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
@ -401,7 +405,7 @@ class GoldLeaf_07 extends TransferModule {
|
|||
// If somehow there are no folders, let's say 0;
|
||||
if (filesOrDirs == null){
|
||||
if (writeGL_PASS()) {
|
||||
logPrinter.print("GL Handle 'GetDirectoryOrFileCount' command", EMsgType.FAIL);
|
||||
print("GL Handle 'GetDirectoryOrFileCount' command", EMsgType.FAIL);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
@ -415,20 +419,20 @@ class GoldLeaf_07 extends TransferModule {
|
|||
this.recentFiles = filesOrDirs;
|
||||
// Otherwise, let's tell how may folders are in there
|
||||
if (writeGL_PASS(intToArrLE(filesOrDirs.length))) {
|
||||
logPrinter.print("GL Handle 'GetDirectoryOrFileCount' command", EMsgType.FAIL);
|
||||
print("GL Handle 'GetDirectoryOrFileCount' command", EMsgType.FAIL);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else if (path.startsWith("SPEC:/")){
|
||||
if (isGetDirectoryCount){ // If dir request then 0 dirs
|
||||
if (writeGL_PASS()) {
|
||||
logPrinter.print("GL Handle 'GetDirectoryCount' command", EMsgType.FAIL);
|
||||
print("GL Handle 'GetDirectoryCount' command", EMsgType.FAIL);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else if (selectedFile != null){ // Else it's file request, if we have selected then we will report 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;
|
||||
}
|
||||
}
|
||||
|
@ -482,7 +486,7 @@ class GoldLeaf_07 extends TransferModule {
|
|||
// return proxyGetDirFile(true);
|
||||
|
||||
if (writeGL_PASS(command)) {
|
||||
logPrinter.print("GL Handle 'GetDirectory' command.", EMsgType.FAIL);
|
||||
print("GL Handle 'GetDirectory' command.", EMsgType.FAIL);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
@ -539,7 +543,7 @@ class GoldLeaf_07 extends TransferModule {
|
|||
//if (proxyForGL) // TODO: NOTE: PROXY TAILS
|
||||
// return proxyGetDirFile(false);
|
||||
if (writeGL_PASS(command)) {
|
||||
logPrinter.print("GL Handle 'GetFile' command.", EMsgType.FAIL);
|
||||
print("GL Handle 'GetFile' command.", EMsgType.FAIL);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
@ -550,7 +554,7 @@ class GoldLeaf_07 extends TransferModule {
|
|||
command.add(intToArrLE(fileNameBytes.length / 2)); // since GL 0.7
|
||||
command.add(fileNameBytes);
|
||||
if (writeGL_PASS(command)) {
|
||||
logPrinter.print("GL Handle 'GetFile' command.", EMsgType.FAIL);
|
||||
print("GL Handle 'GetFile' command.", EMsgType.FAIL);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
@ -562,7 +566,7 @@ class GoldLeaf_07 extends TransferModule {
|
|||
command.add(intToArrLE(fileNameBytes.length / 2)); // since GL 0.7
|
||||
command.add(fileNameBytes);
|
||||
if (writeGL_PASS(command)) {
|
||||
logPrinter.print("GL Handle 'GetFile' command.", EMsgType.FAIL);
|
||||
print("GL Handle 'GetFile' command.", EMsgType.FAIL);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
@ -593,7 +597,7 @@ class GoldLeaf_07 extends TransferModule {
|
|||
command.add(longToArrLE(fileDirElement.length()));
|
||||
}
|
||||
if (writeGL_PASS(command)) {
|
||||
logPrinter.print("GL Handle 'StatPath' command.", EMsgType.FAIL);
|
||||
print("GL Handle 'StatPath' command.", EMsgType.FAIL);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
@ -610,7 +614,7 @@ class GoldLeaf_07 extends TransferModule {
|
|||
command.add(longToArrLE(nspMap.get(filePath).length())); // YES, THIS IS LONG!
|
||||
|
||||
if (writeGL_PASS(command)) {
|
||||
logPrinter.print("GL Handle 'StatPath' command.", EMsgType.FAIL);
|
||||
print("GL Handle 'StatPath' command.", EMsgType.FAIL);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
@ -623,7 +627,7 @@ class GoldLeaf_07 extends TransferModule {
|
|||
command.add(GL_OBJ_TYPE_FILE);
|
||||
command.add(longToArrLE(selectedFile.length()));
|
||||
if (writeGL_PASS(command)) {
|
||||
logPrinter.print("GL Handle 'StatPath' command.", EMsgType.FAIL);
|
||||
print("GL Handle 'StatPath' command.", EMsgType.FAIL);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
@ -651,7 +655,7 @@ class GoldLeaf_07 extends TransferModule {
|
|||
try {
|
||||
if (currentFile.renameTo(newFile)){
|
||||
if (writeGL_PASS()) {
|
||||
logPrinter.print("GL Handle 'Rename' command.", EMsgType.FAIL);
|
||||
print("GL Handle 'Rename' command.", EMsgType.FAIL);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
@ -676,7 +680,7 @@ class GoldLeaf_07 extends TransferModule {
|
|||
try {
|
||||
if (fileToDel.delete()){
|
||||
if (writeGL_PASS()) {
|
||||
logPrinter.print("GL Handle 'Rename' command.", EMsgType.FAIL);
|
||||
print("GL Handle 'Rename' command.", EMsgType.FAIL);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
@ -714,10 +718,10 @@ class GoldLeaf_07 extends TransferModule {
|
|||
}
|
||||
if (result){
|
||||
if (writeGL_PASS()) {
|
||||
logPrinter.print("GL Handle 'Create' command.", EMsgType.FAIL);
|
||||
print("GL Handle 'Create' command.", EMsgType.FAIL);
|
||||
return true;
|
||||
}
|
||||
//logPrinter.print("GL Handle 'Create' command.", EMsgType.PASS);
|
||||
//print("GL Handle 'Create' command.", EMsgType.PASS);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -802,12 +806,12 @@ class GoldLeaf_07 extends TransferModule {
|
|||
"\n Received: " + bytesRead);
|
||||
// Let's tell as a command about our result.
|
||||
if (writeGL_PASS(longToArrLE(size))) {
|
||||
logPrinter.print("GL Handle 'ReadFile' command [CMD]", EMsgType.FAIL);
|
||||
print("GL Handle 'ReadFile' command [CMD]", EMsgType.FAIL);
|
||||
return true;
|
||||
}
|
||||
// Let's bypass bytes we read total
|
||||
if (writeToUsb(chunk)) {
|
||||
logPrinter.print("GL Handle 'ReadFile' command", EMsgType.FAIL);
|
||||
print("GL Handle 'ReadFile' command", EMsgType.FAIL);
|
||||
return true;
|
||||
}
|
||||
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);
|
||||
// Let's tell as a command about our result.
|
||||
if (writeGL_PASS(longToArrLE(size))) {
|
||||
logPrinter.print("GL Handle 'ReadFile' command [CMD]", EMsgType.FAIL);
|
||||
print("GL Handle 'ReadFile' command [CMD]", EMsgType.FAIL);
|
||||
return true;
|
||||
}
|
||||
// Let's bypass bytes we read total
|
||||
if (writeToUsb(chunk)) {
|
||||
logPrinter.print("GL Handle 'ReadFile' command", EMsgType.FAIL);
|
||||
print("GL Handle 'ReadFile' command", EMsgType.FAIL);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
@ -839,14 +843,14 @@ class GoldLeaf_07 extends TransferModule {
|
|||
}
|
||||
catch (NullPointerException ignored){}
|
||||
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{
|
||||
splitReader.close();
|
||||
}
|
||||
catch (NullPointerException ignored){}
|
||||
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;
|
||||
randAccessFile = null;
|
||||
|
@ -888,7 +892,7 @@ class GoldLeaf_07 extends TransferModule {
|
|||
byte[] transferredData;
|
||||
|
||||
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;
|
||||
}
|
||||
try{
|
||||
|
@ -899,7 +903,7 @@ class GoldLeaf_07 extends TransferModule {
|
|||
}
|
||||
// Report we're good
|
||||
if (writeGL_PASS()) {
|
||||
logPrinter.print("GL Handle 'WriteFile' command", EMsgType.FAIL);
|
||||
print("GL Handle 'WriteFile' command", EMsgType.FAIL);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
@ -926,7 +930,7 @@ class GoldLeaf_07 extends TransferModule {
|
|||
command.add(intToArrLE(selectedFileNameBytes.length / 2)); // since GL 0.7
|
||||
command.add(selectedFileNameBytes);
|
||||
if (writeGL_PASS(command)) {
|
||||
logPrinter.print("GL Handle 'SelectFile' command", EMsgType.FAIL);
|
||||
print("GL Handle 'SelectFile' command", EMsgType.FAIL);
|
||||
this.selectedFile = null;
|
||||
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
|
||||
continue;
|
||||
default:
|
||||
logPrinter.print("GL Data transfer issue [read]\n Returned: " +
|
||||
print("GL Data transfer issue [read]\n Returned: " +
|
||||
UsbErrorCodes.getErrCode(result) +
|
||||
"\n GL Execution stopped", EMsgType.FAIL);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
logPrinter.print("GL Execution interrupted", EMsgType.INFO);
|
||||
print("GL Execution interrupted", EMsgType.INFO);
|
||||
return null;
|
||||
}
|
||||
private byte[] readGL_file(){
|
||||
|
@ -1035,13 +1039,13 @@ class GoldLeaf_07 extends TransferModule {
|
|||
case LibUsb.ERROR_TIMEOUT:
|
||||
continue;
|
||||
default:
|
||||
logPrinter.print("GL Data transfer issue [read]\n Returned: " +
|
||||
print("GL Data transfer issue [read]\n Returned: " +
|
||||
UsbErrorCodes.getErrCode(result) +
|
||||
"\n GL Execution stopped", EMsgType.FAIL);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
logPrinter.print("GL Execution interrupted", EMsgType.INFO);
|
||||
print("GL Execution interrupted", EMsgType.INFO);
|
||||
return null;
|
||||
}
|
||||
/**
|
||||
|
@ -1066,10 +1070,10 @@ class GoldLeaf_07 extends TransferModule {
|
|||
|
||||
private boolean writeGL_FAIL(String reportToUImsg){
|
||||
if (writeToUsb(Arrays.copyOf(CMD_GLCO_FAILURE, 4096))){
|
||||
logPrinter.print(reportToUImsg, EMsgType.WARNING);
|
||||
print(reportToUImsg, EMsgType.WARNING);
|
||||
return true;
|
||||
}
|
||||
logPrinter.print(reportToUImsg, EMsgType.FAIL);
|
||||
print(reportToUImsg, EMsgType.FAIL);
|
||||
return false;
|
||||
}
|
||||
/**
|
||||
|
@ -1091,7 +1095,7 @@ class GoldLeaf_07 extends TransferModule {
|
|||
if (writeBufTransferred.get() == message.length)
|
||||
return false;
|
||||
else {
|
||||
logPrinter.print("GL Data transfer issue [write]\n Requested: " +
|
||||
print("GL Data transfer issue [write]\n Requested: " +
|
||||
message.length +
|
||||
"\n Transferred: " +
|
||||
writeBufTransferred.get(), EMsgType.FAIL);
|
||||
|
@ -1100,13 +1104,13 @@ class GoldLeaf_07 extends TransferModule {
|
|||
case LibUsb.ERROR_TIMEOUT:
|
||||
continue;
|
||||
default:
|
||||
logPrinter.print("GL Data transfer issue [write]\n Returned: " +
|
||||
print("GL Data transfer issue [write]\n Returned: " +
|
||||
UsbErrorCodes.getErrCode(result) +
|
||||
"\n GL Execution stopped", EMsgType.FAIL);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
logPrinter.print("GL Execution interrupted", EMsgType.INFO);
|
||||
print("GL Execution interrupted", EMsgType.INFO);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -103,7 +103,7 @@ class GoldLeaf_08 extends TransferModule {
|
|||
|
||||
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" +
|
||||
"HOME:/ equals "
|
||||
+System.getProperty("user.home"), EMsgType.INFO);
|
||||
|
@ -273,7 +273,7 @@ class GoldLeaf_08 extends TransferModule {
|
|||
* */
|
||||
private boolean startOrEndFile(){
|
||||
if (writeGL_PASS()){
|
||||
logPrinter.print("GL Handle 'StartFile' command", EMsgType.FAIL);
|
||||
print("GL Handle 'StartFile' command", EMsgType.FAIL);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
@ -288,7 +288,7 @@ class GoldLeaf_08 extends TransferModule {
|
|||
byte[] drivesCnt = intToArrLE(2); //2
|
||||
// Write count of drives
|
||||
if (writeGL_PASS(drivesCnt)) {
|
||||
logPrinter.print("GL Handle 'ListDrives' command", EMsgType.FAIL);
|
||||
print("GL Handle 'ListDrives' command", EMsgType.FAIL);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
@ -344,7 +344,7 @@ class GoldLeaf_08 extends TransferModule {
|
|||
command.add(totalSize);
|
||||
|
||||
if (writeGL_PASS(command)) {
|
||||
logPrinter.print("GL Handle 'GetDriveInfo' command", EMsgType.FAIL);
|
||||
print("GL Handle 'GetDriveInfo' command", EMsgType.FAIL);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -360,7 +360,7 @@ class GoldLeaf_08 extends TransferModule {
|
|||
byte[] specialPathCnt = intToArrLE(0);
|
||||
// Write count of special paths
|
||||
if (writeGL_PASS(specialPathCnt)) {
|
||||
logPrinter.print("GL Handle 'SpecialPathCount' command", EMsgType.FAIL);
|
||||
print("GL Handle 'SpecialPathCount' command", EMsgType.FAIL);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
@ -382,13 +382,13 @@ class GoldLeaf_08 extends TransferModule {
|
|||
if (path.equals("VIRT:/")) {
|
||||
if (isGetDirectoryCount){
|
||||
if (writeGL_PASS()) {
|
||||
logPrinter.print("GL Handle 'GetDirectoryCount' command", EMsgType.FAIL);
|
||||
print("GL Handle 'GetDirectoryCount' command", EMsgType.FAIL);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else {
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
@ -429,7 +429,7 @@ class GoldLeaf_08 extends TransferModule {
|
|||
// If somehow there are no folders, let's say 0;
|
||||
if (filesOrDirs == null){
|
||||
if (writeGL_PASS()) {
|
||||
logPrinter.print("GL Handle 'GetDirectoryOrFileCount' command", EMsgType.FAIL);
|
||||
print("GL Handle 'GetDirectoryOrFileCount' command", EMsgType.FAIL);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
@ -443,20 +443,20 @@ class GoldLeaf_08 extends TransferModule {
|
|||
this.recentFiles = filesOrDirs;
|
||||
// Otherwise, let's tell how may folders are in there
|
||||
if (writeGL_PASS(intToArrLE(filesOrDirs.length))) {
|
||||
logPrinter.print("GL Handle 'GetDirectoryOrFileCount' command", EMsgType.FAIL);
|
||||
print("GL Handle 'GetDirectoryOrFileCount' command", EMsgType.FAIL);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else if (path.startsWith("SPEC:/")){
|
||||
if (isGetDirectoryCount){ // If dir request then 0 dirs
|
||||
if (writeGL_PASS()) {
|
||||
logPrinter.print("GL Handle 'GetDirectoryCount' command", EMsgType.FAIL);
|
||||
print("GL Handle 'GetDirectoryCount' command", EMsgType.FAIL);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else if (selectedFile != null){ // Else it's file request, if we have selected then we will report 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;
|
||||
}
|
||||
}
|
||||
|
@ -510,7 +510,7 @@ class GoldLeaf_08 extends TransferModule {
|
|||
// return proxyGetDirFile(true);
|
||||
|
||||
if (writeGL_PASS(command)) {
|
||||
logPrinter.print("GL Handle 'GetDirectory' command.", EMsgType.FAIL);
|
||||
print("GL Handle 'GetDirectory' command.", EMsgType.FAIL);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
@ -567,7 +567,7 @@ class GoldLeaf_08 extends TransferModule {
|
|||
//if (proxyForGL) // TODO: NOTE: PROXY TAILS
|
||||
// return proxyGetDirFile(false);
|
||||
if (writeGL_PASS(command)) {
|
||||
logPrinter.print("GL Handle 'GetFile' command.", EMsgType.FAIL);
|
||||
print("GL Handle 'GetFile' command.", EMsgType.FAIL);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
@ -578,7 +578,7 @@ class GoldLeaf_08 extends TransferModule {
|
|||
command.add(intToArrLE(fileNameBytes.length / 2)); // since GL 0.7
|
||||
command.add(fileNameBytes);
|
||||
if (writeGL_PASS(command)) {
|
||||
logPrinter.print("GL Handle 'GetFile' command.", EMsgType.FAIL);
|
||||
print("GL Handle 'GetFile' command.", EMsgType.FAIL);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
@ -590,7 +590,7 @@ class GoldLeaf_08 extends TransferModule {
|
|||
command.add(intToArrLE(fileNameBytes.length / 2)); // since GL 0.7
|
||||
command.add(fileNameBytes);
|
||||
if (writeGL_PASS(command)) {
|
||||
logPrinter.print("GL Handle 'GetFile' command.", EMsgType.FAIL);
|
||||
print("GL Handle 'GetFile' command.", EMsgType.FAIL);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
@ -621,7 +621,7 @@ class GoldLeaf_08 extends TransferModule {
|
|||
command.add(longToArrLE(fileDirElement.length()));
|
||||
}
|
||||
if (writeGL_PASS(command)) {
|
||||
logPrinter.print("GL Handle 'StatPath' command.", EMsgType.FAIL);
|
||||
print("GL Handle 'StatPath' command.", EMsgType.FAIL);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
@ -638,7 +638,7 @@ class GoldLeaf_08 extends TransferModule {
|
|||
command.add(longToArrLE(nspMap.get(filePath).length())); // YES, THIS IS LONG!
|
||||
|
||||
if (writeGL_PASS(command)) {
|
||||
logPrinter.print("GL Handle 'StatPath' command.", EMsgType.FAIL);
|
||||
print("GL Handle 'StatPath' command.", EMsgType.FAIL);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
@ -651,7 +651,7 @@ class GoldLeaf_08 extends TransferModule {
|
|||
command.add(GL_OBJ_TYPE_FILE);
|
||||
command.add(longToArrLE(selectedFile.length()));
|
||||
if (writeGL_PASS(command)) {
|
||||
logPrinter.print("GL Handle 'StatPath' command.", EMsgType.FAIL);
|
||||
print("GL Handle 'StatPath' command.", EMsgType.FAIL);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
@ -679,7 +679,7 @@ class GoldLeaf_08 extends TransferModule {
|
|||
try {
|
||||
if (currentFile.renameTo(newFile)){
|
||||
if (writeGL_PASS()) {
|
||||
logPrinter.print("GL Handle 'Rename' command.", EMsgType.FAIL);
|
||||
print("GL Handle 'Rename' command.", EMsgType.FAIL);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
@ -704,7 +704,7 @@ class GoldLeaf_08 extends TransferModule {
|
|||
try {
|
||||
if (fileToDel.delete()){
|
||||
if (writeGL_PASS()) {
|
||||
logPrinter.print("GL Handle 'Rename' command.", EMsgType.FAIL);
|
||||
print("GL Handle 'Rename' command.", EMsgType.FAIL);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
@ -742,10 +742,10 @@ class GoldLeaf_08 extends TransferModule {
|
|||
}
|
||||
if (result){
|
||||
if (writeGL_PASS()) {
|
||||
logPrinter.print("GL Handle 'Create' command.", EMsgType.FAIL);
|
||||
print("GL Handle 'Create' command.", EMsgType.FAIL);
|
||||
return true;
|
||||
}
|
||||
//logPrinter.print("GL Handle 'Create' command.", EMsgType.PASS);
|
||||
//print("GL Handle 'Create' command.", EMsgType.PASS);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -830,12 +830,12 @@ class GoldLeaf_08 extends TransferModule {
|
|||
"\n Received: " + bytesRead);
|
||||
// Let's tell as a command about our result.
|
||||
if (writeGL_PASS(longToArrLE(size))) {
|
||||
logPrinter.print("GL Handle 'ReadFile' command [CMD]", EMsgType.FAIL);
|
||||
print("GL Handle 'ReadFile' command [CMD]", EMsgType.FAIL);
|
||||
return true;
|
||||
}
|
||||
// Let's bypass bytes we read total
|
||||
if (writeToUsb(chunk)) {
|
||||
logPrinter.print("GL Handle 'ReadFile' command", EMsgType.FAIL);
|
||||
print("GL Handle 'ReadFile' command", EMsgType.FAIL);
|
||||
return true;
|
||||
}
|
||||
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);
|
||||
// Let's tell as a command about our result.
|
||||
if (writeGL_PASS(longToArrLE(size))) {
|
||||
logPrinter.print("GL Handle 'ReadFile' command [CMD]", EMsgType.FAIL);
|
||||
print("GL Handle 'ReadFile' command [CMD]", EMsgType.FAIL);
|
||||
return true;
|
||||
}
|
||||
// Let's bypass bytes we read total
|
||||
if (writeToUsb(chunk)) {
|
||||
logPrinter.print("GL Handle 'ReadFile' command", EMsgType.FAIL);
|
||||
print("GL Handle 'ReadFile' command", EMsgType.FAIL);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
@ -867,14 +867,14 @@ class GoldLeaf_08 extends TransferModule {
|
|||
}
|
||||
catch (NullPointerException ignored){}
|
||||
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{
|
||||
splitReader.close();
|
||||
}
|
||||
catch (NullPointerException ignored){}
|
||||
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;
|
||||
randAccessFile = null;
|
||||
|
@ -916,7 +916,7 @@ class GoldLeaf_08 extends TransferModule {
|
|||
byte[] transferredData;
|
||||
|
||||
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;
|
||||
}
|
||||
try{
|
||||
|
@ -927,7 +927,7 @@ class GoldLeaf_08 extends TransferModule {
|
|||
}
|
||||
// Report we're good
|
||||
if (writeGL_PASS()) {
|
||||
logPrinter.print("GL Handle 'WriteFile' command", EMsgType.FAIL);
|
||||
print("GL Handle 'WriteFile' command", EMsgType.FAIL);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
@ -957,7 +957,7 @@ class GoldLeaf_08 extends TransferModule {
|
|||
command.add(intToArrLE(selectedFileNameBytes.length / 2)); // since GL 0.7
|
||||
command.add(selectedFileNameBytes);
|
||||
if (writeGL_PASS(command)) {
|
||||
logPrinter.print("GL Handle 'SelectFile' command", EMsgType.FAIL);
|
||||
print("GL Handle 'SelectFile' command", EMsgType.FAIL);
|
||||
this.selectedFile = null;
|
||||
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
|
||||
continue;
|
||||
default:
|
||||
logPrinter.print("GL Data transfer issue [read]\n Returned: " +
|
||||
print("GL Data transfer issue [read]\n Returned: " +
|
||||
UsbErrorCodes.getErrCode(result) +
|
||||
"\n GL Execution stopped", EMsgType.FAIL);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
logPrinter.print("GL Execution interrupted", EMsgType.INFO);
|
||||
print("GL Execution interrupted", EMsgType.INFO);
|
||||
return null;
|
||||
}
|
||||
private byte[] readGL_file(){
|
||||
|
@ -1060,13 +1060,13 @@ class GoldLeaf_08 extends TransferModule {
|
|||
case LibUsb.ERROR_TIMEOUT:
|
||||
continue;
|
||||
default:
|
||||
logPrinter.print("GL Data transfer issue [read]\n Returned: " +
|
||||
print("GL Data transfer issue [read]\n Returned: " +
|
||||
UsbErrorCodes.getErrCode(result) +
|
||||
"\n GL Execution stopped", EMsgType.FAIL);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
logPrinter.print("GL Execution interrupted", EMsgType.INFO);
|
||||
print("GL Execution interrupted", EMsgType.INFO);
|
||||
return null;
|
||||
}
|
||||
/**
|
||||
|
@ -1091,10 +1091,10 @@ class GoldLeaf_08 extends TransferModule {
|
|||
|
||||
private boolean writeGL_FAIL(String reportToUImsg){
|
||||
if (writeToUsb(Arrays.copyOf(CMD_GLCO_FAILURE, 4096))){
|
||||
logPrinter.print(reportToUImsg, EMsgType.WARNING);
|
||||
print(reportToUImsg, EMsgType.WARNING);
|
||||
return true;
|
||||
}
|
||||
logPrinter.print(reportToUImsg, EMsgType.FAIL);
|
||||
print(reportToUImsg, EMsgType.FAIL);
|
||||
return false;
|
||||
}
|
||||
/**
|
||||
|
@ -1116,7 +1116,7 @@ class GoldLeaf_08 extends TransferModule {
|
|||
if (writeBufTransferred.get() == message.length)
|
||||
return false;
|
||||
else {
|
||||
logPrinter.print("GL Data transfer issue [write]\n Requested: " +
|
||||
print("GL Data transfer issue [write]\n Requested: " +
|
||||
message.length +
|
||||
"\n Transferred: "+writeBufTransferred.get(), EMsgType.FAIL);
|
||||
return true;
|
||||
|
@ -1124,13 +1124,13 @@ class GoldLeaf_08 extends TransferModule {
|
|||
case LibUsb.ERROR_TIMEOUT:
|
||||
continue;
|
||||
default:
|
||||
logPrinter.print("GL Data transfer issue [write]\n Returned: " +
|
||||
print("GL Data transfer issue [write]\n Returned: " +
|
||||
UsbErrorCodes.getErrCode(result) +
|
||||
"\n GL Execution stopped", EMsgType.FAIL);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
logPrinter.print("GL Execution interrupted", EMsgType.INFO);
|
||||
print("GL Execution interrupted", EMsgType.INFO);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -50,7 +50,7 @@ class TinFoil extends TransferModule {
|
|||
|
||||
TinFoil(DeviceHandle handler, LinkedHashMap<String, File> nspMap, CancellableRunnable task, ILogPrinter logPrinter){
|
||||
super(handler, nspMap, task, logPrinter);
|
||||
logPrinter.print("============= Tinfoil =============", EMsgType.INFO);
|
||||
print("============= Tinfoil =============", EMsgType.INFO);
|
||||
|
||||
if (! sendListOfFiles())
|
||||
return;
|
||||
|
@ -69,25 +69,25 @@ class TinFoil extends TransferModule {
|
|||
byte[] padding = new byte[8];
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
logPrinter.print("TF Send list of files complete.", EMsgType.PASS);
|
||||
print("TF Send list of files complete.", EMsgType.PASS);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -114,7 +114,7 @@ class TinFoil extends TransferModule {
|
|||
* After we sent commands to NS, this chain starts
|
||||
* */
|
||||
private boolean proceedCommands(){
|
||||
logPrinter.print("TF Awaiting for NS commands.", EMsgType.INFO);
|
||||
print("TF Awaiting for NS commands.", EMsgType.INFO);
|
||||
try{
|
||||
byte[] deviceReply;
|
||||
byte command;
|
||||
|
@ -127,18 +127,18 @@ class TinFoil extends TransferModule {
|
|||
|
||||
switch (command){
|
||||
case CMD_EXIT:
|
||||
logPrinter.print("TF Transfer complete.", EMsgType.PASS);
|
||||
print("TF Transfer complete.", EMsgType.PASS);
|
||||
return true;
|
||||
case CMD_FILE_RANGE_DEFAULT:
|
||||
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())
|
||||
return false; // catches exception
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception e){
|
||||
logPrinter.print(e.getMessage(), EMsgType.INFO);
|
||||
print(e.getMessage(), EMsgType.INFO);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -169,7 +169,7 @@ class TinFoil extends TransferModule {
|
|||
|
||||
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 Size: %-20d 0x%x",
|
||||
nspFileName,
|
||||
|
@ -188,28 +188,28 @@ class TinFoil extends TransferModule {
|
|||
else
|
||||
sendNormalFile(nspFile, size, offset);
|
||||
} catch (IOException ioe){
|
||||
logPrinter.print("TF IOException:\n "+ioe.getMessage(), EMsgType.FAIL);
|
||||
print("TF IOException:\n "+ioe.getMessage(), EMsgType.FAIL);
|
||||
ioe.printStackTrace();
|
||||
return true;
|
||||
} 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);
|
||||
ae.printStackTrace();
|
||||
return true;
|
||||
} 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);
|
||||
npe.printStackTrace();
|
||||
return true;
|
||||
}
|
||||
catch (Exception defe){
|
||||
logPrinter.print(defe.getMessage(), EMsgType.FAIL);
|
||||
print(defe.getMessage(), EMsgType.FAIL);
|
||||
return true;
|
||||
}
|
||||
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;
|
||||
long currentOffset = 0;
|
||||
int chunk = 8388608; // = 8Mb;
|
||||
|
@ -237,7 +237,7 @@ class TinFoil extends TransferModule {
|
|||
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;
|
||||
long currentOffset = 0;
|
||||
int chunk = 8388608;
|
||||
|
@ -278,17 +278,17 @@ class TinFoil extends TransferModule {
|
|||
final byte[] twelveZeroBytes = new byte[12];
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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 false;
|
||||
|
@ -308,7 +308,7 @@ class TinFoil extends TransferModule {
|
|||
while (! task.isCancelled() ) {
|
||||
/*
|
||||
if (varVar != 0)
|
||||
logPrinter.print("writeUsb() retry cnt: "+varVar, EMsgType.INFO); //NOTE: DEBUG
|
||||
print("writeUsb() retry cnt: "+varVar, EMsgType.INFO); //NOTE: DEBUG
|
||||
varVar++;
|
||||
*/
|
||||
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:
|
||||
if (writeBufTransferred.get() == message.length)
|
||||
return false;
|
||||
logPrinter.print("TF Data transfer issue [write]" +
|
||||
print("TF Data transfer issue [write]" +
|
||||
"\n Requested: "+message.length+
|
||||
"\n Transferred: "+writeBufTransferred.get(), EMsgType.FAIL);
|
||||
return true;
|
||||
|
@ -326,13 +326,13 @@ class TinFoil extends TransferModule {
|
|||
//writeBufTransferred.clear(); // MUST BE HERE IF WE 'GET()' IT
|
||||
continue;
|
||||
default:
|
||||
logPrinter.print("TF Data transfer issue [write]" +
|
||||
print("TF Data transfer issue [write]" +
|
||||
"\n Returned: "+ UsbErrorCodes.getErrCode(result) +
|
||||
"\n (execution stopped)", EMsgType.FAIL);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
logPrinter.print("TF Execution interrupted", EMsgType.INFO);
|
||||
print("TF Execution interrupted", EMsgType.INFO);
|
||||
return true;
|
||||
}
|
||||
/**
|
||||
|
|
|
@ -51,7 +51,7 @@ public abstract class TransferModule {
|
|||
File[] subFiles = f.listFiles((file, name) -> name.matches("[0-9]{2}"));
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -59,7 +59,7 @@ public abstract class TransferModule {
|
|||
|
||||
for (int i = subFiles.length - 2; i > 0 ; i--){
|
||||
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);
|
||||
return true;
|
||||
}
|
||||
|
@ -69,7 +69,7 @@ public abstract class TransferModule {
|
|||
long lastFileLength = subFiles[subFiles.length-1].length();
|
||||
|
||||
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);
|
||||
return true;
|
||||
}
|
||||
|
@ -77,4 +77,13 @@ public abstract class TransferModule {
|
|||
});
|
||||
}
|
||||
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
|
||||
public void run() {
|
||||
logPrinter.print("\tStart", EMsgType.INFO);
|
||||
print("\tStart", EMsgType.INFO);
|
||||
|
||||
UsbConnect usbConnect = UsbConnect.connectHomebrewMode(logPrinter);
|
||||
|
||||
|
@ -87,7 +87,15 @@ public class UsbCommunications extends CancellableRunnable {
|
|||
*/
|
||||
private void close(EFileStatus status){
|
||||
logPrinter.update(nspMap, status);
|
||||
logPrinter.print("\tEnd", EMsgType.INFO);
|
||||
print("\tEnd", EMsgType.INFO);
|
||||
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;
|
||||
}
|
||||
catch (Exception e){
|
||||
try {
|
||||
logPrinter.print(e.getMessage(), EMsgType.FAIL);
|
||||
}
|
||||
catch (InterruptedException ignore){}
|
||||
usbConnect.close();
|
||||
}
|
||||
|
||||
|
@ -89,7 +92,10 @@ public class UsbConnect {
|
|||
}
|
||||
catch (Exception e){
|
||||
e.printStackTrace();
|
||||
try {
|
||||
logPrinter.print(e.getMessage(), EMsgType.FAIL);
|
||||
}
|
||||
catch (InterruptedException ignore){}
|
||||
usbConnect.close();
|
||||
}
|
||||
return usbConnect;
|
||||
|
@ -100,7 +106,7 @@ public class UsbConnect {
|
|||
private UsbConnect(ILogPrinter logPrinter){
|
||||
this.logPrinter = logPrinter;
|
||||
this.connected = false;
|
||||
};
|
||||
}
|
||||
|
||||
private void createContextAndInitLibUSB() throws Exception{
|
||||
// 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.
|
||||
returningValue = LibUsb.setAutoDetachKernelDriver(handlerNS, true);
|
||||
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);
|
||||
|
||||
if (returningValue != LibUsb.SUCCESS) {
|
||||
logPrinter.print("Release interface failure: " +
|
||||
print("Release interface failure: " +
|
||||
UsbErrorCodes.getErrCode(returningValue) +
|
||||
" (sometimes it's not an issue)", EMsgType.WARNING);
|
||||
}
|
||||
|
@ -241,4 +247,13 @@ public class UsbConnect {
|
|||
if (contextNS != null)
|
||||
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>
|
||||
</children>
|
||||
</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>
|
||||
<RadioButton fx:id="splitRad" contentDisplay="TOP" mnemonicParsing="false" text="%tabSplMrg_RadioBtn_Split">
|
||||
<toggleGroup>
|
||||
|
@ -50,47 +53,14 @@
|
|||
</toggleGroup>
|
||||
</RadioButton>
|
||||
<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>
|
||||
<Insets left="15.0" right="15.0" />
|
||||
<Insets bottom="10.0" />
|
||||
</VBox.margin>
|
||||
</VBox>
|
||||
<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>
|
||||
</Button>
|
||||
<Label text="%tabSplMrg_Lbl_SaveToLocation" />
|
||||
<Label fx:id="saveToPathLbl" />
|
||||
</children>
|
||||
</HBox>
|
||||
<Label fx:id="saveToPathLbl" maxWidth="200.0" textOverrun="CENTER_WORD_ELLIPSIS" />
|
||||
<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" />
|
||||
<VBox>
|
||||
<children>
|
||||
|
@ -101,6 +71,21 @@
|
|||
</HBox>
|
||||
</children>
|
||||
</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>
|
||||
<Insets bottom="5.0" left="5.0" right="5.0" top="5.0" />
|
||||
</padding>
|
||||
|
|
|
@ -205,6 +205,7 @@
|
|||
.table-view .table-cell{
|
||||
-fx-text-fill: #f7fafa;
|
||||
}
|
||||
|
||||
.table-row-cell, .table-row-cell:selected, .table-row-cell:filled:selected{
|
||||
-fx-background-color: -fx-table-cell-border-color, #424242;
|
||||
-fx-background-insets: 0, 0 0 1 0;
|
||||
|
@ -223,7 +224,35 @@
|
|||
-fx-padding: 0.0em; /* 0 */
|
||||
-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 {
|
||||
-fx-background-color: #2d2d2d;
|
||||
-fx-cursor: hand;
|
||||
|
@ -234,7 +263,7 @@
|
|||
.context-menu .menu-item:focused .label {
|
||||
-fx-text-fill: white;
|
||||
}
|
||||
// -========================== Text Field =====================-
|
||||
/* -========================== Text Field =====================- */
|
||||
.text-field {
|
||||
-fx-prompt-text-fill: #40596c;
|
||||
-fx-border-color: #289de8;
|
||||
|
|
|
@ -242,6 +242,35 @@
|
|||
-fx-padding: 0.0em; /* 0 */
|
||||
-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 *.line {
|
||||
-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