diff --git a/build.gradle b/build.gradle index 9fa1c4d9b34..2b33236acd4 100644 --- a/build.gradle +++ b/build.gradle @@ -125,8 +125,6 @@ dependencies { compile 'commons-logging:commons-logging:1.2' - compile 'org.apache.commons:commons-lang3:3.6' - compile 'org.jsoup:jsoup:1.10.3' compile 'com.mashape.unirest:unirest-java:1.4.9' compile 'info.debatty:java-string-similarity:0.24' @@ -152,6 +150,9 @@ dependencies { testCompile 'com.github.tomakehurst:wiremock:2.6.0' testCompile 'org.assertj:assertj-swing-junit:3.6.0' testCompile 'org.reflections:reflections:0.9.11' + + testCompile 'com.tngtech.archunit:archunit-junit:0.4.0' + testCompile 'org.slf4j:slf4j-jcl:1.7.25' // required by ArchUnit to enable logging over jcl } sourceSets { diff --git a/external-libraries.txt b/external-libraries.txt index d303befdbbe..1bf47425154 100644 --- a/external-libraries.txt +++ b/external-libraries.txt @@ -1,6 +1,9 @@ This document lists the fonts, icons, and libraries used by JabRef. This file is manually kept in sync with build.gradle and the binary jars contained in the lib/ directory. +One can list all depdencies by using Gradle task `depdencyReport`. +It generated the file [build/reports/project/dependencies.txt](build/reports/project/dependencies.txt). + # Legend ## License diff --git a/src/main/java/org/jabref/Globals.java b/src/main/java/org/jabref/Globals.java index 3c5cdad55f0..7e404d1d31c 100644 --- a/src/main/java/org/jabref/Globals.java +++ b/src/main/java/org/jabref/Globals.java @@ -16,10 +16,10 @@ import org.jabref.logic.util.BuildInfo; import org.jabref.preferences.JabRefPreferences; +import com.google.common.base.StandardSystemProperty; import com.microsoft.applicationinsights.TelemetryClient; import com.microsoft.applicationinsights.TelemetryConfiguration; import com.microsoft.applicationinsights.telemetry.SessionState; -import org.apache.commons.lang3.SystemUtils; public class Globals { @@ -87,11 +87,11 @@ private static void startTelemetryClient() { telemetryConfiguration.setTrackingIsDisabled(!Globals.prefs.shouldCollectTelemetry()); telemetryClient = new TelemetryClient(telemetryConfiguration); telemetryClient.getContext().getProperties().put("JabRef version", Globals.BUILD_INFO.getVersion().toString()); - telemetryClient.getContext().getProperties().put("Java version", SystemUtils.JAVA_RUNTIME_VERSION); + telemetryClient.getContext().getProperties().put("Java version", StandardSystemProperty.JAVA_VERSION.value()); telemetryClient.getContext().getUser().setId(Globals.prefs.getOrCreateUserId()); telemetryClient.getContext().getSession().setId(UUID.randomUUID().toString()); - telemetryClient.getContext().getDevice().setOperatingSystem(SystemUtils.OS_NAME); - telemetryClient.getContext().getDevice().setOperatingSystemVersion(SystemUtils.OS_VERSION); + telemetryClient.getContext().getDevice().setOperatingSystem(StandardSystemProperty.OS_NAME.value()); + telemetryClient.getContext().getDevice().setOperatingSystemVersion(StandardSystemProperty.OS_VERSION.value()); telemetryClient.getContext().getDevice().setScreenResolution( Toolkit.getDefaultToolkit().getScreenSize().toString()); diff --git a/src/main/java/org/jabref/architecture/ApacheCommonsLang3Allowed.java b/src/main/java/org/jabref/architecture/ApacheCommonsLang3Allowed.java new file mode 100644 index 00000000000..f398c11f56e --- /dev/null +++ b/src/main/java/org/jabref/architecture/ApacheCommonsLang3Allowed.java @@ -0,0 +1,12 @@ +package org.jabref.architecture; + +/** + * Annotation to indicate that usage of ApacheCommonsLang3 is explicitly allowed. + * The intention is to fully switch to Google Guava and only use Apache Commons Lang3 if there is no other possibility + */ +public @interface ApacheCommonsLang3Allowed { + + // The rationale + String value(); + +} diff --git a/src/main/java/org/jabref/cli/ArgumentProcessor.java b/src/main/java/org/jabref/cli/ArgumentProcessor.java index 1d11dcc723f..8ddcb93dd52 100644 --- a/src/main/java/org/jabref/cli/ArgumentProcessor.java +++ b/src/main/java/org/jabref/cli/ArgumentProcessor.java @@ -51,7 +51,7 @@ import org.jabref.preferences.SearchPreferences; import org.jabref.shared.prefs.SharedDatabasePreferences; -import org.apache.commons.lang3.exception.ExceptionUtils; +import com.google.common.base.Throwables; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -273,7 +273,7 @@ private boolean exportMatches(List loaded) { matches); } catch (Exception ex) { System.err.println(Localization.lang("Could not export file") + " '" + data[1] + "': " - + ExceptionUtils.getStackTrace(ex)); + + Throwables.getStackTraceAsString(ex)); } } } else { @@ -451,7 +451,7 @@ private void exportFile(List loaded, String[] data) { } catch (Exception ex) { System.err.println(Localization.lang("Could not export file") + " '" + data[0] + "': " - + ExceptionUtils.getStackTrace(ex)); + + Throwables.getStackTraceAsString(ex)); } } diff --git a/src/main/java/org/jabref/gui/errorconsole/LogEventViewModel.java b/src/main/java/org/jabref/gui/errorconsole/LogEventViewModel.java index b3e0ec1dfcd..dd906d3c30b 100644 --- a/src/main/java/org/jabref/gui/errorconsole/LogEventViewModel.java +++ b/src/main/java/org/jabref/gui/errorconsole/LogEventViewModel.java @@ -6,7 +6,7 @@ import org.jabref.gui.IconTheme; import org.jabref.logic.util.OS; -import org.apache.commons.lang3.exception.ExceptionUtils; +import com.google.common.base.Throwables; import org.apache.logging.log4j.core.LogEvent; public class LogEventViewModel { @@ -46,7 +46,7 @@ public IconTheme.JabRefIcon getIcon() { } public Optional getStackTrace() { - return Optional.ofNullable(logEvent.getMessage().getThrowable()).map(ExceptionUtils::getStackTrace); + return Optional.ofNullable(logEvent.getMessage().getThrowable()).map(Throwables::getStackTraceAsString); } public String getDetailedText() { diff --git a/src/main/java/org/jabref/gui/groups/GroupNodeViewModel.java b/src/main/java/org/jabref/gui/groups/GroupNodeViewModel.java index 5a8069b08da..e53a54f5099 100644 --- a/src/main/java/org/jabref/gui/groups/GroupNodeViewModel.java +++ b/src/main/java/org/jabref/gui/groups/GroupNodeViewModel.java @@ -33,9 +33,9 @@ import org.jabref.model.groups.GroupTreeNode; import org.jabref.model.strings.StringUtil; +import com.google.common.base.Enums; import com.google.common.eventbus.Subscribe; import de.jensd.fx.glyphs.materialdesignicons.MaterialDesignIcon; -import org.apache.commons.lang3.EnumUtils; import org.fxmisc.easybind.EasyBind; public class GroupNodeViewModel { @@ -187,7 +187,7 @@ public MaterialDesignIcon getIcon() { } private Optional parseIcon(String iconCode) { - return Optional.ofNullable(EnumUtils.getEnum(MaterialDesignIcon.class, iconCode.toUpperCase(Locale.ENGLISH))); + return Enums.getIfPresent(MaterialDesignIcon.class, iconCode.toUpperCase(Locale.ENGLISH)).toJavaUtil(); } public ObservableList getChildren() { diff --git a/src/main/java/org/jabref/gui/preftabs/PreviewPrefsTab.java b/src/main/java/org/jabref/gui/preftabs/PreviewPrefsTab.java index 7cc66841421..b1ef3193fe0 100644 --- a/src/main/java/org/jabref/gui/preftabs/PreviewPrefsTab.java +++ b/src/main/java/org/jabref/gui/preftabs/PreviewPrefsTab.java @@ -27,9 +27,9 @@ import org.jabref.logic.util.TestEntry; import org.jabref.preferences.PreviewPreferences; +import com.google.common.primitives.Ints; import com.jgoodies.forms.builder.FormBuilder; import com.jgoodies.forms.factories.Paddings; -import org.apache.commons.lang3.ArrayUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -95,7 +95,7 @@ private void setupLogic() { chosenModel.add(newIndex, chosenModel.remove(oldIndex)); newSelectedIndices.add(newIndex); } - chosen.setSelectedIndices(ArrayUtils.toPrimitive(newSelectedIndices.toArray(new Integer[newSelectedIndices.size()]))); + chosen.setSelectedIndices(Ints.toArray(newSelectedIndices)); }); btnDown.addActionListener(event -> { @@ -108,7 +108,7 @@ private void setupLogic() { chosenModel.add(newIndex, chosenModel.remove(oldIndex)); newSelectedIndices.add(newIndex); } - chosen.setSelectedIndices(ArrayUtils.toPrimitive(newSelectedIndices.toArray(new Integer[newSelectedIndices.size()]))); + chosen.setSelectedIndices(Ints.toArray(newSelectedIndices)); }); btnDefault.addActionListener(event -> layout.setText(Globals.prefs.getPreviewPreferences() diff --git a/src/main/java/org/jabref/logic/formatter/bibtexfields/HtmlToUnicodeFormatter.java b/src/main/java/org/jabref/logic/formatter/bibtexfields/HtmlToUnicodeFormatter.java index 7ef2e651b24..c598966e7c9 100644 --- a/src/main/java/org/jabref/logic/formatter/bibtexfields/HtmlToUnicodeFormatter.java +++ b/src/main/java/org/jabref/logic/formatter/bibtexfields/HtmlToUnicodeFormatter.java @@ -1,11 +1,13 @@ package org.jabref.logic.formatter.bibtexfields; +import org.jabref.architecture.ApacheCommonsLang3Allowed; import org.jabref.logic.l10n.Localization; import org.jabref.logic.layout.LayoutFormatter; import org.jabref.model.cleanup.Formatter; import org.apache.commons.lang3.StringEscapeUtils; +@ApacheCommonsLang3Allowed("There is no equivalent in Google's Guava") public class HtmlToUnicodeFormatter implements LayoutFormatter, Formatter { @Override diff --git a/src/main/java/org/jabref/logic/integrity/IntegrityMessage.java b/src/main/java/org/jabref/logic/integrity/IntegrityMessage.java index f1d6735c332..c04a63f87fa 100644 --- a/src/main/java/org/jabref/logic/integrity/IntegrityMessage.java +++ b/src/main/java/org/jabref/logic/integrity/IntegrityMessage.java @@ -4,11 +4,10 @@ import org.jabref.model.entry.BibEntry; -import org.apache.commons.lang3.builder.EqualsBuilder; - public final class IntegrityMessage implements Cloneable { private final BibEntry entry; + private final String fieldName; private final String message; @@ -41,22 +40,13 @@ public Object clone() { } @Override - public boolean equals(Object obj) { - if (obj == null) { - return false; - } - if (obj == this) { - return true; - } - if (obj.getClass() != getClass()) { - return false; - } - IntegrityMessage that = (IntegrityMessage) obj; - return new EqualsBuilder() - .append(entry, that.entry) - .append(fieldName, that.fieldName) - .append(message, that.message) - .isEquals(); + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + IntegrityMessage that = (IntegrityMessage) o; + return Objects.equals(entry, that.entry) && + Objects.equals(fieldName, that.fieldName) && + Objects.equals(message, that.message); } @Override diff --git a/src/main/java/org/jabref/model/strings/StringUtil.java b/src/main/java/org/jabref/model/strings/StringUtil.java index 9f52af3fffb..d9cf81c2172 100644 --- a/src/main/java/org/jabref/model/strings/StringUtil.java +++ b/src/main/java/org/jabref/model/strings/StringUtil.java @@ -10,9 +10,12 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; +import org.jabref.architecture.ApacheCommonsLang3Allowed; + import com.google.common.base.CharMatcher; import org.apache.commons.lang3.StringUtils; +@ApacheCommonsLang3Allowed("There is no equivalent in Google's Guava") public class StringUtil { // Non-letters which are used to denote accents in LaTeX-commands, e.g., in {\"{a}} @@ -624,7 +627,11 @@ public static boolean isBlank(Optional string) { return !isNotBlank(string); } + /** + * Checks if a CharSequence is not empty (""), not null and not whitespace only. + */ public static boolean isNotBlank(String string) { + // No Guava equivalent existing return StringUtils.isNotBlank(string); } @@ -678,6 +685,7 @@ public static String unquote(String toUnquote, char quoteChar) { return result.toString(); } + @ApacheCommonsLang3Allowed("No Guava equivalent existing - see https://stackoverflow.com/q/3322152/873282 for a list of other implementations") public static String stripAccents(String searchQuery) { return StringUtils.stripAccents(searchQuery); } @@ -707,6 +715,7 @@ public static List getStringAsWords(String text) { return Arrays.asList(text.split("[\\s,;]+")); } + @ApacheCommonsLang3Allowed("No direct Guava equivalent existing - see https://stackoverflow.com/q/16560635/873282") public static boolean containsIgnoreCase(String text, String searchString) { return StringUtils.containsIgnoreCase(text, searchString); } diff --git a/src/test/java/org/jabref/CodeStyleTests.java b/src/test/java/org/jabref/CodeStyleTests.java index 7a1cef60a65..ec6a5641437 100644 --- a/src/test/java/org/jabref/CodeStyleTests.java +++ b/src/test/java/org/jabref/CodeStyleTests.java @@ -19,6 +19,6 @@ public void StringUtilClassIsSmall() throws Exception { Assert.assertTrue("StringUtil increased in size. " + "We try to keep this class as small as possible. " - + "Thus think twice if you add something to StringUtil.", lineCount <= 715); + + "Thus think twice if you add something to StringUtil.", lineCount <= 722); } } diff --git a/src/test/java/org/jabref/MainArchitectureTests.java b/src/test/java/org/jabref/architecture/MainArchitectureTests.java similarity index 99% rename from src/test/java/org/jabref/MainArchitectureTests.java rename to src/test/java/org/jabref/architecture/MainArchitectureTests.java index ea72ed250ab..7a98c05122c 100644 --- a/src/test/java/org/jabref/MainArchitectureTests.java +++ b/src/test/java/org/jabref/architecture/MainArchitectureTests.java @@ -1,4 +1,4 @@ -package org.jabref; +package org.jabref.architecture; import java.io.IOException; import java.nio.charset.StandardCharsets; diff --git a/src/test/java/org/jabref/architecture/MainArchitectureTestsWithArchUnit.java b/src/test/java/org/jabref/architecture/MainArchitectureTestsWithArchUnit.java new file mode 100644 index 00000000000..6120da6b808 --- /dev/null +++ b/src/test/java/org/jabref/architecture/MainArchitectureTestsWithArchUnit.java @@ -0,0 +1,20 @@ +package org.jabref.architecture; + +import com.tngtech.archunit.junit.AnalyzeClasses; +import com.tngtech.archunit.junit.ArchTest; +import com.tngtech.archunit.junit.ArchUnitRunner; +import com.tngtech.archunit.lang.ArchRule; +import org.junit.runner.RunWith; + +import static com.tngtech.archunit.lang.syntax.ArchRuleDefinition.noClasses; + +@RunWith(ArchUnitRunner.class) +@AnalyzeClasses(packages = "org.jabref") +public class MainArchitectureTestsWithArchUnit { + + @ArchTest + public static final ArchRule doNotUseApacheCommonsLang3 = + noClasses().that().areNotAnnotatedWith(ApacheCommonsLang3Allowed.class) + .should().accessClassesThat().resideInAPackage("org.apache.commons.lang3"); + +} diff --git a/src/test/java/org/jabref/TestArchitectureTests.java b/src/test/java/org/jabref/architecture/TestArchitectureTests.java similarity index 95% rename from src/test/java/org/jabref/TestArchitectureTests.java rename to src/test/java/org/jabref/architecture/TestArchitectureTests.java index 955d731f8c8..b1c0dc618a5 100644 --- a/src/test/java/org/jabref/TestArchitectureTests.java +++ b/src/test/java/org/jabref/architecture/TestArchitectureTests.java @@ -1,4 +1,4 @@ -package org.jabref; +package org.jabref.architecture; import java.io.IOException; import java.nio.charset.StandardCharsets; @@ -17,7 +17,7 @@ import org.junit.runner.RunWith; import org.junit.runners.Parameterized; -import static org.jabref.MainArchitectureTests.CLASS_ORG_JABREF_GLOBALS; +import static org.jabref.architecture.MainArchitectureTests.CLASS_ORG_JABREF_GLOBALS; @RunWith(Parameterized.class) public class TestArchitectureTests {