Package cn.dreampie.lesscss.compiler

Source Code of cn.dreampie.lesscss.compiler.LessCssCompiler

package cn.dreampie.lesscss.compiler;

import org.codehaus.plexus.util.StringUtils;
import org.lesscss.LessCompiler;
import org.lesscss.LessException;
import org.lesscss.LessSource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.util.Arrays;

/**
* Created by wangrenhui on 2014/7/11.
*/
public class LessCssCompiler extends AbstractLessCss {

  private Logger logger = LoggerFactory.getLogger(getClass());

  private Object lessCompiler;
  /**
   * The directory for compiled CSS stylesheets.
   * <p/>
   * parameter expression="${lesscss.outputDirectory}" default-value="${project.build.directory}"
   * required
   */
  protected File outputDirectory;

  /**
   * When <code>true</code> the LESS compiler will compress the CSS stylesheets.
   * <p/>
   * parameter expression="${lesscss.compress}" default-value="false"
   */
  private boolean compress;

  /**
   * When <code>true</code> the plugin will watch for changes in LESS files and compile if it detects one.
   * <p/>
   * parameter expression="${lesscss.watch}" default-value="false"
   */
  protected boolean watch = false;

  /**
   * When <code>true</code> the plugin will watch for changes in LESS files and compile if it detects one.
   * <p/>
   * parameter expression="${lesscss.watchInterval}" default-value="1000"
   */
  private int watchInterval = 1000;

  /**
   * The character encoding the LESS compiler will use for writing the CSS stylesheets.
   * <p/>
   * parameter expression="${lesscss.encoding}" default-value="${project.build.sourceEncoding}"
   */
  private String encoding;

  /**
   * When <code>true</code> forces the LESS compiler to always compile the LESS sources. By default LESS sources are only compiled when modified (including imports) or the CSS stylesheet does not exists.
   * <p/>
   * parameter expression="${lesscss.force}" default-value="false"
   */
  private boolean force;

  /**
   * The location of the LESS JavasSript file.
   * <p/>
   * parameter
   */
  private File lessJs;

  /**
   * The location of the NodeJS executable.
   * <p/>
   * parameter
   */
  private String nodeExecutable;

  /**
   * The format of the output file names.
   * <p/>
   * parameter
   */
  private String outputFileFormat;

  private static final String FILE_NAME_FORMAT_PARAMETER_REGEX = "\\{fileName\\}";

  private long lastErrorModified = 0;

  /**
   * Execute the MOJO.
   *
   * @throws cn.dreampie.lesscss.compiler.LessCssException if something unexpected occurs.
   */
  public void execute() throws LessCssException {
    if (logger.isDebugEnabled()) {
      logger.debug("sourceDirectory = " + sourceDirectory);
      logger.debug("outputDirectory = " + outputDirectory);
      logger.debug("includes = " + Arrays.toString(includes));
      logger.debug("excludes = " + Arrays.toString(excludes));
      logger.debug("force = " + force);
      logger.debug("lessJs = " + lessJs);
      logger.debug("skip = " + skip);
    }

    if (!skip) {
//          Akka.system().scheduler().scheduleOnce(Duration.create(watchInterval, TimeUnit.MILLISECONDS),
//                    new Runnable() {
//                        @Override
//                        public void run() {

      if (watch) {
        logger.info("Watching " + sourceDirectory);
        if (force) {
          force = false;
          logger.info("Disabled the 'force' flag in watch mode.");
        }
        Thread.currentThread().setPriority(Thread.MIN_PRIORITY);
        while (watch && !Thread.currentThread().isInterrupted()) {
          executeInternal();
          try {
            Thread.sleep(watchInterval);
          } catch (InterruptedException e) {
            logger.error("interrupted");
          }
        }
      } else {
        executeInternal();
      }
//                        }
//                    }, Akka.system().dispatcher());
    } else {
      logger.info("Skipping plugin execution per configuration");
    }
  }

  private void executeInternal() throws LessCssException {
    long start = System.currentTimeMillis();

    String[] files = getIncludedFiles();

    if (files == null || files.length < 1) {
      logger.info("Nothing to compile - no LESS sources found");
    } else {
      if (logger.isDebugEnabled()) {
        logger.debug("included files = " + Arrays.toString(files));
      }

      Object lessCompiler = initLessCompiler();
//            if (watch) {
//                logger.info("Watching " + sourceDirectory);
//                if (force) {
//                    force = false;
//                    logger.info("Disabled the 'force' flag in watch mode.");
//                }
//                Thread.currentThread().setPriority(Thread.MIN_PRIORITY);
//                while (watch && !Thread.currentThread().isInterrupted()) {
//                    compileIfChanged(files, lessCompiler);
//                    try {
//                        Thread.sleep(watchInterval);
//                    } catch (InterruptedException e) {
//                        logger.error("interrupted");
//                    }
//                }
//            } else {
      compileIfChanged(files, lessCompiler);
//            }

//            logger.info("Complete Less compile job finished in " + (System.currentTimeMillis() - start) + " ms");
    }
  }

