From 3821fefb127babd35532cf1f3d1b120a2c86415c Mon Sep 17 00:00:00 2001 From: Nikolas Komonen Date: Thu, 3 Jan 2019 15:48:07 -0500 Subject: [PATCH] Cache unavailable URI's Fixes #201 Tests aren't complete, need to find a way to handle exceptions. Signed-off-by: Nikolas Komonen --- .vscode/launch.json | 10 ++-- .../uriresolver/CacheResourcesManager.java | 21 ++++++- .../CacheResourcesManagerTest.java | 57 +++++++++++++++++++ 3 files changed, 81 insertions(+), 7 deletions(-) diff --git a/.vscode/launch.json b/.vscode/launch.json index 4053025f1..024ad291d 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -3,14 +3,12 @@ // Hover to view descriptions of existing attributes. // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 "version": "0.2.0", - "configurations": [ - { + "configurations": [{ "type": "java", - "name": "Debug (Attach)", + "name": "Debug (Attach) - Remote", "request": "attach", "hostName": "localhost", "port": 1054, "projectName": "org.eclipse.lsp4xml" - } - ] - } \ No newline at end of file + }] +} \ No newline at end of file diff --git a/org.eclipse.lsp4xml/src/main/java/org/eclipse/lsp4xml/uriresolver/CacheResourcesManager.java b/org.eclipse.lsp4xml/src/main/java/org/eclipse/lsp4xml/uriresolver/CacheResourcesManager.java index bfa541e9e..1f5dad191 100644 --- a/org.eclipse.lsp4xml/src/main/java/org/eclipse/lsp4xml/uriresolver/CacheResourcesManager.java +++ b/org.eclipse.lsp4xml/src/main/java/org/eclipse/lsp4xml/uriresolver/CacheResourcesManager.java @@ -27,9 +27,14 @@ import java.util.HashMap; import java.util.Map; import java.util.concurrent.CompletableFuture; +import java.util.concurrent.TimeUnit; import java.util.logging.Level; import java.util.logging.Logger; +import com.google.common.cache.Cache; +import com.google.common.cache.CacheBuilder; + + import org.eclipse.lsp4xml.utils.FilesUtils; import org.eclipse.lsp4xml.utils.URIUtils; @@ -38,6 +43,7 @@ * */ public class CacheResourcesManager { + protected final Cache unavailableURICache; private static final String CACHE_PATH = "cache"; private static final Logger LOGGER = Logger.getLogger(CacheResourcesManager.class.getName()); @@ -79,7 +85,13 @@ public String getResourceFromClasspath() { } public CacheResourcesManager() { + this(CacheBuilder.newBuilder().maximumSize(100).expireAfterWrite(30, TimeUnit.SECONDS).build()); + + } + + public CacheResourcesManager(Cache cache) { resourcesLoading = new HashMap<>(); + unavailableURICache = cache; } public Path getResource(final String resourceURI) throws IOException { @@ -87,6 +99,12 @@ public Path getResource(final String resourceURI) throws IOException { if (Files.exists(resourceCachePath)) { return resourceCachePath; } + + if(unavailableURICache.getIfPresent(resourceURI) != null) { + LOGGER.info("Ignored unavailable schema URI: " + resourceURI + "\n"); + return null; + } + CompletableFuture f = null; synchronized (resourcesLoading) { if (resourcesLoading.containsKey(resourceURI)) { @@ -139,11 +157,12 @@ private CompletableFuture downloadResource(final String resourceURI, Path LOGGER.info("Downloaded " + resourceURI + " to " + resourceCachePath + " in " + elapsed + "ms"); } catch (Exception e) { // Do nothing + unavailableURICache.put(resourceURI, true); Throwable rootCause = getRootCause(e); String error = "[" + rootCause.getClass().getTypeName() + "] " + rootCause.getMessage(); LOGGER.log(Level.SEVERE, "Error while downloading " + resourceURI + " to " + resourceCachePath + " : " + error); - throw new CacheResourceDownloadedException("Error while downloading '" + resourceURI + "'.", e); + throw new CacheResourceDownloadedException("Error while downloading '" + resourceURI + "' to " + resourceCachePath + ".", e); } finally { synchronized (resourcesLoading) { resourcesLoading.remove(resourceURI); diff --git a/org.eclipse.lsp4xml/src/test/java/org/eclipse/lsp4xml/uriresolver/CacheResourcesManagerTest.java b/org.eclipse.lsp4xml/src/test/java/org/eclipse/lsp4xml/uriresolver/CacheResourcesManagerTest.java index 28437b4e1..b6ded262f 100644 --- a/org.eclipse.lsp4xml/src/test/java/org/eclipse/lsp4xml/uriresolver/CacheResourcesManagerTest.java +++ b/org.eclipse.lsp4xml/src/test/java/org/eclipse/lsp4xml/uriresolver/CacheResourcesManagerTest.java @@ -12,11 +12,24 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.fail; +import java.io.IOException; +import java.util.concurrent.TimeUnit; + +import com.google.common.cache.CacheBuilder; + +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.ExpectedException; public class CacheResourcesManagerTest { + @Rule + public ExpectedException thrown = ExpectedException.none(); + @Test public void testCanUseCache() { testCanUseCache(true); @@ -32,4 +45,48 @@ private void testCanUseCache(boolean useCacheEnabled) { assertFalse(cacheResourcesManager.canUseCache("file:///foo")); } + @Test + public void testUnavailableCache() { + CacheResourcesManager cacheResourcesManager = new CacheResourcesManager(); + cacheResourcesManager.setUseCache(true); + try { + thrown.expect(CacheResourceDownloadingException.class); + cacheResourcesManager.getResource("http://bad"); + } catch (IOException e) { + + } + + try { + thrown.expect(CacheResourceDownloadedException.class); + assertNull(cacheResourcesManager.getResource("http://bad")); + } catch (IOException e1) { + + } + } + + @Test + + public void testAvailableCache() { + CacheResourcesManager cacheResourcesManager = new CacheResourcesManager(CacheBuilder.newBuilder() + .expireAfterWrite(10, TimeUnit.SECONDS) + .maximumSize(100) + .build()); + cacheResourcesManager.setUseCache(true); + try { + //thrown.expect(CacheResourceDownloadedException.class); + //cacheResourcesManager.getResource("http://bad"); + + //thrown.expect(CacheResourceDownloadedException.class); + assertNull(cacheResourcesManager.getResource("http://bad")); + + TimeUnit.SECONDS.sleep(10); + assertNull(cacheResourcesManager.getResource("http://bad")); + } catch (Exception IOException) { + fail(); + } + + + + } + } \ No newline at end of file