diff --git a/pom.xml b/pom.xml index 728f7fd..aa0e6c9 100644 --- a/pom.xml +++ b/pom.xml @@ -4,12 +4,16 @@ 4.0.0 com.asual.lesscss lesscss-servlet - 1.5.0-SNAPSHOT jar LESS Servlet + 1.3.4-SNAPSHOT A Servlet wrapper for LESS (http://lesscss.org). LESS extends CSS with: variables, mixins, operations and nested rules. http://www.asual.com/lesscss + + Ontotext AD + + The Apache Software License, Version 2.0 @@ -19,33 +23,21 @@ - http://github.com/asual/lesscss-servlet - scm:git:git://github.com:asual/lesscss-servlet.git - scm:git:git@github.com:asual/lesscss-servlet.git - HEAD + https://svn.ontotext.com/svn/forest/lesscss-servlet/trunk + scm:svn:https://svn.ontotext.com/svn/forest/lesscss-servlet/trunk + scm:svn:https://svn.ontotext.com/svn/forest/lesscss-servlet/trunk - - - Rostislav Hristov - rostislav@asual.com - - - - - Asual DZZD - - - com.asual.repositories.releases - Asual Releases Repository - http://www.asual.com/maven/content/repositories/releases + internal + Ontotext Internal Repository + http://maven.ontotext.com/archiva/repository/internal - com.asual.repositories.snapshots - Asual Snapshots Repository - http://www.asual.com/maven/content/repositories/snapshots + snapshots + Ontotext Snapshots Repository + http://maven.ontotext.com/archiva/repository/snapshots @@ -58,7 +50,7 @@ com.asual.lesscss lesscss-engine - 1.5.0-SNAPSHOT + 1.3.0 javax.servlet @@ -84,7 +76,7 @@ com.google.javascript closure-compiler - rr2079.1 + r1918 args4j @@ -124,10 +116,16 @@ 4.10 test + + org.eclipse.jetty + jetty-server + 8.1.2.v20120308 + test + org.eclipse.jetty test-jetty-servlet - 8.1.5.v20120716 + 8.1.2.v20120308 test @@ -148,7 +146,7 @@ org.apache.maven.plugins maven-compiler-plugin - 3.0 + 2.3.2 1.6 1.6 @@ -157,17 +155,12 @@ org.apache.maven.plugins maven-clean-plugin - 2.5 - - - org.apache.maven.plugins - maven-javadoc-plugin - 2.9 + 2.4.1 org.apache.maven.plugins maven-source-plugin - 2.2.1 + 2.1.2 true @@ -182,49 +175,35 @@ org.apache.maven.plugins maven-install-plugin - 2.4 - - - org.apache.maven.plugins - maven-deploy-plugin - 2.7 + 2.3.1 org.apache.maven.plugins maven-release-plugin - 2.4 + 2.2.2 + + + com.google.code.maven-scm-provider-svnjava + maven-scm-provider-svnjava + 2.0.5 + + + org.tmatesoft.svnkit + svnkit + 1.7.4-v1 + + + + + javasvn + + true + deploy + https://svn.ontotext.com/svn/forest/lesscss-servlet/tags + lesscss-servlet-@{project.version} + - - - release-sign-artifacts - - - performRelease - true - - - - - - org.apache.maven.plugins - maven-gpg-plugin - 1.4 - - - sign-artifacts - verify - - sign - - - - - - - - - diff --git a/src/main/java/com/asual/lesscss/LessResource.java b/src/main/java/com/asual/lesscss/LessResource.java index 2b891b6..c129a1a 100644 --- a/src/main/java/com/asual/lesscss/LessResource.java +++ b/src/main/java/com/asual/lesscss/LessResource.java @@ -20,6 +20,8 @@ import java.io.File; import java.io.IOException; import java.net.URL; +import java.util.regex.Matcher; +import java.util.regex.Pattern; import javax.servlet.ServletContext; @@ -27,42 +29,59 @@ * @author Rostislav Hristov */ public class LessResource extends StyleResource { - + private final Log logger = LogFactory.getLog(getClass()); private LessEngine engine; - - public LessResource(LessEngine engine, ServletContext servletContext, - String uri, String charset, boolean cache, boolean compress) - throws ResourceNotFoundException { + + public LessResource(LessEngine engine, ServletContext servletContext, String uri, String charset, boolean cache, boolean compress) throws ResourceNotFoundException { super(servletContext, uri, charset, cache, compress); this.engine = engine; } - + public byte[] getContent() throws LessException, IOException { - if (content == null || !cache) { + if (content == null || (!cache && lastModified < getLastModified())) { logger.debug("Not using cache."); if (engine != null) { logger.debug("LessEngine available, compiling."); - content = (resource instanceof URL ? engine - .compile((URL) resource) : engine - .compile((File) resource)).replaceAll("\\\\n", "\n") - .getBytes(charset); + content = (resource instanceof URL ? + engine.compile((URL) resource) : engine.compile((File) resource)) + .replaceAll("\\\\n", "\n").getBytes(charset); } else { logger.debug("LessEngine not available, treating as regular resource."); - content = resource instanceof URL ? ResourceUtils.readTextUrl( - (URL) resource, charset) : ResourceUtils.readTextFile( - (File) resource, charset); + content = resource instanceof URL ? ResourceUtils.readTextUrl((URL) resource, charset) : ResourceUtils.readTextFile((File) resource, charset); } - lastModified = super.getLastModified(); + lastModified = getLastModified(); if (compress) { logger.debug("Compressing resource."); compress(); } } else { - logger.debug("Using cache, since lastModified: " + lastModified - + " and getLastModified: " + getLastModified()); + logger.debug("Using cache, since lastModified: " + lastModified + " and getLastModified: " + getLastModified()); } return content; } + public long getLastModified() throws IOException { + if (lastModified == null || !cache) { + lastModified = super.getLastModified(); + String content = new String(resource instanceof URL ? ResourceUtils.readTextUrl((URL) resource, charset) : ResourceUtils.readTextFile((File) resource, charset)); + String folder = path.substring(0, path.lastIndexOf(System.getProperty("file.separator")) + 1); + Pattern p = Pattern.compile("@import\\s+(\"[^\"]*\"|'[^']*')"); + Matcher m = p.matcher(content); + while (m.find()) { + String path = folder + m.group(1).replaceAll("\"|'", ""); + File includedFile = new File(path); + if (!includedFile.exists()) { + includedFile = new File(path + ".less"); + } + long importLastModified = includedFile.lastModified(); + if (importLastModified > lastModified) { + lastModified = importLastModified; + } + } + } + logger.debug("getLastModified() in LessResource: " + lastModified); + return lastModified; + } + } \ No newline at end of file diff --git a/src/main/java/com/asual/lesscss/LessServlet.java b/src/main/java/com/asual/lesscss/LessServlet.java index 63f5a7a..06951be 100644 --- a/src/main/java/com/asual/lesscss/LessServlet.java +++ b/src/main/java/com/asual/lesscss/LessServlet.java @@ -28,9 +28,8 @@ public class LessServlet extends ResourceServlet { private final Log logger = LogFactory.getLog(getClass()); protected LessEngine engine; - protected boolean css; - protected String lineNumbers; - + protected boolean css = false; + public void init() { if (getServletConfig() != null) { if (getInitParameter("charset") != null) { @@ -45,9 +44,6 @@ public void init() { if (getInitParameter("css") != null) { css = Boolean.valueOf(getInitParameter("css")); } - if (getInitParameter("lineNumbers") != null) { - lineNumbers = getInitParameter("lineNumbers"); - } } try { initialContext = new javax.naming.InitialContext(); @@ -67,15 +63,10 @@ public void init() { if (getJndiParameter("/less/Css") != null) { css = (Boolean) getJndiParameter("/less/Css"); } - if (getJndiParameter("/less/LineNumbers") != null) { - lineNumbers = (String) getJndiParameter("/less/LineNumbers"); - } } LessOptions options = new LessOptions(); options.setCharset(charset); options.setCss(css); - options.setLineNumbers(lineNumbers); - options.setOptimization(cache ? 3 : 0); engine = new LessEngine(options); } @@ -84,8 +75,7 @@ protected Resource getResource(String uri) throws ResourceNotFoundException { if (!resources.containsKey(uri)) { logger.debug("Using new LessResource for uri " + uri); if ("text/css".equals(mimeType)) { - resources.put(uri, new LessResource(engine, - getServletContext(), uri, charset, cache, compress)); + resources.put(uri, new LessResource(engine, getServletContext(), uri, charset, cache, compress)); return resources.get(uri); } else { return super.getResource(uri); diff --git a/src/main/java/com/asual/lesscss/Resource.java b/src/main/java/com/asual/lesscss/Resource.java index 02f8ceb..8f5a52b 100644 --- a/src/main/java/com/asual/lesscss/Resource.java +++ b/src/main/java/com/asual/lesscss/Resource.java @@ -39,8 +39,7 @@ public class Resource { protected final Log logger = LogFactory.getLog(getClass()); - public Resource(ServletContext servletContext, String uri, String charset, - boolean cache) throws ResourceNotFoundException { + public Resource(ServletContext servletContext, String uri, String charset, boolean cache) throws ResourceNotFoundException { this.servletContext = servletContext; this.charset = charset; @@ -48,21 +47,19 @@ public Resource(ServletContext servletContext, String uri, String charset, URL url = getUrl(uri); File file = getFile(uri); - + if (url != null || (file != null && file.exists())) { path = url != null ? url.getPath() : file.getAbsolutePath(); resource = url != null ? url : file; } else { logger.error("Error processing " + uri + "."); - throw new ResourceNotFoundException("Error processing " + uri + "."); + throw new ResourceNotFoundException("Error processing " + uri + "."); } } - + public byte[] getContent() throws Exception { if (content == null || (!cache && lastModified < getLastModified())) { - content = resource instanceof URL ? ResourceUtils - .readBinaryUrl((URL) resource) : ResourceUtils - .readBinaryFile((File) resource); + content = resource instanceof URL ? ResourceUtils.readBinaryUrl((URL) resource) : ResourceUtils.readBinaryFile((File) resource); lastModified = getLastModified(); } return content; @@ -71,20 +68,18 @@ public byte[] getContent() throws Exception { public long getLastModified() throws IOException { if (lastModified == null || !cache) { if (resource instanceof URL) { - lastModified = ((URL) resource).openConnection() - .getLastModified(); - logger.debug("getLastModified(), URL resource: " + lastModified - + " - for resource: " + resource); - } else { + lastModified = ((URL) resource).openConnection().getLastModified(); + logger.debug("getLastModified(), URL resource: " + lastModified + " - for resource: " + resource); + } + else { lastModified = ((File) resource).lastModified(); - logger.debug("getLastModified(), File resource: " - + lastModified + " - for resource: " + resource); + logger.debug("getLastModified(), File resource: " + lastModified + " - for resource: " + resource); } } logger.debug("getLastModified(): " + lastModified); return lastModified; } - + protected URL getUrl(String path) { try { URL url = servletContext.getResource("/META-INF" + path); @@ -99,8 +94,7 @@ protected URL getUrl(String path) { if (url != null) { return url; } - url = getClass().getClassLoader().getResource( - "META-INF/resources" + path); + url = getClass().getClassLoader().getResource("META-INF/resources" + path); if (url != null) { return url; } @@ -108,7 +102,7 @@ protected URL getUrl(String path) { } return null; } - + protected File getFile(String path) { try { return new File(servletContext.getRealPath(path)); diff --git a/src/main/java/com/asual/lesscss/ResourceNotFoundException.java b/src/main/java/com/asual/lesscss/ResourceNotFoundException.java index cc484e4..349faba 100644 --- a/src/main/java/com/asual/lesscss/ResourceNotFoundException.java +++ b/src/main/java/com/asual/lesscss/ResourceNotFoundException.java @@ -20,13 +20,13 @@ * @author Rostislav Hristov */ public class ResourceNotFoundException extends IOException { - + private static final long serialVersionUID = 5718684064058983151L; public ResourceNotFoundException() { super(); } - + public ResourceNotFoundException(String message) { super(message); } diff --git a/src/main/java/com/asual/lesscss/ResourcePackage.java b/src/main/java/com/asual/lesscss/ResourcePackage.java index 03b2e7e..3b03d76 100644 --- a/src/main/java/com/asual/lesscss/ResourcePackage.java +++ b/src/main/java/com/asual/lesscss/ResourcePackage.java @@ -34,30 +34,29 @@ * @author Rostislav Hristov */ public class ResourcePackage { - + private final static Map cache = new ConcurrentHashMap(); private final static Log logger = LogFactory.getLog(ResourcePackage.class); - private final static List extensions = Arrays.asList("css", "less", - "js"); - + private final static List extensions = Arrays.asList("css", "less", "js"); + private static int NAME_FLAG = 1; private static int VERSION_FLAG = 2; private static int DEFLATE = 32; private static String ENCODING = "UTF-8"; private static String NEW_LINE = "\n"; - private static String SEPARATOR = "-"; - + private static char SEPARATOR = '-'; + private String[] resources; private String version; private String name; private String extension; - + public ResourcePackage(String[] resources) { this.resources = resources; } - + public static ResourcePackage fromString(String source) { - if (!StringUtils.isEmpty(source)) { + if (!StringUtils.isEmpty(source) && !source.equals("/")) { try { String key; String path = null; @@ -73,37 +72,53 @@ public static ResourcePackage fromString(String source) { if (extension != null && !extensions.contains(extension)) { return null; } - String[] parts = path.replaceFirst("^/", "").split(SEPARATOR); + int dashLastIdx = path.lastIndexOf(SEPARATOR); + String name = path; + String version = ""; + if(dashLastIdx > -1){ + name = path.substring(0, dashLastIdx).replaceFirst("^/", ""); + if(name.lastIndexOf(SEPARATOR) != -1){ + dashLastIdx = name.lastIndexOf(SEPARATOR); + version = name.substring(dashLastIdx+1); + name = name.substring(0, dashLastIdx); + } + else{ + version = path.substring(dashLastIdx+1); + } + } if (cache.containsValue(source)) { key = getKeyFromValue(cache, source); } else { - key = parts[parts.length - 1]; + key = name; byte[] bytes = null; try { bytes = Base64.decodeBase64(key.getBytes(ENCODING)); + logger.info("Inflating: "+source); bytes = inflate(bytes); } catch (Exception e) { + logger.debug(e.getMessage(), e); } key = new String(bytes, ENCODING); } String[] data = key.split(NEW_LINE); - ResourcePackage rp = new ResourcePackage( - (String[]) ArrayUtils.subarray(data, 1, data.length)); + ResourcePackage rp = new ResourcePackage((String[]) ArrayUtils.subarray(data, 1, data.length)); int mask = Integer.valueOf(data[0]); if ((mask & NAME_FLAG) != 0) { - rp.setName(parts[0]); + rp.setName(name); } if ((mask & VERSION_FLAG) != 0) { - rp.setVersion(parts[rp.getName() != null ? 1 : 0]); + rp.setVersion(rp.getName() != null ? version : name); } rp.setExtension(extension); return rp; } catch (Exception e) { + logger.debug(e.getMessage(), e); } } return null; } - + + @Override public String toString() { try { if (extension != null && !extensions.contains(extension)) { @@ -116,17 +131,14 @@ public String toString() { if (version != null) { mask = mask | VERSION_FLAG; } - String key = mask + NEW_LINE - + StringUtils.join(resources, NEW_LINE); + String key = mask + NEW_LINE + StringUtils.join(resources, NEW_LINE); if (!cache.containsKey(key)) { byte[] bytes = key.getBytes(ENCODING); StringBuilder sb = new StringBuilder(); sb.append("/"); sb.append(name == null ? "" : name + SEPARATOR); sb.append(version == null ? "" : version + SEPARATOR); - sb.append(Base64.encodeBase64URLSafeString( - bytes.length < DEFLATE ? bytes : deflate(bytes)) - .replaceAll("-", "+")); + sb.append(Base64.encodeBase64URLSafeString(bytes.length < DEFLATE ? bytes : deflate(bytes)).replaceAll("-", "+")); sb.append(extension == null ? "" : "." + extension); cache.put(key, sb.toString()); } @@ -152,7 +164,7 @@ public String getExtension() { public void setExtension(String extension) { this.extension = extension; } - + public String getVersion() { return version; } @@ -160,20 +172,20 @@ public String getVersion() { public void setVersion(String version) { this.version = version; } - + public String[] getResources() { return resources; } - - public static K getKeyFromValue(Map m, V value) { - for (K o : m.keySet()) { + + public static K getKeyFromValue(Map m, V value) { + for (K o : m.keySet()){ if (m.get(o).equals(value)) { return o; } } return null; } - + private static byte[] deflate(byte[] input) throws IOException { Deflater deflater = new Deflater(); deflater.setLevel(Deflater.BEST_COMPRESSION); @@ -188,9 +200,8 @@ private static byte[] deflate(byte[] input) throws IOException { baos.close(); return baos.toByteArray(); } - - private static byte[] inflate(byte[] output) throws DataFormatException, - IOException { + + private static byte[] inflate(byte[] output) throws DataFormatException, IOException { Inflater inflater = new Inflater(); inflater.setInput(output); ByteArrayOutputStream baos = new ByteArrayOutputStream(output.length); diff --git a/src/main/java/com/asual/lesscss/ResourceServlet.java b/src/main/java/com/asual/lesscss/ResourceServlet.java index 412e32c..2ff65db 100644 --- a/src/main/java/com/asual/lesscss/ResourceServlet.java +++ b/src/main/java/com/asual/lesscss/ResourceServlet.java @@ -58,19 +58,19 @@ public class ResourceServlet extends HttpServlet { mimeTypes.put("jpg", "image/jpeg"); mimeTypes.put("png", "image/png"); mimeTypes.put("svg", "image/svg+xml"); - + mimeTypes.put("oga", "audio/ogg"); mimeTypes.put("ogg", "audio/ogg"); mimeTypes.put("ogv", "video/ogg"); mimeTypes.put("mp4", "video/mp4"); mimeTypes.put("webm", "video/webm"); - + mimeTypes.put("ttf", "font/truetype"); mimeTypes.put("otf", "font/opentype"); mimeTypes.put("eot", "application/vnd.ms-fontobject"); mimeTypes.put("woff", "application/x-font-woff"); } - + public void init() { if (getServletConfig() != null) { if (getInitParameter("charset") != null) { @@ -100,7 +100,7 @@ public void init() { } } } - + protected Object getJndiParameter(String name) { try { return initialContext.lookup("java:comp/env" + name); @@ -113,44 +113,39 @@ protected Resource getResource(String uri) throws ResourceNotFoundException { String mimeType = getResourceMimeType(uri); if (!resources.containsKey(uri)) { if ("text/css".equals(mimeType)) { - resources.put(uri, new StyleResource(getServletContext(), uri, - charset, cache, compress)); + resources.put(uri, new StyleResource(getServletContext(), uri, charset, cache, compress)); } else if ("text/javascript".equals(mimeType)) { - resources.put(uri, new ScriptResource(getServletContext(), uri, - charset, cache, compress)); + resources.put(uri, new ScriptResource(getServletContext(), uri, charset, cache, compress)); } else { - resources.put(uri, new Resource(getServletContext(), uri, - charset, cache)); + resources.put(uri, new Resource(getServletContext(), uri, charset, cache)); } } return resources.get(uri); } - + protected byte[] getResourceContent(String uri) throws Exception { Resource resource = getResource(uri); return resource.getContent(); } - - protected long getResourceLastModified(String uri) throws IOException { + + protected long getResourceLastModified(String uri) throws IOException { Resource resource = getResource(uri); return resource.getLastModified(); } - + protected String getResourceMimeType(String uri) { String extension = uri.substring(uri.lastIndexOf(".") + 1); - String mimeType = mimeTypes.containsKey(extension) ? mimeTypes - .get(extension) : getServletContext().getMimeType(uri); + String mimeType = mimeTypes.containsKey(extension) ? mimeTypes.get(extension) : getServletContext().getMimeType(uri); return mimeType != null ? mimeType : "application/octet-stream"; } - - protected byte[] mergeContent(byte[] c1, byte[] c2) - throws UnsupportedEncodingException { + + protected byte[] mergeContent(byte[] c1, byte[] c2) throws UnsupportedEncodingException { byte[] line = "\n".getBytes(charset); int l1 = c1.length; int l2 = l1 != 0 ? line.length : 0; int l3 = c2.length; byte[] result = new byte[l1 + l2 + l3]; - + for (int i = 0; i < l1; i++) { result[i] = c1[i]; } @@ -163,57 +158,41 @@ protected byte[] mergeContent(byte[] c1, byte[] c2) return result; } - public void service(HttpServletRequest request, HttpServletResponse response) - throws ServletException { + public void service(HttpServletRequest request, HttpServletResponse response) throws ServletException { try { - ResourcePackage rp = ResourcePackage.fromString(request - .getPathInfo()); - String[] uri = (rp != null) ? rp.getResources() - : new String[] { (request.getContextPath() - + request.getServletPath() + (request.getPathInfo() == null ? "" - : request.getPathInfo())) }; + ResourcePackage rp = ResourcePackage.fromString(request.getPathInfo()); + String[] uri = (rp != null) ? rp.getResources() : new String[] {request.getRequestURI().replaceAll("/+", "/")}; String mimeType = getResourceMimeType(uri[0]); long lastModified = 0; byte[] content = new byte[0]; for (String resource : uri) { - resource = resource.replaceAll("^" + request.getContextPath(), - ""); + resource = resource.replaceAll("^" + request.getContextPath(), ""); try { - content = mergeContent(content, - getResourceContent(resource)); + content = mergeContent(content, getResourceContent(resource)); + lastModified = Math.max(lastModified, getResourceLastModified(resource)); } catch (IOException e) { logger.error("Cannot find " + resource + "."); - response.setStatus(HttpServletResponse.SC_NOT_FOUND); - return; } - lastModified = Math.max(lastModified, - getResourceLastModified(resource)); } long ifModifiedSince = request.getDateHeader("If-Modified-Since"); - if (ifModifiedSince != 0 - && ifModifiedSince / milliseconds == lastModified - / milliseconds) { - logger.debug("Return with SC_NOT_MODIFIED, since " - + ifModifiedSince + " == " + lastModified); - response.setHeader("Cache-control", "max-age=" + maxAge); + if (ifModifiedSince != 0 && ifModifiedSince/milliseconds == lastModified/milliseconds) { + logger.debug("Return with SC_NOT_MODIFIED, since " + ifModifiedSince + " == " + lastModified); response.setStatus(HttpServletResponse.SC_NOT_MODIFIED); return; } if (cache) { maxAge = 0; } - response.setContentType(mimeType - + (mimeType.startsWith("text/") ? ";charset=" + charset - : "")); + response.setContentType(mimeType + (mimeType.startsWith("text/") ? ";charset=" + charset : "")); response.setDateHeader("Last-Modified", lastModified); - response.setDateHeader("Expires", System.currentTimeMillis() - + maxAge * milliseconds); + response.setDateHeader("Expires", System.currentTimeMillis() + maxAge*milliseconds); response.setHeader("Cache-control", "max-age=" + maxAge); response.setContentLength(content.length); response.getOutputStream().write(content); response.getOutputStream().flush(); response.getOutputStream().close(); } catch (Exception e) { + logger.error(e.getMessage(), e); throw new ServletException(e.getMessage(), e); } } diff --git a/src/main/java/com/asual/lesscss/ResourceUtils.java b/src/main/java/com/asual/lesscss/ResourceUtils.java index a603bff..6b9cb48 100644 --- a/src/main/java/com/asual/lesscss/ResourceUtils.java +++ b/src/main/java/com/asual/lesscss/ResourceUtils.java @@ -32,11 +32,10 @@ * @author Rostislav Hristov */ public class ResourceUtils { - + private static final Log logger = LogFactory.getLog(ResourceUtils.class); - - public static byte[] readTextUrl(URL source, String encoding) - throws IOException { + + public static byte[] readTextUrl(URL source, String encoding) throws IOException { byte[] result; try { URLConnection urlc = source.openConnection(); @@ -60,9 +59,8 @@ public static byte[] readTextUrl(URL source, String encoding) } return result; } - - public static byte[] readTextFile(File source, String encoding) - throws IOException { + + public static byte[] readTextFile(File source, String encoding) throws IOException { byte[] result; try { StringBuffer sb = new StringBuffer(1024); @@ -85,7 +83,7 @@ public static byte[] readTextFile(File source, String encoding) } return result; } - + public static byte[] readBinaryUrl(URL source) throws IOException { byte[] result; try { @@ -109,7 +107,7 @@ public static byte[] readBinaryUrl(URL source) throws IOException { } return result; } - + public static byte[] readBinaryFile(File source) throws IOException { byte[] result; try { @@ -132,17 +130,17 @@ public static byte[] readBinaryFile(File source) throws IOException { } return result; } - + /** - * Generic unicode textreader, which will use BOM mark to identify the - * encoding to be used. If BOM is not found then use a given default or - * system encoding. + * Generic unicode textreader, which will use BOM mark + * to identify the encoding to be used. If BOM is not found + * then use a given default or system encoding. * * @author Thomas Weidenfeller * @author Aki Nieminen */ private static class UnicodeReader extends Reader { - + PushbackInputStream internalIn; InputStreamReader internalIn2 = null; String defaultEnc; @@ -150,57 +148,53 @@ private static class UnicodeReader extends Reader { private static final int BOM_SIZE = 4; /** - * @param in - * inputstream to be read - * @param defaultEnc - * default encoding if stream does not have BOM marker. Give - * NULL to use system-level default. + * @param in inputstream to be read + * @param defaultEnc default encoding if stream does not have + * BOM marker. Give NULL to use system-level default. */ public UnicodeReader(InputStream in, String defaultEnc) { internalIn = new PushbackInputStream(in, BOM_SIZE); this.defaultEnc = defaultEnc; } - + /** - * Get stream encoding or NULL if stream is uninitialized. Call init() - * or read() method to initialize it. + * Get stream encoding or NULL if stream is uninitialized. + * Call init() or read() method to initialize it. */ public String getEncoding() { - if (internalIn2 == null) - return null; + if (internalIn2 == null) return null; return internalIn2.getEncoding(); } /** - * Read-ahead four bytes and check for BOM marks. Extra bytes are unread - * back to the stream, only BOM bytes are skipped. + * Read-ahead four bytes and check for BOM marks. Extra bytes are + * unread back to the stream, only BOM bytes are skipped. */ protected void init() throws IOException { - - if (internalIn2 != null) - return; + + if (internalIn2 != null) return; String encoding; byte bom[] = new byte[BOM_SIZE]; int n, unread; n = internalIn.read(bom, 0, bom.length); - if ((bom[0] == (byte) 0x00) && (bom[1] == (byte) 0x00) - && (bom[2] == (byte) 0xFE) && (bom[3] == (byte) 0xFF)) { + if ( (bom[0] == (byte)0x00) && (bom[1] == (byte)0x00) && + (bom[2] == (byte)0xFE) && (bom[3] == (byte)0xFF) ) { encoding = "UTF-32BE"; unread = n - 4; - } else if ((bom[0] == (byte) 0xFF) && (bom[1] == (byte) 0xFE) - && (bom[2] == (byte) 0x00) && (bom[3] == (byte) 0x00)) { + } else if ( (bom[0] == (byte)0xFF) && (bom[1] == (byte)0xFE) && + (bom[2] == (byte)0x00) && (bom[3] == (byte)0x00) ) { encoding = "UTF-32LE"; unread = n - 4; - } else if ((bom[0] == (byte) 0xEF) && (bom[1] == (byte) 0xBB) - && (bom[2] == (byte) 0xBF)) { + } else if ( (bom[0] == (byte)0xEF) && (bom[1] == (byte)0xBB) && + (bom[2] == (byte)0xBF) ) { encoding = "UTF-8"; unread = n - 3; - } else if ((bom[0] == (byte) 0xFE) && (bom[1] == (byte) 0xFF)) { + } else if ( (bom[0] == (byte)0xFE) && (bom[1] == (byte)0xFF) ) { encoding = "UTF-16BE"; unread = n - 2; - } else if ((bom[0] == (byte) 0xFF) && (bom[1] == (byte) 0xFE)) { + } else if ( (bom[0] == (byte)0xFF) && (bom[1] == (byte)0xFE) ) { encoding = "UTF-16LE"; unread = n - 2; } else { @@ -209,8 +203,7 @@ protected void init() throws IOException { unread = n; } - if (unread > 0) - internalIn.unread(bom, (n - unread), unread); + if (unread > 0) internalIn.unread(bom, (n - unread), unread); // Use given encoding if (encoding == null) { @@ -230,5 +223,5 @@ public int read(char[] cbuf, int off, int len) throws IOException { return internalIn2.read(cbuf, off, len); } - } + } } \ No newline at end of file diff --git a/src/main/java/com/asual/lesscss/ScriptResource.java b/src/main/java/com/asual/lesscss/ScriptResource.java index a5114a6..71fe356 100644 --- a/src/main/java/com/asual/lesscss/ScriptResource.java +++ b/src/main/java/com/asual/lesscss/ScriptResource.java @@ -39,22 +39,17 @@ * @author Rostislav Hristov */ public class ScriptResource extends Resource { - + protected boolean compress; - public ScriptResource(ServletContext servletContext, String uri, - String charset, boolean cache, boolean compress) - throws ResourceNotFoundException { + public ScriptResource(ServletContext servletContext, String uri, String charset, boolean cache, boolean compress) throws ResourceNotFoundException { super(servletContext, uri, charset, cache); this.compress = compress; } public byte[] getContent() throws IOException { - if (content == null - || (content != null && !cache && lastModified < getLastModified())) { - content = resource instanceof URL ? ResourceUtils.readTextUrl( - (URL) resource, charset) : ResourceUtils.readTextFile( - (File) resource, charset); + if (content == null || (content != null && !cache && lastModified < getLastModified())) { + content = resource instanceof URL ? ResourceUtils.readTextUrl((URL) resource, charset) : ResourceUtils.readTextFile((File) resource, charset); lastModified = getLastModified(); if (compress) { compress(); @@ -62,23 +57,20 @@ public byte[] getContent() throws IOException { } return content; } - + private void compress() throws UnsupportedEncodingException, IOException { ByteArrayOutputStream baos = new ByteArrayOutputStream(); InputStream is = new ByteArrayInputStream(content); Writer out = new OutputStreamWriter(baos, charset); CompilerOptions options = new CompilerOptions(); - CompilationLevel.SIMPLE_OPTIMIZATIONS - .setOptionsForCompilationLevel(options); + CompilationLevel.SIMPLE_OPTIMIZATIONS.setOptionsForCompilationLevel(options); Compiler.setLoggingLevel(Level.OFF); Compiler compiler = new Compiler(); compiler.disableThreads(); - Result result = compiler.compile(new JSSourceFile[] {}, - new JSSourceFile[] { JSSourceFile.fromInputStream("is", is) }, - options); + Result result = compiler.compile(new JSSourceFile[] {}, + new JSSourceFile[] { JSSourceFile.fromInputStream("is", is) }, options); if (result.success) { - Pattern pattern = Pattern.compile("^/\\*.*?\\*/\\s?", - Pattern.DOTALL); + Pattern pattern = Pattern.compile("^/\\*.*?\\*/\\s?", Pattern.DOTALL); Matcher matcher = pattern.matcher(new String(content, charset)); while (matcher.find()) { out.write(matcher.group()); diff --git a/src/main/java/com/asual/lesscss/StyleResource.java b/src/main/java/com/asual/lesscss/StyleResource.java index c52cb26..8e626b7 100644 --- a/src/main/java/com/asual/lesscss/StyleResource.java +++ b/src/main/java/com/asual/lesscss/StyleResource.java @@ -32,19 +32,15 @@ public class StyleResource extends Resource { protected boolean compress; - - public StyleResource(ServletContext servletContext, String uri, - String charset, boolean cache, boolean compress) - throws ResourceNotFoundException { + + public StyleResource(ServletContext servletContext, String uri, String charset, boolean cache, boolean compress) throws ResourceNotFoundException { super(servletContext, uri, charset, cache); this.compress = compress; } public byte[] getContent(String path) throws IOException { if (content == null || (!cache && lastModified < getLastModified())) { - content = resource instanceof URL ? ResourceUtils.readTextUrl( - (URL) resource, charset) : ResourceUtils.readTextFile( - (File) resource, charset); + content = resource instanceof URL ? ResourceUtils.readTextUrl((URL) resource, charset) : ResourceUtils.readTextFile((File) resource, charset); lastModified = getLastModified(); if (compress) { compress(); @@ -52,25 +48,22 @@ public byte[] getContent(String path) throws IOException { } return content; } - + protected void compress() throws IOException { - URL cssmin = getClass().getClassLoader().getResource( - "META-INF/cssmin.js"); + URL cssmin = getClass().getClassLoader().getResource("META-INF/cssmin.js"); Context cx = Context.enter(); cx.setOptimizationLevel(9); Global global = new Global(); global.init(cx); Scriptable scope = cx.initStandardObjects(global); cx.evaluateString(scope, "var exports = {};", "exports", 1, null); - cx.evaluateReader(scope, new InputStreamReader(cssmin.openConnection() - .getInputStream()), cssmin.getFile(), 1, null); + cx.evaluateReader(scope, new InputStreamReader(cssmin.openConnection().getInputStream()), cssmin.getFile(), 1, null); Scriptable exports = (Scriptable) scope.get("exports", scope); Scriptable compressor = (Scriptable) exports.get("compressor", exports); Function fn = (Function) compressor.get("cssmin", compressor); - content = ((String) Context.call(null, fn, compressor, compressor, - new Object[] { new String(content, charset).replaceFirst( - "^/\\*", "/*!") })).getBytes(charset); + content = ((String) Context.call(null, fn, compressor, compressor, new Object[] { + new String(content, charset).replaceFirst("^/\\*", "/*!")})).getBytes(charset); Context.exit(); } - + } \ No newline at end of file diff --git a/src/test/java/com/asual/lesscss/LessServletTest.java b/src/test/java/com/asual/lesscss/LessServletTest.java index 5b3ee7c..46af748 100644 --- a/src/test/java/com/asual/lesscss/LessServletTest.java +++ b/src/test/java/com/asual/lesscss/LessServletTest.java @@ -27,20 +27,19 @@ /** * @author Rostislav Hristov */ -public class LessServletTest { +public class LessServletTest { private static ServletTester tester; - + @BeforeClass public static void before() throws Exception { tester = new ServletTester(); tester.setClassLoader(LessServletTest.class.getClassLoader()); tester.setContextPath("/"); - tester.addServlet(LessServlet.class, "*.css").setInitParameter("css", - "true"); + tester.addServlet(LessServlet.class, "*.css").setInitParameter("css", "true"); tester.start(); } - + @Test public void css() throws IOException, Exception { HttpTester request = new HttpTester(); @@ -52,10 +51,10 @@ public void css() throws IOException, Exception { response.parse(tester.getResponses(request.generate())); assertEquals("body{color:#f0f0f0}", response.getContent()); } - + @AfterClass public static void after() throws Exception { tester.stop(); } - + } \ No newline at end of file diff --git a/src/test/java/com/asual/lesscss/ResourcePackageTest.java b/src/test/java/com/asual/lesscss/ResourcePackageTest.java index 1190ee0..582a588 100644 --- a/src/test/java/com/asual/lesscss/ResourcePackageTest.java +++ b/src/test/java/com/asual/lesscss/ResourcePackageTest.java @@ -24,25 +24,22 @@ /** * @author Rostislav Hristov */ -public class ResourcePackageTest { - +public class ResourcePackageTest { + @Test public void css() throws IOException, Exception { - ResourcePackage rp = new ResourcePackage(new String[] { - "/css/test1.css", "/css/test2.css" }); + ResourcePackage rp = new ResourcePackage(new String[] {"/css/test1.css", "/css/test2.css"}); rp.setName("package"); rp.setVersion("1.0.0"); rp.setExtension("css"); - assertEquals( - "/package-1.0.0-MwovY3NzL3Rlc3QxLmNzcwovY3NzL3Rlc3QyLmNzcw.css", - rp.toString()); + assertEquals("/package-1.0.0-MwovY3NzL3Rlc3QxLmNzcwovY3NzL3Rlc3QyLmNzcw.css", rp.toString()); } - + @Test public void js() throws Exception { String name = "test"; - String[] resources = new String[] { "/js/test1.js", "/js/test2.js", - "/js/test3.js", "/js/test4.js", "/js/test5.js" }; + String[] resources = new String[] { + "/js/test1.js", "/js/test2.js", "/js/test3.js", "/js/test4.js", "/js/test5.js"}; String version = "1.0.0"; ResourcePackage rp = new ResourcePackage(resources); rp.setName(name); @@ -52,5 +49,29 @@ public void js() throws Exception { assertEquals(name, rp.getName()); assertArrayEquals(resources, rp.getResources()); assertEquals(version, rp.getVersion()); + /* + rp = new ResourcePackage(resources); + rp.setVersion(version); + rp.setExtension("js"); + rp = ResourcePackage.fromString(rp.toString()); + assertEquals(null, rp.getName()); + assertEquals(version, rp.getVersion()); + */ + } + + @Test + public void js2() { + String name = "jquery.caret-range"; + String version = "1.0"; + String[] resources = new String[] {"/js/jquery.caret-range-1.0.js" }; + + ResourcePackage rp = new ResourcePackage(resources); + rp.setName(name); + rp.setVersion(version); + rp.setExtension("js"); + rp = ResourcePackage.fromString(rp.toString()); + assertEquals(name, rp.getName()); + assertArrayEquals(resources, rp.getResources()); + assertEquals(version, rp.getVersion()); } } \ No newline at end of file diff --git a/src/test/java/com/asual/lesscss/ResourceServletTest.java b/src/test/java/com/asual/lesscss/ResourceServletTest.java index 8969811..2871260 100644 --- a/src/test/java/com/asual/lesscss/ResourceServletTest.java +++ b/src/test/java/com/asual/lesscss/ResourceServletTest.java @@ -25,20 +25,20 @@ /** * @author Rostislav Hristov */ -public class ResourceServletTest { +public class ResourceServletTest { private static ServletTester tester; - + @BeforeClass public static void before() throws Exception { tester = new ServletTester(); tester.setClassLoader(ResourceServletTest.class.getClassLoader()); tester.setContextPath("/"); - tester.addServlet(ResourceServlet.class, "/*").setInitParameter( - "compress", "true"); + tester.addServlet(ResourceServlet.class, "/*") + .setInitParameter("compress", "true"); tester.start(); } - + @Test public void img() throws Exception { HttpTester request = new HttpTester(); @@ -49,15 +49,12 @@ public void img() throws Exception { HttpTester response = new HttpTester(); response.parse(tester.getResponses(request.generate())); assertEquals("image/png", response.getContentType()); - assertEquals( - 13831, - response.getContent().getBytes(response.getCharacterEncoding()).length); + assertEquals(13831, response.getContent().getBytes(response.getCharacterEncoding()).length); } - + @Test public void js() throws Exception { - ResourcePackage rp = new ResourcePackage(new String[] { "/js/test1.js", - "/js/test2.js" }); + ResourcePackage rp = new ResourcePackage(new String[] {"/js/test1.js", "/js/test2.js"}); HttpTester request = new HttpTester(); request.setMethod("GET"); request.setHeader("Host", "tester"); @@ -74,15 +71,12 @@ public void js() throws Exception { sb.append(" * License and copyright 2\n"); sb.append(" */\n"); sb.append("var test2=2;"); - assertEquals( - sb.toString(), - response.getContent().replaceAll( - System.getProperty("line.separator"), "\n")); + assertEquals(sb.toString(), response.getContent().replaceAll(System.getProperty("line.separator"), "\n")); } - + @AfterClass public static void after() throws Exception { tester.stop(); } - + } \ No newline at end of file diff --git a/src/test/resources/META-INF/js/test-1.js b/src/test/resources/META-INF/js/test-1.js new file mode 100644 index 0000000..149a522 --- /dev/null +++ b/src/test/resources/META-INF/js/test-1.js @@ -0,0 +1,10 @@ +/* + * License and copyright 1 + */ + +var test1 = 1; +(function() { + var longName = 1; + longName = 2; + return longName; +})(); \ No newline at end of file