diff --git a/.gitignore b/.gitignore index ccc9fd9..416ded9 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,4 @@ -*.DS_Store \ No newline at end of file +*.DS_Store +/lib +/dist +/tmp \ No newline at end of file diff --git a/app/controllers/press/Press.java b/app/controllers/press/Press.java index dbfaf11..ac8415c 100644 --- a/app/controllers/press/Press.java +++ b/app/controllers/press/Press.java @@ -1,48 +1,47 @@ package controllers.press; -import java.io.ByteArrayInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.UnsupportedEncodingException; - import org.joda.time.DateTime; import org.joda.time.format.DateTimeFormat; import org.joda.time.format.DateTimeFormatter; - +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import play.exceptions.UnexpectedException; import play.mvc.Controller; -import press.CachingStrategy; -import press.PluginConfig; -import press.ScriptCompressedFileManager; -import press.ScriptCompressor; -import press.ScriptRequestHandler; -import press.StyleCompressedFileManager; -import press.StyleCompressor; -import press.StyleRequestHandler; +import play.db.jpa.NoTransaction; +import press.*; import press.io.CompressedFile; import press.io.FileIO; +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.UnsupportedEncodingException; + +@NoTransaction public class Press extends Controller { - public static final DateTimeFormatter httpDateTimeFormatter = DateTimeFormat + private static final DateTimeFormatter httpDateTimeFormatter = DateTimeFormat .forPattern("EEE, dd MMM yyyy HH:mm:ss 'GMT'"); + private static final Logger logger = LoggerFactory.getLogger(Press.class); + public static void getCompressedJS(String key) { key = FileIO.unescape(key); CompressedFile compressedFile = new ScriptCompressedFileManager().getCompressedFile(key); - renderCompressedFile(compressedFile, "JavaScript"); + renderCompressedFile(key, compressedFile, "JavaScript"); } public static void getCompressedCSS(String key) { key = FileIO.unescape(key); CompressedFile compressedFile = new StyleCompressedFileManager().getCompressedFile(key); - renderCompressedFile(compressedFile, "CSS"); + renderCompressedFile(key, compressedFile, "CSS"); } - private static void renderCompressedFile(CompressedFile compressedFile, String type) { + private static void renderCompressedFile(String key, CompressedFile compressedFile, String type) { flash.keep(); if (compressedFile == null) { - renderBadResponse(type); + renderBadResponse(key, type); + return; } InputStream inputStream = compressedFile.inputStream(); @@ -71,7 +70,7 @@ private static void renderCompressedFile(CompressedFile compressedFile, String t // part of the key, so if the file changes, the key in the html file // will be modified, and the browser will request a new version. Each // version can therefore be cached indefinitely. - if (PluginConfig.cache.equals(CachingStrategy.Change)) { + if (PluginConfig.cache == CachingStrategy.Change) { // Cache for a year response.setHeader("Cache-Control", "max-age=" + 31536000); response.setHeader("Expires", httpDateTimeFormatter.print(new DateTime().plusYears(1))); @@ -101,7 +100,7 @@ public static void clearCSSCache() { renderText("Cleared " + count + " CSS files from cache"); } - private static void renderBadResponse(String fileType) { + private static void renderBadResponse(String key, String fileType) { String response = "/*\n"; response += "The compressed " + fileType + " file could not be generated.\n"; response += "This can occur in two situations:\n"; @@ -113,6 +112,7 @@ private static void renderBadResponse(String fileType) { response += "2. There was an exception thrown while rendering the "; response += "page.\n"; response += "*/"; + logger.error("Bad response to " + key + " (" + fileType + "): " + response); renderBinaryResponse(response); } diff --git a/app/play.plugins b/app/play.plugins deleted file mode 100644 index 8c6a130..0000000 --- a/app/play.plugins +++ /dev/null @@ -1 +0,0 @@ -100:press.Plugin \ No newline at end of file diff --git a/app/press/PlayLessEngine.java b/app/press/PlayLessEngine.java deleted file mode 100644 index bb73b2c..0000000 --- a/app/press/PlayLessEngine.java +++ /dev/null @@ -1,184 +0,0 @@ -package press; - -import java.io.BufferedReader; -import java.io.File; -import java.io.FileNotFoundException; -import java.io.FileReader; -import java.io.IOException; -import java.util.Collections; -import java.util.HashSet; -import java.util.List; -import java.util.Set; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import org.apache.commons.io.IOUtils; -import org.mozilla.javascript.WrappedException; - -import play.Logger; -import play.cache.Cache; - -import com.asual.lesscss.LessEngine; -import com.asual.lesscss.LessException; - -/** - * Copied and modified from - * https://github.com/lunatech-labs/play-module-less/blob - * /master/src/play/modules/less/PlayLessEngine.java LessEngine wrapper for Play - */ -public class PlayLessEngine { - - LessEngine lessEngine; - static Pattern importPattern = Pattern.compile(".*@import\\s*\"(.*?)\".*"); - - PlayLessEngine() { - lessEngine = new LessEngine(); - } - - /** - * Get the CSS for this less file either from the cache, or compile it. - */ - public String get(File lessFile, boolean compress) { - String cacheKey = "less_" + lessFile.getPath() + latestModified(lessFile); - String css = cacheGet(cacheKey, String.class); - if (css == null) { - css = compile(lessFile, compress); - cacheSet(cacheKey, css); - } - return css; - } - - /** - * Returns the latest of the last modified dates of this file and all files - * it imports - */ - public static long latestModified(File lessFile) { - long lastModified = lessFile.lastModified(); - for (File imported : getAllImports(lessFile)) { - lastModified = Math.max(lastModified, imported.lastModified()); - } - return lastModified; - } - - /** - * Returns a set composed of the file itself, followed by all files that it - * imports, the files they import, etc - */ - public static Set getAllImports(File lessFile) { - Set imports = new HashSet(); - getAllImports(lessFile, imports); - return imports; - } - - protected static void getAllImports(File lessFile, Set imports) { - imports.add(lessFile); - for (File imported : getImportsFromCacheOrFile(lessFile)) { - if (!imports.contains(imported)) { - getAllImports(imported, imports); - } - } - } - - protected static Set getImportsFromCacheOrFile(File lessFile) { - String cacheKey = "less_imports_" + lessFile.getPath() + lessFile.lastModified(); - - Set files = null; - cacheGet(cacheKey, Set.class); - - if (files == null) { - try { - files = getImportsFromFile(lessFile); - cacheSet(cacheKey, files); - } catch (IOException e) { - Logger.error(e, "IOException trying to determine imports in LESS file"); - files = new HashSet(); - } - } - return files; - } - - protected static Set getImportsFromFile(File lessFile) throws IOException { - if (!lessFile.exists()) { - return Collections.emptySet(); - } - - BufferedReader r = new BufferedReader(new FileReader(lessFile)); - try { - Set files = new HashSet(); - String line; - while ((line = r.readLine()) != null) { - Matcher m = importPattern.matcher(line); - while (m.find()) { - File file = new File(lessFile.getParentFile(), m.group(1)); - if (!file.exists()) - file = new File(lessFile.getParentFile(), m.group(1) + ".less"); - files.add(file); - files.addAll(getImportsFromCacheOrFile(file)); - } - } - return files; - } finally { - IOUtils.closeQuietly(r); - } - } - - protected String compile(File lessFile, boolean compress) { - try { - String css = lessEngine.compile(lessFile, compress); - // There seems to be a bug whereby \n's are sometimes escaped - return css.replace("\\n", "\n"); - } catch (LessException e) { - return handleException(lessFile, e); - } - } - - public String handleException(File lessFile, LessException e) { - Logger.warn(e, "Less exception"); - - String filename = e.getFilename(); - List extractList = e.getExtract(); - String extract = null; - if (extractList != null) { - extract = extractList.toString(); - } - - // LessEngine reports the file as null when it's not an @imported file - if (filename == null) { - filename = lessFile.getName(); - } - - // Try to detect missing imports (flaky) - if (extract == null && e.getCause() instanceof WrappedException) { - WrappedException we = (WrappedException) e.getCause(); - if (we.getCause() instanceof FileNotFoundException) { - FileNotFoundException fnfe = (FileNotFoundException) we.getCause(); - extract = fnfe.getMessage(); - } - } - - return formatMessage(filename, e.getLine(), e.getColumn(), extract, e.getType()); - } - - public String formatMessage(String filename, int line, int column, String extract, - String errorType) { - return "body:before {display: block; color: #c00; white-space: pre; font-family: monospace; background: #FDD9E1; border-top: 1px solid pink; border-bottom: 1px solid pink; padding: 10px; content: \"[LESS ERROR] " - + String.format("%s:%s: %s (%s)", filename, line, extract, errorType) + "\"; }"; - } - - private static T cacheGet(String key, Class clazz) { - try { - return Cache.get(key, clazz); - } catch (NullPointerException e) { - Logger.info("LESS module: Cache not initialized yet. Request to regular action required to initialize cache in DEV mode."); - return null; - } - } - - private static void cacheSet(String key, Object value) { - try { - Cache.set(key, value); - } catch (NullPointerException e) { - Logger.info("LESS module: Cache not initialized yet. Request to regular action required to initialize cache in DEV mode."); - } - } -} \ No newline at end of file diff --git a/app/press/PressLogger.java b/app/press/PressLogger.java deleted file mode 100644 index 60b1182..0000000 --- a/app/press/PressLogger.java +++ /dev/null @@ -1,9 +0,0 @@ -package press; - -import play.Logger; - -public class PressLogger { - public static void trace(String message, Object... args) { - Logger.trace("Press: " + message, args); - } -} diff --git a/app/press/ScriptCompressor.java b/app/press/ScriptCompressor.java deleted file mode 100644 index b21dac4..0000000 --- a/app/press/ScriptCompressor.java +++ /dev/null @@ -1,81 +0,0 @@ -package press; - -import java.io.File; -import java.io.IOException; -import java.io.Reader; -import java.io.Writer; -import java.util.List; -import java.util.Map; - -import org.mozilla.javascript.ErrorReporter; -import org.mozilla.javascript.EvaluatorException; - -import play.Logger; -import play.vfs.VirtualFile; -import press.io.CompressedFile; -import press.io.FileIO; - -import com.yahoo.platform.yui.compressor.JavaScriptCompressor; - -public class ScriptCompressor extends Compressor { - public static final String EXTENSION = ".js"; - - public static int clearCache() { - return clearCache(PluginConfig.js.compressedDir, EXTENSION); - } - - static class PressErrorReporter implements ErrorReporter { - private static final String PREFIX = "[YUI Compressor] "; - private static final String FORMAT_STRING = "%s:%d (char %d) %s"; - String fileName; - - public PressErrorReporter(String fileName) { - this.fileName = fileName; - } - - public void warning(String message, String sourceName, int line, String lineSource, - int lineOffset) { - if (line < 0 || (line == 1 && lineOffset == 0)) { - Logger.warn(PREFIX + message); - } else { - Logger.warn(PREFIX + FORMAT_STRING, fileName, line, lineOffset, message); - } - } - - public void error(String message, String sourceName, int line, String lineSource, - int lineOffset) { - if (line < 0 || (line == 1 && lineOffset == 0)) { - Logger.error(PREFIX + message); - } else { - Logger.error(PREFIX + FORMAT_STRING, fileName, line, lineOffset, message); - } - } - - public EvaluatorException runtimeError(String message, String sourceName, int line, - String lineSource, int lineOffset) { - error(message, sourceName, line, lineSource, lineOffset); - return new EvaluatorException(message); - } - } - - @Override - public void compress(File sourceFile, Writer out, boolean compress) throws IOException { - if (!compress) { - FileIO.write(FileIO.getReader(sourceFile), out); - return; - } - - ErrorReporter errorReporter = new PressErrorReporter(sourceFile.getName()); - Reader in = FileIO.getReader(sourceFile); - JavaScriptCompressor compressor = new JavaScriptCompressor(in, errorReporter); - compressor.compress(out, PluginConfig.js.lineBreak, PluginConfig.js.munge, - PluginConfig.js.warn, PluginConfig.js.preserveAllSemiColons, - PluginConfig.js.preserveStringLiterals); - } - - @Override - public String getCompressedFileKey(List componentFiles) { - Map files = FileInfo.getFileLastModifieds(componentFiles); - return CacheManager.getCompressedFileKey(files, EXTENSION); - } -} diff --git a/app/views/tags/press/compressed-script.tag b/app/views/tags/press/compressed-script.html similarity index 88% rename from app/views/tags/press/compressed-script.tag rename to app/views/tags/press/compressed-script.html index 40dbb50..d1339ef 100644 --- a/app/views/tags/press/compressed-script.tag +++ b/app/views/tags/press/compressed-script.html @@ -12,4 +12,4 @@ * See the plugin documentation for more information. * }* -${ press.Plugin.compressedJSTag() } \ No newline at end of file +${ press.Plugin.compressedJSTag(_arg).raw() } \ No newline at end of file diff --git a/app/views/tags/press/compressed-stylesheet.tag b/app/views/tags/press/compressed-stylesheet.html similarity index 90% rename from app/views/tags/press/compressed-stylesheet.tag rename to app/views/tags/press/compressed-stylesheet.html index eca3a74..b7f7550 100644 --- a/app/views/tags/press/compressed-stylesheet.tag +++ b/app/views/tags/press/compressed-stylesheet.html @@ -16,4 +16,4 @@ * See the plugin documentation for more information. * }* -${ press.Plugin.compressedCSSTag() } \ No newline at end of file +${ press.Plugin.compressedCSSTag(_arg, _media).raw() } \ No newline at end of file diff --git a/app/views/tags/press/script.tag b/app/views/tags/press/script.html similarity index 96% rename from app/views/tags/press/script.tag rename to app/views/tags/press/script.html index 65b06a9..997b92c 100644 --- a/app/views/tags/press/script.tag +++ b/app/views/tags/press/script.html @@ -37,4 +37,4 @@ } }% -${ press.Plugin.addJS(_src, _compress) } \ No newline at end of file +${ press.Plugin.addJS(_src, _compress).raw() } \ No newline at end of file diff --git a/app/views/tags/press/single-script.tag b/app/views/tags/press/single-script.html similarity index 94% rename from app/views/tags/press/single-script.tag rename to app/views/tags/press/single-script.html index 2ea6baa..aae2297 100644 --- a/app/views/tags/press/single-script.tag +++ b/app/views/tags/press/single-script.html @@ -20,4 +20,4 @@ throw new play.exceptions.TagInternalException("src attribute cannot be empty for press.single-script tag"); } }% -${ press.Plugin.addSingleJS(_src) } \ No newline at end of file +${ press.Plugin.addSingleJS(_src).raw() } \ No newline at end of file diff --git a/app/views/tags/press/single-stylesheet.tag b/app/views/tags/press/single-stylesheet.html similarity index 75% rename from app/views/tags/press/single-stylesheet.tag rename to app/views/tags/press/single-stylesheet.html index e5647ce..67ab4e3 100644 --- a/app/views/tags/press/single-stylesheet.tag +++ b/app/views/tags/press/single-stylesheet.html @@ -5,10 +5,10 @@ * for easy debugging. * * eg: - * #{press.single-stylesheet "widget.css"} + * #{press.single-stylesheet "widget.css", media:'screen'} * * will output: - * + * * * See the plugin documentation for more information. * @@ -20,4 +20,4 @@ throw new play.exceptions.TagInternalException("src attribute cannot be empty for press.single-stylesheet tag"); } }% -${ press.Plugin.addSingleCSS(_src) } \ No newline at end of file +${ press.Plugin.addSingleCSS(_src, _media).raw() } \ No newline at end of file diff --git a/app/views/tags/press/stylesheet.tag b/app/views/tags/press/stylesheet.html similarity index 88% rename from app/views/tags/press/stylesheet.tag rename to app/views/tags/press/stylesheet.html index 3cd9f61..554a891 100644 --- a/app/views/tags/press/stylesheet.tag +++ b/app/views/tags/press/stylesheet.html @@ -12,8 +12,9 @@ * * eg: * #{press.stylesheet src: "widget.css"} - * #{press.stylesheet src: "ui.css"} + * #{press.stylesheet src: "ui.css", media:'screen'} * #{press.stylesheet src: "validation.css"} + * #{stylesheet 'print.css', media:'print'/} * #{press.stylesheet src: "path/*.css"} * #{press.stylesheet src: "path/**.css"} * @@ -36,4 +37,4 @@ } }% -${ press.Plugin.addCSS(_src, _compress) } \ No newline at end of file +${ press.Plugin.addCSS(_src, _compress, _media).raw() } \ No newline at end of file diff --git a/build.sh b/build.sh new file mode 100755 index 0000000..42cbf30 --- /dev/null +++ b/build.sh @@ -0,0 +1,15 @@ +#!/bin/bash +MODULE="press" +VERSION=`grep self conf/dependencies.yml | sed "s/.*$MODULE //"` +TARGET=/var/www/repo/play-$MODULE/$MODULE-$VERSION.zip + +rm -fr dist +play dependencies --sync || exit $? +play build-module || exit $? +zip --delete dist/*.zip "lib/mockito*" + +if [ -e $TARGET ]; then + echo "Not publishing, $MODULE-$VERSION already exists" +else + cp dist/*.zip $TARGET +fi diff --git a/build.xml b/build.xml index 00c081c..fb2e7a1 100644 --- a/build.xml +++ b/build.xml @@ -1,46 +1,86 @@ - - - - - - - - - - - - - - + + + + + + + + + + + + + + - + + + + + + + + + + + +
+ +
+
+
+
- - - - - - - - - - -
- -
-
-
- -
+ + + - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/commands.pyc b/commands.pyc index 13759ef..aaa8d63 100644 Binary files a/commands.pyc and b/commands.pyc differ diff --git a/conf/dependencies.yml b/conf/dependencies.yml new file mode 100644 index 0000000..19e00d0 --- /dev/null +++ b/conf/dependencies.yml @@ -0,0 +1,5 @@ +self: play -> press 3.3 + +require: + - play 1.3+ + - org.mockito -> mockito-all 1.10.19 diff --git a/jars/yuicompressor-2.4.8-stripped.jar b/jars/yuicompressor-2.4.8-stripped.jar new file mode 100644 index 0000000..293c8d7 Binary files /dev/null and b/jars/yuicompressor-2.4.8-stripped.jar differ diff --git a/lib/lesscss-engine-1.3.3.jar b/lib/lesscss-engine-1.3.3.jar deleted file mode 100644 index aa53f60..0000000 Binary files a/lib/lesscss-engine-1.3.3.jar and /dev/null differ diff --git a/lib/yuicompressor-2.4.7.jar b/lib/yuicompressor-2.4.7.jar deleted file mode 100644 index 3c9a408..0000000 Binary files a/lib/yuicompressor-2.4.7.jar and /dev/null differ diff --git a/play-press.iml b/play-press.iml new file mode 100644 index 0000000..5908a83 --- /dev/null +++ b/play-press.iml @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/play.plugins b/src/play.plugins new file mode 100644 index 0000000..2091e7d --- /dev/null +++ b/src/play.plugins @@ -0,0 +1 @@ +100:press.Plugin diff --git a/app/press/CacheManager.java b/src/press/CacheManager.java similarity index 95% rename from app/press/CacheManager.java rename to src/press/CacheManager.java index 1671f01..316331f 100644 --- a/app/press/CacheManager.java +++ b/src/press/CacheManager.java @@ -1,14 +1,11 @@ package press; -import java.io.File; -import java.util.List; -import java.util.Map; - import play.libs.Crypto; -import play.templates.JavaExtensions; import press.io.CompressedFile; import press.io.FileIO; +import java.util.Map; + public class CacheManager { public static boolean useCachedFile(CompressedFile file) { diff --git a/app/press/CachingStrategy.java b/src/press/CachingStrategy.java similarity index 100% rename from app/press/CachingStrategy.java rename to src/press/CachingStrategy.java index 941b861..a4e4e88 100644 --- a/app/press/CachingStrategy.java +++ b/src/press/CachingStrategy.java @@ -1,10 +1,10 @@ package press; +import play.templates.JavaExtensions; + import java.util.Arrays; import java.util.List; -import play.templates.JavaExtensions; - public enum CachingStrategy { Always, Never, Change; diff --git a/app/press/CompressedFileManager.java b/src/press/CompressedFileManager.java similarity index 90% rename from app/press/CompressedFileManager.java rename to src/press/CompressedFileManager.java index 7662b9f..b0a5fbb 100644 --- a/app/press/CompressedFileManager.java +++ b/src/press/CompressedFileManager.java @@ -1,16 +1,14 @@ package press; -import java.util.ArrayList; -import java.util.List; - -import play.vfs.VirtualFile; import press.io.CompressedFile; +import java.util.List; + public abstract class CompressedFileManager { private PressFileWriter pressFileWriter; private Compressor compressor; - public CompressedFileManager(Compressor compressor) { + protected CompressedFileManager(Compressor compressor) { this.compressor = compressor; this.pressFileWriter = new PressFileWriter(compressor); } @@ -46,5 +44,5 @@ public CompressedFile getCompressedFile(List componentFiles) { return pressFileWriter.writeCompressedFile(componentFiles, file); } - public abstract String getCompressedDir(); + abstract String getCompressedDir(); } diff --git a/app/press/Compressor.java b/src/press/Compressor.java similarity index 66% rename from app/press/Compressor.java rename to src/press/Compressor.java index e27ed68..09c0a63 100644 --- a/app/press/Compressor.java +++ b/src/press/Compressor.java @@ -1,23 +1,19 @@ package press; +import press.io.CompressedFile; + import java.io.File; import java.io.IOException; import java.io.Writer; import java.util.List; -import play.PlayPlugin; -import play.libs.Crypto; -import play.templates.JavaExtensions; -import press.io.CompressedFile; -import press.io.FileIO; - public abstract class Compressor { /** * A key unique for the list of component files and their last modified date */ - abstract public String getCompressedFileKey(List componentFiles); + public abstract String getCompressedFileKey(List componentFiles); - abstract public void compress(File file, Writer out, boolean compress) throws IOException; + public abstract void compress(File file, Writer out, boolean compress) throws IOException; protected static int clearCache(String compressedDir, String extension) { return CompressedFile.clearCache(compressedDir, extension); diff --git a/app/press/ConfigHelper.java b/src/press/ConfigHelper.java similarity index 85% rename from app/press/ConfigHelper.java rename to src/press/ConfigHelper.java index 7242ada..800cb1b 100644 --- a/app/press/ConfigHelper.java +++ b/src/press/ConfigHelper.java @@ -11,7 +11,7 @@ public static String getString(String configKey) { public static String getString(String configKey, String defaultValue) { String value = Play.configuration.getProperty(configKey); - if (value == null || value.length() == 0) { + if (value == null || value.isEmpty()) { return defaultValue; } @@ -24,11 +24,11 @@ public static Boolean getBoolean(String configKey) { public static Boolean getBoolean(String configKey, Boolean defaultValue) { String asStr = Play.configuration.getProperty(configKey); - if (asStr == null || asStr.length() == 0) { + if (asStr == null || asStr.isEmpty()) { return defaultValue; } - if (asStr.equals("true") || asStr.equals("false")) { + if ("true".equals(asStr) || "false".equals(asStr)) { return Boolean.parseBoolean(asStr); } @@ -41,7 +41,7 @@ public static Integer getInt(String configKey) { public static Integer getInt(String configKey, Integer defaultValue) { String asStr = Play.configuration.getProperty(configKey); - if (asStr == null || asStr.length() == 0) { + if (asStr == null || asStr.isEmpty()) { return defaultValue; } diff --git a/app/press/DuplicateFileException.java b/src/press/DuplicateFileException.java similarity index 100% rename from app/press/DuplicateFileException.java rename to src/press/DuplicateFileException.java diff --git a/app/press/FileInfo.java b/src/press/FileInfo.java similarity index 97% rename from app/press/FileInfo.java rename to src/press/FileInfo.java index 51690c9..46f26c8 100644 --- a/app/press/FileInfo.java +++ b/src/press/FileInfo.java @@ -1,15 +1,14 @@ package press; +import play.vfs.VirtualFile; + import java.io.File; import java.io.Serializable; import java.util.ArrayList; -import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Map; -import play.vfs.VirtualFile; - public class FileInfo implements Serializable { boolean compress; public File file; diff --git a/src/press/LessException.java b/src/press/LessException.java new file mode 100644 index 0000000..1831fd8 --- /dev/null +++ b/src/press/LessException.java @@ -0,0 +1,19 @@ +package press; + +public class LessException extends RuntimeException { + private final String filename; + + public LessException(String message, String filename) { + super(message); + this.filename = filename; + } + + public LessException(String message, Throwable cause, String filename) { + super(message, cause); + this.filename = filename; + } + + public String getFilename() { + return filename; + } +} diff --git a/src/press/NodeLessEngine.java b/src/press/NodeLessEngine.java new file mode 100644 index 0000000..ca31506 --- /dev/null +++ b/src/press/NodeLessEngine.java @@ -0,0 +1,62 @@ +package press; + +import org.apache.commons.io.IOUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import play.Play; +import play.vfs.VirtualFile; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; + +public class NodeLessEngine { + private static final Logger logger = LoggerFactory.getLogger(NodeLessEngine.class); + + public static boolean canBeUsed() { + try { + Process lessc = new ProcessBuilder("lessc", "-v").start(); + try (InputStream in = lessc.getInputStream()) { + String version = IOUtils.toString(in, "UTF-8"); + logger.info("Using " + version.trim()); + return true; + } + } + catch (IOException e) { + logger.info("No lessc in path, will work in precompiled mode only"); + return false; + } + } + + public String compile(File input, boolean compress) throws LessException { + try { + String shellPath = Play.configuration.getProperty("press.shell", "bash"); + String lesscPrefix = Play.configuration.getProperty("press.lessc.prefix", "lessc"); + String lesscSuffix = Play.configuration.getProperty("press.lessc.suffix", ""); + Process lessc = new ProcessBuilder(shellPath, "-o", "pipefail", "-c", lesscPrefix + " " + (compress ? "-x" : "") + " --no-color " + + "--include-path=" + joinPlayRoots() + " " + input.getPath() + lesscSuffix) + .directory(Play.applicationPath).redirectErrorStream(true).start(); + try (InputStream in = lessc.getInputStream()) { + String css = IOUtils.toString(in, "UTF-8"); + int exitCode = lessc.waitFor(); + if (exitCode != 0) { + throw new LessException("lessc exited with error code " + exitCode + ": " + css, input.getAbsolutePath()); + } + return css; + } + } + catch (IOException|InterruptedException e) { + throw new LessException("Failed to launch lessc for " + input, e, input.getAbsolutePath()); + } + } + + private String joinPlayRoots() { + StringBuilder roots = new StringBuilder(); + for (VirtualFile root : Play.roots) { + File dir = new File(root.getRealFile(), "public/stylesheets"); + if (dir.exists()) + roots.append(dir).append(':'); + } + return roots.toString(); + } +} diff --git a/src/press/PlayLessEngine.java b/src/press/PlayLessEngine.java new file mode 100644 index 0000000..9c4d369 --- /dev/null +++ b/src/press/PlayLessEngine.java @@ -0,0 +1,164 @@ +package press; + +import org.apache.commons.io.IOUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import play.Play; +import play.cache.Cache; +import play.vfs.VirtualFile; +import press.io.CompressedFile; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.io.Writer; +import java.util.Collections; +import java.util.HashSet; +import java.util.Set; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * Copied and modified from + * https://github.com/lunatech-labs/play-module-less/blob + * /master/src/play/modules/less/PlayLessEngine.java LessEngine wrapper for Play + */ +public class PlayLessEngine { + private static final Logger logger = LoggerFactory.getLogger(PlayLessEngine.class); + + private final NodeLessEngine lessEngine; + private static final Pattern importPattern = Pattern.compile("@import\\s*[\"'](.*?)[\"']"); + + public PlayLessEngine() { + if (!Play.usePrecompiled && !NodeLessEngine.canBeUsed()) throw new RuntimeException("Cannot use lessc, not installed?"); + lessEngine = new NodeLessEngine(); + } + + /** + * Get the CSS for this less file either from the cache, or compile it. + */ + public String get(File lessFile, boolean compress) { + File precompiled = new File(lessFile.getPath() + ".css"); + if (precompiled.exists()) { + logger.debug("Serving precompiled {}", precompiled); + return VirtualFile.open(precompiled).contentAsString(); + } + + String cacheKey = lessFile.getName() + "." + latestModified(lessFile); + CompressedFile cachedFile = CompressedFile.create(cacheKey, PluginConfig.css.compressedDir); + if (cachedFile.exists()) { + try (InputStream is = cachedFile.inputStream()) { + return IOUtils.toString(is, "UTF-8"); + } + catch (IOException e) { + throw new RuntimeException(e); + } + } + + logger.debug("Compiling {}", lessFile); + String css = compile(lessFile, compress); + try { + Writer out = cachedFile.startWrite(); + out.write(css); + return css; + } + catch (IOException e) { + throw new RuntimeException(e); + } + finally { + cachedFile.close(); + } + } + + /** + * Returns the latest of the last modified dates of this file and all files + * it imports + */ + public long latestModified(File lessFile) { + long lastModified = lessFile.lastModified(); + for (File imported : getAllImports(lessFile)) { + lastModified = Math.max(lastModified, imported.lastModified()); + } + return lastModified; + } + + /** + * Returns a set composed of the file itself, followed by all files that it + * imports, the files they import, etc + */ + public static Set getAllImports(File lessFile) { + Set imports = new HashSet<>(); + getAllImports(lessFile, imports); + return imports; + } + + protected static void getAllImports(File lessFile, Set imports) { + imports.add(lessFile); + for (File imported : getImportsFromCacheOrFile(VirtualFile.open(lessFile))) { + if (!imports.contains(imported)) { + getAllImports(imported, imports); + } + } + } + + @SuppressWarnings("unchecked") + protected static Set getImportsFromCacheOrFile(VirtualFile lessFile) { + String cacheKey = "less_imports_" + lessFile.getRealFile() + lessFile.lastModified(); + + Set files = Cache.get(cacheKey, Set.class); + if (files == null) { + try { + files = getImportsFromFile(lessFile); + Cache.set(cacheKey, files); + } + catch (IOException e) { + logger.error("IOException trying to determine imports in LESS file", e); + files = new HashSet<>(); + } + } + return files; + } + + protected static Set getImportsFromFile(VirtualFile lessFile) throws IOException { + if (!lessFile.exists()) { + return Collections.emptySet(); + } + + String content = lessFile.contentAsString(); + + Set files = new HashSet<>(); + String virtualParentPath = lessFile.relativePath().replaceFirst("^\\{.*?\\}", "").replaceFirst("/[^/]*$", ""); + Matcher m = importPattern.matcher(content); + while (m.find()) { + VirtualFile file = Play.getVirtualFile(virtualParentPath + "/" + m.group(1)); + if (file == null && !m.group(1).endsWith(".less")) + file = Play.getVirtualFile(virtualParentPath + "/" + m.group(1) + ".less"); + if (file != null) { + files.add(file.getRealFile()); + files.addAll(getImportsFromCacheOrFile(file)); + } + } + + return files; + } + + public String compile(File lessFile, boolean compress) { + try { + return lessEngine.compile(lessFile, compress); + } + catch (LessException e) { + logger.error("Less error in file {}: {}", lessFile.getAbsolutePath(), e.getMessage()); + if (Play.mode.isDev()) { + // Change the caller code so that it doesn't cache the broken CSS file + return formatLessError(e.getMessage()); + } + else + throw e; + } + } + + protected String formatLessError(String error) { + return "body:before {display: block; color: #c00; white-space: pre; font-family: monospace; background: #FDD9E1; border-top: 1px solid pink; border-bottom: 1px solid pink; padding: 10px; content: \"" + + ("[LESS ERROR]\n" + error).replace("\n", "\\00000a").replace("\"", "\\000022") + "\"; }"; + } +} diff --git a/app/press/Plugin.java b/src/press/Plugin.java similarity index 84% rename from app/press/Plugin.java rename to src/press/Plugin.java index 681826e..0189277 100644 --- a/app/press/Plugin.java +++ b/src/press/Plugin.java @@ -1,14 +1,14 @@ package press; -import java.lang.reflect.Method; - import play.PlayPlugin; import play.mvc.Http.Request; import play.mvc.Http.Response; import play.vfs.VirtualFile; +import java.lang.reflect.Method; + public class Plugin extends PlayPlugin { - static ThreadLocal rqManager = new ThreadLocal(); + static final ThreadLocal rqManager = new ThreadLocal<>(); static StaticAssetManager assetManager; @Override @@ -16,9 +16,6 @@ public void onApplicationStart() { // Read the config each time the application is restarted PluginConfig.readConfig(); - // Clear the asset cache - RequestManager.clearCache(); - // Recreate the asset manager assetManager = new StaticAssetManager(); } @@ -44,8 +41,8 @@ public static String addSingleJS(String fileName) { /** * Add a single CSS file to compression */ - public static String addSingleCSS(String fileName) { - return rqManager.get().addSingleFile(RequestManager.RQ_TYPE_STYLE, fileName); + public static String addSingleCSS(String fileName, String media) { + return rqManager.get().addSingleFile(RequestManager.RQ_TYPE_STYLE, fileName, media); } /** @@ -60,22 +57,22 @@ public static String addJS(String src, boolean packFile) { * Adds the given source file(s) to the CSS compressor, returning the file * signature to be output in HTML */ - public static String addCSS(String src, boolean packFile) { - return rqManager.get().addMultiFile(RequestManager.RQ_TYPE_STYLE, src, packFile); + public static String addCSS(String src, boolean packFile, String media) { + return rqManager.get().addMultiFile(RequestManager.RQ_TYPE_STYLE, src, packFile, media); } /** * Outputs the tag indicating where the compressed JS should be included. */ - public static String compressedJSTag() { - return rqManager.get().compressedTag(RequestManager.RQ_TYPE_SCRIPT); + public static String compressedJSTag(String key) { + return rqManager.get().compressedTag(RequestManager.RQ_TYPE_SCRIPT, key); } /** * Outputs the tag indicating where the compressed CSS should be included. */ - public static String compressedCSSTag() { - return rqManager.get().compressedTag(RequestManager.RQ_TYPE_STYLE); + public static String compressedCSSTag(String key, String media) { + return rqManager.get().compressedTag(RequestManager.RQ_TYPE_STYLE, key, media); } @Override diff --git a/app/press/PluginConfig.java b/src/press/PluginConfig.java similarity index 93% rename from app/press/PluginConfig.java rename to src/press/PluginConfig.java index 80c4967..890f7a6 100644 --- a/app/press/PluginConfig.java +++ b/src/press/PluginConfig.java @@ -1,7 +1,8 @@ package press; -import play.Play; -import play.Play.Mode; +import static play.Play.Mode.DEV; +import static play.Play.Mode.PROD; +import static play.Play.mode; public class PluginConfig { /** @@ -9,14 +10,14 @@ public class PluginConfig { */ public static class DefaultConfig { // Whether the plugin is enabled - public static final boolean enabled = (Play.mode == Mode.PROD); + public static final boolean enabled = mode == PROD; // The caching strategy public static final CachingStrategy cache = CachingStrategy.Change; // Whether the cache can be cleared through the web interface // Default is to be available in dev only - public static final boolean cacheClearEnabled = (Play.mode == Mode.DEV); + public static final boolean cacheClearEnabled = mode == DEV; // Whether to use the file system or memory to store compressed files public static final boolean inMemoryStorage = false; @@ -50,10 +51,10 @@ public static class DefaultConfig { public static class js { // The directory where source javascript files are read from - public static final String srcDir = "/public/javascripts/"; + public static final String srcDir = "public/javascripts/"; // The directory where compressed javascript files are written to - public static final String compressedDir = "/public/javascripts/press/"; + public static final String compressedDir = "tmp/press/javascripts/"; // Options for YUI JS compression public static final int lineBreak = -1; @@ -65,10 +66,10 @@ public static class js { public static class css { // The directory where source css files are read from - public static final String srcDir = "/public/stylesheets/"; + public static final String srcDir = "public/stylesheets/"; // The directory where compressed css files are written to - public static final String compressedDir = "/public/stylesheets/press/"; + public static final String compressedDir = "tmp/press/stylesheets/"; // Options for YUI CSS compression public static final int lineBreak = -1; @@ -185,10 +186,6 @@ private static void logConfig() { } public static String addTrailingSlash(String dir) { - if (dir.charAt(dir.length() - 1) != '/') { - return dir + '/'; - } - - return dir; + return dir.endsWith("/") ? dir : dir + '/'; } } diff --git a/app/press/PressException.java b/src/press/PressException.java similarity index 100% rename from app/press/PressException.java rename to src/press/PressException.java diff --git a/app/press/PressFileWriter.java b/src/press/PressFileWriter.java similarity index 78% rename from app/press/PressFileWriter.java rename to src/press/PressFileWriter.java index 31cbfc1..3d3134c 100644 --- a/app/press/PressFileWriter.java +++ b/src/press/PressFileWriter.java @@ -1,22 +1,13 @@ package press; -import java.io.BufferedReader; -import java.io.File; -import java.io.FileReader; -import java.io.IOException; -import java.io.InputStreamReader; -import java.io.Writer; -import java.util.ArrayList; -import java.util.List; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import play.Logger; import play.exceptions.UnexpectedException; -import play.vfs.VirtualFile; import press.io.CompressedFile; import press.io.FileIO; +import java.io.*; +import java.util.List; +import java.util.regex.Pattern; + public class PressFileWriter { static final String PRESS_SIGNATURE = "press-1.0"; static final String PATTERN_TEXT = "^/\\*" + PRESS_SIGNATURE + "\\*/$"; @@ -52,7 +43,7 @@ public CompressedFile writeCompressedFile(List componentFiles, Compres long timeAfter = System.currentTimeMillis(); PressLogger.trace("Time to compress files for '%s': %d milli-seconds", - FileIO.getFileNameFromPath(file.name()), (timeAfter - timeStart)); + FileIO.getFileNameFromPath(file.name()), timeAfter - timeStart); } catch (Exception e) { throw new UnexpectedException(e); } finally { @@ -82,14 +73,11 @@ public static boolean hasPressHeader(File file) { if (!file.exists()) { return false; } - BufferedReader reader = new BufferedReader(new FileReader(file)); - String firstLine = reader.readLine(); - reader.close(); - Matcher matcher = HEADER_PATTERN.matcher(firstLine); - if (matcher.matches()) { - return true; + try (FileReader in = new FileReader(file)) { + try (BufferedReader reader = new BufferedReader(in)) { + return HEADER_PATTERN.matcher(reader.readLine()).matches(); } - return false; + } } catch (IOException e) { return false; } diff --git a/src/press/PressLogger.java b/src/press/PressLogger.java new file mode 100644 index 0000000..0cc8e24 --- /dev/null +++ b/src/press/PressLogger.java @@ -0,0 +1,11 @@ +package press; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class PressLogger { + private static final Logger logger = LoggerFactory.getLogger(PressLogger.class); + public static void trace(String message, Object... args) { + logger.trace(message, args); + } +} diff --git a/app/press/RequestHandler.java b/src/press/RequestHandler.java similarity index 67% rename from app/press/RequestHandler.java rename to src/press/RequestHandler.java index ce5fe0b..7d6a4e4 100644 --- a/app/press/RequestHandler.java +++ b/src/press/RequestHandler.java @@ -1,24 +1,26 @@ package press; -import java.util.HashMap; -import java.util.Map; - import play.mvc.Router; import play.vfs.VirtualFile; import press.io.FileIO; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + public abstract class RequestHandler { - Map files = new HashMap(); + private final Set files = new HashSet<>(); - abstract String getTag(String src); + abstract String getTag(String src, String... args); - abstract protected SourceFileManager getSourceManager(); + abstract SourceFileManager getSourceManager(); - abstract protected CompressedFileManager getCompressedFileManager(); + abstract CompressedFileManager getCompressedFileManager(); - abstract public String getCompressedUrl(String requestKey); + abstract String getCompressedUrl(String requestKey); - abstract public String getSingleFileCompressionKey(String fileName); + abstract String getSingleFileCompressionKey(String fileName); protected String getSingleFileCompressionKey(String fileName, SourceFileManager tmpManager) { PressLogger.trace("Request to compress single file %s", fileName); @@ -33,8 +35,8 @@ public VirtualFile checkFileExists(String fileName) { return getSourceManager().checkFileExists(fileName); } - public String add(String fileName, boolean packFile) { - return getSourceManager().add(fileName, packFile); + public void add(String fileName, boolean packFile) { + getSourceManager().add(fileName, packFile); } public void saveFileList() { @@ -46,14 +48,13 @@ public String closeRequest() { } protected void checkForDuplicates(String fileName) { - if (!files.containsKey(fileName)) { - files.put(fileName, true); + if (!files.contains(fileName)) { + files.add(fileName); return; } SourceFileManager srcManager = getSourceManager(); - throw new DuplicateFileException(srcManager.getFileType(), fileName, - srcManager.getTagName()); + throw new DuplicateFileException(srcManager.getFileType(), fileName, srcManager.getTagName()); } protected static String getCompressedUrl(String action, String requestKey) { diff --git a/app/press/RequestManager.java b/src/press/RequestManager.java similarity index 77% rename from app/press/RequestManager.java rename to src/press/RequestManager.java index f257b65..9970761 100644 --- a/app/press/RequestManager.java +++ b/src/press/RequestManager.java @@ -19,7 +19,7 @@ private RequestHandler getRequestHandler(boolean rqType) { return rqType == RQ_TYPE_SCRIPT ? scriptRequestHandler : styleRequestHandler; } - public String addSingleFile(boolean rqType, String fileName) { + public String addSingleFile(boolean rqType, String fileName, String ... args) { RequestHandler handler = getRequestHandler(rqType); VirtualFile file = handler.checkFileExists(fileName); @@ -30,10 +30,10 @@ public String addSingleFile(boolean rqType, String fileName) { src = Router.reverse(file); } - return handler.getTag(src); + return handler.getTag(src, args); } - public String addMultiFile(boolean rqType, String src, boolean packFile) { + public String addMultiFile(boolean rqType, String src, boolean packFile, String ... args) { RequestHandler handler = getRequestHandler(rqType); String baseUrl = handler.getSrcDir(); String result = ""; @@ -42,20 +42,25 @@ public String addMultiFile(boolean rqType, String src, boolean packFile) { handler.checkForDuplicates(fileName); if (performCompression()) { - result += handler.add(fileName, packFile) + "\n"; + handler.add(fileName, packFile); } else { - result += handler.getTag(Router.reverse(file)); + result += handler.getTag(Router.reverse(file), args); } } return result; } - public String compressedTag(boolean rqType) { + public String compressedTag(boolean rqType, String key, String ... args) { RequestHandler handler = getRequestHandler(rqType); if (performCompression()) { - String requestKey = handler.closeRequest(); - return handler.getTag(handler.getCompressedUrl(requestKey)); + String requestKey; + if (key != null) { + handler.getSourceManager().requestKey = key; + requestKey = key; + } + else requestKey = handler.closeRequest(); + return handler.getTag(handler.getCompressedUrl(requestKey), args); } return ""; } diff --git a/app/press/ScriptCompressedFileManager.java b/src/press/ScriptCompressedFileManager.java similarity index 82% rename from app/press/ScriptCompressedFileManager.java rename to src/press/ScriptCompressedFileManager.java index 3c3dafa..879c17d 100644 --- a/app/press/ScriptCompressedFileManager.java +++ b/src/press/ScriptCompressedFileManager.java @@ -5,7 +5,7 @@ public ScriptCompressedFileManager() { super(new ScriptCompressor()); } - public String getCompressedDir() { + @Override public String getCompressedDir() { return PluginConfig.js.compressedDir; } } diff --git a/src/press/ScriptCompressor.java b/src/press/ScriptCompressor.java new file mode 100644 index 0000000..18149ef --- /dev/null +++ b/src/press/ScriptCompressor.java @@ -0,0 +1,28 @@ +package press; + +import press.io.FileIO; + +import java.io.File; +import java.io.IOException; +import java.io.Writer; +import java.util.List; +import java.util.Map; + +public class ScriptCompressor extends Compressor { + public static final String EXTENSION = ".js"; + + public static int clearCache() { + return clearCache(PluginConfig.js.compressedDir, EXTENSION); + } + + @Override + public void compress(File sourceFile, Writer out, boolean compress) throws IOException { + FileIO.write(FileIO.getReader(sourceFile), out); + } + + @Override + public String getCompressedFileKey(List componentFiles) { + Map files = FileInfo.getFileLastModifieds(componentFiles); + return CacheManager.getCompressedFileKey(files, EXTENSION); + } +} diff --git a/app/press/ScriptRequestHandler.java b/src/press/ScriptRequestHandler.java similarity index 88% rename from app/press/ScriptRequestHandler.java rename to src/press/ScriptRequestHandler.java index 2023505..a320931 100644 --- a/app/press/ScriptRequestHandler.java +++ b/src/press/ScriptRequestHandler.java @@ -10,8 +10,8 @@ public String getCompressedUrl(String requestKey) { } @Override - public String getTag(String src) { - return "\n"; } diff --git a/app/press/ScriptSourceFileManager.java b/src/press/ScriptSourceFileManager.java similarity index 63% rename from app/press/ScriptSourceFileManager.java rename to src/press/ScriptSourceFileManager.java index cd9e1bd..6d893d8 100644 --- a/app/press/ScriptSourceFileManager.java +++ b/src/press/ScriptSourceFileManager.java @@ -2,7 +2,6 @@ public class ScriptSourceFileManager extends SourceFileManager { public ScriptSourceFileManager() { - super("JavaScript", ScriptCompressor.EXTENSION, "#{press.script}", - "#{press.compressed-script}", "", PluginConfig.js.srcDir); + super("JavaScript", ScriptCompressor.EXTENSION, "#{press.script}", "#{press.compressed-script}", PluginConfig.js.srcDir); } } diff --git a/app/press/SourceFileManager.java b/src/press/SourceFileManager.java similarity index 52% rename from app/press/SourceFileManager.java rename to src/press/SourceFileManager.java index f20910e..4401cb1 100644 --- a/app/press/SourceFileManager.java +++ b/src/press/SourceFileManager.java @@ -1,23 +1,15 @@ package press; -import java.io.UnsupportedEncodingException; -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; - import play.PlayPlugin; import play.cache.Cache; -import play.exceptions.UnexpectedException; import play.libs.Crypto; -import play.mvc.Http.Request; -import play.mvc.Http.Response; import play.templates.JavaExtensions; import play.vfs.VirtualFile; import press.io.FileIO; +import java.util.*; +import java.util.Map.Entry; + public abstract class SourceFileManager extends PlayPlugin { // File type, eg "JavaScript" @@ -32,36 +24,19 @@ public abstract class SourceFileManager extends PlayPlugin { // Compressed file tag name, eg "#{press.compressed-script}" String compressedTagName; - // Signatures for the start and end of a request to compress a file, - // eg "" would result in a compress request like: - // - String pressRequestStart; - String pressRequestEnd; - - // Directory where the source files are read from, eg "/public/javascripts" + // Directory where the source files are read from, eg "public/javascripts" String srcDir; // The key used to identify this request String requestKey = null; - // Keep track of the response object created when rendering started. It - // can change if there's a 404 or 500 error. - Response currentResponse; - // The list of files compressed as part of this request Map fileInfos; - public SourceFileManager(String fileType, String extension, String tagName, - String compressedTagName, String pressRequestStart, String pressRequestEnd, - String srcDir) { - - this.fileInfos = new HashMap(); - this.currentResponse = Response.current(); - + protected SourceFileManager(String fileType, String extension, String tagName, String compressedTagName, String srcDir) { + this.fileInfos = new LinkedHashMap<>(); this.fileType = fileType; this.extension = extension; - this.pressRequestStart = pressRequestStart; - this.pressRequestEnd = pressRequestEnd; this.tagName = tagName; this.compressedTagName = compressedTagName; this.srcDir = PluginConfig.addTrailingSlash(srcDir); @@ -77,10 +52,8 @@ public String getFileType() { /** * Adds a file to the list of files to be compressed - * - * @return the file request signature to be output in the HTML */ - public String add(String fileName, boolean compress) { + public void add(String fileName, boolean compress) { if (compress) { PressLogger.trace("Adding %s to output", fileName); } else { @@ -93,8 +66,6 @@ public String add(String fileName, boolean compress) { // Add the file to the list of files to be compressed fileInfos.put(fileName, new FileInfo(compress, checkFileExists(fileName))); - - return getFileRequestSignature(fileName); } /** @@ -126,7 +97,7 @@ public String getRequestKey(Map fileInfoMap) { key += entry.getKey(); // If we use the 'Change' caching strategy, make the modified // timestamp of each file part of the key. - if (PluginConfig.cache.equals(CachingStrategy.Change)) { + if (PluginConfig.cache == CachingStrategy.Change) { key += entry.getValue().getLastModified(); } } @@ -144,7 +115,7 @@ public void saveFileList() { // If the file list is not empty, then there have been files added // to compression but they will not be output. So throw an // exception telling the user he needs to add some files. - if (fileInfos.size() > 0) { + if (!fileInfos.isEmpty()) { String msg = fileInfos.size() + " files added to compression with "; msg += tagName + " tag but no " + compressedTagName + " tag was found. "; msg += "You must include a " + compressedTagName + " tag in the template "; @@ -157,60 +128,15 @@ public void saveFileList() { return; } - // The press tag may not always have been executed by the template - // engine in the same order that the resulting