org.primefaces.extensions.optimizerplugin.ClosureCompilerOptimizer.java Source code

Java tutorial

Introduction

Here is the source code for org.primefaces.extensions.optimizerplugin.ClosureCompilerOptimizer.java

Source

/*
 * Copyright 2011 PrimeFaces Extensions.
 *
 * 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.
 *
 * $Id: ClosureCompilerOptimizer.java 513 2011-12-01 18:58:10Z ovaraksin@googlemail.com $
 */

package org.primefaces.extensions.optimizerplugin;

import java.io.File;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;

import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.logging.Log;

import org.codehaus.plexus.util.FileUtils;
import org.codehaus.plexus.util.StringUtils;

import com.google.common.io.Files;
import com.google.javascript.jscomp.CompilationLevel;
import com.google.javascript.jscomp.Compiler;
import com.google.javascript.jscomp.CompilerOptions;
import com.google.javascript.jscomp.JSError;
import com.google.javascript.jscomp.JSSourceFile;
import com.google.javascript.jscomp.Result;
import com.google.javascript.jscomp.WarningLevel;

/**
 * Class for Google Closure Compiler doing JavaScript optimization.
 *
 * @author  Oleg Varaksin / last modified by $Author: ovaraksin@googlemail.com $
 * @version $Revision: 513 $
 * @since   0.1
 */
public class ClosureCompilerOptimizer extends AbstractOptimizer {

    // Note: empty externs, probably CommandLineRunner.getDefaultExterns() would be better
    private static final List<JSSourceFile> EXTERNS_EMPTY = new ArrayList<JSSourceFile>();

    private static final String OPTIMIZED_FILE_EXTENSION = ".optjs";

    @Override
    public void optimize(final ResourcesSetAdapter rsa, final Log log) throws MojoExecutionException {
        CompilationLevel compLevel = rsa.getCompilationLevel();
        CompilerOptions options = new CompilerOptions();
        compLevel.setOptionsForCompilationLevel(options);

        WarningLevel warnLevel = rsa.getWarningLevel();
        warnLevel.setOptionsForWarningLevel(options);
        com.google.javascript.jscomp.Compiler.setLoggingLevel(Level.WARNING);

        try {
            Charset cset = Charset.forName(rsa.getEncoding());

            if (rsa.getAggregation() == null) {
                // no aggregation
                for (File file : rsa.getFiles()) {
                    log.info("Optimize JS file " + file.getName() + " ...");
                    addToOriginalSize(file);

                    JSSourceFile jsSourceFile = JSSourceFile.fromFile(file, cset);
                    List<JSSourceFile> interns = new ArrayList<JSSourceFile>();
                    interns.add(jsSourceFile);

                    // compile
                    Compiler compiler = compile(log, interns, options, rsa.isFailOnWarning());

                    // generate output
                    String path = file.getCanonicalPath();
                    if (StringUtils.isNotBlank(rsa.getSuffix())) {
                        // write compiled content into the new file
                        File outputFile = getFileWithSuffix(path, rsa.getSuffix());
                        Files.write(compiler.toSource(), outputFile, cset);

                        // statistic
                        addToOptimizedSize(outputFile);
                    } else {
                        // path of temp. file
                        String pathOptimized = FileUtils.removeExtension(path) + OPTIMIZED_FILE_EXTENSION;

                        // create a new temp. file
                        File outputFile = new File(pathOptimized);
                        Files.touch(outputFile);

                        // write compiled content into the new file and rename it (overwrite the original file)
                        Files.write(compiler.toSource(), outputFile, cset);
                        FileUtils.rename(outputFile, file);

                        // statistic
                        addToOptimizedSize(file);
                    }
                }
            } else if (rsa.getAggregation().getOutputFile() != null) {
                // aggregation to one output file
                File outputFile;

                if (!rsa.getAggregation().isWithoutCompress()) {
                    // with compressing before aggregation
                    List<JSSourceFile> interns = new ArrayList<JSSourceFile>();
                    for (File file : rsa.getFiles()) {
                        log.info("Optimize JS file " + file.getName() + " ...");
                        addToOriginalSize(file);

                        interns.add(JSSourceFile.fromFile(file, cset));
                    }

                    // compile
                    Compiler compiler = compile(log, interns, options, rsa.isFailOnWarning());

                    int filesCount = rsa.getFiles().size();
                    if (rsa.getAggregation().getPrependedFile() != null) {
                        filesCount++;
                    }

                    if (filesCount > 1) {
                        log.info("Aggregation is running ...");
                    }

                    // get right output file
                    outputFile = getOutputFile(rsa);

                    long sizeBefore = outputFile.length();

                    if (rsa.getAggregation().getPrependedFile() != null) {
                        // write / append to be prepended file into / to the output file
                        prependFile(rsa.getAggregation().getPrependedFile(), outputFile, cset, rsa.getEncoding());
                    }

                    // write / append compiled content into / to the output file
                    Files.append(compiler.toSource(), outputFile, cset);

                    // statistic
                    addToOptimizedSize(outputFile.length() - sizeBefore);

                    if (filesCount > 1) {
                        log.info(filesCount + " files were successfully aggregated.");
                    }
                } else {
                    // only aggregation without compressing
                    outputFile = aggregateFiles(rsa, cset, log);
                }

                // delete single files if necessary
                deleteFilesIfNecessary(rsa, log);

                // rename aggregated file if necessary
                renameOutputFileIfNecessary(rsa, outputFile);
            } else {
                // should not happen
                log.error("Wrong plugin's internal state.");
            }
        } catch (Exception e) {
            throw new MojoExecutionException("Resources optimization failure: " + e.getLocalizedMessage(), e);
        }
    }

    protected Compiler compile(final Log log, final List<JSSourceFile> interns, final CompilerOptions options,
            final boolean failOnWarning) throws MojoExecutionException {
        // compile
        com.google.javascript.jscomp.Compiler compiler = new Compiler();
        Result result = compiler.compile(EXTERNS_EMPTY, interns, options);

        // evaluate result
        evalResult(result, log, failOnWarning);

        return compiler;
    }

    protected void evalResult(final Result result, final Log log, final boolean failOnWarning)
            throws MojoExecutionException {
        if (result.warnings != null) {
            for (JSError warning : result.warnings) {
                log.warn(warning.toString());
            }
        }

        if (result.warnings != null && result.warnings.length > 0 && failOnWarning) {
            throw new MojoExecutionException("Resources optimization failure. Please fix warnings and try again.");
        }

        if (result.errors != null) {
            for (JSError error : result.errors) {
                log.error(error.toString());
            }
        }

        if (result.errors != null && result.errors.length > 0) {
            throw new MojoExecutionException("Resources optimization failure. Please fix errors and try again.");
        }

        if (!result.success) {
            throw new MojoExecutionException("Resources optimization failure. Please fix errors and try again.");
        }
    }
}