architecture.common.util.L10NUtils.java Source code

Java tutorial

Introduction

Here is the source code for architecture.common.util.L10NUtils.java

Source

/*
 * Copyright 2012 Donghyuck, Son
 *
 * 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.
 */
package architecture.common.util;

import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.MissingResourceException;

import javax.xml.parsers.SAXParserFactory;

import org.apache.commons.io.IOUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.xml.sax.Attributes;
import org.xml.sax.InputSource;
import org.xml.sax.Locator;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.DefaultHandler;

import architecture.common.i18n.Localizer;
import architecture.common.i18n.LocalizerFactory;

public class L10NUtils {

    private static Log log = LogFactory.getLog(L10NUtils.class);

    private static final L10NUtils SINGLETON = new L10NUtils(true);

    public static final String I18N_XML_RESOURCE = "META-INF/i18n.xml";

    public static final String I18N_CUSTOM_XML_RESOURCE = "i18n_custom.xml";

    private List<LocalizerKey> localizers = new ArrayList<LocalizerKey>();

    private L10NUtils(boolean load) {
        // 1.  jar ?? ?? META-INF/i18n.xml ?  ?  properties ? 
        // .
        try {
            if (load) {
                loadProps(I18N_XML_RESOURCE, true);
            }
        } catch (IOException e) {
            log.debug((new StringBuilder()).append("Unable to access I18n file, " + I18N_XML_RESOURCE + ": ")
                    .append(e.toString()).toString());
        }

        // 1.  jar ? ?? i18n_custom.xml ?  ?  properties ?  .
        try {
            if (load) {
                loadProps(I18N_CUSTOM_XML_RESOURCE, true);
            }
        } catch (IOException e) {
            log.debug(((new StringBuilder())
                    .append("Unable to access I18n user file, " + I18N_CUSTOM_XML_RESOURCE + ": ")
                    .append(e.toString()).toString()));
        }
    }

    public static L10NUtils getInstance() {
        return SINGLETON;
    }

    public static String format(String id, Object... args) {
        return MessageFormat.format(getMessage(id), args);
    }

    public static String format(String id, Locale locale, Object... args) {
        return MessageFormat.format(getMessage(id, locale), args);
    }

    public static String format(String id, Locale locale, ClassLoader cl, Object... args) {
        return MessageFormat.format(getMessage(id, locale, cl), args);
    }

    public static String codeToString(int code) {
        return Localizer.decimalformat.format(code);
    }

    public static String getMessage(String id) {
        return getLocalizer(id).getMessage(id);
    }

    public static String getMessage(String id, Locale locale) {
        return getLocalizer(id, locale).getMessage(id);
    }

    public static String getMessage(String id, Locale locale, ClassLoader cl) {
        return getLocalizer(id, locale, cl).getMessage(id);
    }

    private void loadProps(String resource, boolean breakOnError) throws IOException {

        HashSet<URL> hashset = new HashSet<URL>();
        if (log.isDebugEnabled()) {
            log.debug((new StringBuilder()).append("Searching ").append(resource).toString());
        }
        Enumeration<URL> urls = Thread.currentThread().getContextClassLoader().getResources(resource);
        if (urls != null) {
            URL url;
            for (; urls.hasMoreElements(); hashset.add(url)) {
                url = urls.nextElement();
                if (log.isDebugEnabled())
                    log.debug((new StringBuilder()).append("Adding ").append(url).toString());
            }
        }

        for (URL url : hashset) {
            if (log.isDebugEnabled())
                log.debug((new StringBuilder()).append("Loading from ").append(url).toString());
            InputStream is = null;
            try {
                is = url.openStream();
                InputSource input = new InputSource(is);
                SAXParserFactory factory = SAXParserFactory.newInstance();
                factory.setNamespaceAware(true);
                XMLReader xmlreader = factory.newSAXParser().getXMLReader();
                I18nParsingHandler handler = new I18nParsingHandler();
                xmlreader.setContentHandler(handler);
                xmlreader.setDTDHandler(handler);
                xmlreader.setEntityResolver(handler);
                xmlreader.setErrorHandler(handler);
                xmlreader.parse(input);
                localizers.addAll(handler.localizers);
            } catch (IOException e) {
                if (log.isDebugEnabled())
                    log.debug((new StringBuilder()).append("Skipping ").append(url).toString());
                if (breakOnError)
                    throw e;
            } catch (Exception e) {
                log.error(e);
            } finally {
                if (is != null)
                    IOUtils.closeQuietly(is);
            }
        }

    }

    public static Localizer getLocalizer(String key) throws MissingResourceException {
        return getLocalizer(key, Locale.getDefault(), null);
    }

    public static Localizer getLocalizer(String key, Locale locale) throws MissingResourceException {
        return getLocalizer(key, locale, null);
    }

