![JAR search and dependency download from the Maven repository](/logo.png)
com.github.houbie.lesscss.builder.CompilationTask Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of lesscss Show documentation
Show all versions of lesscss Show documentation
Lesscss is a java wrapper for the JavaScript LESS to CSS compiler
/*
* Copyright (c) 2013 Houbrechts IT
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.github.houbie.lesscss.builder;
import com.github.houbie.lesscss.LessCompiler;
import com.github.houbie.lesscss.LessCompilerImpl;
import com.github.houbie.lesscss.LessParseException;
import com.github.houbie.lesscss.engine.LessCompilationEngine;
import com.github.houbie.lesscss.utils.IOUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.*;
import java.util.*;
import static com.github.houbie.lesscss.LessCompiler.CompilationDetails;
/**
* A CompilationTask can be used to lazy compile one or more LESS files that are set with @see setCompilationUnits
* The compilation will only be executed if one of the (imported) sources is newer than the resulting CSS.
* A CompilationTask caches information about imported files by default in ${user.home}\.lesscss
* This class also provides a daemon that periodically checks for changes in the (imported) LESS sources.
* This class is typically used in build scripts (ANT, Gradle...).
*
* @author Ivo Houbrechts
*/
public class CompilationTask {
private static final Logger logger = LoggerFactory.getLogger(CompilationTask.class);
private File cacheDir;
private LessCompiler lessCompiler;
private Set compilationUnits = new HashSet();
private CompilationListener compilationListener;
private long customJavaScriptHashCode;
protected Thread daemon;
private boolean stopDaemon;
/**
* Default constructor, uses ${user.home}/.lesscss as cache directory.
*
* @param engine javascript LessEngine
* @throws IOException When a resource cannot be read/written
*/
public CompilationTask(LessCompilationEngine engine) throws IOException {
this(engine, (Reader) null);
}
/**
* @param engine javascript LessEngine
* @param cacheDir The directory where import information will be cached.
* @throws IOException When a resource cannot be read/written
*/
public CompilationTask(LessCompilationEngine engine, File cacheDir) throws IOException {
this(engine, (Reader) null, cacheDir);
}
/**
* @param engine javascript LessEngine
* @param customJavaScript File containing custom JavaScript functions (@see LessCompilerImpl)
* @param cacheDir The directory where import information will be cached.
* @throws IOException When a resource cannot be read/written
*/
public CompilationTask(LessCompilationEngine engine, File customJavaScript, File cacheDir) throws IOException {
this(engine, new FileReader(customJavaScript), cacheDir);
}
/**
* @param engine javascript LessEngine
* @param customJavaScriptReader Reader for reading custom JavaScript functions (@see LessCompilerImpl)
* @throws IOException When a resource cannot be read/written
*/
public CompilationTask(LessCompilationEngine engine, Reader customJavaScriptReader) throws IOException {
this(engine, customJavaScriptReader, null);
}
/**
* @param engine javascript LessEngine
* @param customJavaScriptReader Reader for reading custom JavaScript functions (@see LessCompilerImpl)
* @param cacheDir The directory where import information will be cached.
* @throws IOException When a resource cannot be read/written
*/
public CompilationTask(LessCompilationEngine engine, Reader customJavaScriptReader, File cacheDir) throws IOException {
if (customJavaScriptReader != null) {
String customJavaScript = IOUtils.read(customJavaScriptReader);
lessCompiler = new LessCompilerImpl(engine, customJavaScript);
customJavaScriptHashCode = customJavaScript.hashCode();
} else {
lessCompiler = new LessCompilerImpl(engine);
}
this.cacheDir = (cacheDir == null) ? new File(new File(System.getProperty("user.home")), ".lesscss") : cacheDir;
}
/**
* Execute the lazy compilation.
*
* @return the compilation units that were dirty and got compiled
* @throws IOException When a resource cannot be read/written
*/
public Collection execute() throws IOException {
List compiledUnits = new ArrayList();
logger.debug("CompilationTask: execute");
long start = System.currentTimeMillis();
for (CompilationUnit unit : compilationUnits) {
if (compileIfDirty(unit)) {
compiledUnits.add(unit);
}
}
logger.debug("execute finished in {} millis", System.currentTimeMillis() - start);
return compiledUnits;
}
/**
* Start a daemon thread that will execute this CompilationTask periodically.
*
* @param interval execution interval in milliseconds
*/
public void startDaemon(final long interval) {
if (daemon != null) {
throw new RuntimeException("Trying to start daemon while it is still running");
}
stopDaemon = false;
daemon = new Thread(new Runnable() {
@Override
public void run() {
try {
while (!stopDaemon) {
try {
Collection units = execute();
if (!units.isEmpty() && compilationListener != null) {
compilationListener.notifySuccessfulCompilation(units);
}
} catch (LessParseException e) {
System.out.println(e.getMessage());
}
Thread.sleep(interval);
}
} catch (Exception e) {
e.printStackTrace();
}
daemon = null;
}
}, "LessCompilationDaemon");
daemon.setDaemon(true);
daemon.start();
}
/**
* Stop the daemon thread.
*/
public void stopDaemon() {
stopDaemon = true;
}
/**
* Compile a CompilationUnit if dirty.
*
* @param unit CompilationUnit
* @return true if the CompilationUnit was dirty
* @throws IOException
*/
private boolean compileIfDirty(CompilationUnit unit) throws IOException {
if (isDirty(unit)) {
logger.debug("compiling less: {}", unit);
long start = System.currentTimeMillis();
try {
String sourceMapFileName = unit.getSourceMapFile() != null ? unit.getSourceMapFile().getPath() : null;
CompilationDetails compilationResult = lessCompiler.compileWithDetails(unit.getSourceAsString(), unit.getResourceReader(), unit.getOptions(), unit.getSourceLocation(), unit.getDestination().getPath(), sourceMapFileName);
if (unit.getDestination() != null) {
unit.getDestination().getParentFile().mkdirs();
IOUtils.writeFile(compilationResult.getResult(), unit.getDestination(), unit.getEncoding());
}
if (unit.getSourceMapFile() != null && compilationResult.getSourceMap() != null) {
unit.getSourceMapFile().getParentFile().mkdirs();
IOUtils.writeFile(compilationResult.getSourceMap(), unit.getSourceMapFile(), unit.getEncoding());
}
updateImportsAndCache(unit, compilationResult.getImports());
logger.info("compilation of less {} finished in {} millis", unit, System.currentTimeMillis() - start);
return true;
} catch (LessParseException e) {
unit.setExceptionTimestamp(System.currentTimeMillis());
cache(unit);
throw e;
}
}
return false;
}
private boolean isDirty(CompilationUnit unit) {
CompilationUnit cachedUnit = readFromCache(unit);
return cachedUnit == null || !unit.isEquivalent(cachedUnit) || cachedUnit.isDirty();
}
protected CompilationUnit readFromCache(CompilationUnit unit) {
File cacheFile = getCacheFile(unit);
if (cacheFile.canRead()) {
try {
return (CompilationUnit) new ObjectInputStream(new FileInputStream(cacheFile)).readObject();
} catch (Exception e) {
logger.warn("Could not read cached compilationUnit", e);
}
}
return null;
}
private void updateImportsAndCache(CompilationUnit unit, List imports) throws IOException {
unit.setImports(imports);
cache(unit);
}
private File getCacheFile(CompilationUnit unit) {
File dir = new File(cacheDir, Long.toHexString(customJavaScriptHashCode));
return new File(dir, Long.toHexString(unit.hashCode()));
}
@SuppressWarnings("ResultOfMethodCallIgnored")
private void cache(CompilationUnit unit) {
try {
File file = getCacheFile(unit);
file.getParentFile().mkdirs();
ObjectOutputStream os = new ObjectOutputStream(new FileOutputStream(file));
os.writeObject(unit);
os.flush();
os.close();
} catch (IOException e) {
logger.error("Could not cache compilationUnit", e);
}
}
public File getCacheDir() {
return cacheDir;
}
public void setCacheDir(File cacheDir) {
this.cacheDir = cacheDir;
}
public LessCompiler getLessCompiler() {
return lessCompiler;
}
protected void setLessCompiler(LessCompiler lessCompiler) {
this.lessCompiler = lessCompiler;
}
public Set getCompilationUnits() {
return compilationUnits;
}
public void setCompilationUnits(Set compilationUnits) {
this.compilationUnits = compilationUnits;
}
public CompilationListener getCompilationListener() {
return compilationListener;
}
public void setCompilationListener(CompilationListener compilationListener) {
this.compilationListener = compilationListener;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy