org.jahia.utils.maven.plugin.resources.JavaScriptDictionaryMojo.java Source code

Java tutorial

Introduction

Here is the source code for org.jahia.utils.maven.plugin.resources.JavaScriptDictionaryMojo.java

Source

/**
 * ==========================================================================================
 * =                   JAHIA'S DUAL LICENSING - IMPORTANT INFORMATION                       =
 * ==========================================================================================
 *
 *                                 http://www.jahia.com
 *
 *     Copyright (C) 2002-2018 Jahia Solutions Group SA. All rights reserved.
 *
 *     THIS FILE IS AVAILABLE UNDER TWO DIFFERENT LICENSES:
 *     1/GPL OR 2/JSEL
 *
 *     1/ GPL
 *     ==================================================================================
 *
 *     IF YOU DECIDE TO CHOOSE THE GPL LICENSE, YOU MUST COMPLY WITH THE FOLLOWING TERMS:
 *
 *     This program is free software: you can redistribute it and/or modify
 *     it under the terms of the GNU General Public License as published by
 *     the Free Software Foundation, either version 3 of the License, or
 *     (at your option) any later version.
 *
 *     This program is distributed in the hope that it will be useful,
 *     but WITHOUT ANY WARRANTY; without even the implied warranty of
 *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 *     GNU General Public License for more details.
 *
 *     You should have received a copy of the GNU General Public License
 *     along with this program. If not, see <http://www.gnu.org/licenses/>.
 *
 *
 *     2/ JSEL - Commercial and Supported Versions of the program
 *     ===================================================================================
 *
 *     IF YOU DECIDE TO CHOOSE THE JSEL LICENSE, YOU MUST COMPLY WITH THE FOLLOWING TERMS:
 *
 *     Alternatively, commercial and supported versions of the program - also known as
 *     Enterprise Distributions - must be used in accordance with the terms and conditions
 *     contained in a separate written agreement between you and Jahia Solutions Group SA.
 *
 *     If you are unsure which license is appropriate for your use,
 *     please contact the sales department at sales@jahia.com.
 */
package org.jahia.utils.maven.plugin.resources;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.Collections;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Locale;
import java.util.MissingResourceException;
import java.util.PropertyResourceBundle;
import java.util.ResourceBundle;

import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.maven.model.Resource;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.project.MavenProject;

/**
 * Converts resource bundles into a JavaScript dictionary for use in UI.<br>
 * 
 * @goal javascript-dictionary
 * @phase process-resources
 * @author Sergiy Shyrkov
 */
public class JavaScriptDictionaryMojo extends AbstractMojo {

    protected static String escape(String value) {
        StringBuilder out = new StringBuilder(value.length() * 2);
        int sz = value.length();
        for (int i = 0; i < sz; i++) {
            char ch = value.charAt(i);

            // handle unicode
            if (ch > 0xfff) {
                out.append("\\u" + hex(ch));
            } else if (ch > 0xff) {
                out.append("\\u0" + hex(ch));
            } else if (ch > 0x7f) {
                out.append("\\u00" + hex(ch));
            } else if (ch < 32) {
                switch (ch) {
                case '\b':
                    out.append('\\');
                    out.append('b');
                    break;
                case '\n':
                    out.append('\\');
                    out.append('n');
                    break;
                case '\t':
                    out.append('\\');
                    out.append('t');
                    break;
                case '\f':
                    out.append('\\');
                    out.append('f');
                    break;
                case '\r':
                    out.append('\\');
                    out.append('r');
                    break;
                default:
                    if (ch > 0xf) {
                        out.append("\\u00" + hex(ch));
                    } else {
                        out.append("\\u000" + hex(ch));
                    }
                    break;
                }
            } else {
                switch (ch) {
                case '\'':
                    out.append('\\');
                    out.append('\'');
                    break;
                case '"':
                    out.append('\\');
                    out.append('"');
                    break;
                case '\\':
                    out.append('\\');
                    out.append('\\');
                    break;
                case '/':
                    out.append('\\');
                    out.append('/');
                    break;
                default:
                    out.append(ch);
                    break;
                }
            }
        }

        return out.toString();
    }

    protected static String getValue(ResourceBundle bundle, String key) {
        String value = null;
        try {
            value = bundle.getString(key);
        } catch (MissingResourceException e) {
            // ignore
        }
        return value;
    }

    protected static String hex(char ch) {
        return Integer.toHexString(ch).toUpperCase(Locale.ENGLISH);
    }

    protected static ResourceBundle lookupBundle(File src, String resourceBundle, String... locales)
            throws IOException {
        ResourceBundle rb = null;
        for (String locale : locales) {
            File f = new File(src, resourceBundle + "_" + locale + ".properties");
            if (f.exists()) {
                InputStream is = null;
                try {
                    is = FileUtils.openInputStream(f);
                    rb = new PropertyResourceBundle(is);
                    break;
                } finally {
                    IOUtils.closeQuietly(is);
                }
            }
        }
        return rb;
    }

