be.rubus.angularprime.build.maven.AngularDirectiveMojo.java Source code

Java tutorial

Introduction

Here is the source code for be.rubus.angularprime.build.maven.AngularDirectiveMojo.java

Source

/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements. See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership. The ASF licenses this file
 * to you 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 be.rubus.angularprime.build.maven;

import com.google.javascript.jscomp.CompilationLevel;
import com.google.javascript.jscomp.WarningLevel;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.project.MavenProject;
import org.apache.maven.shared.filtering.MavenResourcesFiltering;
import org.codehaus.plexus.util.FileUtils;
import org.primefaces.extensions.optimizerplugin.*;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;

/**
 * Generates (combines) and optimize the JavaScript and CSS files for AngularPrime.
 *
 * @goal generate-optimize-resources
 * @phase process-resources
 */
public class AngularDirectiveMojo extends AbstractMojo {

    private static final String[] DEFAULT_INCLUDES = { "**/*.css", "**/*.js" };

    private static final String[] DEFAULT_EXCLUDES = {};

    // Location of the output
    private static final String PRODUCTION_LOCATION = "/../build/production";

    private static final String DEVELOPMENT_LOCATION = "/../build/development";

    /**
     * The maven project.
     *
     * @parameter expression="${project}"
     * @readonly
     */
    private MavenProject project;

    /**
     * @component role="org.apache.maven.shared.filtering.MavenResourcesFiltering" role-hint="default"
     * @required
     */
    protected MavenResourcesFiltering mavenResourcesFiltering;

    /**
     * Encoding to read files.
     *
     * @parameter expression="${encoding}" default-value="UTF-8"
     * @required
     */
    private String encoding;

    /**
     * Compilation level for Google Closure Compiler.
     *
     * @parameter expression="${compilationLevel}" default-value="SIMPLE_OPTIMIZATIONS"
     */
    private String compilationLevel;

    /**
     * Warning level for Google Closure Compiler.
     *
     * @parameter expression="${warningLevel}" default-value="QUIET"
     */
    private String warningLevel;

    private List<File> directoriesToProcess;

    private DataUriTokenResolver dataUriTokenResolver;

    private String imagesDir;

    /**
     * Main entry point of the plugin.
     *
     * @throws MojoExecutionException
     * @throws MojoFailureException
     */
    public void execute() throws MojoExecutionException, MojoFailureException {
        getLog().info("Creation of AngularPrime resource artifacts started ...");

        imagesDir = project.getBasedir().getAbsolutePath() + "/src/main/resources/META-INF/resources";

        buildForProduction();
        buildForDevelopment();

    }

