getURLByDoi(DOI doi) throws IOException, NullPointerException {
return Optional.of(link);
}
+ private Document getPage(String url) throws IOException {
+ return Jsoup.connect(url)
+ .userAgent(URLDownload.USER_AGENT)
+ .referrer("www.google.com")
+ .ignoreHttpErrors(true)
+ .get();
+ }
+
/**
* Constructs a URL based on the query, size and page number.
- *
* Extract the numerical internal ID and add it to the URL to receive a link to a {@link BibEntry}
+ *
*
* @param luceneQuery the search query.
* @return A URL that lets us download a .bib file
- * @throws URISyntaxException from {@link URIBuilder}'s build() method
- * @throws IOException from {@link Connection}'s get() method
*/
- private Document getPage(QueryNode luceneQuery) throws URISyntaxException, IOException {
+ private static String getUrlForQuery(QueryNode luceneQuery) throws URISyntaxException {
String query = new DefaultQueryTransformer().transformLuceneQuery(luceneQuery).orElse("");
URIBuilder source = new URIBuilder(SEARCH);
source.addParameter("type", "publication");
source.addParameter("query", query);
- return Jsoup.connect(source.build().toString())
- .userAgent(URLDownload.USER_AGENT)
- .referrer("www.google.com")
- .ignoreHttpErrors(true)
- .get();
+ String url = source.build().toString();
+ return url;
}
@Override
@@ -206,13 +209,21 @@ public TrustLevel getTrustLevel() {
@Override
public List performSearch(QueryNode luceneQuery) throws FetcherException {
Document html;
+
+ String url;
try {
- html = getPage(luceneQuery);
+ url = getUrlForQuery(luceneQuery);
+ } catch (URISyntaxException e) {
+ throw new FetcherException("Invalid URL", e);
+ }
+
+ try {
+ html = getPage(url);
// ResearchGate's server blocks when too many request are made
if (!html.getElementsByClass("nova-legacy-v-publication-item__title").hasText()) {
- throw new FetcherException("ResearchGate server unavailable");
+ throw FetcherException.ofUrl(url, "ResearchGate server unavailable");
}
- } catch (URISyntaxException | IOException e) {
+ } catch (IOException e) {
throw new FetcherException("URL is not correct", e);
}
@@ -234,7 +245,7 @@ public List performSearch(QueryNode luceneQuery) throws FetcherExcepti
entry = parser.parseSingleEntry(bib);
entry.ifPresent(list::add);
} catch (ParseException e) {
- LOGGER.debug("Entry is not convertible to Bibtex", e);
+ LOGGER.debug("Entry is not convertible to BibTeX", e);
}
}
return list;
@@ -245,7 +256,7 @@ private BufferedReader getInputStream(String urlString) {
URL url = new URL(urlString);
return new BufferedReader(new InputStreamReader(url.openStream()));
} catch (IOException e) {
- LOGGER.debug("Wrong URL:", e);
+ LOGGER.debug("Wrong URL", e);
}
return null;
}
diff --git a/src/main/java/org/jabref/logic/importer/fetcher/RfcFetcher.java b/src/main/java/org/jabref/logic/importer/fetcher/RfcFetcher.java
index db1df209765..43849ff3319 100644
--- a/src/main/java/org/jabref/logic/importer/fetcher/RfcFetcher.java
+++ b/src/main/java/org/jabref/logic/importer/fetcher/RfcFetcher.java
@@ -7,7 +7,6 @@
import java.util.Optional;
import org.jabref.logic.help.HelpFile;
-import org.jabref.logic.importer.FetcherException;
import org.jabref.logic.importer.IdBasedParserFetcher;
import org.jabref.logic.importer.ImportFormatPreferences;
import org.jabref.logic.importer.Parser;
@@ -46,7 +45,7 @@ public Optional getHelpPage() {
* @return the URL of the RFC resource
*/
@Override
- public URL getUrlForIdentifier(String identifier) throws URISyntaxException, MalformedURLException, FetcherException {
+ public URL getUrlForIdentifier(String identifier) throws URISyntaxException, MalformedURLException {
String prefixedIdentifier = identifier.toLowerCase(Locale.ENGLISH);
// if not a "draft" version
if ((!prefixedIdentifier.startsWith(DRAFT_PREFIX)) && (!prefixedIdentifier.startsWith("rfc"))) {
diff --git a/src/main/java/org/jabref/logic/importer/fetcher/ScholarArchiveFetcher.java b/src/main/java/org/jabref/logic/importer/fetcher/ScholarArchiveFetcher.java
index 27a5273f45b..3c1521e1861 100644
--- a/src/main/java/org/jabref/logic/importer/fetcher/ScholarArchiveFetcher.java
+++ b/src/main/java/org/jabref/logic/importer/fetcher/ScholarArchiveFetcher.java
@@ -8,7 +8,6 @@
import java.util.Optional;
import java.util.stream.IntStream;
-import org.jabref.logic.importer.FetcherException;
import org.jabref.logic.importer.PagedSearchBasedParserFetcher;
import org.jabref.logic.importer.ParseException;
import org.jabref.logic.importer.Parser;
@@ -46,7 +45,7 @@ public class ScholarArchiveFetcher implements PagedSearchBasedParserFetcher {
* @return URL
*/
@Override
- public URL getURLForQuery(QueryNode luceneQuery, int pageNumber) throws URISyntaxException, MalformedURLException, FetcherException {
+ public URL getURLForQuery(QueryNode luceneQuery, int pageNumber) throws URISyntaxException, MalformedURLException {
URIBuilder uriBuilder = new URIBuilder(API_URL);
uriBuilder.addParameter("q", new ScholarArchiveQueryTransformer().transformLuceneQuery(luceneQuery).orElse(""));
uriBuilder.addParameter("from", String.valueOf(getPageSize() * pageNumber));
diff --git a/src/main/java/org/jabref/logic/importer/fetcher/SemanticScholar.java b/src/main/java/org/jabref/logic/importer/fetcher/SemanticScholar.java
index ab993deeeb1..09f8534e6a3 100644
--- a/src/main/java/org/jabref/logic/importer/fetcher/SemanticScholar.java
+++ b/src/main/java/org/jabref/logic/importer/fetcher/SemanticScholar.java
@@ -133,15 +133,16 @@ String getURLBySource(String source) throws IOException, FetcherException {
}
@Override
- public URL getURLForQuery(QueryNode luceneQuery, int pageNumber) throws URISyntaxException, MalformedURLException, FetcherException {
+ public URL getURLForQuery(QueryNode luceneQuery, int pageNumber) throws URISyntaxException, MalformedURLException {
URIBuilder uriBuilder = new URIBuilder(SOURCE_WEB_SEARCH);
uriBuilder.addParameter("query", new DefaultQueryTransformer().transformLuceneQuery(luceneQuery).orElse(""));
uriBuilder.addParameter("offset", String.valueOf(pageNumber * getPageSize()));
uriBuilder.addParameter("limit", String.valueOf(Math.min(getPageSize(), 10000 - pageNumber * getPageSize())));
// All fields need to be specified
uriBuilder.addParameter("fields", "paperId,externalIds,url,title,abstract,venue,year,authors");
- LOGGER.debug("URL for query: {}", uriBuilder.build().toURL());
- return uriBuilder.build().toURL();
+ URL result = uriBuilder.build().toURL();
+ LOGGER.debug("URL for query: {}", result);
+ return result;
}
/**
diff --git a/src/main/java/org/jabref/logic/importer/fetcher/SpringerFetcher.java b/src/main/java/org/jabref/logic/importer/fetcher/SpringerFetcher.java
index b271b113c39..33be2ee890e 100644
--- a/src/main/java/org/jabref/logic/importer/fetcher/SpringerFetcher.java
+++ b/src/main/java/org/jabref/logic/importer/fetcher/SpringerFetcher.java
@@ -11,7 +11,6 @@
import java.util.stream.Collectors;
import org.jabref.logic.help.HelpFile;
-import org.jabref.logic.importer.FetcherException;
import org.jabref.logic.importer.ImporterPreferences;
import org.jabref.logic.importer.PagedSearchBasedParserFetcher;
import org.jabref.logic.importer.Parser;
@@ -185,8 +184,7 @@ public String getTestUrl() {
* @return URL
*/
@Override
- public URL getURLForQuery(QueryNode luceneQuery, int pageNumber) throws URISyntaxException, MalformedURLException, FetcherException {
-
+ public URL getURLForQuery(QueryNode luceneQuery, int pageNumber) throws URISyntaxException, MalformedURLException {
URIBuilder uriBuilder = new URIBuilder(API_URL);
uriBuilder.addParameter("q", new SpringerQueryTransformer().transformLuceneQuery(luceneQuery).orElse("")); // Search query
uriBuilder.addParameter("api_key", importerPreferences.getApiKey(getName()).orElse(API_KEY)); // API key
diff --git a/src/main/java/org/jabref/logic/importer/fetcher/ZbMATH.java b/src/main/java/org/jabref/logic/importer/fetcher/ZbMATH.java
index 8f88bdf0675..b02c19d9025 100644
--- a/src/main/java/org/jabref/logic/importer/fetcher/ZbMATH.java
+++ b/src/main/java/org/jabref/logic/importer/fetcher/ZbMATH.java
@@ -104,7 +104,7 @@ public URL getURLForEntry(BibEntry entry) throws URISyntaxException, MalformedUR
}
@Override
- public URL getURLForQuery(QueryNode luceneQuery) throws URISyntaxException, MalformedURLException, FetcherException {
+ public URL getURLForQuery(QueryNode luceneQuery) throws URISyntaxException, MalformedURLException {
URIBuilder uriBuilder = new URIBuilder("https://zbmath.org/bibtexoutput/");
uriBuilder.addParameter("q", new ZbMathQueryTransformer().transformLuceneQuery(luceneQuery).orElse("")); // search all fields
uriBuilder.addParameter("start", "0"); // start index
@@ -113,7 +113,7 @@ public URL getURLForQuery(QueryNode luceneQuery) throws URISyntaxException, Malf
}
@Override
- public URL getUrlForIdentifier(String identifier) throws URISyntaxException, MalformedURLException, FetcherException {
+ public URL getUrlForIdentifier(String identifier) throws URISyntaxException, MalformedURLException {
URIBuilder uriBuilder = new URIBuilder("https://zbmath.org/bibtexoutput/");
String query = "an:".concat(identifier); // use an: to search for a zbMATH identifier
uriBuilder.addParameter("q", query);
diff --git a/src/main/java/org/jabref/logic/importer/fetcher/isbntobibtex/DoiToBibtexConverterComIsbnFetcher.java b/src/main/java/org/jabref/logic/importer/fetcher/isbntobibtex/DoiToBibtexConverterComIsbnFetcher.java
index 1ebc813c7bc..66bd0235ee6 100644
--- a/src/main/java/org/jabref/logic/importer/fetcher/isbntobibtex/DoiToBibtexConverterComIsbnFetcher.java
+++ b/src/main/java/org/jabref/logic/importer/fetcher/isbntobibtex/DoiToBibtexConverterComIsbnFetcher.java
@@ -8,7 +8,6 @@
import java.util.stream.IntStream;
import java.util.stream.Stream;
-import org.jabref.logic.importer.FetcherException;
import org.jabref.logic.importer.ImportFormatPreferences;
import org.jabref.logic.importer.ParseException;
import org.jabref.logic.importer.Parser;
@@ -40,7 +39,7 @@ public String getName() {
}
@Override
- public URL getUrlForIdentifier(String identifier) throws URISyntaxException, MalformedURLException, FetcherException {
+ public URL getUrlForIdentifier(String identifier) throws URISyntaxException, MalformedURLException {
this.ensureThatIsbnIsValid(identifier);
return new URIBuilder(BASE_URL)
.setPathSegments("getInfo.php")
diff --git a/src/main/java/org/jabref/logic/importer/fetcher/isbntobibtex/EbookDeIsbnFetcher.java b/src/main/java/org/jabref/logic/importer/fetcher/isbntobibtex/EbookDeIsbnFetcher.java
index 42effb2bf05..f55ba6eaa76 100644
--- a/src/main/java/org/jabref/logic/importer/fetcher/isbntobibtex/EbookDeIsbnFetcher.java
+++ b/src/main/java/org/jabref/logic/importer/fetcher/isbntobibtex/EbookDeIsbnFetcher.java
@@ -7,7 +7,6 @@
import org.jabref.logic.cleanup.FieldFormatterCleanup;
import org.jabref.logic.formatter.bibtexfields.NormalizeNamesFormatter;
import org.jabref.logic.formatter.bibtexfields.NormalizePagesFormatter;
-import org.jabref.logic.importer.FetcherException;
import org.jabref.logic.importer.ImportFormatPreferences;
import org.jabref.logic.importer.fetcher.AbstractIsbnFetcher;
import org.jabref.model.entry.BibEntry;
@@ -31,7 +30,7 @@ public String getName() {
}
@Override
- public URL getUrlForIdentifier(String identifier) throws URISyntaxException, MalformedURLException, FetcherException {
+ public URL getUrlForIdentifier(String identifier) throws URISyntaxException, MalformedURLException {
this.ensureThatIsbnIsValid(identifier);
return new URIBuilder(BASE_URL)
.addParameter("isbn", identifier)
diff --git a/src/main/java/org/jabref/logic/importer/fetcher/isbntobibtex/OpenLibraryIsbnFetcher.java b/src/main/java/org/jabref/logic/importer/fetcher/isbntobibtex/OpenLibraryIsbnFetcher.java
index 3283a169cf8..cb8e7267d77 100644
--- a/src/main/java/org/jabref/logic/importer/fetcher/isbntobibtex/OpenLibraryIsbnFetcher.java
+++ b/src/main/java/org/jabref/logic/importer/fetcher/isbntobibtex/OpenLibraryIsbnFetcher.java
@@ -11,7 +11,6 @@
import java.util.stream.Stream;
import org.jabref.logic.importer.AuthorListParser;
-import org.jabref.logic.importer.FetcherException;
import org.jabref.logic.importer.ImportFormatPreferences;
import org.jabref.logic.importer.ParseException;
import org.jabref.logic.importer.Parser;
@@ -53,7 +52,7 @@ public String getName() {
}
@Override
- public URL getUrlForIdentifier(String identifier) throws URISyntaxException, MalformedURLException, FetcherException {
+ public URL getUrlForIdentifier(String identifier) throws URISyntaxException, MalformedURLException {
this.ensureThatIsbnIsValid(identifier);
return new URIBuilder(BASE_URL)
.setPathSegments("isbn", identifier + ".json")
diff --git a/src/main/java/org/jabref/logic/importer/fileformat/ACMPortalParser.java b/src/main/java/org/jabref/logic/importer/fileformat/ACMPortalParser.java
index fb60e4a92f4..e1eef008b2c 100644
--- a/src/main/java/org/jabref/logic/importer/fileformat/ACMPortalParser.java
+++ b/src/main/java/org/jabref/logic/importer/fileformat/ACMPortalParser.java
@@ -83,16 +83,16 @@ public List parseDoiSearchPage(InputStream stream) throws ParseException
return doiList;
}
- /**
- * Obtain BibEntry according to DOI
- *
- * @param doiList DOI List
- * @return BibEntry List
- */
public List getBibEntriesFromDoiList(List doiList) throws FetcherException {
List bibEntries = new ArrayList<>();
CookieHandler.setDefault(new CookieManager());
- try (InputStream stream = new URLDownload(getUrlFromDoiList(doiList)).asInputStream()) {
+ URL urlFromDoiList;
+ try {
+ urlFromDoiList = getUrlFromDoiList(doiList);
+ } catch (URISyntaxException | MalformedURLException e) {
+ throw new FetcherException("Wrong URL", e);
+ }
+ try (InputStream stream = new URLDownload(urlFromDoiList).asInputStream()) {
String jsonString = new String((stream.readAllBytes()), StandardCharsets.UTF_8);
JsonElement jsonElement = JsonParser.parseString(jsonString);
@@ -104,8 +104,8 @@ public List getBibEntriesFromDoiList(List doiList) throws Fetc
}
}
}
- } catch (IOException | URISyntaxException e) {
- throw new FetcherException("A network error occurred while fetching from ", e);
+ } catch (IOException e) {
+ throw new FetcherException(urlFromDoiList, e);
}
return bibEntries;
diff --git a/src/main/java/org/jabref/logic/net/URLDownload.java b/src/main/java/org/jabref/logic/net/URLDownload.java
index 4720ebd7b1c..c5e312279bd 100644
--- a/src/main/java/org/jabref/logic/net/URLDownload.java
+++ b/src/main/java/org/jabref/logic/net/URLDownload.java
@@ -364,13 +364,14 @@ private static void copy(InputStream in, Writer out, Charset encoding) throws IO
}
/**
- * Open a connection to this object's URL (with specified settings). If accessing an HTTP URL, don't forget
- * to close the resulting connection after usage.
+ * Open a connection to this object's URL (with specified settings).
+ *
+ * If accessing an HTTP URL, remeber to close the resulting connection after usage.
*
* @return an open connection
*/
public URLConnection openConnection() throws IOException {
- URLConnection connection = this.source.openConnection();
+ URLConnection connection = getUrlConnection();
connection.setConnectTimeout((int) connectTimeout.toMillis());
for (Entry entry : this.parameters.entrySet()) {
connection.setRequestProperty(entry.getKey(), entry.getValue());
@@ -383,17 +384,18 @@ public URLConnection openConnection() throws IOException {
}
if (connection instanceof HttpURLConnection httpURLConnection) {
- // this does network i/o: GET + read returned headers
int status;
try {
+ // this does network i/o: GET + read returned headers
status = httpURLConnection.getResponseCode();
} catch (IOException e) {
LOGGER.error("Error getting response code", e);
// TODO: Convert e to FetcherClientException
+ // Same TODO as in org.jabref.logic.importer.EntryBasedParserFetcher.performSearch.
+ // Maybe do this in org.jabref.logic.importer.FetcherException.getLocalizedMessage
throw e;
}
- // normally, 3xx is redirect
if ((status == HttpURLConnection.HTTP_MOVED_TEMP)
|| (status == HttpURLConnection.HTTP_MOVED_PERM)
|| (status == HttpURLConnection.HTTP_SEE_OTHER)) {
@@ -405,15 +407,30 @@ public URLConnection openConnection() throws IOException {
SimpleHttpResponse httpResponse = new SimpleHttpResponse(httpURLConnection);
LOGGER.info("{}", httpResponse);
if ((status >= 400) && (status < 500)) {
- throw new IOException(new FetcherClientException(httpResponse));
+ throw new IOException(new FetcherClientException(this.source, httpResponse));
} else if (status >= 500) {
- throw new IOException(new FetcherServerException(httpResponse));
+ throw new IOException(new FetcherServerException(this.source, httpResponse));
}
}
}
return connection;
}
+ private URLConnection getUrlConnection() throws IOException {
+ URLConnection connection = this.source.openConnection();
+ connection.setConnectTimeout((int) connectTimeout.toMillis());
+ for (Entry entry : this.parameters.entrySet()) {
+ connection.setRequestProperty(entry.getKey(), entry.getValue());
+ }
+ if (!this.postData.isEmpty()) {
+ connection.setDoOutput(true);
+ try (DataOutputStream wr = new DataOutputStream(connection.getOutputStream())) {
+ wr.writeBytes(this.postData);
+ }
+ }
+ return connection;
+ }
+
public void setConnectTimeout(Duration connectTimeout) {
if (connectTimeout != null) {
this.connectTimeout = connectTimeout;
diff --git a/src/main/resources/l10n/JabRef_en.properties b/src/main/resources/l10n/JabRef_en.properties
index 18afe55150c..5a4ef4ebcdd 100644
--- a/src/main/resources/l10n/JabRef_en.properties
+++ b/src/main/resources/l10n/JabRef_en.properties
@@ -1842,7 +1842,6 @@ Fetcher\ '%0'\ did\ not\ find\ an\ entry\ for\ id\ '%1'.=Fetcher '%0' did not fi
Select\ first\ entry=Select first entry
Select\ last\ entry=Select last entry
-Invalid\ ISBN\:\ '%0'.=Invalid ISBN: '%0'.
should\ be\ an\ integer\ or\ normalized=should be an integer or normalized
should\ be\ normalized=should be normalized
@@ -2615,12 +2614,14 @@ Illegal\ characters\ in\ the\ file\ name\ detected.\nFile\ will\ be\ renamed\ to
Rename\ and\ add=Rename and add
Failed\ to\ download\ from\ URL=Failed to download from URL
-401\ Unauthorized\:\ Access\ Denied.\ You\ are\ not\ authorized\ to\ access\ this\ resource.\ Please\ check\ your\ credentials\ and\ try\ again.\ If\ you\ believe\ you\ should\ have\ access,\ please\ contact\ the\ administrator\ for\ assistance.\nURL\:\ %0\nDetails\:\ %1=401 Unauthorized: Access Denied. You are not authorized to access this resource. Please check your credentials and try again. If you believe you should have access, please contact the administrator for assistance.\nURL: %0\nDetails: %1
-403\ Forbidden\:\ Access\ Denied.\ You\ do\ not\ have\ permission\ to\ access\ this\ resource.\ Please\ contact\ the\ administrator\ for\ assistance\ or\ try\ a\ different\ action.\nURL\:\ %0\nDetails\:\ %1=403 Forbidden: Access Denied. You do not have permission to access this resource. Please contact the administrator for assistance or try a different action.\nURL: %0\nDetails: %1
-404\ Not\ Found\ Error\:\ The\ requested\ resource\ could\ not\ be\ found.\ It\ seems\ that\ the\ file\ you\ are\ trying\ to\ download\ is\ not\ available\ or\ has\ been\ moved.\ Please\ verify\ the\ URL\ and\ try\ again.\ If\ you\ believe\ this\ is\ an\ error,\ please\ contact\ the\ administrator\ for\ further\ assistance.\nURL\:\ %0\nDetails\:\ %1=404 Not Found Error: The requested resource could not be found. It seems that the file you are trying to download is not available or has been moved. Please verify the URL and try again. If you believe this is an error, please contact the administrator for further assistance.\nURL: %0\nDetails: %1
-Error\ downloading\ from\ URL.\ Cause\ is\ likely\ the\ server\ side.\nPlease\ try\ again\ later\ or\ contact\ the\ server\ administrator.\nURL\:\ %0\nDetails\:\ %1=Error downloading from URL. Cause is likely the server side.\nPlease try again later or contact the server administrator.\nURL: %0\nDetails: %1
+401\ Unauthorized\:\ Access\ Denied.\ You\ are\ not\ authorized\ to\ access\ this\ resource.\ Please\ check\ your\ credentials\ and\ try\ again.\ If\ you\ believe\ you\ should\ have\ access,\ please\ contact\ the\ administrator\ for\ assistance.=401 Unauthorized: Access Denied. You are not authorized to access this resource. Please check your credentials and try again. If you believe you should have access, please contact the administrator for assistance.
+403\ Forbidden\:\ Access\ Denied.\ You\ do\ not\ have\ permission\ to\ access\ this\ resource.\ Please\ contact\ the\ administrator\ for\ assistance\ or\ try\ a\ different\ action.=403 Forbidden: Access Denied. You do not have permission to access this resource. Please contact the administrator for assistance or try a different action.
+404\ Not\ Found\ Error\:\ The\ requested\ resource\ could\ not\ be\ found.\ It\ seems\ that\ the\ file\ you\ are\ trying\ to\ download\ is\ not\ available\ or\ has\ been\ moved.\ Please\ verify\ the\ URL\ and\ try\ again.\ If\ you\ believe\ this\ is\ an\ error,\ please\ contact\ the\ administrator\ for\ further\ assistance.=404 Not Found Error: The requested resource could not be found. It seems that the file you are trying to download is not available or has been moved. Please verify the URL and try again. If you believe this is an error, please contact the administrator for further assistance.
+Error\ downloading\ from\ URL.\ Cause\ is\ likely\ the\ server\ side.\nPlease\ try\ again\ later\ or\ contact\ the\ server\ administrator.=Error downloading from URL. Cause is likely the server side.\nPlease try again later or contact the server administrator.
+Something\ is\ wrong\ on\ JabRef\ side.\ Please\ check\ the\ URL\ and\ try\ again.=Something is wrong on JabRef side. Please check the URL and try again.
+URL\:\ %0=URL: %0
+URL\:\ %0\nHTTP\ %1\ %2\n%3=URL: %0\nHTTP %1 %2\n%3
Please\ check\ the\ URL\ and\ try\ again.\nURL\:\ %0\nDetails\:\ %1=Please check the URL and try again.\nURL: %0\nDetails: %1
-Something\ is\ wrong\ on\ JabRef\ side.\ Please\ check\ the\ URL\ and\ try\ again.\nURL\:\ %0\nDetails\:\ %1=Something is wrong on JabRef side. Please check the URL and try again.\nURL: %0\nDetails: %1
Finished=Finished
Finished\ writing\ metadata\ for\ library\ %0\ (%1\ succeeded,\ %2\ skipped,\ %3\ errors).=Finished writing metadata for library %0 (%1 succeeded, %2 skipped, %3 errors).
From 7801226a3faa049aa9a5b280a10218b99632a9f2 Mon Sep 17 00:00:00 2001
From: Oliver Kopp
Date: Mon, 12 Aug 2024 02:03:48 +0200
Subject: [PATCH 28/42] Use FetcherException more often
Also improve localization
---
.../org/jabref/cli/ArgumentProcessor.java | 3 +-
.../java/org/jabref/gui/DialogService.java | 6 +-
.../gui/entryeditor/SciteTabViewModel.java | 27 +++---
.../SemanticScholarFetcher.java | 92 +++++++++----------
.../logic/importer/FetcherException.java | 17 +++-
.../fetcher/AstrophysicsDataSystem.java | 10 +-
.../importer/fetcher/BibsonomyScraper.java | 3 +-
.../importer/fetcher/BiodiversityLibrary.java | 26 ++++--
...OfComputerScienceBibliographiesParser.java | 5 +-
.../logic/importer/fetcher/DoiFetcher.java | 17 +---
.../jabref/logic/importer/fetcher/IEEE.java | 26 +++++-
.../importer/fetcher/INSPIREFetcher.java | 3 +-
.../logic/importer/fetcher/JstorFetcher.java | 8 +-
.../logic/importer/fetcher/ResearchGate.java | 2 +-
.../logic/importer/util/ShortDOIService.java | 8 +-
.../org/jabref/logic/net/URLDownload.java | 78 +++++++++++-----
src/main/resources/l10n/JabRef_en.properties | 8 +-
.../importer/fetcher/GoogleScholarTest.java | 2 +-
.../importer/fetcher/ResearchGateTest.java | 2 +-
.../fileformat/ACMPortalParserTest.java | 8 +-
.../org/jabref/logic/net/URLDownloadTest.java | 18 ++--
21 files changed, 209 insertions(+), 160 deletions(-)
diff --git a/src/main/java/org/jabref/cli/ArgumentProcessor.java b/src/main/java/org/jabref/cli/ArgumentProcessor.java
index 909fc46c6e2..6ce14604a64 100644
--- a/src/main/java/org/jabref/cli/ArgumentProcessor.java
+++ b/src/main/java/org/jabref/cli/ArgumentProcessor.java
@@ -1,6 +1,7 @@
package org.jabref.cli;
import java.io.IOException;
+import java.net.MalformedURLException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
@@ -133,7 +134,7 @@ private Optional importFile(String argument) {
// Download web resource to temporary file
try {
file = new URLDownload(address).toTemporaryFile();
- } catch (IOException e) {
+ } catch (FetcherException | MalformedURLException e) {
System.err.println(Localization.lang("Problem downloading from %1", address) + e.getLocalizedMessage());
return Optional.empty();
}
diff --git a/src/main/java/org/jabref/gui/DialogService.java b/src/main/java/org/jabref/gui/DialogService.java
index 309f227817a..a0a48c5ee87 100644
--- a/src/main/java/org/jabref/gui/DialogService.java
+++ b/src/main/java/org/jabref/gui/DialogService.java
@@ -117,11 +117,11 @@ default void showErrorDialogAndWait(FetcherException fetcherException) {
if (httpResponse.isPresent()) {
int statusCode = httpResponse.get().statusCode();
if (statusCode == 401) {
- this.showInformationDialogAndWait(failedTitle, Localization.lang("401 Unauthorized: Access Denied. You are not authorized to access this resource. Please check your credentials and try again. If you believe you should have access, please contact the administrator for assistance.") + "\n\n" + localizedMessage);
+ this.showInformationDialogAndWait(failedTitle, Localization.lang("Access denied. You are not authorized to access this resource. Please check your credentials and try again. If you believe you should have access, please contact the administrator for assistance.") + "\n\n" + localizedMessage);
} else if (statusCode == 403) {
- this.showInformationDialogAndWait(failedTitle, Localization.lang("403 Forbidden: Access Denied. You do not have permission to access this resource. Please contact the administrator for assistance or try a different action.") + "\n\n" + localizedMessage);
+ this.showInformationDialogAndWait(failedTitle, Localization.lang("Access denied. You do not have permission to access this resource. Please contact the administrator for assistance or try a different action.") + "\n\n" + localizedMessage);
} else if (statusCode == 404) {
- this.showInformationDialogAndWait(failedTitle, Localization.lang("404 Not Found Error: The requested resource could not be found. It seems that the file you are trying to download is not available or has been moved. Please verify the URL and try again. If you believe this is an error, please contact the administrator for further assistance.") + "\n\n" + localizedMessage);
+ this.showInformationDialogAndWait(failedTitle, Localization.lang("The requested resource could not be found. It seems that the file you are trying to download is not available or has been moved. Please verify the URL and try again. If you believe this is an error, please contact the administrator for further assistance.") + "\n\n" + localizedMessage);
} else {
this.showErrorDialogAndWait(failedTitle, Localization.lang("Something is wrong on JabRef side. Please check the URL and try again.") + "\n\n" + localizedMessage);
}
diff --git a/src/main/java/org/jabref/gui/entryeditor/SciteTabViewModel.java b/src/main/java/org/jabref/gui/entryeditor/SciteTabViewModel.java
index 43aa1b41e57..2a8216ea0c4 100644
--- a/src/main/java/org/jabref/gui/entryeditor/SciteTabViewModel.java
+++ b/src/main/java/org/jabref/gui/entryeditor/SciteTabViewModel.java
@@ -1,6 +1,5 @@
package org.jabref.gui.entryeditor;
-import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URISyntaxException;
@@ -102,22 +101,18 @@ public SciteTallyModel fetchTallies(DOI doi) throws FetcherException {
} catch (MalformedURLException | URISyntaxException ex) {
throw new FetcherException("Malformed URL for DOI", ex);
}
- try {
- LOGGER.debug("Fetching tallies from {}", url);
- URLDownload download = new URLDownload(url);
- String response = download.asString();
- LOGGER.debug("Response {}", response);
- JSONObject tallies = new JSONObject(response);
- if (tallies.has("detail")) {
- String message = tallies.getString("detail");
- throw new FetcherException(message);
- } else if (!tallies.has("total")) {
- throw new FetcherException("Unexpected result data.");
- }
- return SciteTallyModel.fromJSONObject(tallies);
- } catch (IOException ioex) {
- throw new FetcherException(url, "Failed to retrieve tallies for DOI", ioex);
+ LOGGER.debug("Fetching tallies from {}", url);
+ URLDownload download = new URLDownload(url);
+ String response = download.asString();
+ LOGGER.debug("Response {}", response);
+ JSONObject tallies = new JSONObject(response);
+ if (tallies.has("detail")) {
+ String message = tallies.getString("detail");
+ throw new FetcherException(message);
+ } else if (!tallies.has("total")) {
+ throw new FetcherException("Unexpected result data.");
}
+ return SciteTallyModel.fromJSONObject(tallies);
}
public ObjectProperty statusProperty() {
diff --git a/src/main/java/org/jabref/gui/entryeditor/citationrelationtab/semanticscholar/SemanticScholarFetcher.java b/src/main/java/org/jabref/gui/entryeditor/citationrelationtab/semanticscholar/SemanticScholarFetcher.java
index 639b045f09c..82ad2767f6a 100644
--- a/src/main/java/org/jabref/gui/entryeditor/citationrelationtab/semanticscholar/SemanticScholarFetcher.java
+++ b/src/main/java/org/jabref/gui/entryeditor/citationrelationtab/semanticscholar/SemanticScholarFetcher.java
@@ -1,6 +1,5 @@
package org.jabref.gui.entryeditor.citationrelationtab.semanticscholar;
-import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URL;
@@ -34,60 +33,55 @@ public String getAPIUrl(String entry_point, BibEntry entry) {
@Override
public List searchCitedBy(BibEntry entry) throws FetcherException {
- if (entry.getDOI().isPresent()) {
- URL citationsUrl;
- try {
- citationsUrl = URI.create(getAPIUrl("citations", entry)).toURL();
- } catch (MalformedURLException e) {
- throw new FetcherException("Malformed URL", e);
- }
- try {
- URLDownload urlDownload = new URLDownload(citationsUrl);
-
- String apiKey = getApiKey();
- if (!apiKey.isEmpty()) {
- urlDownload.addHeader("x-api-key", apiKey);
- }
- CitationsResponse citationsResponse = new Gson()
- .fromJson(urlDownload.asString(), CitationsResponse.class);
-
- return citationsResponse.getData()
- .stream().filter(citationDataItem -> citationDataItem.getCitingPaper() != null)
- .map(citationDataItem -> citationDataItem.getCitingPaper().toBibEntry()).toList();
- } catch (IOException e) {
- throw new FetcherException(citationsUrl, "Could not fetch", e);
- }
+ if (!entry.getDOI().isPresent()) {
+ return List.of();
}
- return List.of();
+
+ URL citationsUrl;
+ try {
+ citationsUrl = URI.create(getAPIUrl("citations", entry)).toURL();
+ } catch (MalformedURLException e) {
+ throw new FetcherException("Malformed URL", e);
+ }
+ URLDownload urlDownload = new URLDownload(citationsUrl);
+
+ String apiKey = getApiKey();
+ if (!apiKey.isEmpty()) {
+ urlDownload.addHeader("x-api-key", apiKey);
+ }
+ CitationsResponse citationsResponse = new Gson()
+ .fromJson(urlDownload.asString(), CitationsResponse.class);
+
+ return citationsResponse.getData()
+ .stream().filter(citationDataItem -> citationDataItem.getCitingPaper() != null)
+ .map(citationDataItem -> citationDataItem.getCitingPaper().toBibEntry()).toList();
}
@Override
public List searchCiting(BibEntry entry) throws FetcherException {
- if (entry.getDOI().isPresent()) {
- URL referencesUrl;
- try {
- referencesUrl = URI.create(getAPIUrl("references", entry)).toURL();
- } catch (MalformedURLException e) {
- throw new FetcherException("Malformed URL", e);
- }
- try {
- URLDownload urlDownload = new URLDownload(referencesUrl);
- String apiKey = getApiKey();
- if (!apiKey.isEmpty()) {
- urlDownload.addHeader("x-api-key", apiKey);
- }
- ReferencesResponse referencesResponse = new Gson()
- .fromJson(urlDownload.asString(), ReferencesResponse.class);
-
- return referencesResponse.getData()
- .stream()
- .filter(citationDataItem -> citationDataItem.getCitedPaper() != null)
- .map(referenceDataItem -> referenceDataItem.getCitedPaper().toBibEntry()).toList();
- } catch (IOException e) {
- throw new FetcherException(referencesUrl, "Could not fetch", e);
- }
+ if (!entry.getDOI().isPresent()) {
+ return List.of();
}
- return List.of();
+
+ URL referencesUrl;
+ try {
+ referencesUrl = URI.create(getAPIUrl("references", entry)).toURL();
+ } catch (MalformedURLException e) {
+ throw new FetcherException("Malformed URL", e);
+ }
+
+ URLDownload urlDownload = new URLDownload(referencesUrl);
+ String apiKey = getApiKey();
+ if (!apiKey.isEmpty()) {
+ urlDownload.addHeader("x-api-key", apiKey);
+ }
+ ReferencesResponse referencesResponse = new Gson()
+ .fromJson(urlDownload.asString(), ReferencesResponse.class);
+
+ return referencesResponse.getData()
+ .stream()
+ .filter(citationDataItem -> citationDataItem.getCitedPaper() != null)
+ .map(referenceDataItem -> referenceDataItem.getCitedPaper().toBibEntry()).toList();
}
@Override
diff --git a/src/main/java/org/jabref/logic/importer/FetcherException.java b/src/main/java/org/jabref/logic/importer/FetcherException.java
index e330c22a0e1..3340258ab79 100644
--- a/src/main/java/org/jabref/logic/importer/FetcherException.java
+++ b/src/main/java/org/jabref/logic/importer/FetcherException.java
@@ -7,6 +7,7 @@
import org.jabref.http.dto.SimpleHttpResponse;
import org.jabref.logic.JabRefException;
import org.jabref.logic.l10n.Localization;
+import org.jabref.model.strings.StringUtil;
public class FetcherException extends JabRefException {
@@ -18,7 +19,8 @@ public class FetcherException extends JabRefException {
private final SimpleHttpResponse httpResponse;
public FetcherException(String url, SimpleHttpResponse httpResponse) {
- super("URL: %s\nHTTP %s %s\n%s".formatted(url, httpResponse.statusCode(), httpResponse.responseMessage(), httpResponse.responseBody()));
+ // Empty string handled at org.jabref.logic.importer.FetcherException.getPrefix.
+ super("");
this.url = url;
this.httpResponse = httpResponse;
}
@@ -58,6 +60,9 @@ private FetcherException(String url, String errorMessage, Throwable cause, Objec
}
public FetcherException(String errorMessage, Throwable cause) {
+ // TODO: Convert IOException e to FetcherClientException
+ // Same TODO as in org.jabref.logic.importer.EntryBasedParserFetcher.performSearch.
+ // Maybe do this in org.jabref.logic.importer.FetcherException.getLocalizedMessage
super(errorMessage, cause);
httpResponse = null;
url = null;
@@ -87,6 +92,14 @@ public static FetcherException ofUrl(String url, String errorMessage, Throwable
return new FetcherException(url, errorMessage, cause, null);
}
+ public static FetcherException of(URL url, SimpleHttpResponse simpleHttpResponse) {
+ if (simpleHttpResponse.statusCode() >= 500) {
+ return new FetcherServerException(url, simpleHttpResponse);
+ } else {
+ return new FetcherClientException(url, simpleHttpResponse);
+ }
+ }
+
@Override
public String getLocalizedMessage() {
// TODO: This should be moved to a separate class converting "any" exception object to a localized message
@@ -107,7 +120,7 @@ private String getRedactedUrl() {
private String getPrefix() {
String superLocalizedMessage = super.getLocalizedMessage();
- if (superLocalizedMessage != null) {
+ if (!StringUtil.isBlank(superLocalizedMessage)) {
return superLocalizedMessage + "\n";
} else {
return "";
diff --git a/src/main/java/org/jabref/logic/importer/fetcher/AstrophysicsDataSystem.java b/src/main/java/org/jabref/logic/importer/fetcher/AstrophysicsDataSystem.java
index 21c06541d2a..373cd064427 100644
--- a/src/main/java/org/jabref/logic/importer/fetcher/AstrophysicsDataSystem.java
+++ b/src/main/java/org/jabref/logic/importer/fetcher/AstrophysicsDataSystem.java
@@ -1,6 +1,5 @@
package org.jabref.logic.importer.fetcher;
-import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URISyntaxException;
import java.net.URL;
@@ -204,9 +203,8 @@ private List fetchBibcodes(URL url) throws FetcherException {
bibcodes.add(codes.getJSONObject(i).getString("bibcode"));
}
return bibcodes;
- } catch (IOException e) {
- throw new FetcherException(url, "A network error occurred", e);
} catch (JSONException e) {
+ LOGGER.error("Error while parsing JSON", e);
return Collections.emptyList();
}
}
@@ -231,8 +229,7 @@ public Optional performSearchById(String identifier) throws FetcherExc
return Optional.empty();
}
if (fetchedEntries.size() > 1) {
- LOGGER.info("Fetcher " + getName() + "found more than one result for identifier " + identifier
- + ". We will use the first entry.");
+ LOGGER.info("Fetcher {} found more than one result for identifier {}. We will use the first entry.", getName(), identifier);
}
BibEntry entry = fetchedEntries.getFirst();
return Optional.of(entry);
@@ -274,10 +271,9 @@ private List performSearchByIds(Collection identifiers) throws
return fetchedEntries;
} catch (JSONException e) {
+ LOGGER.error("Error while parsing JSON", e);
return Collections.emptyList();
}
- } catch (IOException e) {
- throw new FetcherException(urLforExport, "A network error occurred", e);
} catch (ParseException e) {
throw new FetcherException(urLforExport, "An internal parser error occurred", e);
}
diff --git a/src/main/java/org/jabref/logic/importer/fetcher/BibsonomyScraper.java b/src/main/java/org/jabref/logic/importer/fetcher/BibsonomyScraper.java
index f506d0128f2..724ac0a6f0a 100644
--- a/src/main/java/org/jabref/logic/importer/fetcher/BibsonomyScraper.java
+++ b/src/main/java/org/jabref/logic/importer/fetcher/BibsonomyScraper.java
@@ -4,6 +4,7 @@
import java.net.URL;
import java.util.Optional;
+import org.jabref.logic.importer.FetcherException;
import org.jabref.logic.importer.ImportFormatPreferences;
import org.jabref.logic.importer.ParseException;
import org.jabref.logic.importer.fileformat.BibtexParser;
@@ -38,7 +39,7 @@ public static Optional getEntry(String entryUrl, ImportFormatPreferenc
URL url = new URL(BibsonomyScraper.BIBSONOMY_SCRAPER + cleanURL + BibsonomyScraper.BIBSONOMY_SCRAPER_POST);
String bibtex = new URLDownload(url).asString();
return BibtexParser.singleFromString(bibtex, importFormatPreferences);
- } catch (IOException ex) {
+ } catch (IOException | FetcherException ex) {
LOGGER.warn("Could not download entry", ex);
return Optional.empty();
} catch (ParseException ex) {
diff --git a/src/main/java/org/jabref/logic/importer/fetcher/BiodiversityLibrary.java b/src/main/java/org/jabref/logic/importer/fetcher/BiodiversityLibrary.java
index 039d45c3c07..99ce61c4ca9 100644
--- a/src/main/java/org/jabref/logic/importer/fetcher/BiodiversityLibrary.java
+++ b/src/main/java/org/jabref/logic/importer/fetcher/BiodiversityLibrary.java
@@ -1,6 +1,5 @@
package org.jabref.logic.importer.fetcher;
-import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URISyntaxException;
import java.net.URL;
@@ -9,6 +8,7 @@
import java.util.List;
import java.util.stream.IntStream;
+import org.jabref.logic.importer.FetcherException;
import org.jabref.logic.importer.ImporterPreferences;
import org.jabref.logic.importer.ParseException;
import org.jabref.logic.importer.Parser;
@@ -23,6 +23,7 @@
import org.jabref.model.entry.field.StandardField;
import org.jabref.model.entry.types.StandardEntryType;
+import com.google.common.annotations.VisibleForTesting;
import kong.unirest.core.json.JSONArray;
import kong.unirest.core.json.JSONException;
import kong.unirest.core.json.JSONObject;
@@ -79,7 +80,8 @@ public URL getItemMetadataURL(String identifier) throws URISyntaxException, Malf
return uriBuilder.build().toURL();
}
- public URL getPartMetadataURL(String identifier) throws URISyntaxException, MalformedURLException {
+ @VisibleForTesting
+ URL getPartMetadataURL(String identifier) throws URISyntaxException, MalformedURLException {
URIBuilder uriBuilder = new URIBuilder(getBaseURL().toURI());
uriBuilder.addParameter("op", "GetPartMetadata");
uriBuilder.addParameter("pages", "f");
@@ -89,17 +91,22 @@ public URL getPartMetadataURL(String identifier) throws URISyntaxException, Malf
return uriBuilder.build().toURL();
}
- public JSONObject getDetails(URL url) throws IOException {
+ public JSONObject getDetails(URL url) throws FetcherException {
URLDownload download = new URLDownload(url);
String response = download.asString();
Logger.debug("Response {}", response);
return new JSONObject(response).getJSONArray("Result").getJSONObject(0);
}
- public BibEntry parseBibJSONtoBibtex(JSONObject item, BibEntry entry) throws IOException, URISyntaxException {
+ public BibEntry parseBibJSONtoBibtex(JSONObject item, BibEntry entry) throws FetcherException {
if (item.has("BHLType")) {
if ("Part".equals(item.getString("BHLType"))) {
- URL url = getPartMetadataURL(item.getString("PartID"));
+ URL url;
+ try {
+ url = getPartMetadataURL(item.getString("PartID"));
+ } catch (URISyntaxException | MalformedURLException e) {
+ throw new FetcherException("Malformed URL", e);
+ }
JSONObject itemsDetails = getDetails(url);
entry.setField(StandardField.LANGUAGE, itemsDetails.optString("Language", ""));
@@ -112,7 +119,12 @@ public BibEntry parseBibJSONtoBibtex(JSONObject item, BibEntry entry) throws IOE
}
if ("Item".equals(item.getString("BHLType"))) {
- URL url = getItemMetadataURL(item.getString("ItemID"));
+ URL url = null;
+ try {
+ url = getItemMetadataURL(item.getString("ItemID"));
+ } catch (URISyntaxException | MalformedURLException e) {
+ throw new FetcherException("Malformed URL", e);
+ }
JSONObject itemsDetails = getDetails(url);
entry.setField(StandardField.EDITOR, itemsDetails.optString("Sponsor", ""));
entry.setField(StandardField.PUBLISHER, itemsDetails.optString("HoldingInstitution", ""));
@@ -185,7 +197,7 @@ public Parser getParser() {
BibEntry entry = jsonResultToBibEntry(item);
try {
entry = parseBibJSONtoBibtex(item, entry);
- } catch (JSONException | IOException | URISyntaxException exception) {
+ } catch (JSONException | FetcherException exception) {
throw new ParseException("Error when parsing entry", exception);
}
entries.add(entry);
diff --git a/src/main/java/org/jabref/logic/importer/fetcher/CollectionOfComputerScienceBibliographiesParser.java b/src/main/java/org/jabref/logic/importer/fetcher/CollectionOfComputerScienceBibliographiesParser.java
index 4a351e40cfc..c2f8aebe2be 100644
--- a/src/main/java/org/jabref/logic/importer/fetcher/CollectionOfComputerScienceBibliographiesParser.java
+++ b/src/main/java/org/jabref/logic/importer/fetcher/CollectionOfComputerScienceBibliographiesParser.java
@@ -9,6 +9,7 @@
import java.util.stream.Collectors;
import org.jabref.logic.formatter.bibtexfields.HtmlToUnicodeFormatter;
+import org.jabref.logic.importer.FetcherException;
import org.jabref.logic.importer.ImportFormatPreferences;
import org.jabref.logic.importer.ParseException;
import org.jabref.logic.importer.Parser;
@@ -38,7 +39,7 @@ public List parseEntries(InputStream inputStream) throws ParseExceptio
.collect(Collectors.joining());
return bibtexParser.parseEntries(bibtexDataString);
- } catch (IOException e) {
+ } catch (IOException | FetcherException e) {
throw new ParseException(e);
}
}
@@ -51,7 +52,7 @@ private List matchRegexFromInputStreamHtml(InputStream inputStream, Patt
}
}
- private List parseBibtexStringsFromLinks(List links) throws IOException {
+ private List parseBibtexStringsFromLinks(List links) throws IOException, FetcherException {
List bibtexStringsFromAllLinks = new ArrayList<>();
for (String link : links) {
try (InputStream inputStream = new URLDownload(link).asInputStream()) {
diff --git a/src/main/java/org/jabref/logic/importer/fetcher/DoiFetcher.java b/src/main/java/org/jabref/logic/importer/fetcher/DoiFetcher.java
index 005122afa1e..49a28e140ba 100644
--- a/src/main/java/org/jabref/logic/importer/fetcher/DoiFetcher.java
+++ b/src/main/java/org/jabref/logic/importer/fetcher/DoiFetcher.java
@@ -95,7 +95,7 @@ private void doAPILimiting(String identifier) {
LOGGER.trace("Thread %s, searching for DOI '%s', waited %.2fs because of API rate limiter".formatted(
Thread.currentThread().threadId(), identifier, waitingTime));
}
- } catch (IOException e) {
+ } catch (FetcherException | MalformedURLException e) {
LOGGER.warn("Could not limit DOI API access rate", e);
}
}
@@ -141,16 +141,9 @@ public Optional performSearchById(String identifier) throws FetcherExc
String bibtexString;
URLConnection openConnection;
- try {
- openConnection = download.openConnection();
- bibtexString = URLDownload.asString(openConnection).trim();
- } catch (IOException e) {
- // an IOException with a nested FetcherException will be thrown when you encounter a 400x or 500x http status code
- if (e.getCause() instanceof FetcherException fe) {
- throw fe;
- }
- throw e;
- }
+
+ openConnection = download.openConnection();
+ bibtexString = URLDownload.asString(openConnection).trim();
// BibTeX entry
fetchedEntry = BibtexParser.singleFromString(bibtexString, preferences);
@@ -222,7 +215,7 @@ public List performSearch(BibEntry entry) throws FetcherException {
*
* @param doi the DOI to be searched
*/
- public Optional getAgency(DOI doi) throws IOException {
+ public Optional getAgency(DOI doi) throws FetcherException, MalformedURLException {
Optional agency = Optional.empty();
try {
URLDownload download = getUrlDownload(new URL(DOI.AGENCY_RESOLVER + "/" + doi.getDOI()));
diff --git a/src/main/java/org/jabref/logic/importer/fetcher/IEEE.java b/src/main/java/org/jabref/logic/importer/fetcher/IEEE.java
index c444dcff212..185e9e3906b 100644
--- a/src/main/java/org/jabref/logic/importer/fetcher/IEEE.java
+++ b/src/main/java/org/jabref/logic/importer/fetcher/IEEE.java
@@ -1,7 +1,6 @@
package org.jabref.logic.importer.fetcher;
import java.io.BufferedReader;
-import java.io.IOException;
import java.io.InputStreamReader;
import java.net.MalformedURLException;
import java.net.URISyntaxException;
@@ -15,6 +14,7 @@
import java.util.stream.Collectors;
import org.jabref.logic.help.HelpFile;
+import org.jabref.logic.importer.FetcherException;
import org.jabref.logic.importer.FulltextFetcher;
import org.jabref.logic.importer.ImportFormatPreferences;
import org.jabref.logic.importer.ImporterPreferences;
@@ -134,7 +134,7 @@ private static BibEntry parseJsonResponse(JSONObject jsonEntry, Character keywor
}
@Override
- public Optional findFullText(BibEntry entry) throws IOException {
+ public Optional findFullText(BibEntry entry) throws FetcherException {
Objects.requireNonNull(entry);
String stampString = "";
@@ -161,7 +161,12 @@ public Optional findFullText(BibEntry entry) throws IOException {
Optional doi = entry.getField(StandardField.DOI).flatMap(DOI::parse);
if (doi.isPresent() && doi.get().getDOI().startsWith(IEEE_DOI) && doi.get().getExternalURI().isPresent()) {
// Download the HTML page from IEEE
- URLDownload urlDownload = new URLDownload(doi.get().getExternalURI().get().toURL());
+ URLDownload urlDownload = null;
+ try {
+ urlDownload = new URLDownload(doi.get().getExternalURI().get().toURL());
+ } catch (MalformedURLException e) {
+ throw new FetcherException("Malformed URL", e);
+ }
// We don't need to modify the cookies, but we need support for them
urlDownload.getCookieFromUrl();
@@ -181,7 +186,12 @@ public Optional findFullText(BibEntry entry) throws IOException {
}
// Download the HTML page containing a frame with the PDF
- URLDownload urlDownload = new URLDownload(BASE_URL + stampString);
+ URLDownload urlDownload;
+ try {
+ urlDownload = new URLDownload(BASE_URL + stampString);
+ } catch (MalformedURLException e) {
+ throw new FetcherException("Malformed URL", e);
+ }
// We don't need to modify the cookies, but we need support for them
urlDownload.getCookieFromUrl();
@@ -191,7 +201,13 @@ public Optional findFullText(BibEntry entry) throws IOException {
if (matcher.find()) {
// The PDF was found
LOGGER.debug("Full text document found on IEEE Xplore");
- return Optional.of(new URL(matcher.group(1)));
+ URL value;
+ try {
+ value = new URL(matcher.group(1));
+ } catch (MalformedURLException e) {
+ throw new FetcherException("Malformed URL", e);
+ }
+ return Optional.of(value);
}
return Optional.empty();
}
diff --git a/src/main/java/org/jabref/logic/importer/fetcher/INSPIREFetcher.java b/src/main/java/org/jabref/logic/importer/fetcher/INSPIREFetcher.java
index 696b423f5e3..8038ea2edd0 100644
--- a/src/main/java/org/jabref/logic/importer/fetcher/INSPIREFetcher.java
+++ b/src/main/java/org/jabref/logic/importer/fetcher/INSPIREFetcher.java
@@ -1,6 +1,5 @@
package org.jabref.logic.importer.fetcher;
-import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URISyntaxException;
@@ -112,7 +111,7 @@ public List performSearch(BibEntry entry) throws FetcherException {
List results = getParser().parseEntries(download.asInputStream());
results.forEach(this::doPostCleanup);
return results;
- } catch (IOException | ParseException e) {
+ } catch (ParseException e) {
throw new FetcherException(url, e);
}
}
diff --git a/src/main/java/org/jabref/logic/importer/fetcher/JstorFetcher.java b/src/main/java/org/jabref/logic/importer/fetcher/JstorFetcher.java
index c381a6ada2f..eb54b87dff0 100644
--- a/src/main/java/org/jabref/logic/importer/fetcher/JstorFetcher.java
+++ b/src/main/java/org/jabref/logic/importer/fetcher/JstorFetcher.java
@@ -12,6 +12,7 @@
import java.util.Optional;
import java.util.stream.Collectors;
+import org.jabref.logic.importer.FetcherException;
import org.jabref.logic.importer.FulltextFetcher;
import org.jabref.logic.importer.IdBasedParserFetcher;
import org.jabref.logic.importer.ImportFormatPreferences;
@@ -81,7 +82,8 @@ public Parser getParser() {
if (text.startsWith("@")) {
return parser.parseEntries(text);
}
- // input stream contains html
+ // otherwise: input stream contains html
+
List entries;
try {
Document doc = Jsoup.parse(inputStream, null, HOST);
@@ -95,7 +97,7 @@ public Parser getParser() {
stringBuilder.append(data);
}
entries = new ArrayList<>(parser.parseEntries(stringBuilder.toString()));
- } catch (IOException e) {
+ } catch (IOException | FetcherException e) {
throw new ParseException("Could not download data from jstor.org", e);
}
return entries;
@@ -108,7 +110,7 @@ public String getName() {
}
@Override
- public Optional findFullText(BibEntry entry) throws IOException {
+ public Optional findFullText(BibEntry entry) throws FetcherException, IOException {
if (entry.getField(StandardField.URL).isEmpty()) {
return Optional.empty();
}
diff --git a/src/main/java/org/jabref/logic/importer/fetcher/ResearchGate.java b/src/main/java/org/jabref/logic/importer/fetcher/ResearchGate.java
index 883722d8296..d9c9011a822 100644
--- a/src/main/java/org/jabref/logic/importer/fetcher/ResearchGate.java
+++ b/src/main/java/org/jabref/logic/importer/fetcher/ResearchGate.java
@@ -116,7 +116,7 @@ private Document getHTML(BibEntry entry) throws FetcherException, IOException {
throw new FetcherException("Could not find a pdf");
}
- Optional getURLByString(String query) throws IOException, NullPointerException {
+ Optional getURLByString(String query) throws IOException, FetcherException {
URIBuilder source;
String link;
try {
diff --git a/src/main/java/org/jabref/logic/importer/util/ShortDOIService.java b/src/main/java/org/jabref/logic/importer/util/ShortDOIService.java
index f10996f9b4f..e9c6446fc19 100644
--- a/src/main/java/org/jabref/logic/importer/util/ShortDOIService.java
+++ b/src/main/java/org/jabref/logic/importer/util/ShortDOIService.java
@@ -1,11 +1,11 @@
package org.jabref.logic.importer.util;
-import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
+import org.jabref.logic.importer.FetcherException;
import org.jabref.logic.importer.ParseException;
import org.jabref.logic.net.URLDownload;
import org.jabref.model.entry.identifier.DOI;
@@ -36,8 +36,8 @@ public DOI getShortDOI(DOI doi) throws ShortDOIServiceException {
private JSONObject makeRequest(DOI doi) throws ShortDOIServiceException {
- URIBuilder uriBuilder = null;
- URL url = null;
+ URIBuilder uriBuilder;
+ URL url;
try {
uriBuilder = new URIBuilder(BASIC_URL);
@@ -58,7 +58,7 @@ private JSONObject makeRequest(DOI doi) throws ShortDOIServiceException {
throw new ShortDOIServiceException("Cannot get short DOI");
}
return resultAsJSON;
- } catch (ParseException | IOException | JSONException e) {
+ } catch (ParseException | JSONException | FetcherException e) {
throw new ShortDOIServiceException("Cannot get short DOI", e);
}
}
diff --git a/src/main/java/org/jabref/logic/net/URLDownload.java b/src/main/java/org/jabref/logic/net/URLDownload.java
index c5e312279bd..0394bda31b1 100644
--- a/src/main/java/org/jabref/logic/net/URLDownload.java
+++ b/src/main/java/org/jabref/logic/net/URLDownload.java
@@ -2,7 +2,6 @@
import java.io.BufferedInputStream;
import java.io.BufferedReader;
-import java.io.ByteArrayInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
@@ -42,6 +41,7 @@
import org.jabref.http.dto.SimpleHttpResponse;
import org.jabref.logic.importer.FetcherClientException;
+import org.jabref.logic.importer.FetcherException;
import org.jabref.logic.importer.FetcherServerException;
import org.jabref.logic.util.io.FileUtil;
@@ -241,7 +241,7 @@ public void setPostData(String postData) {
*
* @return the downloaded string
*/
- public String asString() throws IOException {
+ public String asString() throws FetcherException {
return asString(StandardCharsets.UTF_8, this.openConnection());
}
@@ -251,7 +251,7 @@ public String asString() throws IOException {
* @param encoding the desired String encoding
* @return the downloaded string
*/
- public String asString(Charset encoding) throws IOException {
+ public String asString(Charset encoding) throws FetcherException {
return asString(encoding, this.openConnection());
}
@@ -261,7 +261,7 @@ public String asString(Charset encoding) throws IOException {
* @param existingConnection an existing connection
* @return the downloaded string
*/
- public static String asString(URLConnection existingConnection) throws IOException {
+ public static String asString(URLConnection existingConnection) throws FetcherException {
return asString(StandardCharsets.UTF_8, existingConnection);
}
@@ -272,16 +272,17 @@ public static String asString(URLConnection existingConnection) throws IOExcepti
* @param connection an existing connection
* @return the downloaded string
*/
- public static String asString(Charset encoding, URLConnection connection) throws IOException {
-
+ public static String asString(Charset encoding, URLConnection connection) throws FetcherException {
try (InputStream input = new BufferedInputStream(connection.getInputStream());
Writer output = new StringWriter()) {
copy(input, output, encoding);
return output.toString();
+ } catch (IOException e) {
+ throw new FetcherException("Error downloading", e);
}
}
- public List getCookieFromUrl() throws IOException {
+ public List getCookieFromUrl() throws FetcherException {
CookieManager cookieManager = new CookieManager();
CookieHandler.setDefault(cookieManager);
cookieManager.setCookiePolicy(CookiePolicy.ACCEPT_ALL);
@@ -302,27 +303,41 @@ public List getCookieFromUrl() throws IOException {
*
* @param destination the destination file path.
*/
- public void toFile(Path destination) throws IOException {
+ public void toFile(Path destination) throws FetcherException {
try (InputStream input = new BufferedInputStream(this.openConnection().getInputStream())) {
Files.copy(input, destination, StandardCopyOption.REPLACE_EXISTING);
} catch (IOException e) {
LOGGER.warn("Could not copy input", e);
- throw e;
+ throw new FetcherException("Could not copy input", e);
}
}
/**
* Takes the web resource as the source for a monitored input stream.
*/
- public ProgressInputStream asInputStream() throws IOException {
+ public ProgressInputStream asInputStream() throws FetcherException {
HttpURLConnection urlConnection = (HttpURLConnection) this.openConnection();
- if ((urlConnection.getResponseCode() == HttpURLConnection.HTTP_NOT_FOUND) || (urlConnection.getResponseCode() == HttpURLConnection.HTTP_BAD_REQUEST)) {
- LOGGER.error("Response message {} returned for url {}", urlConnection.getResponseMessage(), urlConnection.getURL());
- return new ProgressInputStream(new ByteArrayInputStream(new byte[0]), 0);
+ int responseCode;
+ try {
+ responseCode = urlConnection.getResponseCode();
+ } catch (IOException e) {
+ throw new FetcherException("Error getting response code", e);
+ }
+ LOGGER.debug("Response code: {}", responseCode); // We could check for != 200, != 204
+ if (responseCode >= 300) {
+ SimpleHttpResponse simpleHttpResponse = new SimpleHttpResponse(urlConnection);
+ LOGGER.error("Failed to read from url: {}", simpleHttpResponse);
+ throw FetcherException.of(this.source, simpleHttpResponse);
}
long fileSize = urlConnection.getContentLengthLong();
- return new ProgressInputStream(new BufferedInputStream(urlConnection.getInputStream()), fileSize);
+ InputStream inputStream;
+ try {
+ inputStream = urlConnection.getInputStream();
+ } catch (IOException e) {
+ throw new FetcherException("Error getting input stream", e);
+ }
+ return new ProgressInputStream(new BufferedInputStream(inputStream), fileSize);
}
/**
@@ -330,7 +345,7 @@ public ProgressInputStream asInputStream() throws IOException {
*
* @return the path of the temporary file.
*/
- public Path toTemporaryFile() throws IOException {
+ public Path toTemporaryFile() throws FetcherException {
// Determine file name and extension from source url
String sourcePath = source.getPath();
@@ -340,7 +355,12 @@ public Path toTemporaryFile() throws IOException {
String extension = "." + FileUtil.getFileExtension(fileNameWithExtension).orElse("tmp");
// Create temporary file and download to it
- Path file = Files.createTempFile(fileName, extension);
+ Path file = null;
+ try {
+ file = Files.createTempFile(fileName, extension);
+ } catch (IOException e) {
+ throw new FetcherException("Could not create temporary file", e);
+ }
file.toFile().deleteOnExit();
toFile(file);
@@ -370,8 +390,13 @@ private static void copy(InputStream in, Writer out, Charset encoding) throws IO
*
* @return an open connection
*/
- public URLConnection openConnection() throws IOException {
- URLConnection connection = getUrlConnection();
+ public URLConnection openConnection() throws FetcherException {
+ URLConnection connection;
+ try {
+ connection = getUrlConnection();
+ } catch (IOException e) {
+ throw new FetcherException("Error opening connection", e);
+ }
connection.setConnectTimeout((int) connectTimeout.toMillis());
for (Entry entry : this.parameters.entrySet()) {
connection.setRequestProperty(entry.getKey(), entry.getValue());
@@ -380,6 +405,8 @@ public URLConnection openConnection() throws IOException {
connection.setDoOutput(true);
try (DataOutputStream wr = new DataOutputStream(connection.getOutputStream())) {
wr.writeBytes(this.postData);
+ } catch (IOException e) {
+ throw new FetcherException("Could not write output", e);
}
}
@@ -390,10 +417,7 @@ public URLConnection openConnection() throws IOException {
status = httpURLConnection.getResponseCode();
} catch (IOException e) {
LOGGER.error("Error getting response code", e);
- // TODO: Convert e to FetcherClientException
- // Same TODO as in org.jabref.logic.importer.EntryBasedParserFetcher.performSearch.
- // Maybe do this in org.jabref.logic.importer.FetcherException.getLocalizedMessage
- throw e;
+ throw new FetcherException("Error getting response code", e);
}
if ((status == HttpURLConnection.HTTP_MOVED_TEMP)
@@ -402,14 +426,18 @@ public URLConnection openConnection() throws IOException {
// get redirect url from "location" header field
String newUrl = connection.getHeaderField("location");
// open the new connection again
- connection = new URLDownload(newUrl).openConnection();
+ try {
+ connection = new URLDownload(newUrl).openConnection();
+ } catch (MalformedURLException e) {
+ throw new FetcherException("Could not open URL Download", e);
+ }
} else {
SimpleHttpResponse httpResponse = new SimpleHttpResponse(httpURLConnection);
LOGGER.info("{}", httpResponse);
if ((status >= 400) && (status < 500)) {
- throw new IOException(new FetcherClientException(this.source, httpResponse));
+ throw new FetcherClientException(this.source, httpResponse);
} else if (status >= 500) {
- throw new IOException(new FetcherServerException(this.source, httpResponse));
+ throw new FetcherServerException(this.source, httpResponse);
}
}
}
diff --git a/src/main/resources/l10n/JabRef_en.properties b/src/main/resources/l10n/JabRef_en.properties
index 5a4ef4ebcdd..8d543167ddd 100644
--- a/src/main/resources/l10n/JabRef_en.properties
+++ b/src/main/resources/l10n/JabRef_en.properties
@@ -2614,11 +2614,11 @@ Illegal\ characters\ in\ the\ file\ name\ detected.\nFile\ will\ be\ renamed\ to
Rename\ and\ add=Rename and add
Failed\ to\ download\ from\ URL=Failed to download from URL
-401\ Unauthorized\:\ Access\ Denied.\ You\ are\ not\ authorized\ to\ access\ this\ resource.\ Please\ check\ your\ credentials\ and\ try\ again.\ If\ you\ believe\ you\ should\ have\ access,\ please\ contact\ the\ administrator\ for\ assistance.=401 Unauthorized: Access Denied. You are not authorized to access this resource. Please check your credentials and try again. If you believe you should have access, please contact the administrator for assistance.
-403\ Forbidden\:\ Access\ Denied.\ You\ do\ not\ have\ permission\ to\ access\ this\ resource.\ Please\ contact\ the\ administrator\ for\ assistance\ or\ try\ a\ different\ action.=403 Forbidden: Access Denied. You do not have permission to access this resource. Please contact the administrator for assistance or try a different action.
-404\ Not\ Found\ Error\:\ The\ requested\ resource\ could\ not\ be\ found.\ It\ seems\ that\ the\ file\ you\ are\ trying\ to\ download\ is\ not\ available\ or\ has\ been\ moved.\ Please\ verify\ the\ URL\ and\ try\ again.\ If\ you\ believe\ this\ is\ an\ error,\ please\ contact\ the\ administrator\ for\ further\ assistance.=404 Not Found Error: The requested resource could not be found. It seems that the file you are trying to download is not available or has been moved. Please verify the URL and try again. If you believe this is an error, please contact the administrator for further assistance.
-Error\ downloading\ from\ URL.\ Cause\ is\ likely\ the\ server\ side.\nPlease\ try\ again\ later\ or\ contact\ the\ server\ administrator.=Error downloading from URL. Cause is likely the server side.\nPlease try again later or contact the server administrator.
+Access\ denied.\ You\ are\ not\ authorized\ to\ access\ this\ resource.\ Please\ check\ your\ credentials\ and\ try\ again.\ If\ you\ believe\ you\ should\ have\ access,\ please\ contact\ the\ administrator\ for\ assistance.=Access denied. You are not authorized to access this resource. Please check your credentials and try again. If you believe you should have access, please contact the administrator for assistance.
+Access\ denied.\ You\ do\ not\ have\ permission\ to\ access\ this\ resource.\ Please\ contact\ the\ administrator\ for\ assistance\ or\ try\ a\ different\ action.=Access denied. You do not have permission to access this resource. Please contact the administrator for assistance or try a different action.
+The\ requested\ resource\ could\ not\ be\ found.\ It\ seems\ that\ the\ file\ you\ are\ trying\ to\ download\ is\ not\ available\ or\ has\ been\ moved.\ Please\ verify\ the\ URL\ and\ try\ again.\ If\ you\ believe\ this\ is\ an\ error,\ please\ contact\ the\ administrator\ for\ further\ assistance.=The requested resource could not be found. It seems that the file you are trying to download is not available or has been moved. Please verify the URL and try again. If you believe this is an error, please contact the administrator for further assistance.
Something\ is\ wrong\ on\ JabRef\ side.\ Please\ check\ the\ URL\ and\ try\ again.=Something is wrong on JabRef side. Please check the URL and try again.
+Error\ downloading\ from\ URL.\ Cause\ is\ likely\ the\ server\ side.\nPlease\ try\ again\ later\ or\ contact\ the\ server\ administrator.=Error downloading from URL. Cause is likely the server side.\nPlease try again later or contact the server administrator.
URL\:\ %0=URL: %0
URL\:\ %0\nHTTP\ %1\ %2\n%3=URL: %0\nHTTP %1 %2\n%3
Please\ check\ the\ URL\ and\ try\ again.\nURL\:\ %0\nDetails\:\ %1=Please check the URL and try again.\nURL: %0\nDetails: %1
diff --git a/src/test/java/org/jabref/logic/importer/fetcher/GoogleScholarTest.java b/src/test/java/org/jabref/logic/importer/fetcher/GoogleScholarTest.java
index 4432e20a19b..a3a96315a11 100644
--- a/src/test/java/org/jabref/logic/importer/fetcher/GoogleScholarTest.java
+++ b/src/test/java/org/jabref/logic/importer/fetcher/GoogleScholarTest.java
@@ -38,7 +38,7 @@ void setUp() {
}
@Test
- void linkFound() throws IOException, FetcherException {
+ void linkFound() throws Exception {
entry.setField(StandardField.TITLE, "Towards Application Portability in Platform as a Service");
assertEquals(
diff --git a/src/test/java/org/jabref/logic/importer/fetcher/ResearchGateTest.java b/src/test/java/org/jabref/logic/importer/fetcher/ResearchGateTest.java
index 5fdccc287c6..8ccc6f6f1af 100644
--- a/src/test/java/org/jabref/logic/importer/fetcher/ResearchGateTest.java
+++ b/src/test/java/org/jabref/logic/importer/fetcher/ResearchGateTest.java
@@ -56,7 +56,7 @@ void fullTextNotFoundByDOI() throws IOException, FetcherException {
}
@Test
- void getDocumentByTitle() throws IOException, NullPointerException {
+ void getDocumentByTitle() throws Exception {
Optional source = fetcher.getURLByString(entry.getTitle().get());
assertTrue(source.isPresent() && source.get().startsWith(URL_PAGE));
}
diff --git a/src/test/java/org/jabref/logic/importer/fileformat/ACMPortalParserTest.java b/src/test/java/org/jabref/logic/importer/fileformat/ACMPortalParserTest.java
index fc1672af602..d9f641ab855 100644
--- a/src/test/java/org/jabref/logic/importer/fileformat/ACMPortalParserTest.java
+++ b/src/test/java/org/jabref/logic/importer/fileformat/ACMPortalParserTest.java
@@ -1,6 +1,5 @@
package org.jabref.logic.importer.fileformat;
-import java.io.IOException;
import java.net.CookieHandler;
import java.net.CookieManager;
import java.net.MalformedURLException;
@@ -11,7 +10,6 @@
import java.util.Optional;
import org.jabref.logic.importer.FetcherException;
-import org.jabref.logic.importer.ParseException;
import org.jabref.logic.net.URLDownload;
import org.jabref.model.entry.BibEntry;
import org.jabref.model.entry.field.StandardField;
@@ -69,7 +67,7 @@ void setUp() throws URISyntaxException, MalformedURLException {
}
@Test
- void parseEntries() throws IOException, ParseException {
+ void parseEntries() throws Exception {
CookieHandler.setDefault(new CookieManager());
List bibEntries = parser.parseEntries(new URLDownload(searchUrl).asInputStream());
for (BibEntry bibEntry : bibEntries) {
@@ -79,7 +77,7 @@ void parseEntries() throws IOException, ParseException {
}
@Test
- void parseDoiSearchPage() throws ParseException, IOException {
+ void parseDoiSearchPage() throws Exception {
String testDoi = "10.1145/3129790.3129810";
CookieHandler.setDefault(new CookieManager());
List doiList = parser.parseDoiSearchPage(new URLDownload(searchUrl).asInputStream());
@@ -139,7 +137,7 @@ void parseBibEntryWithFamilyAuthorOnly() {
}
@Test
- void noEntryFound() throws URISyntaxException, IOException, ParseException {
+ void noEntryFound() throws Exception {
CookieHandler.setDefault(new CookieManager());
URL url = new URIBuilder("https://dl.acm.org/action/doSearch?AllField=10.1145/3129790.31298").build().toURL();
List bibEntries = parser.parseEntries(new URLDownload(url).asInputStream());
diff --git a/src/test/java/org/jabref/logic/net/URLDownloadTest.java b/src/test/java/org/jabref/logic/net/URLDownloadTest.java
index 926d5c67c38..2c9e41b2b11 100644
--- a/src/test/java/org/jabref/logic/net/URLDownloadTest.java
+++ b/src/test/java/org/jabref/logic/net/URLDownloadTest.java
@@ -28,21 +28,21 @@ public class URLDownloadTest {
private static final Logger LOGGER = LoggerFactory.getLogger(URLDownloadTest.class);
@Test
- public void stringDownloadWithSetEncoding() throws IOException {
+ public void stringDownloadWithSetEncoding() throws Exception {
URLDownload dl = new URLDownload(new URL("http://www.google.com"));
assertTrue(dl.asString().contains("Google"), "google.com should contain google");
}
@Test
- public void stringDownload() throws IOException {
+ public void stringDownload() throws Exception {
URLDownload dl = new URLDownload(new URL("http://www.google.com"));
assertTrue(dl.asString(StandardCharsets.UTF_8).contains("Google"), "google.com should contain google");
}
@Test
- public void fileDownload() throws IOException {
+ public void fileDownload() throws Exception {
File destination = File.createTempFile("jabref-test", ".html");
try {
URLDownload dl = new URLDownload(new URL("http://www.google.com"));
@@ -57,14 +57,14 @@ public void fileDownload() throws IOException {
}
@Test
- public void determineMimeType() throws IOException {
+ public void determineMimeType() throws Exception {
URLDownload dl = new URLDownload(new URL("http://www.google.com"));
assertTrue(dl.getMimeType().startsWith("text/html"));
}
@Test
- public void downloadToTemporaryFilePathWithoutFileSavesAsTmpFile() throws IOException {
+ public void downloadToTemporaryFilePathWithoutFileSavesAsTmpFile() throws Exception {
URLDownload google = new URLDownload(new URL("http://www.google.com"));
String path = google.toTemporaryFile().toString();
@@ -72,7 +72,7 @@ public void downloadToTemporaryFilePathWithoutFileSavesAsTmpFile() throws IOExce
}
@Test
- public void downloadToTemporaryFileKeepsName() throws IOException {
+ public void downloadToTemporaryFileKeepsName() throws Exception {
URLDownload google = new URLDownload(new URL("https://github.com/JabRef/jabref/blob/main/LICENSE"));
String path = google.toTemporaryFile().toString();
@@ -81,7 +81,7 @@ public void downloadToTemporaryFileKeepsName() throws IOException {
@Test
@DisabledOnCIServer("CI Server is apparently blocked")
- public void downloadOfFTPSucceeds() throws IOException {
+ public void downloadOfFTPSucceeds() throws Exception {
URLDownload ftp = new URLDownload(new URL("ftp://ftp.informatik.uni-stuttgart.de/pub/library/ncstrl.ustuttgart_fi/INPROC-2016-15/INPROC-2016-15.pdf"));
Path path = ftp.toTemporaryFile();
@@ -89,7 +89,7 @@ public void downloadOfFTPSucceeds() throws IOException {
}
@Test
- public void downloadOfHttpSucceeds() throws IOException {
+ public void downloadOfHttpSucceeds() throws Exception {
URLDownload ftp = new URLDownload(new URL("http://www.jabref.org"));
Path path = ftp.toTemporaryFile();
@@ -97,7 +97,7 @@ public void downloadOfHttpSucceeds() throws IOException {
}
@Test
- public void downloadOfHttpsSucceeds() throws IOException {
+ public void downloadOfHttpsSucceeds() throws Exception {
URLDownload ftp = new URLDownload(new URL("https://www.jabref.org"));
Path path = ftp.toTemporaryFile();
From 836b997a0a5efca3d45d687d7e7f8e799b4755b8 Mon Sep 17 00:00:00 2001
From: Oliver Kopp
Date: Mon, 12 Aug 2024 02:16:19 +0200
Subject: [PATCH 29/42] Add some debug
---
.../org/jabref/logic/importer/FetcherException.java | 11 +++++++++++
1 file changed, 11 insertions(+)
diff --git a/src/main/java/org/jabref/logic/importer/FetcherException.java b/src/main/java/org/jabref/logic/importer/FetcherException.java
index 3340258ab79..03b762c2783 100644
--- a/src/main/java/org/jabref/logic/importer/FetcherException.java
+++ b/src/main/java/org/jabref/logic/importer/FetcherException.java
@@ -1,5 +1,6 @@
package org.jabref.logic.importer;
+import java.io.IOException;
import java.net.URL;
import java.util.Optional;
import java.util.regex.Pattern;
@@ -9,7 +10,11 @@
import org.jabref.logic.l10n.Localization;
import org.jabref.model.strings.StringUtil;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
public class FetcherException extends JabRefException {
+ private static final Logger LOGGER = LoggerFactory.getLogger(FetcherException.class);
Pattern API_KEY_PATTERN = Pattern.compile("(?i)(api|key|api[-_]?key)=[^&]*");
@@ -63,7 +68,13 @@ public FetcherException(String errorMessage, Throwable cause) {
// TODO: Convert IOException e to FetcherClientException
// Same TODO as in org.jabref.logic.importer.EntryBasedParserFetcher.performSearch.
// Maybe do this in org.jabref.logic.importer.FetcherException.getLocalizedMessage
+
+ // Idea (from org.jabref.logic.importer.fetcher.GoogleScholar.performSearchPaged)
+ // if (e.getMessage().contains("Server returned HTTP response code: 503 for URL")) {
super(errorMessage, cause);
+ if (LOGGER.isDebugEnabled() && (cause instanceof IOException)) {
+ LOGGER.debug("I/O exception", cause);
+ }
httpResponse = null;
url = null;
}
From 89c845dee5ff7b289b001a35fee26640830cb241 Mon Sep 17 00:00:00 2001
From: Oliver Kopp
Date: Mon, 12 Aug 2024 02:22:44 +0200
Subject: [PATCH 30/42] Keep response body
---
src/main/java/org/jabref/logic/net/URLDownload.java | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/src/main/java/org/jabref/logic/net/URLDownload.java b/src/main/java/org/jabref/logic/net/URLDownload.java
index 0394bda31b1..7dd4503d47a 100644
--- a/src/main/java/org/jabref/logic/net/URLDownload.java
+++ b/src/main/java/org/jabref/logic/net/URLDownload.java
@@ -431,7 +431,8 @@ public URLConnection openConnection() throws FetcherException {
} catch (MalformedURLException e) {
throw new FetcherException("Could not open URL Download", e);
}
- } else {
+ } else if (status >= 400) {
+ // in case of an error, propagate the error message
SimpleHttpResponse httpResponse = new SimpleHttpResponse(httpURLConnection);
LOGGER.info("{}", httpResponse);
if ((status >= 400) && (status < 500)) {
From ca3b01cb454bf2ed3b93ea376b86f14d37487871 Mon Sep 17 00:00:00 2001
From: Oliver Kopp
Date: Mon, 12 Aug 2024 18:42:06 +0200
Subject: [PATCH 31/42] Move default implementation to "real" class
---
.../java/org/jabref/gui/DialogService.java | 38 +-----------------
.../org/jabref/gui/JabRefDialogService.java | 40 +++++++++++++++++++
2 files changed, 42 insertions(+), 36 deletions(-)
diff --git a/src/main/java/org/jabref/gui/DialogService.java b/src/main/java/org/jabref/gui/DialogService.java
index a0a48c5ee87..5a6cc7d7919 100644
--- a/src/main/java/org/jabref/gui/DialogService.java
+++ b/src/main/java/org/jabref/gui/DialogService.java
@@ -20,11 +20,7 @@
import org.jabref.gui.util.BaseDialog;
import org.jabref.gui.util.DirectoryDialogConfiguration;
import org.jabref.gui.util.FileDialogConfiguration;
-import org.jabref.http.dto.SimpleHttpResponse;
-import org.jabref.logic.importer.FetcherClientException;
import org.jabref.logic.importer.FetcherException;
-import org.jabref.logic.importer.FetcherServerException;
-import org.jabref.logic.l10n.Localization;
import org.controlsfx.control.textfield.CustomPasswordField;
import org.controlsfx.dialog.ProgressDialog;
@@ -101,39 +97,9 @@ default Optional showEditableChoiceDialogAndWait(String title, String con
*
* @param exception the exception causing the error
*/
- default void showErrorDialogAndWait(Exception exception) {
- if (exception instanceof FetcherException) {
- // Somehow, Java does not route correctly to the other method
- showErrorDialogAndWait((FetcherException) exception);
- } else {
- showErrorDialogAndWait(Localization.lang("Unhandled exception occurred."), exception);
- }
- }
+ void showErrorDialogAndWait(Exception exception);
- default void showErrorDialogAndWait(FetcherException fetcherException) {
- String failedTitle = Localization.lang("Failed to download from URL");
- String localizedMessage = fetcherException.getLocalizedMessage();
- Optional httpResponse = fetcherException.getHttpResponse();
- if (httpResponse.isPresent()) {
- int statusCode = httpResponse.get().statusCode();
- if (statusCode == 401) {
- this.showInformationDialogAndWait(failedTitle, Localization.lang("Access denied. You are not authorized to access this resource. Please check your credentials and try again. If you believe you should have access, please contact the administrator for assistance.") + "\n\n" + localizedMessage);
- } else if (statusCode == 403) {
- this.showInformationDialogAndWait(failedTitle, Localization.lang("Access denied. You do not have permission to access this resource. Please contact the administrator for assistance or try a different action.") + "\n\n" + localizedMessage);
- } else if (statusCode == 404) {
- this.showInformationDialogAndWait(failedTitle, Localization.lang("The requested resource could not be found. It seems that the file you are trying to download is not available or has been moved. Please verify the URL and try again. If you believe this is an error, please contact the administrator for further assistance.") + "\n\n" + localizedMessage);
- } else {
- this.showErrorDialogAndWait(failedTitle, Localization.lang("Something is wrong on JabRef side. Please check the URL and try again.") + "\n\n" + localizedMessage);
- }
- } else if (fetcherException instanceof FetcherClientException) {
- this.showErrorDialogAndWait(failedTitle, Localization.lang("Something is wrong on JabRef side. Please check the URL and try again.") + "\n\n" + localizedMessage);
- } else if (fetcherException instanceof FetcherServerException) {
- this.showInformationDialogAndWait(failedTitle,
- Localization.lang("Error downloading from URL. Cause is likely the server side.\nPlease try again later or contact the server administrator.") + "\n\n" + localizedMessage);
- } else {
- this.showErrorDialogAndWait(failedTitle, localizedMessage);
- }
- }
+ void showErrorDialogAndWait(FetcherException fetcherException);
/**
* Create and display error dialog displaying the given exception.
diff --git a/src/main/java/org/jabref/gui/JabRefDialogService.java b/src/main/java/org/jabref/gui/JabRefDialogService.java
index 1e572069602..f50820c1c8e 100644
--- a/src/main/java/org/jabref/gui/JabRefDialogService.java
+++ b/src/main/java/org/jabref/gui/JabRefDialogService.java
@@ -47,6 +47,10 @@
import org.jabref.gui.util.FileDialogConfiguration;
import org.jabref.gui.util.UiTaskExecutor;
import org.jabref.gui.util.ZipFileChooser;
+import org.jabref.http.dto.SimpleHttpResponse;
+import org.jabref.logic.importer.FetcherClientException;
+import org.jabref.logic.importer.FetcherException;
+import org.jabref.logic.importer.FetcherServerException;
import org.jabref.logic.l10n.Localization;
import com.tobiasdiez.easybind.EasyBind;
@@ -205,6 +209,42 @@ public void showErrorDialogAndWait(String message, Throwable exception) {
exceptionDialog.showAndWait();
}
+ @Override
+ public void showErrorDialogAndWait(Exception exception) {
+ if (exception instanceof FetcherException) {
+ // Somehow, Java does not route correctly to the other method
+ showErrorDialogAndWait((FetcherException) exception);
+ } else {
+ showErrorDialogAndWait(Localization.lang("Unhandled exception occurred."), exception);
+ }
+ }
+
+ @Override
+ public void showErrorDialogAndWait(FetcherException fetcherException) {
+ String failedTitle = Localization.lang("Failed to download from URL");
+ String localizedMessage = fetcherException.getLocalizedMessage();
+ Optional httpResponse = fetcherException.getHttpResponse();
+ if (httpResponse.isPresent()) {
+ int statusCode = httpResponse.get().statusCode();
+ if (statusCode == 401) {
+ this.showInformationDialogAndWait(failedTitle, Localization.lang("Access denied. You are not authorized to access this resource. Please check your credentials and try again. If you believe you should have access, please contact the administrator for assistance.") + "\n\n" + localizedMessage);
+ } else if (statusCode == 403) {
+ this.showInformationDialogAndWait(failedTitle, Localization.lang("Access denied. You do not have permission to access this resource. Please contact the administrator for assistance or try a different action.") + "\n\n" + localizedMessage);
+ } else if (statusCode == 404) {
+ this.showInformationDialogAndWait(failedTitle, Localization.lang("The requested resource could not be found. It seems that the file you are trying to download is not available or has been moved. Please verify the URL and try again. If you believe this is an error, please contact the administrator for further assistance.") + "\n\n" + localizedMessage);
+ } else {
+ this.showErrorDialogAndWait(failedTitle, Localization.lang("Something is wrong on JabRef side. Please check the URL and try again.") + "\n\n" + localizedMessage);
+ }
+ } else if (fetcherException instanceof FetcherClientException) {
+ this.showErrorDialogAndWait(failedTitle, Localization.lang("Something is wrong on JabRef side. Please check the URL and try again.") + "\n\n" + localizedMessage);
+ } else if (fetcherException instanceof FetcherServerException) {
+ this.showInformationDialogAndWait(failedTitle,
+ Localization.lang("Error downloading from URL. Cause is likely the server side.\nPlease try again later or contact the server administrator.") + "\n\n" + localizedMessage);
+ } else {
+ this.showErrorDialogAndWait(failedTitle, localizedMessage);
+ }
+ }
+
@Override
public void showErrorDialogAndWait(String title, String content, Throwable exception) {
ExceptionDialog exceptionDialog = new ExceptionDialog(exception);
From ded5c56331710c94775a3f8e7366abb4866fcee9 Mon Sep 17 00:00:00 2001
From: Oliver Kopp
Date: Mon, 12 Aug 2024 19:01:32 +0200
Subject: [PATCH 32/42] Keep URL and HTTP untranslated
---
.../java/org/jabref/logic/importer/FetcherException.java | 6 +++---
src/main/resources/l10n/JabRef_en.properties | 2 --
2 files changed, 3 insertions(+), 5 deletions(-)
diff --git a/src/main/java/org/jabref/logic/importer/FetcherException.java b/src/main/java/org/jabref/logic/importer/FetcherException.java
index 03b762c2783..005795e928e 100644
--- a/src/main/java/org/jabref/logic/importer/FetcherException.java
+++ b/src/main/java/org/jabref/logic/importer/FetcherException.java
@@ -7,7 +7,6 @@
import org.jabref.http.dto.SimpleHttpResponse;
import org.jabref.logic.JabRefException;
-import org.jabref.logic.l10n.Localization;
import org.jabref.model.strings.StringUtil;
import org.slf4j.Logger;
@@ -117,9 +116,10 @@ public String getLocalizedMessage() {
// TODO: 5% of the "new-ers" pass a "real" localized message. See org.jabref.logic.importer.fetcher.GoogleScholar.addHitsFromQuery. We should maybe make use of this (and rewrite the whole message handling)
// TODO: Try to convert IOException to some more meaningful information here (or at org.jabref.gui.DialogService.showErrorDialogAndWait(org.jabref.logic.importer.FetcherException)). See also org.jabref.logic.net.URLDownload.openConnection
if (httpResponse != null) {
- return getPrefix() + Localization.lang("URL: %0\nHTTP %1 %2\n%3", getRedactedUrl(), httpResponse.statusCode(), httpResponse.responseMessage(), httpResponse.responseBody());
+ // We decided to not "translate" technical terms (URL, HTTP)
+ return getPrefix() + String.format("URL: %s\nHTTP %d %s\n%s", getRedactedUrl(), httpResponse.statusCode(), httpResponse.responseMessage(), httpResponse.responseBody());
} else if (url != null) {
- return getPrefix() + Localization.lang("URL: %0", getRedactedUrl());
+ return getPrefix() + "URL: %s".format(getRedactedUrl());
} else {
return super.getLocalizedMessage();
}
diff --git a/src/main/resources/l10n/JabRef_en.properties b/src/main/resources/l10n/JabRef_en.properties
index 8d543167ddd..59ec8e76926 100644
--- a/src/main/resources/l10n/JabRef_en.properties
+++ b/src/main/resources/l10n/JabRef_en.properties
@@ -2619,8 +2619,6 @@ Access\ denied.\ You\ do\ not\ have\ permission\ to\ access\ this\ resource.\ Pl
The\ requested\ resource\ could\ not\ be\ found.\ It\ seems\ that\ the\ file\ you\ are\ trying\ to\ download\ is\ not\ available\ or\ has\ been\ moved.\ Please\ verify\ the\ URL\ and\ try\ again.\ If\ you\ believe\ this\ is\ an\ error,\ please\ contact\ the\ administrator\ for\ further\ assistance.=The requested resource could not be found. It seems that the file you are trying to download is not available or has been moved. Please verify the URL and try again. If you believe this is an error, please contact the administrator for further assistance.
Something\ is\ wrong\ on\ JabRef\ side.\ Please\ check\ the\ URL\ and\ try\ again.=Something is wrong on JabRef side. Please check the URL and try again.
Error\ downloading\ from\ URL.\ Cause\ is\ likely\ the\ server\ side.\nPlease\ try\ again\ later\ or\ contact\ the\ server\ administrator.=Error downloading from URL. Cause is likely the server side.\nPlease try again later or contact the server administrator.
-URL\:\ %0=URL: %0
-URL\:\ %0\nHTTP\ %1\ %2\n%3=URL: %0\nHTTP %1 %2\n%3
Please\ check\ the\ URL\ and\ try\ again.\nURL\:\ %0\nDetails\:\ %1=Please check the URL and try again.\nURL: %0\nDetails: %1
Finished=Finished
From cb350b0a6237f1c5f78c53a5254b6b26281399b9 Mon Sep 17 00:00:00 2001
From: Oliver Kopp
Date: Mon, 12 Aug 2024 19:18:56 +0200
Subject: [PATCH 33/42] Delete 2x "ofUrl"
---
.../logic/importer/FetcherException.java | 8 ----
.../importer/fetcher/IacrEprintFetcher.java | 2 +-
.../logic/importer/fetcher/MrDLibFetcher.java | 48 +++++++++----------
.../logic/importer/fetcher/ResearchGate.java | 18 +++----
4 files changed, 33 insertions(+), 43 deletions(-)
diff --git a/src/main/java/org/jabref/logic/importer/FetcherException.java b/src/main/java/org/jabref/logic/importer/FetcherException.java
index 005795e928e..dfe847bd432 100644
--- a/src/main/java/org/jabref/logic/importer/FetcherException.java
+++ b/src/main/java/org/jabref/logic/importer/FetcherException.java
@@ -90,14 +90,6 @@ public FetcherException(String errorMessage, String localizedMessage, Throwable
url = null;
}
- public static FetcherException ofUrl(String url, Throwable cause) {
- return new FetcherException(url, cause, null);
- }
-
- public static FetcherException ofUrl(String url, String errorMessage) {
- return new FetcherException(url, errorMessage, null, null);
- }
-
public static FetcherException ofUrl(String url, String errorMessage, Throwable cause) {
return new FetcherException(url, errorMessage, cause, null);
}
diff --git a/src/main/java/org/jabref/logic/importer/fetcher/IacrEprintFetcher.java b/src/main/java/org/jabref/logic/importer/fetcher/IacrEprintFetcher.java
index 0a58be73d71..35c0ba1bbe9 100644
--- a/src/main/java/org/jabref/logic/importer/fetcher/IacrEprintFetcher.java
+++ b/src/main/java/org/jabref/logic/importer/fetcher/IacrEprintFetcher.java
@@ -64,7 +64,7 @@ private Optional createEntryFromIacrCitation(String validIdentifier) t
try {
return BibtexParser.singleFromString(actualEntry, prefs);
} catch (ParseException e) {
- throw FetcherException.ofUrl(Localization.lang("Entry from %0 could not be parsed.", "IACR"), e);
+ throw new FetcherException(Localization.lang("Entry from %0 could not be parsed.", "IACR"), e);
}
}
diff --git a/src/main/java/org/jabref/logic/importer/fetcher/MrDLibFetcher.java b/src/main/java/org/jabref/logic/importer/fetcher/MrDLibFetcher.java
index 2d1205c6692..ba12ac0d9aa 100644
--- a/src/main/java/org/jabref/logic/importer/fetcher/MrDLibFetcher.java
+++ b/src/main/java/org/jabref/logic/importer/fetcher/MrDLibFetcher.java
@@ -1,8 +1,10 @@
package org.jabref.logic.importer.fetcher;
import java.io.IOException;
+import java.net.MalformedURLException;
import java.net.URI;
import java.net.URISyntaxException;
+import java.net.URL;
import java.util.Calendar;
import java.util.List;
import java.util.Optional;
@@ -58,7 +60,14 @@ public List performSearch(BibEntry entry) throws FetcherException {
return List.of();
}
- String response = makeServerRequest(title.get());
+ URL url;
+ try {
+ url = constructQuery(title.get());
+ } catch (URISyntaxException | MalformedURLException e) {
+ throw new FetcherException("Invalid URL", e);
+ }
+
+ String response = makeServerRequest(url);
MrDLibImporter importer = new MrDLibImporter();
ParserResult parserResult;
try {
@@ -75,7 +84,7 @@ public List performSearch(BibEntry entry) throws FetcherException {
}
} catch (IOException e) {
LOGGER.error("Error while fetching", e);
- throw FetcherException.ofUrl(constructQuery(title.get()), e);
+ throw new FetcherException(url, e);
}
return parserResult.getDatabase().getEntries();
}
@@ -91,31 +100,25 @@ public String getDescription() {
/**
* Contact the server with the title of the selected item
*
- * @param queryByTitle the query holds the title of the selected entry. Used to make a query to the MDL Server
* @return Returns the server response. This is an XML document as a String.
*/
- private String makeServerRequest(String queryByTitle) throws FetcherException {
- String url = constructQuery(queryByTitle);
- try {
- URLDownload urlDownload = new URLDownload(url);
- String response = urlDownload.asString();
+ private String makeServerRequest(URL url) throws FetcherException {
+ URLDownload urlDownload = new URLDownload(url);
+ String response = urlDownload.asString();
- // Conversion of < and >
- response = response.replace(">", ">");
- response = response.replace("<", "<");
- return response;
- } catch (IOException e) {
- throw FetcherException.ofUrl(url, e);
- }
+ // Conversion of < and >
+ response = response.replace(">", ">");
+ response = response.replace("<", "<");
+ return response;
}
/**
* Constructs the query based on title of the BibEntry. Adds statistical stuff to the url.
*
- * @param queryWithTitle the title of the bib entry.
+ * @param queryWithTitle the query holds the title of the selected entry. Used to make a query to the MDL Server
* @return the string used to make the query at mdl server
*/
- private String constructQuery(String queryWithTitle) {
+ private URL constructQuery(String queryWithTitle) throws URISyntaxException, MalformedURLException {
// The encoding does not work for / so we convert them by our own
queryWithTitle = queryWithTitle.replace("/", " ");
URIBuilder builder = new URIBuilder();
@@ -136,13 +139,8 @@ private String constructQuery(String queryWithTitle) {
builder.addParameter("timezone", Calendar.getInstance().getTimeZone().getID());
}
- try {
- URI uri = builder.build();
- LOGGER.trace("Request: {}", uri.toString());
- return uri.toString();
- } catch (URISyntaxException e) {
- LOGGER.error("Invalid URI", e);
- }
- return "";
+ URI uri = builder.build();
+ LOGGER.trace("Request: {}", uri.toString());
+ return uri.toURL();
}
}
diff --git a/src/main/java/org/jabref/logic/importer/fetcher/ResearchGate.java b/src/main/java/org/jabref/logic/importer/fetcher/ResearchGate.java
index d9c9011a822..1f1f0196ed1 100644
--- a/src/main/java/org/jabref/logic/importer/fetcher/ResearchGate.java
+++ b/src/main/java/org/jabref/logic/importer/fetcher/ResearchGate.java
@@ -3,6 +3,7 @@
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
+import java.net.MalformedURLException;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.ArrayList;
@@ -169,8 +170,8 @@ Optional getURLByDoi(DOI doi) throws IOException, NullPointerException {
return Optional.of(link);
}
- private Document getPage(String url) throws IOException {
- return Jsoup.connect(url)
+ private Document getPage(URL url) throws IOException {
+ return Jsoup.connect(url.toString())
.userAgent(URLDownload.USER_AGENT)
.referrer("www.google.com")
.ignoreHttpErrors(true)
@@ -185,13 +186,12 @@ private Document getPage(String url) throws IOException {
* @param luceneQuery the search query.
* @return A URL that lets us download a .bib file
*/
- private static String getUrlForQuery(QueryNode luceneQuery) throws URISyntaxException {
+ private static URL getUrlForQuery(QueryNode luceneQuery) throws URISyntaxException, MalformedURLException {
String query = new DefaultQueryTransformer().transformLuceneQuery(luceneQuery).orElse("");
URIBuilder source = new URIBuilder(SEARCH);
source.addParameter("type", "publication");
source.addParameter("query", query);
- String url = source.build().toString();
- return url;
+ return source.build().toURL();
}
@Override
@@ -210,10 +210,10 @@ public TrustLevel getTrustLevel() {
public List performSearch(QueryNode luceneQuery) throws FetcherException {
Document html;
- String url;
+ URL url;
try {
url = getUrlForQuery(luceneQuery);
- } catch (URISyntaxException e) {
+ } catch (URISyntaxException | MalformedURLException e) {
throw new FetcherException("Invalid URL", e);
}
@@ -221,10 +221,10 @@ public List performSearch(QueryNode luceneQuery) throws FetcherExcepti
html = getPage(url);
// ResearchGate's server blocks when too many request are made
if (!html.getElementsByClass("nova-legacy-v-publication-item__title").hasText()) {
- throw FetcherException.ofUrl(url, "ResearchGate server unavailable");
+ throw new FetcherException(url, "Required HTML element not found", null);
}
} catch (IOException e) {
- throw new FetcherException("URL is not correct", e);
+ throw new FetcherException(url, e);
}
Elements sol = html.getElementsByClass("nova-legacy-v-publication-item__title");
From 7687bbd2382bb73b6aaf3bd322987fd480cb38ca Mon Sep 17 00:00:00 2001
From: Oliver Kopp
Date: Mon, 12 Aug 2024 19:24:05 +0200
Subject: [PATCH 34/42] Remove "ofUrl" and dummy constructors
---
.../logic/importer/FetcherException.java | 22 --------
.../importer/fetcher/IacrEprintFetcher.java | 52 ++++++++++++++-----
2 files changed, 39 insertions(+), 35 deletions(-)
diff --git a/src/main/java/org/jabref/logic/importer/FetcherException.java b/src/main/java/org/jabref/logic/importer/FetcherException.java
index dfe847bd432..2a7f0bdc63f 100644
--- a/src/main/java/org/jabref/logic/importer/FetcherException.java
+++ b/src/main/java/org/jabref/logic/importer/FetcherException.java
@@ -45,24 +45,6 @@ public FetcherException(URL url, String errorMessage, Throwable cause) {
this.url = url.toString();
}
- /**
- * @param dummy Required to distinguish of {@link FetcherException#FetcherException(String, Throwable)}, which is for a FetcherException with an error message
- */
- private FetcherException(String url, Throwable cause, Object dummy) {
- super(cause);
- httpResponse = null;
- this.url = url;
- }
-
- /**
- * @param dummy Required to distinguish of {@link FetcherException#FetcherException(String, String, Throwable)}, which is for a localized FetcherException
- */
- private FetcherException(String url, String errorMessage, Throwable cause, Object dummy) {
- super(errorMessage, cause);
- httpResponse = null;
- this.url = url;
- }
-
public FetcherException(String errorMessage, Throwable cause) {
// TODO: Convert IOException e to FetcherClientException
// Same TODO as in org.jabref.logic.importer.EntryBasedParserFetcher.performSearch.
@@ -90,10 +72,6 @@ public FetcherException(String errorMessage, String localizedMessage, Throwable
url = null;
}
- public static FetcherException ofUrl(String url, String errorMessage, Throwable cause) {
- return new FetcherException(url, errorMessage, cause, null);
- }
-
public static FetcherException of(URL url, SimpleHttpResponse simpleHttpResponse) {
if (simpleHttpResponse.statusCode() >= 500) {
return new FetcherServerException(url, simpleHttpResponse);
diff --git a/src/main/java/org/jabref/logic/importer/fetcher/IacrEprintFetcher.java b/src/main/java/org/jabref/logic/importer/fetcher/IacrEprintFetcher.java
index 35c0ba1bbe9..d1d630ffe21 100644
--- a/src/main/java/org/jabref/logic/importer/fetcher/IacrEprintFetcher.java
+++ b/src/main/java/org/jabref/logic/importer/fetcher/IacrEprintFetcher.java
@@ -1,6 +1,8 @@
package org.jabref.logic.importer.fetcher;
import java.io.IOException;
+import java.net.MalformedURLException;
+import java.net.URI;
import java.net.URL;
import java.util.Objects;
import java.util.Optional;
@@ -19,10 +21,14 @@
import org.jabref.model.entry.field.StandardField;
import org.jabref.model.strings.StringUtil;
-public class IacrEprintFetcher implements FulltextFetcher, IdBasedFetcher {
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+public class IacrEprintFetcher implements FulltextFetcher, IdBasedFetcher {
public static final String NAME = "IACR eprints";
+ private static final Logger LOGGER = LoggerFactory.getLogger(IacrEprintFetcher.class);
+
private static final Pattern WITHOUT_LETTERS_SPACE = Pattern.compile("[^0-9/]");
private static final Predicate IDENTIFIER_PREDICATE = Pattern.compile("\\d{4}/\\d{3,5}").asPredicate();
@@ -55,7 +61,13 @@ public Optional performSearchById(String identifier) throws FetcherExc
}
private Optional createEntryFromIacrCitation(String validIdentifier) throws FetcherException {
- String bibtexCitationHtml = getHtml(CITATION_URL_PREFIX + validIdentifier);
+ URL url;
+ try {
+ url = URI.create(CITATION_URL_PREFIX + validIdentifier).toURL();
+ } catch (MalformedURLException e) {
+ throw new FetcherException("Invalid URL", e);
+ }
+ String bibtexCitationHtml = getHtml(url);
if (bibtexCitationHtml.contains("No such report found")) {
throw new FetcherException(Localization.lang("No results found."));
}
@@ -69,7 +81,13 @@ private Optional createEntryFromIacrCitation(String validIdentifier) t
}
private void setAdditionalFields(BibEntry entry, String identifier) throws FetcherException {
- String entryUrl = DESCRIPTION_URL_PREFIX + identifier;
+ URL entryUrl;
+ try {
+ entryUrl = URI.create(DESCRIPTION_URL_PREFIX + identifier).toURL();
+ } catch (MalformedURLException e) {
+ throw new FetcherException("Invalid URL", e);
+ }
+
String descriptiveHtml = getHtml(entryUrl);
entry.setField(StandardField.ABSTRACT, getAbstract(descriptiveHtml));
@@ -77,8 +95,12 @@ private void setAdditionalFields(BibEntry entry, String identifier) throws Fetch
// Version information for entries after year 2000
if (isFromOrAfterYear2000(entry)) {
- String entryVersion = VERSION_URL_PREFIX + identifier;
- String versionHtml = getHtml(entryVersion);
+ try {
+ entryUrl = URI.create(VERSION_URL_PREFIX + identifier).toURL();
+ } catch (MalformedURLException e) {
+ throw new FetcherException("Invalid URL", e);
+ }
+ String versionHtml = getHtml(entryUrl);
String version = getVersion(identifier, versionHtml);
entry.setField(StandardField.VERSION, version);
entry.setField(StandardField.URL, entryUrl + "/" + version);
@@ -103,13 +125,9 @@ private String getDate(String descriptiveHtml) throws FetcherException {
return dateStringAsInHtml;
}
- private String getHtml(String url) throws FetcherException {
- try {
- URLDownload download = new URLDownload(url);
- return download.asString();
- } catch (IOException e) {
- throw FetcherException.ofUrl(url, Localization.lang("Could not retrieve entry data from '%0'.", url), e);
- }
+ private String getHtml(URL url) throws FetcherException {
+ URLDownload download = new URLDownload(url);
+ return download.asString();
}
private String getRequiredValueBetween(String from, String to, String haystack) throws FetcherException {
@@ -140,7 +158,15 @@ public Optional findFullText(BibEntry entry) throws IOException, FetcherExc
Optional urlField = entry.getField(StandardField.URL);
if (urlField.isPresent()) {
- String descriptiveHtml = getHtml(urlField.get());
+ URL url;
+ try {
+ url = URI.create(urlField.get()).toURL();
+ } catch (MalformedURLException e) {
+ LOGGER.warn("Invalid URL {}", urlField.get(), e);
+ return Optional.empty();
+ }
+
+ String descriptiveHtml = getHtml(url);
String startOfFulltextLink = "
Date: Mon, 12 Aug 2024 19:27:01 +0200
Subject: [PATCH 35/42] Make FetcherException(URL url, SimpleHttpResponse
httpResponse) protected
---
.../logic/importer/FetcherException.java | 18 +++++++++---------
1 file changed, 9 insertions(+), 9 deletions(-)
diff --git a/src/main/java/org/jabref/logic/importer/FetcherException.java b/src/main/java/org/jabref/logic/importer/FetcherException.java
index 2a7f0bdc63f..77e6715d050 100644
--- a/src/main/java/org/jabref/logic/importer/FetcherException.java
+++ b/src/main/java/org/jabref/logic/importer/FetcherException.java
@@ -29,7 +29,7 @@ public FetcherException(String url, SimpleHttpResponse httpResponse) {
this.httpResponse = httpResponse;
}
- public FetcherException(URL url, SimpleHttpResponse httpResponse) {
+ protected FetcherException(URL url, SimpleHttpResponse httpResponse) {
this(url.toString(), httpResponse);
}
@@ -72,14 +72,6 @@ public FetcherException(String errorMessage, String localizedMessage, Throwable
url = null;
}
- public static FetcherException of(URL url, SimpleHttpResponse simpleHttpResponse) {
- if (simpleHttpResponse.statusCode() >= 500) {
- return new FetcherServerException(url, simpleHttpResponse);
- } else {
- return new FetcherClientException(url, simpleHttpResponse);
- }
- }
-
@Override
public String getLocalizedMessage() {
// TODO: This should be moved to a separate class converting "any" exception object to a localized message
@@ -115,4 +107,12 @@ public Optional getHttpResponse() {
public Optional getUrl() {
return Optional.ofNullable(url);
}
+
+ public static FetcherException of(URL url, SimpleHttpResponse simpleHttpResponse) {
+ if (simpleHttpResponse.statusCode() >= 500) {
+ return new FetcherServerException(url, simpleHttpResponse);
+ } else {
+ return new FetcherClientException(url, simpleHttpResponse);
+ }
+ }
}
From d151e2bfaf21f39df7f488e47c1e793869411a9d Mon Sep 17 00:00:00 2001
From: Oliver Kopp
Date: Mon, 12 Aug 2024 19:43:53 +0200
Subject: [PATCH 36/42] Adapt test
---
src/test/java/org/jabref/logic/net/URLDownloadTest.java | 6 ++----
1 file changed, 2 insertions(+), 4 deletions(-)
diff --git a/src/test/java/org/jabref/logic/net/URLDownloadTest.java b/src/test/java/org/jabref/logic/net/URLDownloadTest.java
index 2c9e41b2b11..0b4771d2fb9 100644
--- a/src/test/java/org/jabref/logic/net/URLDownloadTest.java
+++ b/src/test/java/org/jabref/logic/net/URLDownloadTest.java
@@ -128,11 +128,9 @@ public void connectTimeoutIsNeverNull() throws MalformedURLException {
}
@Test
- public void test503ErrorThrowsNestedIOExceptionWithFetcherServerException() throws Exception {
+ public void test503ErrorThrowsFetcherServerException() throws Exception {
URLDownload urlDownload = new URLDownload(new URL("http://httpstat.us/503"));
-
- Exception exception = assertThrows(IOException.class, urlDownload::asString);
- assertInstanceOf(FetcherServerException.class, exception.getCause());
+ assertThrows(FetcherServerException.class, urlDownload::asString);
}
@Test
From 847c3bf693ee66cfed7c0be37130f89d28ff88d5 Mon Sep 17 00:00:00 2001
From: Oliver Kopp
Date: Mon, 12 Aug 2024 19:46:37 +0200
Subject: [PATCH 37/42] Fix connection opened twice
---
src/main/java/org/jabref/logic/net/URLDownload.java | 12 ------------
1 file changed, 12 deletions(-)
diff --git a/src/main/java/org/jabref/logic/net/URLDownload.java b/src/main/java/org/jabref/logic/net/URLDownload.java
index 7dd4503d47a..db9e3b4d9f7 100644
--- a/src/main/java/org/jabref/logic/net/URLDownload.java
+++ b/src/main/java/org/jabref/logic/net/URLDownload.java
@@ -397,18 +397,6 @@ public URLConnection openConnection() throws FetcherException {
} catch (IOException e) {
throw new FetcherException("Error opening connection", e);
}
- connection.setConnectTimeout((int) connectTimeout.toMillis());
- for (Entry entry : this.parameters.entrySet()) {
- connection.setRequestProperty(entry.getKey(), entry.getValue());
- }
- if (!this.postData.isEmpty()) {
- connection.setDoOutput(true);
- try (DataOutputStream wr = new DataOutputStream(connection.getOutputStream())) {
- wr.writeBytes(this.postData);
- } catch (IOException e) {
- throw new FetcherException("Could not write output", e);
- }
- }
if (connection instanceof HttpURLConnection httpURLConnection) {
int status;
From 1a3da174943c6ee6feea2d59afae9eebe4fa5556 Mon Sep 17 00:00:00 2001
From: Oliver Kopp
Date: Mon, 12 Aug 2024 20:00:43 +0200
Subject: [PATCH 38/42] Adapt test
---
src/test/java/org/jabref/logic/net/URLDownloadTest.java | 8 ++------
1 file changed, 2 insertions(+), 6 deletions(-)
diff --git a/src/test/java/org/jabref/logic/net/URLDownloadTest.java b/src/test/java/org/jabref/logic/net/URLDownloadTest.java
index 0b4771d2fb9..38b0846d8a5 100644
--- a/src/test/java/org/jabref/logic/net/URLDownloadTest.java
+++ b/src/test/java/org/jabref/logic/net/URLDownloadTest.java
@@ -1,7 +1,6 @@
package org.jabref.logic.net;
import java.io.File;
-import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.nio.charset.StandardCharsets;
@@ -17,7 +16,6 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import static org.junit.jupiter.api.Assertions.assertInstanceOf;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
@@ -134,10 +132,8 @@ public void test503ErrorThrowsFetcherServerException() throws Exception {
}
@Test
- public void test429ErrorThrowsNestedIOExceptionWithFetcherServerException() throws Exception {
+ public void test429ErrorThrowsFetcherClientException() throws Exception {
URLDownload urlDownload = new URLDownload(new URL("http://httpstat.us/429"));
-
- Exception exception = assertThrows(IOException.class, urlDownload::asString);
- assertInstanceOf(FetcherClientException.class, exception.getCause());
+ Exception exception = assertThrows(FetcherClientException.class, urlDownload::asString);
}
}
From ca979c98e4ff3bf315976154e812804dab88e2f7 Mon Sep 17 00:00:00 2001
From: Oliver Kopp
Date: Mon, 12 Aug 2024 23:11:42 +0200
Subject: [PATCH 39/42] Remove obsolete localization
---
src/main/resources/l10n/JabRef_en.properties | 1 -
1 file changed, 1 deletion(-)
diff --git a/src/main/resources/l10n/JabRef_en.properties b/src/main/resources/l10n/JabRef_en.properties
index 59ec8e76926..9cec9d1f4f2 100644
--- a/src/main/resources/l10n/JabRef_en.properties
+++ b/src/main/resources/l10n/JabRef_en.properties
@@ -1917,7 +1917,6 @@ Removes\ all\ line\ breaks\ in\ the\ field\ content.=Removes all line breaks in
Remove\ hyphenated\ line\ breaks=Remove hyphenated line breaks
Removes\ all\ hyphenated\ line\ breaks\ in\ the\ field\ content.=Removes all hyphenated line breaks in the field content.
-Could\ not\ retrieve\ entry\ data\ from\ '%0'.=Could not retrieve entry data from '%0'.
Entry\ from\ %0\ could\ not\ be\ parsed.=Entry from %0 could not be parsed.
Invalid\ identifier\:\ '%0'.=Invalid identifier: '%0'.
empty\ citation\ key=empty citation key
From d6d16ac148c39a83b270543d1a421226188ff971 Mon Sep 17 00:00:00 2001
From: Oliver Kopp
Date: Mon, 12 Aug 2024 23:13:11 +0200
Subject: [PATCH 40/42] Fix instanceOf Pattern
---
src/main/java/org/jabref/gui/JabRefDialogService.java | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/main/java/org/jabref/gui/JabRefDialogService.java b/src/main/java/org/jabref/gui/JabRefDialogService.java
index f50820c1c8e..b92954bff36 100644
--- a/src/main/java/org/jabref/gui/JabRefDialogService.java
+++ b/src/main/java/org/jabref/gui/JabRefDialogService.java
@@ -211,9 +211,9 @@ public void showErrorDialogAndWait(String message, Throwable exception) {
@Override
public void showErrorDialogAndWait(Exception exception) {
- if (exception instanceof FetcherException) {
+ if (exception instanceof FetcherException fetcherException) {
// Somehow, Java does not route correctly to the other method
- showErrorDialogAndWait((FetcherException) exception);
+ showErrorDialogAndWait(fetcherException);
} else {
showErrorDialogAndWait(Localization.lang("Unhandled exception occurred."), exception);
}
From 3405e211f08855a3c37db10f499391e9ee972b0b Mon Sep 17 00:00:00 2001
From: Oliver Kopp
Date: Mon, 12 Aug 2024 23:17:44 +0200
Subject: [PATCH 41/42] .formatted works.
---
src/main/java/org/jabref/logic/importer/FetcherException.java | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/main/java/org/jabref/logic/importer/FetcherException.java b/src/main/java/org/jabref/logic/importer/FetcherException.java
index 77e6715d050..47f672a8c51 100644
--- a/src/main/java/org/jabref/logic/importer/FetcherException.java
+++ b/src/main/java/org/jabref/logic/importer/FetcherException.java
@@ -79,9 +79,9 @@ public String getLocalizedMessage() {
// TODO: Try to convert IOException to some more meaningful information here (or at org.jabref.gui.DialogService.showErrorDialogAndWait(org.jabref.logic.importer.FetcherException)). See also org.jabref.logic.net.URLDownload.openConnection
if (httpResponse != null) {
// We decided to not "translate" technical terms (URL, HTTP)
- return getPrefix() + String.format("URL: %s\nHTTP %d %s\n%s", getRedactedUrl(), httpResponse.statusCode(), httpResponse.responseMessage(), httpResponse.responseBody());
+ return getPrefix() + "URL: %s\nHTTP %d %s\n%s".formatted(getRedactedUrl(), httpResponse.statusCode(), httpResponse.responseMessage(), httpResponse.responseBody());
} else if (url != null) {
- return getPrefix() + "URL: %s".format(getRedactedUrl());
+ return getPrefix() + "URL: %s".formatted(getRedactedUrl());
} else {
return super.getLocalizedMessage();
}
From d92e2a5737cc6e15984fb3346993e7cc986d2fc7 Mon Sep 17 00:00:00 2001
From: Oliver Kopp
Date: Mon, 12 Aug 2024 23:19:59 +0200
Subject: [PATCH 42/42] Add CHANGELOG.md entry
---
CHANGELOG.md | 1 +
1 file changed, 1 insertion(+)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index bcc7ea5fe45..1191882234c 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -26,6 +26,7 @@ Note that this project **does not** adhere to [Semantic Versioning](https://semv
### Changed
+- When a communication error with an [online service](https://docs.jabref.org/collect/import-using-online-bibliographic-database) occurs, JabRef displays the HTTP error. [#11223](https://github.com/JabRef/jabref/issues/11223)
- The Pubmed/Medline Plain importer now imports the PMID field as well [#11488](https://github.com/JabRef/jabref/issues/11488)
- The 'Check for updates' menu bar button is now always enabled. [#11485](https://github.com/JabRef/jabref/pull/11485)
- JabRef respects the [configuration for storing files relative to the .bib file](https://docs.jabref.org/finding-sorting-and-cleaning-entries/filelinks#directories-for-files) in more cases. [#11492](https://github.com/JabRef/jabref/pull/11492)