    /**
     * key ?  ? ?? ?? ?? Localizer ? .
     * 
     * @param key
     * @param locale
     * @param classloader
     * @return
     * @throws MissingResourceException
     */
    public static Localizer getLocalizer(String key, Locale locale, ClassLoader classloader)
            throws MissingResourceException {

        Locale localeToUse = locale;
        String keyToUse = key;
        ClassLoader cl = classloader;

        if (keyToUse == null)
            throw new NullPointerException("No key name provided");
        if (localeToUse == null)
            localeToUse = Locale.getDefault();

        if (cl != null) {
            Localizer localizer = L10NUtils.SINGLETON.getLocalizerBundle(key, locale, cl);
            if (localizer != null)
                return localizer;
        }

        cl = L10NUtils.class.getClassLoader();
        if (cl == null)
            cl = ClassLoader.getSystemClassLoader();
        if (cl == null) {
            if (log.isDebugEnabled())
                log.debug("no system classs loader");
            cl = Thread.currentThread().getContextClassLoader();
            if (cl == null) {
                if (log.isDebugEnabled())
                    log.debug("no context class loader");
            } else if (log.isDebugEnabled())
                log.debug("Using context class loader");
        }

        Localizer localizer = L10NUtils.SINGLETON.getLocalizerBundle(key, locale, cl);
        if (localizer == null) {
            ClassLoader clToUse = Thread.currentThread().getContextClassLoader();
            localizer = L10NUtils.SINGLETON.getLocalizerBundle(key, locale, clToUse);
            if (localizer == null)
                throw new MissingResourceException((new StringBuilder()).append("Can't locate bundle for class '")
                        .append(key).append("'").toString(), key, "");
        }
        return localizer;
    }

    public Localizer getLocalizerBundle(String key, Locale locale, ClassLoader classloader)
            throws MissingResourceException {

        LocalizerKey keyToUse = getLocalizerKey(key);
        if (keyToUse != null)
            return LocalizerFactory.getLocalizer(keyToUse.bundleName, locale, classloader);

        return null;
    }

    private LocalizerKey getLocalizerKey(String key) {
        Integer i = new Integer(key);
        for (LocalizerKey k : localizers) {
            if (k.codes.contains(i)) {
                return k;
            }
        }
        return null;
    }

    private static class LocalizerKey {

        int hash;
        Locale locale;
        String bundleName;
        List<Integer> codes;

        private LocalizerKey(Integer code, Locale locale) {
            this.bundleName = "*";
            this.locale = locale;
            this.codes = new ArrayList<Integer>(1);
            this.codes.add(code);
        }

        private LocalizerKey() {
            locale = null;
            bundleName = null;
            codes = new ArrayList<Integer>();
        }

        public int hashCode() {
            if (hash == 0) {
                if (bundleName != null)
                    hash = bundleName.hashCode();
                if (locale != null)
                    hash = hash | locale.hashCode();
                if (codes != null)
                    hash = hash | codes.hashCode();
            }
            return hash;
        }

        public String toString() {

            StringBuilder builder = new StringBuilder();
            builder.append('[');
            builder.append("LocalizerKey");
            builder.append('=');
            builder.append(bundleName);
            builder.append(',');
            builder.append(locale);
            builder.append(',');
            builder.append(codes.size());
            builder.append(']');
            return builder.toString();
        }

        public boolean equals(Object obj) {
            if (obj == this)
                return true;
            if (obj instanceof LocalizerKey) {
                LocalizerKey key = (LocalizerKey) obj;
                if ("*".equals(key.bundleName)) {
                    for (Integer c : key.codes) {
                        if (codes.contains(c))
                            return true;
                    }
                }

            }
            return false;
        }

    }

    private static class I18nParsingHandler extends DefaultHandler {

        Locator locator;
        List<LocalizerKey> localizers;
        StringBuilder value;
        LocalizerKey key;

        private I18nParsingHandler() {
            localizers = new ArrayList<LocalizerKey>();
            value = new StringBuilder();
        }

        public void setDocumentLocator(Locator locator) {
            this.locator = locator;
        }

        @Override
        public void characters(char[] ch, int start, int length) throws SAXException {
            value.append(ch, start, length);
        }

        public void endElement(String uri, String localName, String qName) throws SAXException {
            if (!StringUtils.isEmpty(qName))
                if (qName.equals("localizer") && key != null)
                    localizers.add(key);
            value.setLength(0);
        }

        @Override
        public void startElement(String uri, String localName, String qName, Attributes attributes)
                throws SAXException {
            if (!StringUtils.isEmpty(qName))
                if (qName.equals("localizer")) {
                    key = new LocalizerKey();
                    int i = attributes.getLength();
                    for (int j = 0; j < i; j++) {
                        String name = attributes.getQName(j);
                        String value = attributes.getValue(j);
                        if (name.equals("bundleName"))
                            key.bundleName = value;
                        else if (name.equals("codes")) {
                            String[] codes = StringUtils.split(value, ",");
                            for (String code : codes) {
                                if (code.contains("-")) {
                                    String[] range = StringUtils.split(code, "-");
                                    for (int k = Integer.parseInt(range[0]); k <= Integer.parseInt(range[1]); k++) {
                                        key.codes.add(k);
                                    }
                                } else {
                                    key.codes.add(Integer.parseInt(code));
                                }
                            }
                        } else
                            throw new SAXParseException("Invalid attribute: " + name, locator);
                    }
                }

        }

    }
}