diff options
author | Leif Åstrand <leif@vaadin.com> | 2014-11-15 18:24:17 +0200 |
---|---|---|
committer | Vaadin Code Review <review@vaadin.com> | 2015-01-09 12:43:17 +0000 |
commit | 07e00fe8e09a224be2631df2e1ae2b8cbb46d466 (patch) | |
tree | 589780fa20039daab44c4e0a10aa4d3db80feaa5 /server | |
parent | 441472f311ef9f38af233705d2480766c50e51d1 (diff) | |
download | vaadin-framework-07e00fe8e09a224be2631df2e1ae2b8cbb46d466.tar.gz vaadin-framework-07e00fe8e09a224be2631df2e1ae2b8cbb46d466.zip |
Persist scss cache (#15228)
Change-Id: I29bf746c3100df15bb04cc03b28ae64db4c5f987
Diffstat (limited to 'server')
-rw-r--r-- | server/src/com/vaadin/server/VaadinServlet.java | 124 |
1 files changed, 120 insertions, 4 deletions
diff --git a/server/src/com/vaadin/server/VaadinServlet.java b/server/src/com/vaadin/server/VaadinServlet.java index d1242676da..aa76dc8e08 100644 --- a/server/src/com/vaadin/server/VaadinServlet.java +++ b/server/src/com/vaadin/server/VaadinServlet.java @@ -28,6 +28,7 @@ import java.lang.reflect.Method; import java.net.MalformedURLException; import java.net.URL; import java.net.URLConnection; +import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Enumeration; @@ -45,14 +46,21 @@ import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import com.google.gwt.thirdparty.guava.common.base.Charsets; +import com.google.gwt.thirdparty.guava.common.io.Files; import com.vaadin.annotations.VaadinServletConfiguration; import com.vaadin.annotations.VaadinServletConfiguration.InitParameterName; import com.vaadin.sass.internal.ScssStylesheet; import com.vaadin.server.communication.ServletUIInitHandler; import com.vaadin.shared.JsonConstants; +import com.vaadin.shared.Version; import com.vaadin.ui.UI; import com.vaadin.util.CurrentInstance; +import elemental.json.Json; +import elemental.json.JsonArray; +import elemental.json.JsonObject; + @SuppressWarnings("serial") public class VaadinServlet extends HttpServlet implements Constants { @@ -61,14 +69,47 @@ public class VaadinServlet extends HttpServlet implements Constants { private final String css; private final List<String> sourceUris; private final long timestamp; + private final String scssFileName; - public ScssCacheEntry(String css, List<String> sourceUris) { + public ScssCacheEntry(String scssFileName, String css, + List<String> sourceUris) { + this.scssFileName = scssFileName; this.css = css; this.sourceUris = sourceUris; timestamp = getLastModified(); } + public ScssCacheEntry(JsonObject json) { + css = json.getString("css"); + timestamp = Long.parseLong(json.getString("timestamp")); + + sourceUris = new ArrayList<String>(); + + JsonArray uris = json.getArray("uris"); + for (int i = 0; i < uris.length(); i++) { + sourceUris.add(uris.getString(i)); + } + + // Not set for cache entries read from disk + scssFileName = null; + } + + public String asJson() { + JsonArray uris = Json.createArray(); + for (String uri : sourceUris) { + uris.set(uris.length(), uri); + } + + JsonObject object = Json.createObject(); + object.put("version", Version.getFullVersion()); + object.put("timestamp", Long.toString(timestamp)); + object.put("uris", uris); + object.put("css", css); + + return object.toJson(); + } + public String getCss() { return css; } @@ -117,6 +158,10 @@ public class VaadinServlet extends HttpServlet implements Constants { } } + public String getScssFileName() { + return scssFileName; + } + } private VaadinServletService servletService; @@ -612,7 +657,14 @@ public class VaadinServlet extends HttpServlet implements Constants { * Global cache of scss compilation results. This map is protected from * concurrent access by {@link #SCSS_MUTEX}. */ - private static final Map<String, ScssCacheEntry> scssCache = new HashMap<String, ScssCacheEntry>(); + private final Map<String, ScssCacheEntry> scssCache = new HashMap<String, ScssCacheEntry>(); + + /** + * Keeps track of whether a warning about not being able to persist cache + * files has already been printed. The flag is protected from concurrent + * access by {@link #SCSS_MUTEX}. + */ + private static boolean scssCompileWarWarningEmitted = false; /** * Returns the default theme. Must never return null. @@ -900,10 +952,20 @@ public class VaadinServlet extends HttpServlet implements Constants { synchronized (SCSS_MUTEX) { ScssCacheEntry cacheEntry = scssCache.get(scssFilename); + if (cacheEntry == null) { + try { + cacheEntry = loadPersistedScssCache(scssFilename, sc); + } catch (Exception e) { + getLogger().log(Level.WARNING, + "Could not read persisted scss cache", e); + } + } + if (cacheEntry == null || !cacheEntry.isStillValid()) { cacheEntry = compileScssOnTheFly(filename, scssFilename, sc); - scssCache.put(scssFilename, cacheEntry); + persistCacheEntry(cacheEntry); } + scssCache.put(scssFilename, cacheEntry); if (cacheEntry == null) { // compilation did not produce any result, but logged a message @@ -920,6 +982,29 @@ public class VaadinServlet extends HttpServlet implements Constants { } } + private ScssCacheEntry loadPersistedScssCache(String scssFilename, + ServletContext sc) throws IOException { + String realFilename = sc.getRealPath(scssFilename); + + File scssCacheFile = getScssCacheFile(new File(realFilename)); + if (!scssCacheFile.exists()) { + return null; + } + + String jsonString = Files.toString(scssCacheFile, Charsets.UTF_8); + + JsonObject entryJson = Json.parse(jsonString); + + String cacheVersion = entryJson.getString("version"); + if (!Version.getFullVersion().equals(cacheVersion)) { + // Compiled for some other Vaadin version, discard cache + scssCacheFile.delete(); + return null; + } + + return new ScssCacheEntry(entryJson); + } + private ScssCacheEntry compileScssOnTheFly(String filename, String scssFilename, ServletContext sc) throws IOException { String realFilename = sc.getRealPath(scssFilename); @@ -951,7 +1036,8 @@ public class VaadinServlet extends HttpServlet implements Constants { return null; } - return new ScssCacheEntry(scss.printState(), scss.getSourceUris()); + return new ScssCacheEntry(realFilename, scss.printState(), + scss.getSourceUris()); } /** @@ -1196,6 +1282,36 @@ public class VaadinServlet extends HttpServlet implements Constants { getService().destroy(); } + private static void persistCacheEntry(ScssCacheEntry cacheEntry) { + String scssFileName = cacheEntry.getScssFileName(); + if (scssFileName == null) { + if (!scssCompileWarWarningEmitted) { + getLogger() + .warning( + "Could not persist scss cache because no real file was found for the compiled scss file. " + + "This might happen e.g. if serving the scss file directly from a .war file."); + scssCompileWarWarningEmitted = true; + } + return; + } + + File scssFile = new File(scssFileName); + File cacheFile = getScssCacheFile(scssFile); + + String cacheEntryJsonString = cacheEntry.asJson(); + + try { + Files.write(cacheEntryJsonString, cacheFile, Charsets.UTF_8); + } catch (IOException e) { + getLogger().log(Level.WARNING, + "Error persisting scss cache " + cacheFile, e); + } + } + + private static File getScssCacheFile(File scssFile) { + return new File(scssFile.getParentFile(), scssFile.getName() + ".cache"); + } + /** * Escapes characters to html entities. An exception is made for some * "safe characters" to keep the text somewhat readable. |