    /**
     * Do we need to add the processed files into project's resources.
     * 
     * @parameter default-value="true"
     */
    protected boolean addToProjectResources;

    protected File base;

    protected File dest;

    /**
     * The name of the dictionary variable to use in generated JavaScript output files
     * 
     * @parameter default-value="i18n"
     */
    protected String dictionaryName;

    /**
     * Comma- or space-separated list of language codes for resource bundle to process
     * 
     * @parameter default-value="de,en,fr"
     */
    protected String languages;

    /**
     * Should the output files be pretty-printed (line-breaks, whitespace etc.)
     * 
     * @parameter default-value="false"
     */
    protected boolean prettyPrint;

    /**
     * @parameter expression="${project}"
     * @readonly
     */
    protected MavenProject project;

    /**
     * Do we need to quote the keys.
     * 
     * @parameter default-value="true"
     */
    protected boolean quoteKeys;

    /**
     * The name of the resource bundle to be converted
     * 
     * @parameter
     */
    protected String resourceBundle;

    /**
     * The directory to find files in (default is basedir)
     * 
     * @parameter default-value="${basedir}/src/main/resources/resources"
     */
    protected File src;

    /**
     * The sub-directory under destination directory to output files into
     * 
     * @parameter default-value="javascript/i18n"
     */
    protected String targetDirName;

    /**
     * Output file names (without extension)
     * 
     * @parameter
     */
    protected String targetFileName;

    /**
     * Performs conversion of the property file into JavaScript file.
     * 
     * @param locale
     *            locale to be used
     * @throws IOException
     *             in case of an error
     */
    protected void convert(String locale) throws IOException {
        ResourceBundle defBundle = lookupBundle("", "en");
        if (defBundle == null) {
            throw new FileNotFoundException("ERROR : Couldn't find bundle with name " + resourceBundle
                    + ".properties nor " + resourceBundle + "_en.properties in " + src + " folder, skipping...");
        }

        ResourceBundle bundle = locale != null ? lookupBundle(locale) : null;

        if (!dest.exists() && !dest.mkdirs()) {
            throw new IOException("Unable to create folder " + dest);
        }
        File target = new File(dest, targetFileName + (locale != null ? "_" + locale : "") + ".js");
        getLog().info("Creating " + target + " ...");
        PrintWriter out = new PrintWriter(target);
        Enumeration<String> keyEnum = defBundle.getKeys();
        List<String> keys = new LinkedList<String>();
        while (keyEnum.hasMoreElements()) {
            keys.add(keyEnum.nextElement());
        }
        Collections.sort(keys);
        out.print("var ");
        out.print(dictionaryName);
        out.print("={");
        if (prettyPrint) {
            out.println();
        }
        for (Iterator<String> iterator = keys.iterator(); iterator.hasNext();) {
            String key = iterator.next();
            String value = bundle != null ? getValue(bundle, key) : null;
            if (value == null) {
                value = getValue(defBundle, key);
            }

            if (value != null) {
                if (quoteKeys) {
                    out.append("\"");
                }
                out.append(processKey(key));
                if (quoteKeys) {
                    out.append("\"");
                }
                out.append(":\"").append(processValue(value)).append("\"");
                if (iterator.hasNext()) {
                    out.append(",");
                }
                if (prettyPrint) {
                    out.println();
                }
            }
        }
        out.print("};");
        if (prettyPrint) {
            out.println();
        }

        out.flush();
        out.close();
        getLog().info("done");
    }

    public void execute() throws MojoExecutionException, MojoFailureException {
        init();
        getLog().info("Converting resource bundle " + resourceBundle + " into JavaScript files...");
        try {
            getLog().info("...no locale (default file)");
            convert(null);
            for (String lc : StringUtils.split(languages, " ,")) {
                String l = lc.trim();
                getLog().info("...locale " + l);
                convert(l);
            }
        } catch (IOException e) {
            throw new MojoExecutionException(e.getMessage(), e);
        }
        getLog().info("...conversion done.");

        if (addToProjectResources && dest.isDirectory()) {
            Resource resource = new Resource();
            resource.setDirectory(base.getPath());
            project.addResource(resource);
        }
    }

    protected void init() {
        base = new File(project.getBuild().getDirectory(), "i18n2js");
        dest = new File(base, targetDirName != null && targetDirName.length() > 0 ? targetDirName : "javascript");

        if (resourceBundle == null) {
            // let's guess
            if (new File(src, project.getArtifactId() + "_en.properties").isFile()) {
                resourceBundle = project.getArtifactId();
            }
        }
        if (resourceBundle == null) {
            throw new IllegalArgumentException("No resource bundle file for conversion specified");
        }

        if (targetFileName == null) {
            targetFileName = project.getArtifactId() + "-i18n";
        }
    }

    protected ResourceBundle lookupBundle(String... locales) throws IOException {
        return lookupBundle(src, resourceBundle, locales);
    }

    protected String processKey(String key) {
        return key;
    }

    protected String processValue(String value) {
        return escape(value);
    }
}