Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
# no generated files in version control
src/main/gen/

# do not distribute Oracle's JDBC driver
lib/ojdbc.jar

# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
hs_err*

Expand Down
1 change: 1 addition & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ install: true
# allow gui testing on travis
before_script:
- psql -c 'create database jabref;' -U postgres
- mysql -u root -e 'create database jabref'

script:
- ./gradlew check
Expand Down
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ We refer to [GitHub issues](https://github.com/JabRef/jabref/issues) by using `#
## [Unreleased]

### Changed
- [#970](https://github.com/JabRef/jabref/issues/970): Implementation of shared database support (full system) with event based synchronization for MySQL, PostgreSQL and Oracle database systems.
- Externally fetched information can be merged for entries with an ISBN
- Externally fetched information can be merged for entries with an ArXiv eprint
- [#462](https://github.com/JabRef/jabref/issues/462) Extend the OpenConsoleFeature by offering a selection between default terminal emulator and configurable command execution.
Expand Down
38 changes: 38 additions & 0 deletions src/main/java/net/sf/jabref/BibDatabaseContext.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,10 @@
import net.sf.jabref.model.database.BibDatabase;
import net.sf.jabref.model.database.BibDatabaseMode;
import net.sf.jabref.model.database.BibDatabaseModeDetection;
import net.sf.jabref.model.database.DatabaseLocation;
import net.sf.jabref.model.entry.FieldName;
import net.sf.jabref.preferences.JabRefPreferences;
import net.sf.jabref.shared.DBMSSynchronizer;

/**
* Represents everything related to a BIB file.
Expand All @@ -25,6 +27,8 @@ public class BibDatabaseContext {
private final Defaults defaults;
/** The file where this database was last saved to. */
private File file;
private DBMSSynchronizer dbmsSynchronizer;
private DatabaseLocation location;

public BibDatabaseContext() {
this(new Defaults());
Expand All @@ -43,9 +47,15 @@ public BibDatabaseContext(BibDatabase database, Defaults defaults) {
}

public BibDatabaseContext(BibDatabase database, MetaData metaData, Defaults defaults) {
this(database, metaData, defaults, DatabaseLocation.LOCAL);
}

public BibDatabaseContext(BibDatabase database, MetaData metaData, Defaults defaults, DatabaseLocation location) {
this.defaults = Objects.requireNonNull(defaults);
this.database = Objects.requireNonNull(database);
this.metaData = Objects.requireNonNull(metaData);

updateDatabaseLocation(location);
}

public BibDatabaseContext(BibDatabase database, MetaData metaData) {
Expand All @@ -62,6 +72,10 @@ public BibDatabaseContext(BibDatabase database, MetaData metaData, File file) {
this(database, metaData, file, new Defaults());
}

public BibDatabaseContext(Defaults defaults, DatabaseLocation location) {
this(new BibDatabase(), new MetaData(), defaults, location);
}

public BibDatabaseMode getMode() {
Optional<BibDatabaseMode> mode = metaData.getMode();

Expand Down Expand Up @@ -181,4 +195,28 @@ private String getFileDirectoryPath(String directoryName) {
public List<String> getFileDirectory() {
return getFileDirectory(FieldName.FILE);
}

public DBMSSynchronizer getDBSynchronizer() {
return this.dbmsSynchronizer;
}

public DatabaseLocation getLocation() {
return this.location;
}

public void updateDatabaseLocation(DatabaseLocation newLocation) {

if ((this.location == DatabaseLocation.SHARED) && (newLocation == DatabaseLocation.LOCAL)) {
this.database.unregisterListener(dbmsSynchronizer);
this.metaData.unregisterListener(dbmsSynchronizer);
}

if (newLocation == DatabaseLocation.SHARED) {
this.dbmsSynchronizer = new DBMSSynchronizer(this);
this.database.registerListener(dbmsSynchronizer);
this.metaData.registerListener(dbmsSynchronizer);
}

this.location = newLocation;
}
}
75 changes: 48 additions & 27 deletions src/main/java/net/sf/jabref/MetaData.java
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@
import java.util.TreeMap;
import java.util.Vector;

import net.sf.jabref.event.GroupUpdatedEvent;
import net.sf.jabref.event.MetaDataChangedEvent;
import net.sf.jabref.importer.fileformat.ParseException;
import net.sf.jabref.logic.config.SaveOrderConfig;
import net.sf.jabref.logic.exporter.FieldFormatterCleanups;
Expand All @@ -43,8 +45,8 @@
import net.sf.jabref.logic.util.strings.StringUtil;
import net.sf.jabref.model.database.BibDatabaseMode;
import net.sf.jabref.model.entry.FieldName;
import net.sf.jabref.sql.DBStrings;

import com.google.common.eventbus.EventBus;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

Expand All @@ -66,14 +68,12 @@ public class MetaData implements Iterable<String> {

private final Map<String, List<String>> metaData = new HashMap<>();
private GroupTreeNode groupsRoot;
private final EventBus eventBus = new EventBus();

private AbstractLabelPattern labelPattern;

private DBStrings dbStrings = new DBStrings();

private Charset encoding = Globals.prefs.getDefaultEncoding();


/**
* The MetaData object stores all meta data sets in Vectors. To ensure that
* the data is written correctly to string, the user of a meta data Vector
Expand All @@ -82,7 +82,22 @@ public class MetaData implements Iterable<String> {
*/
private MetaData(Map<String, String> inData) throws ParseException {
Objects.requireNonNull(inData);
setData(inData);
}

/**
* The MetaData object can be constructed with no data in it.
*/
public MetaData() {
// No data
}

public static MetaData parse(Map<String, String> data) throws ParseException {
return new MetaData(data);
}

public void setData(Map<String, String> inData) throws ParseException {
clearMetaData();
for (Map.Entry<String, String> entry : inData.entrySet()) {
StringReader data = new StringReader(entry.getValue());
List<String> orderedData = new ArrayList<>();
Expand All @@ -98,25 +113,15 @@ private MetaData(Map<String, String> inData) throws ParseException {
if (GROUPSTREE.equals(entry.getKey())) {
putGroups(orderedData);
// the keys "groupsversion" and "groups" were used in JabRef versions around 1.3, we will not support them anymore
eventBus.post(new GroupUpdatedEvent(this));
} else if (SAVE_ACTIONS.equals(entry.getKey())) {
setSaveActions(FieldFormatterCleanups.parse(orderedData));
metaData.put(SAVE_ACTIONS, FieldFormatterCleanups.parse(orderedData).getAsStringList()); // Without MetaDataChangedEvent
} else {
putData(entry.getKey(), orderedData);
metaData.put(entry.getKey(), orderedData);
}
}
}

/**
* The MetaData object can be constructed with no data in it.
*/
public MetaData() {
// No data
}

public static MetaData parse(Map<String, String> data) throws ParseException {
return new MetaData(data);
}

public Optional<SaveOrderConfig> getSaveOrderConfig() {
List<String> storedSaveOrderConfig = getData(SAVE_ORDER_CONFIG);
if (storedSaveOrderConfig != null) {
Expand Down Expand Up @@ -161,7 +166,10 @@ public List<String> getData(String key) {
* @param key the key to remove
*/
public void remove(String key) {
metaData.remove(key);
if (metaData.containsKey(key)) { //otherwise redundant and disturbing events are going to be posted
metaData.remove(key);
postChange();
}
}

/**
Expand All @@ -172,6 +180,7 @@ public void remove(String key) {
*/
public void putData(String key, List<String> orderedData) {
metaData.put(key, orderedData);
postChange();
}

/**
Expand All @@ -182,6 +191,7 @@ public void putData(String key, List<String> orderedData) {
private void putGroups(List<String> orderedData) throws ParseException {
try {
groupsRoot = GroupTreeNode.parse(orderedData, Globals.prefs);
eventBus.post(new GroupUpdatedEvent(this));
} catch (ParseException e) {
throw new ParseException(Localization.lang(
"Group tree could not be parsed. If you save the BibTeX database, all groups will be lost."), e);
Expand All @@ -198,6 +208,7 @@ public GroupTreeNode getGroups() {
*/
public void setGroups(GroupTreeNode root) {
groupsRoot = root;
eventBus.post(new GroupUpdatedEvent(this));
}

/**
Expand Down Expand Up @@ -225,14 +236,6 @@ private static Optional<String> getNextUnit(Reader reader) throws IOException {
return Optional.empty();
}

public DBStrings getDBStrings() {
return dbStrings;
}

public void setDBStrings(DBStrings dbStrings) {
this.dbStrings = dbStrings;
}

/**
* @return the stored label patterns
*/
Expand Down Expand Up @@ -390,7 +393,6 @@ public Map<String, String> getAsStringMap() {
}
serializedMetaData.put(GROUPSTREE, stringBuilder.toString());
}

return serializedMetaData;
}

Expand Down Expand Up @@ -448,6 +450,13 @@ public void clearSaveOrderConfig() {
remove(SAVE_ORDER_CONFIG);
}

/**
* Posts a new {@link MetaDataChangedEvent} on the {@link EventBus}.
*/
public void postChange() {
eventBus.post(new MetaDataChangedEvent(this));
}

/**
* Returns the encoding used during parsing.
*/
Expand All @@ -458,4 +467,16 @@ public Charset getEncoding() {
public void setEncoding(Charset encoding) {
this.encoding = Objects.requireNonNull(encoding);
}

public void clearMetaData() {
metaData.clear();
}

public void registerListener(Object listener) {
this.eventBus.register(listener);
}

public void unregisterListener(Object listener) {
this.eventBus.unregister(listener);
}
}
19 changes: 19 additions & 0 deletions src/main/java/net/sf/jabref/event/GroupUpdatedEvent.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package net.sf.jabref.event;

import net.sf.jabref.MetaData;

public class GroupUpdatedEvent {

private final MetaData metaData;

/**
* @param metaData Affected instance
*/
public GroupUpdatedEvent(MetaData metaData) {
this.metaData = metaData;
}

public MetaData getMetaData() {
return this.metaData;
}
}
22 changes: 22 additions & 0 deletions src/main/java/net/sf/jabref/event/MetaDataChangedEvent.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package net.sf.jabref.event;

import net.sf.jabref.MetaData;

/**
* {@link MetaDataChangedEvent} is fired when a tuple of meta data has been put or removed.
*/
public class MetaDataChangedEvent {

private final MetaData metaData;

/**
* @param metaData Affected instance
*/
public MetaDataChangedEvent(MetaData metaData) {
this.metaData = metaData;
}

public MetaData getMetaData() {
return this.metaData;
}
}
26 changes: 26 additions & 0 deletions src/main/java/net/sf/jabref/event/source/EntryEventSource.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/* Copyright (C) 2016 JabRef contributors.
This program 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 2 of the License, or
(at your option) any later version.

This program 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 this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
package net.sf.jabref.event.source;

/**
* This enum represents the context EntryEvents were sent from.
*/
public enum EntryEventSource {
LOCAL,
SHARED,
UNDO,
SAVE_ACTION
}
Loading