Solve - #87. Break LogPrinterGui
This commit is contained in:
		
							parent
							
								
									79c519b1f3
								
							
						
					
					
						commit
						1176ad9e83
					
				
					 32 changed files with 1348 additions and 738 deletions
				
			
		|  | @ -0,0 +1,102 @@ | |||
| /* | ||||
|     Copyright 2019-2021 Dmitry Isaenko | ||||
|       | ||||
|     This file is part of NS-USBloader. | ||||
| 
 | ||||
|     NS-USBloader is free software: you can redistribute it and/or modify | ||||
|     it under the terms of the GNU General Public License as published by | ||||
|     the Free Software Foundation, either version 3 of the License, or | ||||
|     (at your option) any later version. | ||||
| 
 | ||||
|     NS-USBloader is distributed in the hope that it will be useful, | ||||
|     but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|     GNU General Public License for more details. | ||||
| 
 | ||||
|     You should have received a copy of the GNU General Public License | ||||
|     along with NS-USBloader.  If not, see <https://www.gnu.org/licenses/>. | ||||
|  */ | ||||
| package nsusbloader.Controllers; | ||||
| 
 | ||||
| import javafx.collections.ObservableList; | ||||
| import javafx.fxml.FXML; | ||||
| import javafx.fxml.Initializable; | ||||
| import javafx.scene.control.ContextMenu; | ||||
| import javafx.scene.control.ListCell; | ||||
| import javafx.scene.control.ListView; | ||||
| import javafx.scene.control.MenuItem; | ||||
| 
 | ||||
| import java.io.File; | ||||
| import java.net.URL; | ||||
| import java.util.List; | ||||
| import java.util.ResourceBundle; | ||||
| 
 | ||||
