Improved logic, broke down in classes, Thread quicker
This commit is contained in:
@@ -3,9 +3,16 @@ package org.lumijiez;
|
|||||||
import org.lumijiez.gui.MainFrame;
|
import org.lumijiez.gui.MainFrame;
|
||||||
|
|
||||||
import javax.swing.*;
|
import javax.swing.*;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
public class Main {
|
public class Main {
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
SwingUtilities.invokeLater(() -> new MainFrame().setVisible(true));
|
SwingUtilities.invokeLater(() -> {
|
||||||
|
try {
|
||||||
|
new MainFrame().setVisible(true);
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -3,7 +3,10 @@ import org.lumijiez.tracker.TrackerThread;
|
|||||||
|
|
||||||
import javax.swing.*;
|
import javax.swing.*;
|
||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
public class MainFrame extends JFrame {
|
public class MainFrame extends JFrame {
|
||||||
private final JScrollPane fileListScrollPane = new JScrollPane();
|
private final JScrollPane fileListScrollPane = new JScrollPane();
|
||||||
@@ -19,47 +22,38 @@ public class MainFrame extends JFrame {
|
|||||||
private final JMenuItem pickFolder = new JMenuItem();
|
private final JMenuItem pickFolder = new JMenuItem();
|
||||||
private final JMenu settingsMenu = new JMenu();
|
private final JMenu settingsMenu = new JMenu();
|
||||||
private final JMenuItem settings = new JMenuItem();
|
private final JMenuItem settings = new JMenuItem();
|
||||||
|
private final Map<File, byte[]> fileContents = new HashMap<>();
|
||||||
|
private TrackerThread tracker;
|
||||||
|
|
||||||
public MainFrame() {
|
public MainFrame() throws IOException {
|
||||||
initComponents();
|
initComponents();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void initComponents() {
|
private void initComponents() {
|
||||||
|
|
||||||
|
mainTextPane.setContentType("text/html");
|
||||||
|
|
||||||
JFileChooser folderChooser = new JFileChooser();
|
JFileChooser folderChooser = new JFileChooser();
|
||||||
folderChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
|
folderChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
|
||||||
|
|
||||||
int returnVal = folderChooser.showOpenDialog(this);
|
|
||||||
if (returnVal == JFileChooser.APPROVE_OPTION) {
|
|
||||||
System.out.println("Selected folder: " + folderChooser.getSelectedFile().getAbsolutePath());
|
|
||||||
TrackerThread tr = new TrackerThread(mainTextPane, Path.of(folderChooser.getSelectedFile().getAbsolutePath()));
|
|
||||||
tr.start();
|
|
||||||
}
|
|
||||||
|
|
||||||
setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
|
setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
|
||||||
|
|
||||||
fileList.setModel(new AbstractListModel<>() {
|
int returnVal = folderChooser.showOpenDialog(this);
|
||||||
final String[] strings = {"Item 1", "Item 2", "Item 3", "Item 4", "Item 5"};
|
if (returnVal == JFileChooser.APPROVE_OPTION) {
|
||||||
|
tracker = new TrackerThread(mainTextPane, Path.of(folderChooser.getSelectedFile().getAbsolutePath()), fileContents, fileList);
|
||||||
public int getSize() {
|
tracker.start();
|
||||||
return strings.length;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getElementAt(int i) {
|
|
||||||
return strings[i];
|
|
||||||
}
|
|
||||||
});
|
|
||||||
fileList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
|
fileList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
|
||||||
fileListScrollPane.setViewportView(fileList);
|
fileListScrollPane.setViewportView(fileList);
|
||||||
|
|
||||||
snapshotLabel.setFont(new java.awt.Font("Trebuchet MS", Font.PLAIN, 18)); // NOI18N
|
snapshotLabel.setFont(new java.awt.Font("Trebuchet MS", Font.PLAIN, 18)); // NOI18N
|
||||||
snapshotLabel.setText("Last snapshot:");
|
snapshotLabel.setText("Last snapshot: " + new Date());
|
||||||
|
|
||||||
mainScrollPane.setViewportView(mainTextPane);
|
mainScrollPane.setViewportView(mainTextPane);
|
||||||
|
|
||||||
pathLabel.setFont(new java.awt.Font("Trebuchet MS", Font.PLAIN, 18)); // NOI18N
|
pathLabel.setFont(new java.awt.Font("Trebuchet MS", Font.PLAIN, 18)); // NOI18N
|
||||||
pathLabel.setText("Currently tracking: ");
|
pathLabel.setText("Currently tracking: " + folderChooser.getSelectedFile().getAbsolutePath());
|
||||||
|
|
||||||
CommitButton.setText("Commit");
|
CommitButton.setText("Commit");
|
||||||
CommitButton.addActionListener(this::CommitButtonActionPerformed);
|
CommitButton.addActionListener(this::CommitButtonActionPerformed);
|
||||||
@@ -119,13 +113,14 @@ public class MainFrame extends JFrame {
|
|||||||
.addComponent(CommitButton)
|
.addComponent(CommitButton)
|
||||||
.addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)
|
.addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)
|
||||||
.addComponent(StatusButton)))
|
.addComponent(StatusButton)))
|
||||||
.addContainerGap())
|
.addContainerGap()));
|
||||||
);
|
|
||||||
|
|
||||||
pack();
|
pack();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void CommitButtonActionPerformed(java.awt.event.ActionEvent evt) {
|
private void CommitButtonActionPerformed(java.awt.event.ActionEvent evt) {
|
||||||
|
tracker.reset();
|
||||||
|
mainTextPane.setText("");
|
||||||
|
snapshotLabel.setText("Last snapshot: " + new Date());
|
||||||
}
|
}
|
||||||
|
|
||||||
private void StatusButtonActionPerformed(java.awt.event.ActionEvent evt) {
|
private void StatusButtonActionPerformed(java.awt.event.ActionEvent evt) {
|
||||||
|
|||||||
@@ -1,60 +1,100 @@
|
|||||||
package org.lumijiez.tracker;
|
package org.lumijiez.tracker;
|
||||||
|
|
||||||
|
import org.lumijiez.util.DiffType;
|
||||||
|
import org.lumijiez.util.FileDiffer;
|
||||||
|
import org.lumijiez.util.StateType;
|
||||||
|
|
||||||
import javax.swing.*;
|
import javax.swing.*;
|
||||||
import java.io.IOException;
|
import java.io.File;
|
||||||
import java.nio.file.*;
|
import java.nio.file.*;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
public class TrackerThread extends Thread {
|
public class TrackerThread extends Thread {
|
||||||
private final JTextPane textPane;
|
private final JTextPane textPane;
|
||||||
private final Path path;
|
private final Path path;
|
||||||
|
private Map<File, byte[]> fileContents;
|
||||||
|
private final JList<String> fileList;
|
||||||
|
private final Map<File, StateType> fileStates = new HashMap<>();
|
||||||
|
|
||||||
public TrackerThread(JTextPane textPane, Path path) {
|
public TrackerThread(JTextPane textPane, Path path, Map<File, byte[]> files, JList<String> fileList) {
|
||||||
this.textPane = textPane;
|
this.textPane = textPane;
|
||||||
this.path = path;
|
this.path = path;
|
||||||
|
this.fileContents = files;
|
||||||
|
this.fileList = fileList;
|
||||||
|
init();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void checkDirectory(Path path) {
|
public void init() {
|
||||||
try {
|
System.out.println("Init called");
|
||||||
WatchService watchService = FileSystems.getDefault().newWatchService();
|
fileContents = FileDiffer.crawlDirectory(path);
|
||||||
path.register(watchService, StandardWatchEventKinds.ENTRY_CREATE, StandardWatchEventKinds.ENTRY_MODIFY, StandardWatchEventKinds.ENTRY_DELETE);
|
|
||||||
|
|
||||||
while (true) {
|
ArrayList<String> fileNames = new ArrayList<>();
|
||||||
WatchKey key;
|
|
||||||
try {
|
for (File file : fileContents.keySet()) {
|
||||||
key = watchService.take();
|
fileNames.add(file.getName());
|
||||||
} catch (InterruptedException e) {
|
}
|
||||||
return;
|
fileList.setModel(new AbstractListModel<>() {
|
||||||
|
public int getSize() {
|
||||||
|
return fileNames.size();
|
||||||
|
}
|
||||||
|
public String getElementAt(int i) {
|
||||||
|
return fileNames.get(i);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
for (WatchEvent<?> event : key.pollEvents()) {
|
public void reset() {
|
||||||
WatchEvent.Kind<?> kind = event.kind();
|
fileStates.clear();
|
||||||
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
public void checkDirectory() {
|
||||||
WatchEvent<Path> ev = (WatchEvent<Path>) event;
|
Map<DiffType, ArrayList<File>> result = FileDiffer.diff(fileContents, FileDiffer.crawlDirectory(path));
|
||||||
Path fileName = ev.context();
|
|
||||||
|
|
||||||
System.out.println(kind.name() + ": " + fileName);
|
StringBuilder toShow = new StringBuilder();
|
||||||
|
|
||||||
if (kind == StandardWatchEventKinds.ENTRY_CREATE) {
|
boolean created = false, deleted = false, modified = false;
|
||||||
textPane.setText(textPane.getText() + " file created\n");
|
if (!result.get(DiffType.CREATE).isEmpty()) {
|
||||||
} else if (kind == StandardWatchEventKinds.ENTRY_MODIFY) {
|
created = true;
|
||||||
textPane.setText(textPane.getText() + " file modified\n");
|
for (File file : result.get(DiffType.CREATE)) {
|
||||||
} else if (kind == StandardWatchEventKinds.ENTRY_DELETE) {
|
fileStates.put(file, StateType.NEW);
|
||||||
textPane.setText(textPane.getText() + " file deleted\n");
|
}
|
||||||
|
System.out.println("Created");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!result.get(DiffType.DELETE).isEmpty()) {
|
||||||
|
deleted = true;
|
||||||
|
for (File file : result.get(DiffType.DELETE)) {
|
||||||
|
fileStates.put(file, StateType.DELETED);
|
||||||
|
}
|
||||||
|
System.out.println("Deleted");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!result.get(DiffType.MODIFY).isEmpty()) {
|
||||||
|
modified = true;
|
||||||
|
for (File file : result.get(DiffType.MODIFY)) {
|
||||||
|
fileStates.put(file, StateType.MODIFIED);
|
||||||
|
}
|
||||||
|
System.out.println("Modified");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (created || deleted || modified) {
|
||||||
|
init();
|
||||||
|
for (File file : fileStates.keySet()) {
|
||||||
|
if (fileStates.get(file) != StateType.NONE) {
|
||||||
|
toShow.append(file.getName()).append(" has been ").append(fileStates.get(file).getName()).append("<br>");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
textPane.setText(toShow.toString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean valid = key.reset();
|
|
||||||
if (!valid) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (IOException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
checkDirectory(path);
|
while(this.isAlive()) {
|
||||||
|
checkDirectory();
|
||||||
|
//Thread.sleep(200);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
5
Lab3/src/main/java/org/lumijiez/util/DiffType.java
Normal file
5
Lab3/src/main/java/org/lumijiez/util/DiffType.java
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
package org.lumijiez.util;
|
||||||
|
|
||||||
|
public enum DiffType {
|
||||||
|
CREATE, DELETE, MODIFY, NONE
|
||||||
|
}
|
||||||
61
Lab3/src/main/java/org/lumijiez/util/FileDiffer.java
Normal file
61
Lab3/src/main/java/org/lumijiez/util/FileDiffer.java
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
package org.lumijiez.util;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
public class FileDiffer {
|
||||||
|
public static Map<DiffType, ArrayList<File>> diff(Map<File, byte[]> oldFiles, Map<File, byte[]> newFiles) {
|
||||||
|
Map<DiffType, ArrayList<File>> result = new HashMap<>();
|
||||||
|
|
||||||
|
ArrayList<File> newFileList = new ArrayList<>();
|
||||||
|
ArrayList<File> deletedFileList = new ArrayList<>();
|
||||||
|
ArrayList<File> modifiedFileList = new ArrayList<>();
|
||||||
|
|
||||||
|
for (File file : oldFiles.keySet()) {
|
||||||
|
if (newFiles.get(file) != null) {
|
||||||
|
if (Arrays.compare(oldFiles.get(file), newFiles.get(file)) != 0) {
|
||||||
|
modifiedFileList.add(file);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
deletedFileList.add(file);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (File file : newFiles.keySet()) {
|
||||||
|
if (oldFiles.get(file) == null) {
|
||||||
|
newFileList.add(file);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
result.put(DiffType.CREATE, newFileList);
|
||||||
|
result.put(DiffType.DELETE, deletedFileList);
|
||||||
|
result.put(DiffType.MODIFY, modifiedFileList);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Map<File, byte[]> crawlDirectory(Path path) {
|
||||||
|
Map<File, byte[]> newFileContents = new HashMap<>();
|
||||||
|
try (Stream<Path> paths = Files.walk(path)) {
|
||||||
|
paths.forEach(p -> {
|
||||||
|
if (Files.isRegularFile(p)) {
|
||||||
|
try {
|
||||||
|
newFileContents.put(p.toFile(), Files.readAllBytes(p));
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return newFileContents;
|
||||||
|
}
|
||||||
|
}
|
||||||
14
Lab3/src/main/java/org/lumijiez/util/StateType.java
Normal file
14
Lab3/src/main/java/org/lumijiez/util/StateType.java
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
package org.lumijiez.util;
|
||||||
|
|
||||||
|
public enum StateType {
|
||||||
|
NEW("Created"), MODIFIED("Modified"), DELETED("Deleted"), NONE("Nothing");
|
||||||
|
|
||||||
|
private final String name;
|
||||||
|
StateType(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return this.name;
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user