  private void compileIfChanged(String[] files, Object lessCompiler) throws LessCssException {
    try {
      for (String file : files) {
        File input = new File(sourceDirectory, file);

        buildContext.removeMessages(input);

        if (outputFileFormat != null) {
          file = outputFileFormat.replaceAll(FILE_NAME_FORMAT_PARAMETER_REGEX, file.replace(".less", ""));
        }

        File output = new File(outputDirectory, file.replace(".less", ".css"));

        if (!output.getParentFile().exists() && !output.getParentFile().mkdirs()) {
          throw new LessCssException("Cannot create output directory " + output.getParentFile());
        }

        try {
          LessSource lessSource = new LessSource(input);
          long lessLastModified = lessSource.getLastModifiedIncludingImports();
          if (!output.exists() || (force || output.lastModified() < lessLastModified) && lastErrorModified < lessLastModified) {
            lastErrorModified = lessLastModified;
            long compilationStarted = System.currentTimeMillis();
            logger.info("Compiling LESS source: " + file);
            if (lessCompiler instanceof LessCompiler) {
              ((LessCompiler) lessCompiler).compile(lessSource, output, force);
            } else {
              ((NodeJsLessCssCompiler) lessCompiler).compile(lessSource, output, force);
            }
            buildContext.refresh(output);
            logger.info("Finished compilation to " + outputDirectory + " in " + (System.currentTimeMillis() - compilationStarted) + " ms");
          } else if (!watch) {
            logger.info("Bypassing LESS source: " + file + " (not modified)");
          }
        } catch (IOException e) {
//                    buildContext.addMessage(input, 0, 0, "Error compiling LESS source", BuildContext.SEVERITY_ERROR, e);
          throw new LessCssException("Error while compiling LESS source: " + file, e);
        } catch (LessException e) {
          String message = e.getMessage();
          if (StringUtils.isEmpty(message)) {
            message = "Error compiling LESS source";
          }
//                    buildContext.addMessage(input, 0, 0, "Error compiling LESS source", BuildContext.SEVERITY_ERROR, e);
          throw new LessCssException("Error while compiling LESS source: " + file, e);
        } catch (InterruptedException e) {
//                    buildContext.addMessage(input, 0, 0, "Error compiling LESS source", BuildContext.SEVERITY_ERROR, e);
          throw new LessCssException("Error while compiling LESS source: " + file, e);
        }
      }
    } finally {
      if (lessCompiler instanceof NodeJsLessCssCompiler) {
        ((NodeJsLessCssCompiler) lessCompiler).close();
      }
    }
  }

  private Object initLessCompiler() throws LessCssException {
    if (lessCompiler == null) {
      if (nodeExecutable != null) {
        NodeJsLessCssCompiler nodeJsLessCssCompiler;
        try {
          nodeJsLessCssCompiler = new NodeJsLessCssCompiler(nodeExecutable, compress, encoding, logger);
        } catch (IOException e) {
          throw new LessCssException(e.getMessage(), e);
        }
        if (lessJs != null) {
          throw new LessCssException(
              "Custom LESS JavaScript is not currently supported when using nodeExecutable");
        }
        lessCompiler = nodeJsLessCssCompiler;
      } else {
        LessCompiler newLessCompiler = new LessCompiler();
        newLessCompiler.setCompress(compress);
        newLessCompiler.setEncoding(encoding);
        if (lessJs != null) {
          try {
            newLessCompiler.setLessJs(lessJs.toURI().toURL());
          } catch (MalformedURLException e) {
            throw new LessCssException(
                "Error while loading LESS JavaScript: " + lessJs.getAbsolutePath(), e);
          }
        }
        lessCompiler = newLessCompiler;
      }
    }
    return lessCompiler;
  }


  public File getOutputDirectory() {
    return outputDirectory;
  }

  public void setOutputDirectory(File outputDirectory) {
    this.outputDirectory = outputDirectory;
  }

  public boolean isCompress() {
    return compress;
  }

  public void setCompress(boolean compress) {
    this.compress = compress;
  }

  public boolean isWatch() {
    return watch;
  }

  public void setWatch(boolean watch) {
    this.watch = watch;
  }

  public int getWatchInterval() {
    return watchInterval;
  }

  public void setWatchInterval(int watchInterval) {
    this.watchInterval = watchInterval;
  }

  public String getEncoding() {
    return encoding;
  }

  public void setEncoding(String encoding) {
    this.encoding = encoding;
  }

  public boolean isForce() {
    return force;
  }

  public void setForce(boolean force) {
    this.force = force;
  }

  public File getLessJs() {
    return lessJs;
  }

  public void setLessJs(File lessJs) {
    this.lessJs = lessJs;
  }

  public String getNodeExecutable() {
    return nodeExecutable;
  }

  public void setNodeExecutable(String nodeExecutable) {
    this.nodeExecutable = nodeExecutable;
  }

  public String getOutputFileFormat() {
    return outputFileFormat;
  }

  public void setOutputFileFormat(String outputFileFormat) {
    this.outputFileFormat = outputFileFormat;
  }

  public long getLastErrorModified() {
    return lastErrorModified;
  }

  public void setLastErrorModified(long lastErrorModified) {
    this.lastErrorModified = lastErrorModified;
  }
}
TOP

Related Classes of cn.dreampie.lesscss.compiler.LessCssCompiler

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.