| public class BlockListViewController implements Initializable { | ||||
| 
 | ||||
|     @FXML | ||||
|     private ListView<File> splitMergeListView; | ||||
|     private ObservableList<File> filesList; | ||||
| 
 | ||||
|     private ResourceBundle resourceBundle; | ||||
| 
 | ||||
|     private static class FileListCell extends ListCell<File>{ | ||||
|         @Override | ||||
|         public void updateItem(File file, boolean isEmpty){ | ||||
|             super.updateItem(file, isEmpty); | ||||
| 
 | ||||
|             if (file == null || isEmpty){ | ||||
|                 setText(null); | ||||
|                 return; | ||||
|             } | ||||
|             String fileName = file.getName(); | ||||
|             setText(fileName); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public void initialize(URL url, ResourceBundle resourceBundle) { | ||||
|         this.resourceBundle = resourceBundle; | ||||
|         setFilesListView(); | ||||
|         filesList = splitMergeListView.getItems(); | ||||
|     } | ||||
|     private void setFilesListView(){ | ||||
|         splitMergeListView.setCellFactory(fileListView -> { | ||||
|             ListCell<File> item = new FileListCell(); | ||||
|             setContextMenuToItem(item); | ||||
|             return item; | ||||
|         }); | ||||
|     } | ||||
| 
 | ||||
|     private <T> void setContextMenuToItem(ListCell<T> item){ | ||||
|         ContextMenu contextMenu = new ContextMenu(); | ||||
|         MenuItem deleteMenuItem = new MenuItem(resourceBundle.getString("tab1_table_contextMenu_Btn_BtnDelete")); | ||||
|         deleteMenuItem.setOnAction(actionEvent -> { | ||||
|             filesList.remove(item.getItem()); | ||||
|             splitMergeListView.refresh(); | ||||
|         }); | ||||
|         MenuItem deleteAllMenuItem = new MenuItem(resourceBundle.getString("tab1_table_contextMenu_Btn_DeleteAll")); | ||||
|         deleteAllMenuItem.setOnAction(actionEvent -> { | ||||
|             filesList.clear(); | ||||
|             splitMergeListView.refresh(); | ||||
|         }); | ||||
|         contextMenu.getItems().addAll(deleteMenuItem, deleteAllMenuItem); | ||||
| 
 | ||||
|         item.setContextMenu(contextMenu); | ||||
|     } | ||||
| 
 | ||||
|     public void add(File file){ | ||||
|         if (filesList.contains(file)) | ||||
|             return; | ||||
|         filesList.add(file); | ||||
|     } | ||||
|     public void addAll(List<File> files){ | ||||
|         for (File file : files) { | ||||
|             add(file); | ||||
|         } | ||||
|     } | ||||
|     public ObservableList<File> getItems(){ return filesList; } | ||||
|     public void clear(){ | ||||
|         filesList.clear(); | ||||
|         splitMergeListView.refresh(); | ||||
|     } | ||||
| } | ||||
|  | @ -46,7 +46,7 @@ public class NSLMainController implements Initializable { | |||
|     private Tab GamesTabHolder, RCMTabHolder, SMTabHolder; | ||||
| 
 | ||||
|     @FXML | ||||
|     private GamesController GamesTabController;             // Accessible from Mediator | todo: incapsulate | ||||
|     private GamesController GamesTabController; | ||||
|     @FXML | ||||
|     private SettingsController SettingsTabController; | ||||
|     @FXML | ||||
|  | @ -69,30 +69,32 @@ public class NSLMainController implements Initializable { | |||
|         MediatorControl.getInstance().setController(this); | ||||
| 
 | ||||
|         if (AppPreferences.getInstance().getAutoCheckUpdates()){ | ||||
|             Task<List<String>> updTask = new UpdatesChecker(); | ||||
|             updTask.setOnSucceeded(event->{ | ||||
|                 List<String> result = updTask.getValue(); | ||||
|                 if (result != null){ | ||||
|                     if (!result.get(0).isEmpty()) { | ||||
|                         SettingsTabController.getGenericSettings().setNewVersionLink(result.get(0)); | ||||
|                         ServiceWindow.getInfoNotification( | ||||
|                                 resourceBundle.getString("windowTitleNewVersionAval"), | ||||
|                                 resourceBundle.getString("windowTitleNewVersionAval") + ": " + result.get(0) + "\n\n" + result.get(1)); | ||||
|                     } | ||||
|                 } | ||||
|                 else | ||||
|                     ServiceWindow.getInfoNotification( | ||||
|                             resourceBundle.getString("windowTitleNewVersionUnknown"), | ||||
|                             resourceBundle.getString("windowBodyNewVersionUnknown")); | ||||
|             }); | ||||
|             Thread updates = new Thread(updTask); | ||||
|             updates.setDaemon(true); | ||||
|             updates.start(); | ||||
|             checkForUpdates(); | ||||
|         } | ||||
| 
 | ||||
|         openLastOpenedTab(); | ||||
|     } | ||||
| 
 | ||||
|     private void checkForUpdates(){ | ||||
|         Task<List<String>> updTask = new UpdatesChecker(); | ||||
|         updTask.setOnSucceeded(event->{ | ||||
|             List<String> result = updTask.getValue(); | ||||
|             if (result != null){ | ||||
|                 if (!result.get(0).isEmpty()) { | ||||
|                     SettingsTabController.getGenericSettings().setNewVersionLink(result.get(0)); | ||||
|                     ServiceWindow.getInfoNotification( | ||||
|                             resourceBundle.getString("windowTitleNewVersionAval"), | ||||
|                             resourceBundle.getString("windowTitleNewVersionAval") + ": " + result.get(0) + "\n\n" + result.get(1)); | ||||
|                 } | ||||
|             } | ||||
|             else | ||||
|                 ServiceWindow.getInfoNotification( | ||||
|                         resourceBundle.getString("windowTitleNewVersionUnknown"), | ||||
|                         resourceBundle.getString("windowBodyNewVersionUnknown")); | ||||
|         }); | ||||
|         Thread updates = new Thread(updTask); | ||||
|         updates.setDaemon(true); | ||||
|         updates.start(); | ||||
|     } | ||||
|     /** | ||||
|      * 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,38 +49,30 @@ public class LogPrinterGui implements ILogPrinter { | |||
|      * This is what will print to textArea of the application. | ||||
|      * */ | ||||
|     @Override | ||||
|     public void print(String message, EMsgType type){ | ||||
|         try { | ||||
|             switch (type){ | ||||
|                 case PASS: | ||||
|                     msgQueue.put("[ PASS ] "+message+"\n"); | ||||
|                     break; | ||||
|                 case FAIL: | ||||
|                     msgQueue.put("[ FAIL ] "+message+"\n"); | ||||
|                     break; | ||||
|                 case INFO: | ||||
|                     msgQueue.put("[ INFO ] "+message+"\n"); | ||||
|                     break; | ||||
|                 case WARNING: | ||||
|                     msgQueue.put("[ WARN ] "+message+"\n"); | ||||
|                     break; | ||||
|                 default: | ||||
|                     msgQueue.put(message); | ||||
|             } | ||||
|         } | ||||
|         catch (InterruptedException ie){ | ||||
|             ie.printStackTrace(); | ||||
|     public void print(String message, EMsgType type) throws InterruptedException{ | ||||
|         switch (type){ | ||||
|             case PASS: | ||||
|                 msgQueue.put("[ PASS ] "+message+"\n"); | ||||
|                 break; | ||||
|             case FAIL: | ||||
|                 msgQueue.put("[ FAIL ] "+message+"\n"); | ||||
|                 break; | ||||
|             case INFO: | ||||
|                 msgQueue.put("[ INFO ] "+message+"\n"); | ||||
|                 break; | ||||
|             case WARNING: | ||||
|                 msgQueue.put("[ WARN ] "+message+"\n"); | ||||
|                 break; | ||||
|             default: | ||||
|                 msgQueue.put(message); | ||||
|         } | ||||
|     } | ||||
|     /** | ||||
|      * Update progress for progress bar | ||||
|      * */ | ||||
|     @Override | ||||
|     public void updateProgress(Double value) { | ||||
|         try { | ||||
|             progressQueue.put(value); | ||||
|         } | ||||
|         catch (InterruptedException ignored){}               // TODO: Do something with this | ||||
|     public void updateProgress(Double value) throws InterruptedException { | ||||
|         progressQueue.put(value); | ||||
|     } | ||||
|     /** | ||||
|      * 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; | ||||
| 
 | ||||
|  | @ -50,7 +50,7 @@ public class MessagesConsumer extends AnimationTimer { | |||
|                      BlockingQueue<String> msgQueue, | ||||
|                      BlockingQueue<Double> progressQueue, | ||||
|                      HashMap<String, EFileStatus> statusMap, | ||||
|                      AtomicBoolean oneLinerStatus) { | ||||
|                      AtomicBoolean oneLinerStatus){ | ||||
|         this.appModuleType = appModuleType; | ||||
|         this.isInterrupted = false; | ||||
| 
 | ||||
|  | @ -72,15 +72,15 @@ public class MessagesConsumer extends AnimationTimer { | |||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public void handle(long l) { | ||||
|     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,29 +89,31 @@ public class MessagesConsumer extends AnimationTimer { | |||
|             }); | ||||
|         } | ||||
| 
 | ||||
|         if (isInterrupted) {                                                // It's safe 'cuz it's could't be interrupted while HashMap populating | ||||
|             MediatorControl.getInstance().setBgThreadActive(false, appModuleType); | ||||
|             progressBar.setProgress(0.0); | ||||
|         if (isInterrupted)                 // It's safe 'cuz it's could't be interrupted while HashMap populating | ||||
|             updateElementsAndStop(); | ||||
|     } | ||||
| 
 | ||||
|             if (statusMap.size() > 0){ | ||||
|                 for (String key : statusMap.keySet()) | ||||
|                     tableViewController.setFileStatus(key, statusMap.get(key)); | ||||
|             } | ||||
|     private void updateElementsAndStop(){ | ||||
|         MediatorControl.getInstance().setBgThreadActive(false, appModuleType); | ||||
|         progressBar.setProgress(0.0); | ||||
| 
 | ||||
|             switch (appModuleType){ | ||||
|                 case RCM: | ||||
|                     MediatorControl.getInstance().getRcmController().setOneLineStatus(oneLinerStatus.get()); | ||||
|                     break; | ||||
|                 case NXDT: | ||||
|                     MediatorControl.getInstance().getNxdtController().setOneLineStatus(oneLinerStatus.get()); | ||||
|                     break; | ||||
|                 case SPLIT_MERGE_TOOL: | ||||
|                     MediatorControl.getInstance().getSplitMergeController().setOneLineStatus(oneLinerStatus.get()); | ||||
|                     break; | ||||
|             } | ||||
| 
 | ||||
|             this.stop(); | ||||
|         if (statusMap.size() > 0){ | ||||
|             for (String key : statusMap.keySet()) | ||||
|                 tableViewController.setFileStatus(key, statusMap.get(key)); | ||||
|         } | ||||
| 
 | ||||
|         switch (appModuleType){ | ||||
|             case RCM: | ||||
|                 MediatorControl.getInstance().getRcmController().setOneLineStatus(oneLinerStatus.get()); | ||||
|                 break; | ||||
|             case NXDT: | ||||
|                 MediatorControl.getInstance().getNxdtController().setOneLineStatus(oneLinerStatus.get()); | ||||
|                 break; | ||||
|             case SPLIT_MERGE_TOOL: | ||||
|                 MediatorControl.getInstance().getSplitMergeController().setOneLineStatus(oneLinerStatus.get()); | ||||
|                 break; | ||||
|         } | ||||
|         this.stop(); | ||||
|     } | ||||
| 
 | ||||
|     public void interrupt(){ | ||||
|  |  | |||
|  | @ -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); | ||||
|             Thread thread = new Thread(mergeTask); | ||||
|             thread.setDaemon(true); | ||||
|             thread.start(); | ||||
|             thread.join(); | ||||
|         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); | ||||
|             thread.setDaemon(true); | ||||
|             thread.start(); | ||||
|             thread.join(); | ||||
|         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,15 +55,21 @@ public class NetworkSetupValidator { | |||
|             resolvePort(hostPortNum); | ||||
|         } | ||||
|         catch (Exception e){ | ||||
|             logPrinter.print(e.getMessage(), EMsgType.FAIL); | ||||
|             try { | ||||
|                 logPrinter.print(e.getMessage(), EMsgType.FAIL); | ||||
|             } | ||||
|             catch (InterruptedException ignore){} | ||||
|             valid = false; | ||||
|             return; | ||||
|         } | ||||
|         valid = true; | ||||
|     } | ||||
| 
 | ||||
|     private void validateFiles(List<File> filesList) { | ||||
|         filesList.removeIf(f -> { | ||||
|     private void validateFiles(List<File> filesList){ | ||||
|         filesList.removeIf(this::validator); | ||||
|     } | ||||
|     private boolean validator(File f){ | ||||
|         try { | ||||
|             if (f.isFile()) | ||||
|                 return false; | ||||
| 
 | ||||
|  | @ -76,24 +82,27 @@ public class NetworkSetupValidator { | |||
| 
 | ||||
|             Arrays.sort(subFiles, Comparator.comparingInt(file -> Integer.parseInt(file.getName()))); | ||||
| 
 | ||||
|             for (int i = subFiles.length - 2; i > 0 ; i--){ | ||||
|                 if (subFiles[i].length() != subFiles[i-1].length()) { | ||||
|                     logPrinter.print("NET: Exclude split file: "+f.getName()+ | ||||
|             for (int i = subFiles.length - 2; i > 0; i--) { | ||||
|                 if (subFiles[i].length() != subFiles[i - 1].length()) { | ||||
|                     logPrinter.print("NET: Exclude split file: " + f.getName() + | ||||
|                             "\n      Chunk sizes of the split file are not the same, but has to be.", EMsgType.WARNING); | ||||
|                     return true; | ||||
|                 } | ||||
|             } | ||||
| 
 | ||||
|             long firstFileLength = subFiles[0].length(); | ||||
|             long lastFileLength = subFiles[subFiles.length-1].length(); | ||||
|             long lastFileLength = subFiles[subFiles.length - 1].length(); | ||||
| 
 | ||||
|             if (lastFileLength > firstFileLength){ | ||||
|                 logPrinter.print("NET: Exclude split file: "+f.getName()+ | ||||
|             if (lastFileLength > firstFileLength) { | ||||
|                 logPrinter.print("NET: Exclude split file: " + f.getName() + | ||||
|                         "\n      Chunk sizes of the split file are not the same, but has to be.", EMsgType.WARNING); | ||||
|                 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){ | ||||
|             logPrinter.print(e.getMessage(), EMsgType.FAIL); | ||||
|             try { | ||||
|                 logPrinter.print(e.getMessage(), EMsgType.FAIL); | ||||
|             } | ||||
|             catch (InterruptedException ignore){} | ||||
|             usbConnect.close(); | ||||
|         } | ||||
| 
 | ||||
|  | @ -89,7 +92,10 @@ public class UsbConnect { | |||
|         } | ||||
|         catch (Exception e){ | ||||
|             e.printStackTrace(); | ||||
|             logPrinter.print(e.getMessage(), EMsgType.FAIL); | ||||
|             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,47 +42,42 @@ | |||
|          </GridPane> | ||||
|       </children> | ||||
|    </VBox> | ||||
|    <VBox fillWidth="false" spacing="5.0"> | ||||
|    <HBox spacing="15.0" VBox.vgrow="ALWAYS"> | ||||
|       <children> | ||||
|          <RadioButton fx:id="splitRad" contentDisplay="TOP" mnemonicParsing="false" text="%tabSplMrg_RadioBtn_Split"> | ||||
|             <toggleGroup> | ||||
|                <ToggleGroup fx:id="splitMergeTogGrp" /> | ||||
|             </toggleGroup> | ||||
|          </RadioButton> | ||||
|          <RadioButton fx:id="mergeRad" contentDisplay="TOP" mnemonicParsing="false" text="%tabSplMrg_RadioBtn_Merge" toggleGroup="$splitMergeTogGrp" /> | ||||
|       </children> | ||||
|       <VBox.margin> | ||||
|          <Insets left="15.0" right="15.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> | ||||
|          <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> | ||||
|                      <ToggleGroup fx:id="splitMergeTogGrp" /> | ||||
|                   </toggleGroup> | ||||
|                </RadioButton> | ||||
|                <RadioButton fx:id="mergeRad" contentDisplay="TOP" mnemonicParsing="false" text="%tabSplMrg_RadioBtn_Merge" toggleGroup="$splitMergeTogGrp" /> | ||||
|                   <Button fx:id="selectFileFolderBtn" contentDisplay="TOP" mnemonicParsing="false"> | ||||
|                   <VBox.margin> | ||||
|                      <Insets bottom="10.0" /> | ||||
|                   </VBox.margin> | ||||
|                </Button> | ||||
|                   <Label text="%tabSplMrg_Lbl_SaveToLocation" /> | ||||
|                <Label fx:id="saveToPathLbl" /> | ||||
|                <Label fx:id="saveToPathLbl" maxWidth="200.0" textOverrun="CENTER_WORD_ELLIPSIS" /> | ||||
|                   <Button fx:id="changeSaveToBtn" contentDisplay="TOP" mnemonicParsing="false" text="%tabSplMrg_Btn_ChangeSaveToLocation" /> | ||||
|                <Pane VBox.vgrow="ALWAYS" /> | ||||
|                <VBox> | ||||
|                   <children> | ||||
|                      <HBox alignment="CENTER"> | ||||
|                         <children> | ||||
|                               <Button fx:id="convertBtn" contentDisplay="TOP" mnemonicParsing="false" styleClass="buttonUp" text="%tabSplMrg_Btn_Convert" /> | ||||
|                         </children> | ||||
|                      </HBox> | ||||
|                   </children> | ||||
|                </VBox> | ||||
|             </children> | ||||
|          </HBox> | ||||
|             <Button fx:id="changeSaveToBtn" contentDisplay="TOP" mnemonicParsing="false" text="%tabSplMrg_Btn_ChangeSaveToLocation" /> | ||||
|          </VBox> | ||||
|       </children> | ||||
|       <VBox.margin> | ||||
|          <Insets left="15.0" right="15.0" /> | ||||
|       </VBox.margin> | ||||
|    </VBox> | ||||
|    </HBox> | ||||
|    <HBox alignment="CENTER"> | ||||
|       <children> | ||||
|          <Label fx:id="statusLbl" /> | ||||
|  | @ -91,16 +86,6 @@ | |||
|          <Insets left="15.0" right="15.0" /> | ||||
|       </VBox.margin> | ||||
|    </HBox> | ||||
|    <Pane VBox.vgrow="ALWAYS" /> | ||||
|    <VBox> | ||||
|       <children> | ||||
|          <HBox alignment="CENTER"> | ||||
|             <children> | ||||
|                   <Button fx:id="convertBtn" contentDisplay="TOP" mnemonicParsing="false" styleClass="buttonUp" text="%tabSplMrg_Btn_Convert" /> | ||||
|             </children> | ||||
|          </HBox> | ||||
|       </children> | ||||
|    </VBox> | ||||
|    <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
	
	 Dmitry Isaenko
						Dmitry Isaenko