Not the same object after a deserialization in a data transfer - java

I really need some help down here...
I'm working on drag and drop event in a Jtree.
I've created a TransferHandler to manage the drag and drop.
Source : KineticsTransferHandler.java
package tree;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.io.IOException;
import javax.swing.JComponent;
import javax.swing.JTree;
import javax.swing.TransferHandler;
import javax.swing.tree.TreePath;
import datastructures.base.Acquisition;
import datastructures.base.Kinetics;
import datastructures.base.Location;
public class KineticsTransferHandler extends TransferHandler{
private static final long serialVersionUID = -5653477841078614666L;
final public static DataFlavor ACQUISITION_NODE = new DataFlavor(Acquisition.class, "Acquisition Node");
static DataFlavor flavors[] = { ACQUISITION_NODE };
#Override
public int getSourceActions(JComponent c) {
return MOVE;
}
#Override
protected Transferable createTransferable(JComponent c) {
JTree tree = (JTree) c;
TreePath path = tree.getSelectionPath();
System.out.println(tree.getSelectionPath().toString());
if (path != null) {
Object o = path.getLastPathComponent();
if(o instanceof Acquisition) {
return new AcquisitionTransferable((Acquisition)o);
}
}
return null;
}
#Override
protected void exportDone(JComponent source, Transferable data, int action) {
if(action != NONE) {
JTree tree = (JTree) source;
StudyTreeModel model = (StudyTreeModel)tree.getModel();
model.printStudy();
tree.updateUI();
}
}
#Override
public boolean canImport(TransferHandler.TransferSupport support) {
boolean canImport = false;
if (support.isDrop()) {
Acquisition source = null;
if (support.isDataFlavorSupported(ACQUISITION_NODE)) {
try {
source = (Acquisition) support.getTransferable().getTransferData(ACQUISITION_NODE);
} catch (UnsupportedFlavorException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
if(source != null) {
JTree.DropLocation dropLocation = (JTree.DropLocation)support.getDropLocation();
Object dest = dropLocation.getPath().getLastPathComponent();
canImport = sameLocation(source, dest);
}
}
}
return canImport;
}
/*Verifies that the source and the dest are in the same Location*/
private boolean sameLocation(Acquisition source, Object dest) {
/*...
A method to check if the source has the same Location than the dest.
...*/
}
#Override
public boolean importData(TransferHandler.TransferSupport support) {
boolean importData = false;
if (canImport(support)) {
Acquisition source = null;
if (support.isDataFlavorSupported(ACQUISITION_NODE)) {
try {
source = (Acquisition) support.getTransferable().getTransferData(ACQUISITION_NODE);
((StudyTree)support.getComponent()).gettr
} catch (UnsupportedFlavorException e) {
e.printStackTrace();
return false;
} catch (IOException e) {
e.printStackTrace();
return false;
}
JTree.DropLocation dropLocation = (JTree.DropLocation)support.getDropLocation();
Object dest = dropLocation.getPath().getLastPathComponent();
int childIndex = dropLocation.getChildIndex();
if (sameLocation(source, dest)) {// dest and source get the same Location
/*...
Management of the drop according to the dest.
...*/
}
}
return importData;
}
public class AcquisitionTransferable implements Transferable {
Acquisition acquisition;
public AcquisitionTransferable(Acquisition s) {
acquisition = s;
}
#Override
public Object getTransferData(DataFlavor flavor)
throws UnsupportedFlavorException {
if (!isDataFlavorSupported(flavor))
throw new UnsupportedFlavorException(flavor);
return acquisition;
}
#Override
public DataFlavor[] getTransferDataFlavors() {
return flavors;
}
#Override
public boolean isDataFlavorSupported(DataFlavor flavor) {
return ACQUISITION_NODE.equals(flavor);
}
}
}
It uses an Transferable for the data transfert that I've called AcquisitionTransferable (as you can see in the end).
My problem(s) came(s) from this part
Source : KineticsTransferHandler.canImport(TransferHandler.TransferSupport)
source = (Acquisition) support.getTransferable().getTransferData(ACQUISITION_NODE);
The structure that I've, in the end, in source(the one above) is like a copy of the real one. When I'm debugging, I can see that the source's ID is not the same as in the real one.
But in support(parameter of KineticsTransferHandler.canImport(TransferHandler.TransferSupport)), I've my Jtree which contains the structure, wich is the good one.
So, what I'm thinking is, there is a problem in the access of the structure in getTransferData, it may be a problem with the serialization. When I access my structure, getTransferData deserializes the structure and this is why I get like a clone of it.
Do you have any idea of how I should fix it?

You need to define your DataFlavor with a javaJVMLocalObjectMimeType, to signify that the transferred data resides in the local JVM. In your case, the DataFlavor definition should look like:
final public static DataFlavor ACQUISITION_NODE =
new DataFlavor(DataFlavor.javaJVMLocalObjectMimeType+"; class=\"" +Acquisition.class.getCanonicalName()+"\""
,"Acquisition Node");
Check the other two Java object MIME types here also.

Related

Java DataFlavor for MacOS clipbord

Does the MacOS clipboard use some super-secret DataFlavor that Java apps can only read from, not write to?
I've written an app (Java 15) that copies files to the clipboard, and I can retrieve these files from within my app. But when I go to Finder, it says Clipboard contents: unknown. Here's the code:
public static class FileTransferable implements Transferable {
private final List listOfFiles;
public FileTransferable(List listOfFiles) {
this.listOfFiles = listOfFiles;
}
#Override
public DataFlavor[] getTransferDataFlavors() {
return new DataFlavor[]{DataFlavor.javaFileListFlavor};
}
#Override
public boolean isDataFlavorSupported(DataFlavor flavor) {
return DataFlavor.javaFileListFlavor.equals(flavor);
}
#Override
public Object getTransferData(DataFlavor flavor) throws UnsupportedFlavorException, IOException {
return listOfFiles;
}
}
public void copyItems() {
ArrayList<File> files = new ArrayList<>();
files.add(new File("/Users/fred/Public/IMG0010.HEIC"));
files.add(new File("/Users/fred/Public/IMG0011.HEIC"));
files.add(new File("/Users/fred/Public/IMG0012.HEIC"));
Clipboard clip = Toolkit.getDefaultToolkit().getSystemClipboard();
clip.setContents(new FileTransferable(files), null);
}
Is there any way around this?

Java clipboad mistake

There is such a program. It must analyze the clipboard for the presence of a five-digit number in it. But when you first copy the text that meets the condition, the program works fine, but if you copy the second text in the same window, the program that meets the condition does not work. That is, it works only if you periodically change windows.
The question is to get the program to work with each copy?
import java.awt.*;
import java.awt.datatransfer.*;
import java.io.IOException;
public class Main implements FlavorListener {
private static Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
public static void main(String[] args) throws InterruptedException {
clipboard.addFlavorListener(new Main());
// fall asleep for 100 seconds, otherwise the program will immediately end
Thread.sleep(100 * 1000);
}
#Override
public void flavorsChanged(FlavorEvent event) {
try {
String clipboardContent = (String) clipboard.getData(DataFlavor.stringFlavor);
handleClipboardContent(clipboardContent);
} catch (UnsupportedFlavorException | IOException e) {
// TODO handle error
e.printStackTrace();
}
}
private void handleClipboardContent(String clipboardContent) {
// we check that the length of the string is five
if (clipboardContent != null && clipboardContent.length() == 5)
{
System.out.println(clipboardContent);
}
else {
System.out.println("condition false");
}
}
}
// 12345
// 56789
The FlavorListener will notify you when the "type" of data in the Clipboard has changed, not when the data itself has changed. This means if you copy a String to the Clipboard, you "might" be notified, but if you copy another String to the Clipboard, you won't, because the type of data has not changed.
The "common" solution to the problem you're facing is to reset the contents of the clipboard to a different flavour. The problem with this is, what happens if some other program wants the data? You've just trampled all over it
Instead, you could "peek" at the data on a periodical bases and check to see if the contents has changed or not. A basic solution would be to use a Thread which maintained the hashCode of the current String contents, when the hashCode changes, you would then grab a copy and perform what ever operations you wanted on it.
Maybe something like...
import java.awt.Toolkit;
import java.awt.datatransfer.Clipboard;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.FlavorEvent;
import java.awt.datatransfer.FlavorListener;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.io.IOException;
public class Test {
public static void main(String[] args) {
Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
clipboard.addFlavorListener(new FlavorListener() {
#Override
public void flavorsChanged(FlavorEvent e) {
System.out.println("Flavor has changed");
Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
if (clipboard.isDataFlavorAvailable(DataFlavor.stringFlavor)) {
try {
String text = (String) clipboard.getData(DataFlavor.stringFlavor);
textDidChangeTo(text);
} catch (UnsupportedFlavorException | IOException ex) {
ex.printStackTrace();
}
}
}
});
Thread t = new Thread(new Runnable() {
private Integer currentHashcode;
#Override
public void run() {
while (true) {
try {
Thread.sleep(1000);
} catch (InterruptedException ex) {
}
Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
Transferable contents = clipboard.getContents(this);
if (clipboard.isDataFlavorAvailable(DataFlavor.stringFlavor)) {
try {
String text = (String) clipboard.getData(DataFlavor.stringFlavor);
if (currentHashcode == null) {
currentHashcode = text.hashCode();
} else if (currentHashcode != text.hashCode()) {
currentHashcode = text.hashCode();
textDidChangeTo(text);
}
} catch (UnsupportedFlavorException | IOException ex) {
ex.printStackTrace();
}
} else {
currentHashcode = null;
}
}
}
});
t.start();
}
public static void textDidChangeTo(String text) {
System.out.println("Text did change to: " + text);
}
}
Now, this is far from perfect. It may generate two events when the contents changes from something other then String to String. In this, based on your needs, you probably don't need the FlavorListener, but I've used it for demonstration purposes

JFileChooser with custom FileSystemView implementation

I extended FileSystemView and overwrote every method in this class. The model looks like this:
public class RemoteSystemFilesView extends FileSystemView {
private IDirectoryService directoryService;
public RemoteSystemFilesView(IDirectoryService aDirectoryService){
this.directoryService = aDirectoryService;
}
....
}
The directoryService object returns directories from the remote UNIX server. Then, I create JFileChooser.
JFileChooser fc = new JFileChooser(new RemoteSystemFilesView(new DirectoryService()));
int returnVal = fc.showOpenDialog(this);
The dialog shows remote dirs and files correctly, but then I doubleClick on one of the displayed folders, I expect to navigate into that folder, but instead folder path appears in the field "File name" and that's it. I can't go to any other directory except root (/). Should I implement something else also in JFileChooser, not just in FileSystemView?
The problem might be that your FileSystemView is actually returning plain java.io.File objects.
Instead try to return a VirtualFile wrapper object that extends java.io.File and returns true for the public boolean exists() and wraps returns VirtualFile instead of java.io.File for all the necessary methods.
This is an example of a VirtualFileSystem that I developed. It uses java.nio.Path because my code is mainly based in them. I hope it gives you a good starting point for understanding how to modify your code.
private static class VirtualFileSystemView extends FileSystemView {
final Path base;
final Set<Path> choices;
private VirtualFileSystemView(final Path base,
final Set<Path> choices) {
this.base = base;
this.choices = choices;
}
#Override
protected File createFileSystemRoot(File f) {
return new VirtualFile(f);
}
#Override
public boolean isComputerNode(File dir) {
return false;
}
#Override
public boolean isFloppyDrive(File dir) {
return false;
}
#Override
public boolean isDrive(File dir) {
return false;
}
#Override
public Icon getSystemIcon(File f) {
return null;
}
#Override
public String getSystemTypeDescription(File f) {
return f.toPath().toString();
}
#Override
public String getSystemDisplayName(File f) {
return f.getName();
}
#Override
public File getParentDirectory(final File dir) {
return new VirtualFile(dir.getParentFile());
}
#Override
public File[] getFiles(final File dir, boolean useFileHiding) {
final List<File> files = new ArrayList<>(choices.size());
choices.stream()
.filter((path) -> (path.getParent().equals(dir.toPath()))).
forEach((path) -> {
files.add(new VirtualFile(path.toFile()));
});
return files.toArray(new File[files.size()]);
}
#Override
public File createFileObject(final String path) {
return new VirtualFile(path);
}
#Override
public File createFileObject(final File dir, final String filename) {
Path fileObject;
if (dir != null) {
fileObject = Paths.get(dir.toPath().toString(), filename);
} else {
fileObject = Paths.get(filename);
}
return new VirtualFile(fileObject.toFile());
}
#Override
public File getDefaultDirectory() {
return new VirtualFile(base.toFile());
}
#Override
public File getHomeDirectory() {
return new VirtualFile(base.toFile());
}
#Override
public File[] getRoots() {
final List<File> files = new ArrayList<>(choices.size());
files.add(new VirtualFile(base.toFile()));
return files.toArray(new File[files.size()]);
}
#Override
public boolean isFileSystemRoot(final File dir) {
boolean isRoot = dir.toPath().getParent() == null;
return isRoot;
}
#Override
public boolean isHiddenFile(final File f) {
return false;
}
#Override
public boolean isFileSystem(final File f) {
return !isFileSystemRoot(f);
}
#Override
public File getChild(final File parent, final String fileName) {
return new VirtualFile(parent, fileName);
}
#Override
public boolean isParent(final File folder, final File file) {
return file.toPath().getParent().equals(folder.toPath());
}
#Override
public Boolean isTraversable(final File f) {
boolean isTraversable = false;
for (final Path path : choices) {
if (path.startsWith(f.toPath())) {
isTraversable = true;
break;
}
}
return isTraversable;
}
#Override
public boolean isRoot(final File f) {
boolean isRoot = false;
for (final Path path : choices) {
if (path.getParent().equals(f.toPath())) {
isRoot = true;
}
}
return isRoot;
}
#Override
public File createNewFolder(final File containingDir) throws IOException {
return new VirtualFile(containingDir);
}
private class VirtualFile extends File {
private static final long serialVersionUID = -1752685357864733168L;
private VirtualFile(final File file) {
super(file.toString());
}
private VirtualFile(String pathname) {
super(pathname);
}
private VirtualFile(String parent, String child) {
super(parent, child);
}
private VirtualFile(File parent, String child) {
super(parent, child);
}
#Override
public boolean exists() {
return true;
}
#Override
public boolean isDirectory() {
return VirtualFileSystemView.this.isTraversable(this);
}
#Override
public File getCanonicalFile() throws IOException {
return new VirtualFile(super.getCanonicalFile());
}
#Override
public File getAbsoluteFile() {
return new VirtualFile(super.getAbsoluteFile());
}
#Override
public File getParentFile() {
File parent = super.getParentFile();
if (parent != null) {
parent = new VirtualFile(super.getParentFile());
}
return parent;
}
}
}

Watching a Directory for Changes in Java

I want to watch a directory for file changes. And I used WatchService in java.nio. I can successfully listen for file created event. But I can't listen for file modify event. I checked official java tutorial, but still struggling.
Here is the source code.
import static java.nio.file.LinkOption.NOFOLLOW_LINKS;
import static java.nio.file.StandardWatchEventKinds.ENTRY_CREATE;
import static java.nio.file.StandardWatchEventKinds.OVERFLOW;
import static java.nio.file.StandardWatchEventKinds.ENTRY_DELETE;
import static java.nio.file.StandardWatchEventKinds.ENTRY_MODIFY;
import java.io.File;
import java.io.IOException;
import java.nio.file.FileSystem;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.WatchEvent;
import java.nio.file.WatchEvent.Kind;
import java.nio.file.WatchKey;
import java.nio.file.WatchService;
public class MainWatch {
public static void watchDirectoryPath(Path path) {
// Sanity check - Check if path is a folder
try {
Boolean isFolder = (Boolean) Files.getAttribute(path,
"basic:isDirectory", NOFOLLOW_LINKS);
if (!isFolder) {
throw new IllegalArgumentException("Path: " + path
+ " is not a folder");
}
} catch (IOException ioe) {
// Folder does not exists
ioe.printStackTrace();
}
System.out.println("Watching path: " + path);
// We obtain the file system of the Path
FileSystem fs = path.getFileSystem();
// We create the new WatchService using the new try() block
try (WatchService service = fs.newWatchService()) {
// We register the path to the service
// We watch for creation events
path.register(service, ENTRY_CREATE);
path.register(service, ENTRY_MODIFY);
path.register(service, ENTRY_DELETE);
// Start the infinite polling loop
WatchKey key = null;
while (true) {
key = service.take();
// Dequeueing events
Kind<?> kind = null;
for (WatchEvent<?> watchEvent : key.pollEvents()) {
// Get the type of the event
kind = watchEvent.kind();
if (OVERFLOW == kind) {
continue; // loop
} else if (ENTRY_CREATE == kind) {
// A new Path was created
Path newPath = ((WatchEvent<Path>) watchEvent)
.context();
// Output
System.out.println("New path created: " + newPath);
} else if (ENTRY_MODIFY == kind) {
// modified
Path newPath = ((WatchEvent<Path>) watchEvent)
.context();
// Output
System.out.println("New path modified: " + newPath);
}
}
if (!key.reset()) {
break; // loop
}
}
} catch (IOException ioe) {
ioe.printStackTrace();
} catch (InterruptedException ie) {
ie.printStackTrace();
}
}
public static void main(String[] args) throws IOException,
InterruptedException {
// Folder we are going to watch
// Path folder =
// Paths.get(System.getProperty("C:\\Users\\Isuru\\Downloads"));
File dir = new File("C:\\Users\\Isuru\\Downloads");
watchDirectoryPath(dir.toPath());
}
}
Actually you have incorrectly subscribed to events. Only last listener has been registered with ENTRY_DELETE events type.
To register for all kind of events at once you should use:
path.register(service, ENTRY_CREATE, ENTRY_MODIFY, ENTRY_DELETE);
Warning! Shameless self promotion!
I have created a wrapper around Java 1.7's WatchService that allows registering a directory and any number of glob patterns. This class will take care of the filtering and only emit events you are interested in.
DirectoryWatchService watchService = new SimpleDirectoryWatchService(); // May throw
watchService.register( // May throw
new DirectoryWatchService.OnFileChangeListener() {
#Override
public void onFileCreate(String filePath) {
// File created
}
#Override
public void onFileModify(String filePath) {
// File modified
}
#Override
public void onFileDelete(String filePath) {
// File deleted
}
},
<directory>, // Directory to watch
<file-glob-pattern-1>, // E.g. "*.log"
<file-glob-pattern-2>, // E.g. "input-?.txt"
... // As many patterns as you like
);
watchService.start();
Complete code is in this repo.
I made some classes for this.
public interface FileAvailableListener {
public void fileAvailable(File file) throws IOException;
}
and
public class FileChange {
private long lastModified;
private long size;
private long lastCheck;
public FileChange(File file) {
this.lastModified=file.lastModified();
this.size=file.length();
this.lastCheck = System.currentTimeMillis();
}
public long getLastModified() {
return lastModified;
}
public long getSize() {
return size;
}
public long getLastCheck() {
return lastCheck;
}
public boolean isStable(FileChange other,long stableTime) {
boolean b1 = (getLastModified()==other.getLastModified());
boolean b2 = (getSize()==other.getSize());
boolean b3 = ((other.getLastCheck()-getLastCheck())>stableTime);
return b1 && b2 && b3;
}
}
and
public class DirectoryWatcher {
private Timer timer;
private List<DirectoryMonitorTask> tasks = new ArrayList<DirectoryMonitorTask>();
public DirectoryWatcher() throws URISyntaxException, IOException, InterruptedException {
super();
timer = new Timer(true);
}
public void addDirectoryMonitoringTask(DirectoryMonitorTask task,long period) {
tasks.add(task);
timer.scheduleAtFixedRate(task, 5000, period);
}
public List<DirectoryMonitorTask> getTasks() {
return Collections.unmodifiableList(tasks);
}
public Timer getTimer() {
return timer;
}
}
and
class DirectoryMonitorTask extends TimerTask {
public final static String DIRECTORY_NAME_ARCHIVE="archive";
public final static String DIRECTORY_NAME_ERROR="error";
public final static String LOCK_FILE_EXTENSION=".lock";
public final static String ERROR_FILE_EXTENSION=".error";
public final static String FILE_DATE_FORMAT="yyyyMMddHHmmssSSS";
private String name;
private FileAvailableListener listener;
private Path directory;
private File directoryArchive;
private File directoryError;
private long stableTime;
private FileFilter filter;
private WatchService watchService;
private SimpleDateFormat dateFormatter = new SimpleDateFormat(FILE_DATE_FORMAT);
private Hashtable<File,FileChange> fileMonitor = new Hashtable<File,FileChange>();
public DirectoryMonitorTask(String name,FileAvailableListener listener,Path directory,long stableTime,FileFilter filter) throws IOException {
super();
this.name=name;
this.listener=listener;
this.directory=directory;
this.stableTime=stableTime;
if (stableTime<1) {
stableTime=1000;
}
this.filter=filter;
validateNotNull("Name",name);
validateNotNull("Listener",listener);
validateNotNull("Directory",directory);
validate(directory);
directoryArchive = new File(directory.toFile(),DIRECTORY_NAME_ARCHIVE);
directoryError = new File(directory.toFile(),DIRECTORY_NAME_ERROR);
directoryArchive.mkdir();
directoryError.mkdir();
//
log("Constructed for "+getDirectory().toFile().getAbsolutePath());
initialize();
//
watchService = FileSystems.getDefault().newWatchService();
directory.register(watchService,StandardWatchEventKinds.ENTRY_CREATE,StandardWatchEventKinds.ENTRY_DELETE,StandardWatchEventKinds.ENTRY_MODIFY);
log("Started");
}
private void initialize() {
File[] files = getDirectory().toFile().listFiles();
for (File file : files) {
if (isLockFile(file)) {
file.delete();
} else if (acceptFile(file)) {
fileMonitor.put(file,new FileChange(file));
log("Init file added -"+file.getName());
}
}
}
public SimpleDateFormat getDateFormatter() {
return dateFormatter;
}
public Path getDirectory() {
return directory;
}
public FileAvailableListener getListener() {
return listener;
}
public String getName() {
return name;
}
public WatchService getWatchService() {
return watchService;
}
public long getStableTime() {
return stableTime;
}
public File getDirectoryArchive() {
return directoryArchive;
}
public File getDirectoryError() {
return directoryError;
}
public FileFilter getFilter() {
return filter;
}
public Iterator<File> getMonitoredFiles() {
return fileMonitor.keySet().iterator();
}
#Override
public void run() {
WatchKey key;
try {
key = getWatchService().take();
// Poll all the events queued for the key
for (WatchEvent<?> event : key.pollEvents()) {
#SuppressWarnings("unchecked")
Path filePath = ((WatchEvent<Path>) event).context();
File file = filePath.toFile();
if ((!isLockFile(file)) && (acceptFile(file))) {
switch (event.kind().name()) {
case "ENTRY_CREATE":
//
fileMonitor.put(file,new FileChange(file));
log("File created ["+file.getName()+"]");
break;
//
case "ENTRY_MODIFY":
//
fileMonitor.put(file,new FileChange(file));
log("File modified ["+file.getName()+"]");
break;
//
case "ENTRY_DELETE":
//
log("File deleted ["+file.getName()+"]");
createLockFile(file).delete();
fileMonitor.remove(file);
break;
//
}
}
}
// reset is invoked to put the key back to ready state
key.reset();
} catch (InterruptedException e) {
e.printStackTrace();
}
Iterator<File> it = fileMonitor.keySet().iterator();
while (it.hasNext()) {
File file = it.next();
FileChange fileChange = fileMonitor.get(file);
FileChange fileChangeCurrent = new FileChange(file);
if (fileChange.isStable(fileChangeCurrent, getStableTime())) {
log("File is stable ["+file.getName()+"]");
String filename = getDateFormatter().format(new Date())+"_"+file.getName();
File lockFile = createLockFile(file);
if (!lockFile.exists()) {
log("File do not has lock file ["+file.getName()+"]");
try {
Files.createFile(lockFile.toPath());
log("Processing file ["+file.getName()+"]");
getListener().fileAvailable(file);
file.renameTo(new File(getDirectoryArchive(),filename));
log("Moved to archive file ["+file.getName()+"]");
} catch (IOException e) {
file.renameTo(new File(getDirectoryError(),filename));
createErrorFile(file,e);
log("Moved to error file ["+file.getName()+"]");
} finally {
lockFile.delete();
}
} else {
log("File do has lock file ["+file.getName()+"]");
fileMonitor.remove(file);
}
} else {
log("File is unstable ["+file.getName()+"]");
fileMonitor.put(file,fileChangeCurrent);
}
}
}
public boolean acceptFile(File file) {
if (getFilter()!=null) {
return getFilter().accept(file);
} else {
return true;
}
}
public boolean isLockFile(File file) {
int pos = file.getName().lastIndexOf('.');
String extension="";
if (pos!=-1) {
extension = file.getName().substring(pos).trim().toLowerCase();
}
return(extension.equalsIgnoreCase(LOCK_FILE_EXTENSION));
}
private File createLockFile(File file) {
return new File(file.getParentFile(),file.getName()+LOCK_FILE_EXTENSION);
}
private void createErrorFile(File file,IOException exception) {
File errorFile = new File(file.getParentFile(),file.getName()+ERROR_FILE_EXTENSION);
StringWriter sw = null;
PrintWriter pw = null;
FileWriter fileWriter = null;
try {
//
fileWriter = new FileWriter(errorFile);
if (exception!=null) {
sw = new StringWriter();
pw = new PrintWriter(sw);
exception.printStackTrace(pw);
fileWriter.write(sw.toString());
} else {
fileWriter.write("Exception is null.");
}
//
fileWriter.flush();
//
} catch (IOException e) {
} finally {
if (sw!=null) {
try {
sw.close();
} catch (IOException e1) {
}
}
if (pw!=null) {
pw.close();
}
if (fileWriter!=null) {
try {
fileWriter.close();
} catch (IOException e) {
}
}
}
}
private void validateNotNull(String name,Object obj) {
if (obj==null) {
throw new NullPointerException(name+" is null.");
}
}
private void validate(Path directory) throws IOException {
File file = directory.toFile();
if (!file.exists()) {
throw new IOException("Directory ["+file.getAbsolutePath()+"] do not exists.");
} else if (!file.isDirectory()) {
throw new IOException("Directory ["+file.getAbsolutePath()+"] is not a directory.");
} else if (!file.canRead()) {
throw new IOException("Can not read from directory ["+file.getAbsolutePath()+"].");
} else if (!file.canWrite()) {
throw new IOException("Can not write to directory ["+file.getAbsolutePath()+"] .");
}
}
private void log(String msg) {
//TODO
System.out.println("Task ["+getName()+"] "+msg);
}
}
package p1;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import static java.nio.file.LinkOption.NOFOLLOW_LINKS;
import java.nio.file.StandardWatchEventKinds;
import java.nio.file.WatchEvent;
import java.nio.file.WatchKey;
import java.nio.file.WatchService;
import java.util.List;
public class WatchForFile {
public void WatchMyFolder(String path )
{
File dir = new File(path);
Path myDir= dir.toPath();
try
{
Boolean isFolder = (Boolean) Files.getAttribute(myDir,"basic:isDirectory", NOFOLLOW_LINKS);
if (!isFolder)
{
throw new IllegalArgumentException("Path: " + myDir + " is not a folder");
}
}
catch (IOException ioe)
{
ioe.printStackTrace();
}
System.out.println("Watching path: " + myDir);
try {
WatchService watcher = myDir.getFileSystem().newWatchService();
myDir.register(watcher, StandardWatchEventKinds.ENTRY_CREATE,StandardWatchEventKinds.ENTRY_DELETE, StandardWatchEventKinds.ENTRY_MODIFY);
WatchKey watckKey = watcher.take();
List<WatchEvent<?>> events = watckKey.pollEvents();
for (WatchEvent event : events) {
if (event.kind() == StandardWatchEventKinds.ENTRY_CREATE) {
System.out.println("Created: " + event.kind().toString());
}
if (event.kind() == StandardWatchEventKinds.ENTRY_DELETE) {
System.out.println("Delete: " + event.context().toString());
}
if (event.kind() == StandardWatchEventKinds.ENTRY_MODIFY) {
System.out.println("Modify: " + event.context().toString());
}
}
}
catch (Exception e)
{
System.out.println("Error: " + e.toString());
}
}
}
Check this Code...
https://github.com/omkar9999/FileWatcherHandler
This project allows watching files for different file events like create, modify & delete and then act on these events in a generic way.
How to Use?
Create a Path object representing the directory to monitor for file events.
Path path = Paths.get("/home/omkar/test");
Implement the FileHandler interface to perform an action detected by file event registered.
public class FileHandlerTest implements FileHandler {
private static final Logger LOGGER = Logger.getLogger(FileHandlerTest.class.getName());
/*
* This implemented method will delete the file
*
* #see com.io.util.FileHandler#handle(java.io.File,
* java.nio.file.WatchEvent.Kind)
*/
public void handle(File file, Kind<?> fileEvent) {
LOGGER.log(Level.INFO,"Handler is triggered for file {0}",file.getPath());
if(fileEvent == StandardWatchEventKinds.ENTRY_CREATE) {
try {
boolean deleted = Files.deleteIfExists(Paths.get(file.getPath()));
assertTrue(deleted);
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
Create an instance of an Implemented FileHandler
FileHandlerTest fileHandlerTest = new FileHandlerTest();
Create an instance of a FileWatcher by passing path, an instance of an Implemented FileHandler, and types of file events that you want to monitor separated by commas.
FileWatcher fileWatcher = new FileWatcher(path, fileHandlerTest, StandardWatchEventKinds.ENTRY_CREATE);
Now Create and start a new Thread.
Thread watcherThread = new Thread(fileWatcher);
watcherThread.start();
This thread will start polling for your registered file events and will invoke your custom handle method once any of the registered events are detected.
public class FileWatcher implements Runnable {
private static final Logger LOGGER =Logger.getLogger(FileWatcher.class.getName());
private WatchService watcher;
private FileHandler fileHandler;
private List<Kind<?>> watchedEvents;
private Path directoryWatched;
/**
* #param directory
* #Path directory to watch files into
* #param fileHandler
* #FileHandler implemented instance to handle the file event
* #param watchRecursive
* if directory is to be watched recursively
* #param watchedEvents
* Set of file events watched
*
* #throws IOException
*/
public FileWatcher(Path directory, FileHandler fileHandler, boolean watchRecursive,
WatchEvent.Kind<?>... watchedEvents) throws IOException {
super();
this.watcher = FileSystems.getDefault().newWatchService();
this.fileHandler = fileHandler;
this.directoryWatched = directory;
this.watchedEvents = Arrays.asList(watchedEvents);
if (watchRecursive) {
// register all subfolders
Files.walkFileTree(directory, new SimpleFileVisitor<Path>() {
#Override
public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException {
LOGGER.log(Level.INFO, "Registering {0} ", dir);
dir.register(watcher, StandardWatchEventKinds.ENTRY_CREATE, StandardWatchEventKinds.ENTRY_DELETE,
StandardWatchEventKinds.ENTRY_MODIFY);
return FileVisitResult.CONTINUE;
}
});
} else {
directory.register(watcher, watchedEvents);
}
}
#SuppressWarnings({ "unchecked" })
public void run() {
LOGGER.log(Level.INFO, "Starting FileWatcher for {0}", directoryWatched.toAbsolutePath());
WatchKey key = null;
while (true) {
try {
key = watcher.take();
if (key != null) {
for (WatchEvent<?> event : key.pollEvents()) {
WatchEvent.Kind<?> kind = event.kind();
WatchEvent<Path> ev = (WatchEvent<Path>) event;
//directory in which file event is detected
Path directory = (Path) key.watchable();
Path fileName = ev.context();
if (watchedEvents.contains(kind)) {
LOGGER.log(Level.INFO, "Invoking handle on {0}", fileName.toAbsolutePath());
fileHandler.handle(directory.resolve(fileName).toFile(), kind);
}
}
key.reset();
}
} catch (InterruptedException ex) {
LOGGER.log(Level.SEVERE, "Polling Thread was interrupted ", ex);
Thread.currentThread().interrupt();
}
}
}
}

Simplest way to make custom debug watch in Eclipse?

Is it possible to create custom variable viewers in Eclipse? Suppose I wish to decompose bitfield or see bitmap as an image. Is it possible?
Can you give some simplest example?
UPDATE
I have tried to implement the following example: http://alvinalexander.com/java/jwarehouse/eclipse/org.eclipse.jdt.debug.tests/test-plugin/org/eclipse/jdt/debug/testplugin/detailpane/SimpleDetailPane.java.shtml
My plugin.xml is follows:
<?xml version="1.0" encoding="UTF-8"?>
<?eclipse version="3.0"?>
<plugin>
<extension
point="org.eclipse.debug.ui.detailPaneFactories">
<detailFactories
class="tests.debug.details.DetailPaneFactory"
id="tests.debug.details.detailFactories">
</detailFactories>
</extension>
</plugin>
My DetailPaneFactory.java is follows:
package tests.debug.details;
import java.util.AbstractSet;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import org.eclipse.debug.ui.IDetailPane;
import org.eclipse.debug.ui.IDetailPaneFactory;
import org.eclipse.jface.viewers.IStructuredSelection;
public class DetailPaneFactory implements IDetailPaneFactory {
private HashMap<String,Class<? extends IDetailPane>> classes = new HashMap<String,Class<? extends IDetailPane>>();
private void addClass(Class<? extends IDetailPane> cls) {
try {
String paneID = (String) cls.getField("ID").get(null);
classes.put(paneID, cls);
} catch (IllegalArgumentException | IllegalAccessException
| NoSuchFieldException | SecurityException e) {
throw new RuntimeException(e);
}
finally {
}
}
private Class<? extends IDetailPane> getClass(String paneID) {
Class<? extends IDetailPane> ans = classes.get(paneID);
return ans;
}
public DetailPaneFactory() {
addClass(SimpleDetailPane.class);
}
#Override
public IDetailPane createDetailPane(String paneID) {
Class<? extends IDetailPane> cls = getClass(paneID);
if( cls != null ) {
try {
return cls.newInstance();
} catch (InstantiationException | IllegalAccessException e) {
throw new RuntimeException();
}
}
else {
return null;
}
}
#Override
public String getDetailPaneName(String paneID) {
Class<? extends IDetailPane> cls = getClass(paneID);
if( cls != null ) {
try {
return (String)cls.getField("NAME").get(null);
} catch (IllegalArgumentException | IllegalAccessException
| NoSuchFieldException | SecurityException e) {
throw new RuntimeException(e);
}
}
else {
return null;
}
}
#Override
public String getDetailPaneDescription(String paneID) {
Class<? extends IDetailPane> cls = getClass(paneID);
if( cls != null ) {
try {
return (String)cls.getField("DESCRIPTION").get(null);
} catch (IllegalArgumentException | IllegalAccessException
| NoSuchFieldException | SecurityException e) {
throw new RuntimeException(e);
}
}
else {
return null;
}
}
#Override
public Set<String> getDetailPaneTypes(IStructuredSelection selection) {
return new AbstractSet<String>() {
#Override
public Iterator<String> iterator() {
return new Iterator<String>() {
private Iterator<Map.Entry<String,Class<? extends IDetailPane>>> it = classes.entrySet().iterator();
#Override
public void remove() {
it.remove();
}
#Override
public String next() {
return it.next().getKey();
}
#Override
public boolean hasNext() {
return it.hasNext();
}
};
}
#Override
public int size() {
return classes.size();
}
};
}
#Override
public String getDefaultDetailPane(IStructuredSelection selection) {
return SimpleDetailPane.ID;
}
}
and my SimpleDetailPane.java is as in example.
And it apparently works.
You can use Window / Show View / Expressions and add your expression that could make some calculations and show a textual output. But in order to anything else than a text output you'll have to contribute your own model presentation trough Eclipse platform extension points. See Detail Pane Factories Extension and source of org.eclipse.temp.JavaTableDetailPaneFactory class in Eclipse's own JDT.
As a quick workaround you can also write a static utility method that will open a new window with your image converted from a bitfield and call that method from a Display view using Ctrl-U shortcut.

Categories