    private void processResources(File inputDirectory, boolean withoutCompress) throws MojoExecutionException {

        ResourcesScanner scanner = new ResourcesScanner();
        scanner.scan(inputDirectory, DEFAULT_INCLUDES, DEFAULT_EXCLUDES);

        Aggregation aggr = new Aggregation();
        aggr.setWithoutCompress(withoutCompress);

        for (File directory : directoriesToProcess) {
            try {
                getLog().info("Processing " + directory.getCanonicalPath());
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
            ResourcesScanner subDirScanner = new ResourcesScanner();
            subDirScanner.scan(directory, DEFAULT_INCLUDES, DEFAULT_EXCLUDES);

            Set<File> subDirCssFiles = filterSubDirFiles(scanner.getCssFiles(), subDirScanner.getCssFiles());
            if (!subDirCssFiles.isEmpty()) {

                // handle CSS files
                processCssFiles(directory, subDirCssFiles, getDataUriTokenResolver(),
                        getSubDirAggregation(directory, aggr, ResourcesScanner.CSS_FILE_EXTENSION), null);
            }

            Set<File> subDirJsFiles = filterSubDirFiles(scanner.getJsFiles(), subDirScanner.getJsFiles());
            if (!subDirJsFiles.isEmpty()) {
                // handle JavaScript files
                processJsFiles(directory, subDirJsFiles, getCompilationLevel(compilationLevel),
                        getWarningLevel(warningLevel),
                        getSubDirAggregation(directory, aggr, ResourcesScanner.JS_FILE_EXTENSION), null);
            }
        }
    }

    /**
     * Copies the JavaScript and CSS files from src\main\resources directory to the build directory.
     *
     * @param location Build directory location, relative to to Maven output directory.
     * @return
     * @throws MojoExecutionException
     */
    private File copyResources(String location) throws MojoExecutionException {

        File buildDirectory = new File(project.getBuild().getOutputDirectory() + location);
        CopyUpdatedFiles copier = new CopyUpdatedFiles(buildDirectory, project.getResources());
        copier.execute();

        directoriesToProcess = copier.getDirectoriesToProcess();

        return buildDirectory;
    }

    private void buildForDevelopment() throws MojoExecutionException {
        // Copy to the build directory
        File buildDirectory = copyResources(DEVELOPMENT_LOCATION);

        // Process the widgets that are updated
        processResources(buildDirectory, true);

        useDevelopmentResources(buildDirectory);
    }

    /**
     * Copy the files from the build directory to the web application location.
     *
     * @param buildDirectory The build location
     */
    private void useDevelopmentResources(File buildDirectory) {
        File webAppDirectory = new File(project.getBasedir(), "/src/main/webapp");
        File targetDirectory;
        try {
            List<String> names = FileUtils.getFileNames(buildDirectory, "**/*.css,**/*.js", null, true);
            for (String fileName : names) {
                String normalized = FileUtils.normalize(fileName);
                List<String> parts = extractImportantParts(normalized);
                //parts.add(1, "angularPrime");
                String targetDir = determineTargetLocation(parts, false);
                targetDirectory = new File(webAppDirectory, targetDir);
                FileUtils.copyFileToDirectory(fileName, targetDirectory.getAbsolutePath());
            }

        } catch (IOException e) {
            throw new IllegalArgumentException(e);
        }

    }

    private String determineTargetLocation(List<String> parts, boolean singleResource) {

        if (singleResource && "core.js".equals(parts.get(0))) {
            parts.remove(1); // remove core subdirectory
        }
        if (!singleResource) {
            parts.remove(0);
            parts.add(parts.size() - 1, "libs");
        }
        StringBuilder result = new StringBuilder();
        for (int idx = parts.size(); idx > 0; idx--) {
            result.append('/').append(parts.get(idx - 1));
        }
        return result.toString();
    }

    private List<String> extractImportantParts(String normalized) {
        List<String> result = new ArrayList<String>();
        File f = new File(normalized);
        while (!("development".equals(f.getName()) || "production".equals(f.getName()))) {
            result.add(f.getName());
            f = f.getParentFile();
        }

        return result;
    }

    private void buildForProduction() throws MojoExecutionException {
        // Copy to the build directory
        File buildDirectory = copyResources(PRODUCTION_LOCATION);

        // Process the widgets that are updated
        processResources(buildDirectory, false);

    }

    private Aggregation getSubDirAggregation(final File dir, final Aggregation aggr, final String fileExtension) {
        Aggregation subDirAggr = new Aggregation();
        subDirAggr.setPrependedFile(aggr.getPrependedFile());
        subDirAggr.setRemoveIncluded(aggr.isRemoveIncluded());
        subDirAggr.setWithoutCompress(aggr.isWithoutCompress());
        subDirAggr.setSubDirMode(true);

        File outputFile = new File(dir, dir.getName() + "." + fileExtension);
        subDirAggr.setOutputFile(outputFile);

        return subDirAggr;
    }

    private CompilationLevel getCompilationLevel(final String compilationLevel) throws MojoExecutionException {
        try {
            return CompilationLevel.valueOf(compilationLevel);
        } catch (Exception e) {
            final String errMsg = "Compilation level '" + compilationLevel + "' is wrong. Valid constants are: "
                    + "'WHITESPACE_ONLY', 'SIMPLE_OPTIMIZATIONS', 'ADVANCED_OPTIMIZATIONS'";
            throw new MojoExecutionException(errMsg);

        }
    }

    private WarningLevel getWarningLevel(final String warningLevel) throws MojoExecutionException {
        try {
            return WarningLevel.valueOf(warningLevel);
        } catch (Exception e) {
            final String errMsg = "Warning level '" + warningLevel + "' is wrong. Valid constants are: 'QUIET', "
                    + "'DEFAULT', 'VERBOSE'";
            throw new MojoExecutionException(errMsg);
        }
    }

    private void processCssFiles(final File inputDir, final Set<File> cssFiles,
            final DataUriTokenResolver dataUriTokenResolver, final Aggregation aggr, final String suffix)
            throws MojoExecutionException {
        ResourcesSetAdapter rsa = new ResourcesSetCssAdapter(inputDir, cssFiles, dataUriTokenResolver, aggr,
                encoding, true, suffix);

        YuiCompressorOptimizer yuiOptimizer = new YuiCompressorOptimizer();
        yuiOptimizer.optimize(rsa, getLog());

    }

    private void processJsFiles(final File inputDir, final Set<File> jsFiles,
            final CompilationLevel compilationLevel, final WarningLevel warningLevel, final Aggregation aggr,
            final String suffix) throws MojoExecutionException {

        ResourcesSetAdapter rsa = new ResourcesSetJsAdapter(inputDir, jsFiles, compilationLevel, warningLevel, aggr,
                encoding, true, suffix);

        ClosureCompilerOptimizer closureOptimizer = new ClosureCompilerOptimizer();
        closureOptimizer.optimize(rsa, getLog());

    }

    private static Set<File> filterSubDirFiles(final Set<File> resSetFiles, final Set<File> subDirFiles) {
        Set<File> filteredFiles = new LinkedHashSet<File>();

        if (subDirFiles == null || subDirFiles.isEmpty() || resSetFiles == null || resSetFiles.isEmpty()) {
            return filteredFiles;
        }

        for (File subDirFile : subDirFiles) {
            if (resSetFiles.contains(subDirFile)) {
                filteredFiles.add(subDirFile);
            }
        }

        return filteredFiles;
    }

    private DataUriTokenResolver getDataUriTokenResolver() {
        if (dataUriTokenResolver != null) {
            return dataUriTokenResolver;
        }

        String[] arrImagesDir = imagesDir.split(",");
        File[] fileImagesDir = new File[arrImagesDir.length];
        for (int i = 0; i < arrImagesDir.length; i++) {
            fileImagesDir[i] = new File(arrImagesDir[i]);
        }

        dataUriTokenResolver = new DataUriTokenResolver(fileImagesDir);

        return dataUriTokenResolver;
    }

}