com.github.sommeri.less4j.core.TimeoutedLessCompiler Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of less4j Show documentation
Show all versions of less4j Show documentation
Less language is an extension of css and less4j compiles it into regular css. It adds several dynamic features into css: variables, expressions, nested rules.
Less4j is a port. The original compiler was written in JavaScript and is called less.js. The less language is mostly defined in less.js documentation/issues and by what less.js actually do. Links to less.js:
* home page: http://lesscss.org/
* source code & issues: https://github.com/cloudhead/less.js
package com.github.sommeri.less4j.core;
import java.io.File;
import java.net.URL;
import java.util.concurrent.Callable;
import java.util.concurrent.CancellationException;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import com.github.sommeri.less4j.Less4jException;
import com.github.sommeri.less4j.LessCompiler;
import com.github.sommeri.less4j.LessSource;
import com.github.sommeri.less4j.core.ast.ASTCssNode;
import com.github.sommeri.less4j.core.problems.BugHappened;
public class TimeoutedLessCompiler implements LessCompiler {
private final long timeout;
private final TimeUnit unit;
private final long afterInterruptTimeout;
private final TimeUnit afterInterruptUnit;
public TimeoutedLessCompiler(long timeout, TimeUnit unit) {
this(timeout, unit, 80, TimeUnit.MILLISECONDS);
}
public TimeoutedLessCompiler(long timeout, TimeUnit unit, long afterInterruptTimeout, TimeUnit afterInterruptunit) {
super();
this.timeout = timeout;
this.unit = unit;
this.afterInterruptTimeout = afterInterruptTimeout;
this.afterInterruptUnit = afterInterruptunit;
}
@Override
public CompilationResult compile(String lessContent) throws Less4jException {
return compile(new LessSource.StringSource(lessContent), null);
}
@Override
public CompilationResult compile(String lessContent, Configuration options) throws Less4jException {
return compile(new LessSource.StringSource(lessContent), options);
}
@Override
public CompilationResult compile(File lessFile) throws Less4jException {
LessSource.FileSource lessSource = new LessSource.FileSource(lessFile);
return compile(lessSource, null);
}
@Override
public CompilationResult compile(File lessFile, Configuration options) throws Less4jException {
return compile(new LessSource.FileSource(lessFile, "utf-8"), options);
}
@Override
public CompilationResult compile(URL lessURL) throws Less4jException {
return compile(new LessSource.URLSource(lessURL));
}
@Override
public CompilationResult compile(URL lessURL, Configuration options) throws Less4jException {
return compile(new LessSource.URLSource(lessURL), options);
}
@Override
public CompilationResult compile(LessSource source) throws Less4jException {
return compile(source, new Configuration());
}
@Override
public CompilationResult compile(LessSource source, Configuration options) throws Less4jException {
final LessSource iSource = source;
final Configuration iOption = options;
Callable task = new Callable() {
public CompilationResult call() {
ThreadUnsafeLessCompiler compiler = new ThreadUnsafeLessCompiler();
try {
return compiler.compile(iSource, iOption);
} catch (Less4jException ex) {
throw new Less4jRuntimeException(ex);
}
}
};
ExecutorService executor = Executors.newSingleThreadExecutor();
Future future = executor.submit(task);
try {
boolean terminatedNormally = executor.awaitTermination(timeout, unit);
if (terminatedNormally) {
CompilationResult result = future.get();
return result;
} else {
executor.shutdownNow();
executor.awaitTermination(afterInterruptTimeout, afterInterruptUnit);
return future.get();
}
} catch (CancellationException e) {
throw new BugHappened("Unexpected future cancellation.", (ASTCssNode) null);
} catch (InterruptedException e) {
throw new BugHappened("Unexpected thread interrupt.", (ASTCssNode) null);
} catch (ExecutionException e) {
Throwable cause = e.getCause();
if (cause instanceof Less4jRuntimeException) {
Less4jRuntimeException wrapper = (Less4jRuntimeException) cause;
throw (Less4jException) wrapper.getCause();
}
if (cause instanceof RuntimeException) {
RuntimeException runtimeException = (RuntimeException) cause;
throw runtimeException;
}
if (cause instanceof Error) {
Error error = (Error) cause;
throw error;
}
throw new RuntimeException("Unexpected state, this should not be possible", cause);
}
}
@SuppressWarnings("serial")
private class Less4jRuntimeException extends RuntimeException {
public Less4jRuntimeException(Less4jException ex) {
super(ex);
}
}
}