-
-
Notifications
You must be signed in to change notification settings - Fork 2.6k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge remote-tracking branch 'upstream/master' into fixSetFiles
* upstream/master: (31 commits) Source tab entry duplication (#3360) Use CITE_COMMENT not only for external latex editors but also for cop… (#3351) Updating with new translations (#3348) Upgrade error-prone (#3350) Jabref_pt_BR partially updated (#3349) Used late initialization for context menus (#3340) Fix NPE when calling with bib file as cmd argument (#3343) update mockito-core from 2.10.0 -> 2.11.0 (#3338) Remove underscore in Localized messages (#3336) Localisation: French: new entries translated (#3337) Refactoring: Lazy init of all editor tabs (#3333) Initializing EntryEditor Tabs on focus (#3331) Fix #3292: annotations are now automatically refreshed (#3325) Change integrity message for names depending on database mode (#3330) Fix location bundle with fast access (#3327) Small code cleanup Fix "path not found" exception Small fix in drag and drop handler of linked files (#3328) Fix NPE in MainTable (#3318) Increase relative size of abstract field in editor (#3320) ...
- Loading branch information
Showing
87 changed files
with
1,270 additions
and
1,369 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
161 changes: 161 additions & 0 deletions
161
src/main/java/org/jabref/collab/DatabaseChangeMonitor.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,161 @@ | ||
package org.jabref.collab; | ||
|
||
import java.io.IOException; | ||
import java.nio.file.Files; | ||
import java.nio.file.Path; | ||
import java.util.Optional; | ||
|
||
import javax.swing.SwingUtilities; | ||
|
||
import org.jabref.JabRefExecutorService; | ||
import org.jabref.gui.BasePanel; | ||
import org.jabref.gui.SidePaneManager; | ||
import org.jabref.gui.util.FileUpdateListener; | ||
import org.jabref.gui.util.FileUpdateMonitor; | ||
import org.jabref.logic.util.io.FileBasedLock; | ||
import org.jabref.logic.util.io.FileUtil; | ||
import org.jabref.model.database.BibDatabaseContext; | ||
|
||
import org.apache.commons.logging.Log; | ||
import org.apache.commons.logging.LogFactory; | ||
|
||
public class DatabaseChangeMonitor implements FileUpdateListener { | ||
private static final Log LOGGER = LogFactory.getLog(DatabaseChangeMonitor.class); | ||
|
||
private final BibDatabaseContext database; | ||
private final FileUpdateMonitor fileMonitor; | ||
private final BasePanel panel; | ||
private boolean updatedExternally; | ||
private Path tmpFile; | ||
private long timeStamp; | ||
private long fileSize; | ||
|
||
public DatabaseChangeMonitor(BibDatabaseContext database, FileUpdateMonitor fileMonitor, BasePanel panel) { | ||
this.database = database; | ||
this.fileMonitor = fileMonitor; | ||
this.panel = panel; | ||
|
||
this.database.getDatabasePath().ifPresent(path -> { | ||
try { | ||
fileMonitor.addListenerForFile(path, this); | ||
timeStamp = Files.getLastModifiedTime(path).toMillis(); | ||
fileSize = Files.size(path); | ||
tmpFile = Files.createTempFile("jabref", ".bib"); | ||
tmpFile.toFile().deleteOnExit(); | ||
copyToTemp(path); | ||
} catch (IOException e) { | ||
LOGGER.error("Error while trying to monitor " + path, e); | ||
} | ||
}); | ||
} | ||
|
||
@Override | ||
public void fileUpdated() { | ||
if (panel.isSaving()) { | ||
// We are just saving the file, so this message is most likely due to bad timing. | ||
// If not, we'll handle it on the next polling. | ||
return; | ||
} | ||
|
||
updatedExternally = true; | ||
|
||
final ChangeScanner scanner = new ChangeScanner(panel.frame(), panel, database.getDatabaseFile().orElse(null), tmpFile); | ||
|
||
// Test: running scan automatically in background | ||
if (database.getDatabasePath().isPresent() && !FileBasedLock.waitForFileLock(database.getDatabasePath().get())) { | ||
// The file is locked even after the maximum wait. Do nothing. | ||
LOGGER.error("File updated externally, but change scan failed because the file is locked."); | ||
|
||
// Wait a bit and then try again | ||
try { | ||
Thread.sleep(1000); | ||
} catch (InterruptedException e) { | ||
// Nothing to do | ||
} | ||
fileUpdated(); | ||
return; | ||
} | ||
|
||
JabRefExecutorService.INSTANCE.executeInterruptableTaskAndWait(scanner); | ||
|
||
// Adding the sidepane component is Swing work, so we must do this in the Swing | ||
// thread: | ||
Runnable t = () -> { | ||
|
||
// Check if there is already a notification about external | ||
// changes: | ||
SidePaneManager sidePaneManager = panel.getSidePaneManager(); | ||
boolean hasAlready = sidePaneManager.hasComponent(FileUpdatePanel.class); | ||
if (hasAlready) { | ||
sidePaneManager.hideComponent(FileUpdatePanel.class); | ||
sidePaneManager.unregisterComponent(FileUpdatePanel.class); | ||
} | ||
FileUpdatePanel pan = new FileUpdatePanel(panel, sidePaneManager, | ||
database.getDatabaseFile().orElse(null), scanner); | ||
sidePaneManager.register(pan); | ||
sidePaneManager.show(FileUpdatePanel.class); | ||
}; | ||
|
||
if (scanner.changesFound()) { | ||
SwingUtilities.invokeLater(t); | ||
} else { | ||
updatedExternally = false; | ||
} | ||
} | ||
|
||
/** | ||
* Forces a check on the file, and returns the result. Check if time stamp or the file size has changed. | ||
* | ||
* @return boolean true if the file has changed. | ||
*/ | ||
private boolean hasBeenModified() { | ||
Optional<Path> file = database.getDatabasePath(); | ||
if (file.isPresent()) { | ||
try { | ||
long modified = Files.getLastModifiedTime(file.get()).toMillis(); | ||
if (modified == 0L) { | ||
// File deleted | ||
return false; | ||
} | ||
long fileSizeNow = Files.size(file.get()); | ||
return (timeStamp != modified) || (fileSize != fileSizeNow); | ||
} catch (IOException ex) { | ||
return false; | ||
} | ||
} | ||
return false; | ||
} | ||
|
||
public void unregister() { | ||
database.getDatabasePath().ifPresent(file -> fileMonitor.removeListener(file, this)); | ||
} | ||
|
||
public boolean hasBeenModifiedExternally() { | ||
return updatedExternally || hasBeenModified(); | ||
} | ||
|
||
public void markExternalChangesAsResolved() { | ||
updatedExternally = false; | ||
} | ||
|
||
public void markAsSaved() { | ||
database.getDatabasePath().ifPresent(file -> { | ||
try { | ||
timeStamp = Files.getLastModifiedTime(file).toMillis(); | ||
fileSize = Files.size(file); | ||
|
||
copyToTemp(file); | ||
} catch (IOException ex) { | ||
LOGGER.error("Error while getting file information", ex); | ||
} | ||
}); | ||
} | ||
|
||
private void copyToTemp(Path file) { | ||
FileUtil.copyFile(file, tmpFile, true); | ||
} | ||
|
||
public Path getTempFile() { | ||
return tmpFile; | ||
} | ||
} |
Oops, something went wrong.