Package com.alibaba.toolkit.util.resourcebundle

Source Code of com.alibaba.toolkit.util.resourcebundle.ResourceBundleFactory

/*
* Copyright 2010 Alibaba Group Holding Limited.
* All rights reserved.
*
* 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 com.alibaba.toolkit.util.resourcebundle;

import com.alibaba.toolkit.util.collection.SoftHashMap;
import com.alibaba.toolkit.util.resourcebundle.xml.XMLResourceBundleFactory;

import java.lang.ref.SoftReference;

import java.text.MessageFormat;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;

/**
* ����<code>ResourceBundle</code>��ʵ���Ĺ���.
*
* @version $Id: ResourceBundleFactory.java,v 1.1 2003/07/03 07:26:35 baobao Exp $
* @author Michael Zhou
*/
public abstract class ResourceBundleFactory {
    /**
     * ʹ��ָ����bundle������, Ĭ�ϵ�locale, Ĭ�ϵ�factory��ȡ��resource bundle. Ĭ�ϵ�factory�Ǵ��̵߳�context class
     * loader��ȡ����Դ�ļ�, ����XML�ĸ�ʽ������Դ�ļ�.
     *
     * @param baseName  bundle�Ļ�����
     *
     * @return resource bundle
     *
     * @throws MissingResourceException  ָ��bundleδ�ҵ�, �򴴽�bundle����
     */
    public static final ResourceBundle getBundle(String baseName) {
        return getBundle(baseName, null, (ResourceBundleFactory) null);
    }

    /**
     * ʹ��ָ����bundle������, ָ����locale, Ĭ�ϵ�factory��ȡ��resource bundle. Ĭ�ϵ�factory�Ǵ��̵߳�context class
     * loader��ȡ����Դ�ļ�, ����XML�ĸ�ʽ������Դ�ļ�.
     *
     * @param baseName  bundle�Ļ�����
     * @param locale    ��������
     *
     * @return resource bundle
     *
     * @throws MissingResourceException  ָ��bundleδ�ҵ�, �򴴽�bundle����
     */
    public static final ResourceBundle getBundle(String baseName, Locale locale) {
        return getBundle(baseName, locale, (ResourceBundleFactory) null);
    }

    /**
     * ʹ��ָ����bundle������, ָ����locale, Ĭ�ϵ�factory��ȡ��resource bundle. Ĭ�ϵ�factory�Ǵ�ָ����class loader��ȡ����Դ�ļ�,
     * ����XML�ĸ�ʽ������Դ�ļ�.
     *
     * @param baseName    bundle�Ļ�����
     * @param locale      ��������
     * @param classLoader class loader
     *
     * @return resource bundle
     *
     * @throws MissingResourceException  ָ��bundleδ�ҵ�, �򴴽�bundle����
     */
    public static final ResourceBundle getBundle(String baseName, Locale locale,
                                                 ClassLoader classLoader) {
        return getBundle(baseName, locale, new XMLResourceBundleFactory(classLoader));
    }

    /**
     * ʹ��ָ����bundle������, ָ����locale, ָ����loader, Ĭ�ϵ�factory��ȡ��resource bundle.
     * Ĭ�ϵ�factory�Ǵ�ָ����loader��ȡ����Դ�ļ�, ����XML�ĸ�ʽ������Դ�ļ�.
     *
     * @param baseName  bundle�Ļ�����
     * @param locale    ��������
     * @param loader    bundle��װ����
     *
     * @return resource bundle
     *
     * @throws MissingResourceException  ָ��bundleδ�ҵ�, �򴴽�bundle����
     */
    public static final ResourceBundle getBundle(String baseName, Locale locale,
                                                 ResourceBundleLoader loader) {
        return getBundle(baseName, locale, new XMLResourceBundleFactory(loader));
    }

    /**
     * ʹ��ָ����bundle������, ָ����locale, ָ����factory��ȡ��resource bundle.
     *
     * @param baseName  bundle�Ļ�����
     * @param locale    ��������
     * @param factory   bundle����
     *
     * @return resource bundle
     *
     * @throws MissingResourceException  ָ��bundleδ�ҵ�, �򴴽�bundle����
     */
    public static final ResourceBundle getBundle(String baseName, Locale locale,
                                                 ResourceBundleFactory factory) {
        if (locale == null) {
            locale = Locale.getDefault();
        }

        if (factory == null) {
            factory = new XMLResourceBundleFactory();
        }

        return Helper.getBundleImpl(baseName, locale, factory);
    }

    /**
     * ����<code>ResourceBundle</code>��ʵ��.
     *
     * @param bundleName  Ҫ������bundle����
     *
     * @return �´�����<code>ResourceBundle</code>ʵ��, ���ָ��bundle������, �򷵻�<code>null</code>
     *
     * @throws ResourceBundleCreateException ָ��bundle�ļ�����, ������bundleʵ��ʧ��, �����ļ���ʽ����
     */
    public abstract ResourceBundle createBundle(String bundleName)
            throws ResourceBundleCreateException;

    /**
     * �ж�����<code>ResourceBundleFactory</code>�Ƿ��Ч. �⽫��Ϊ<code>ResourceBundle</code>��cache������.
     *
     * @param obj Ҫ�Ƚϵ���һ������
     *
     * @return �����Ч, �򷵻�<code>true</code>
     */
    public abstract boolean equals(Object obj);

    /**
     * ȡ��hashֵ.  ��Ч��<code>ResourceBundleFactory</code>Ӧ�þ�����ͬ��hashֵ.
     *
     * @return hashֵ
     */
    public abstract int hashCode();

    /**
     * ���Һʹ���bundle����.
     */
    private static final class Helper {
        /** ��(factory, bundleName, defaultLocale)ӳ�䵽bundle�����cache. ���ڴ治��ʱ, cache�����ݻ��Զ��ͷ�. */
        private static final Cache cache = new Cache();

        /**
         * ʹ��ָ����bundle������, ָ����locale, ָ����factory��ȡ��resource bundle.
         *
         * @param baseName  bundle�Ļ�����
         * @param locale    ��������
         * @param factory   bundle����
         *
         * @return resource bundle
         *
         * @throws MissingResourceException  ָ��bundleδ�ҵ�, �򴴽�bundle����
         */
        private static ResourceBundle getBundleImpl(String baseName, Locale locale,
                                                    ResourceBundleFactory factory) {
            if (baseName == null) {
                throw new NullPointerException(ResourceBundleConstant.RB_BASE_NAME_IS_NULL);
            }

            // ʹ��factory��Ϊbundleδ�ҵ��ı��, ������factory��GC���յ�ʱ��, cache���Ӧ����Ҳ���Ա�����.
            final Object NOT_FOUND = factory;

            // ��cache��ȡ��bundle.
            String bundleName   = baseName;
            String localeSuffix = locale.toString();

            if (localeSuffix.length() > 0) {
                bundleName += ("_" + localeSuffix);
            } else if (locale.getVariant().length() > 0) {
                // ����: new Locale("", "", "VARIANT").toString == ""
                bundleName += ("___" + locale.getVariant());
            }

            // ȡ��ϵͳlocale, ע��, ���ֵ���ܱ��ı�, ����ÿ��ִ��ʱ������ȡ.
            Locale defaultLocale = Locale.getDefault();

            Object lookup = cache.get(factory, bundleName, defaultLocale);

            if (NOT_FOUND.equals(lookup)) {
                throwResourceBundleException(true, baseName, locale, null);
            } else if (lookup != null) {
                return (ResourceBundle) lookup;
            }

            // ��ʼ���Ҳ�����bundle.
            Object parent = NOT_FOUND;

            try {
                // ����base bundle.
                Object root = findBundle(factory, baseName, defaultLocale, baseName, null,
                                         NOT_FOUND);

                if (root == null) {
                    root = NOT_FOUND;
                    cache.put(factory, baseName, defaultLocale, root);
                }

                // ������Ҫ·��, ����getBundle("baseName", new Locale("zh", "CN", "Variant")),
                // ��Ҫ·��ΪbaseName_zh, baseName_zh_CN, baseName_zh_CN_Varient.
                final List names        = calculateBundleNames(baseName, locale);
                List       bundlesFound = new ArrayList(ResourceBundleConstant.MAX_BUNDLES_SEARCHED);

                // ���base bundle�Ѿ��ҵ�, ������·��Ϊ��.
                boolean foundInMainBranch = (!NOT_FOUND.equals(root) && names.size() == 0);

                if (!foundInMainBranch) {
                    parent = root;

                    for (int i = 0; i < names.size(); i++) {
                        bundleName = (String) names.get(i);
                        lookup     = findBundle(factory, bundleName, defaultLocale, baseName,
                                                parent, NOT_FOUND);
                        bundlesFound.add(lookup);

                        if (lookup != null) {
                            parent            = lookup;
                            foundInMainBranch = true;
                        }
                    }
                }


                // �����·��δ�ҵ�bundle, �����ϵͳĬ��·��, ���統ǰϵͳĬ��localeΪen_US,
                // ������·��Ϊ: baseName_en, baseName_US.
                parent = root;

                if (!foundInMainBranch) {
                    final List fallbackNames = calculateBundleNames(baseName, defaultLocale);

                    for (int i = 0; i < fallbackNames.size(); i++) {
                        bundleName = (String) fallbackNames.get(i);

                        // ���ϵͳĬ��·������·��һ��, ����Ҫ������ȥ��
                        if (names.contains(bundleName)) {
                            break;
                        }

                        lookup = findBundle(factory, bundleName, defaultLocale, baseName, parent,
                                            NOT_FOUND);

                        if (lookup != null) {
                            parent = lookup;
                        } else {
                            // ����bundle���ݸ���bundle, ����:
                            // ��bundle: baseName_en.xml�Ѿ��ҵ�, ��bundle: baseName_en_USδ�ҵ�,
                            // ��cache��:
                            // baseName       => bundle����: baseName.xml
                            // baseName_en    => bundle����: baseName_en.xml
                            // baseName_en_US => bundle����: baseName_en.xml
                            cache.put(factory, bundleName, defaultLocale, parent);
                        }
                    }
                }

                // ����·����, ����bundle���ݸ���bundle, �������������:
                // 1. bundle����·����, ����getBundle("baseName", new Locale("zh", "CN")),
                //    baseName_zh���ҵ�, ��cache��:
                //    baseName       => bundle����: baseName.xml
                //    baseName_zh    => bundle����: baseName_zh.xml
                //    baseName_zh_CN => bundle����: baseName_zh.xml
                //
                // 2. bundle��ϵͳ·����, ��·��δ�ҵ�, ����getBundle("baseName", new Locale("zh", "CN")),
                //    baseName_zh��baseName_zh_CN��δ�ҵ�, ��ϵͳ·����baseName_en���ҵ�, ��cache��:
                //    baseName       => bundle����: baseName.xml
                //    baseName_zh    => bundle����: baseName_en.xml
                //    baseName_zh_CN => bundle����: baseName_en.xml
                //    baseName_en    => bundle����: baseName_en.xml
                //    baseName_en_US => bundle����: baseName_en.xml
                //
                // 3. bundle�Ļ�����δ�ҵ�:
                //    baseName       => NOT_FOUND
                //    baseName_zh    => NOT_FOUND
                //    baseName_zh_CN => NOT_FOUND
                //    baseName_en    => NOT_FOUND
                //    baseName_en_US => NOT_FOUND
                for (int i = 0; i < names.size(); i++) {
                    final String name        = (String) names.get(i);
                    final Object bundleFound = bundlesFound.get(i);

                    if (bundleFound == null) {
                        cache.put(factory, name, defaultLocale, parent);
                    } else {
                        parent = bundleFound;
                    }
                }
            } catch (Exception e) {
                // ������ResourceBundleCreateException������RuntimeException.
                cache.cleanUpConstructionList();
                throwResourceBundleException(false, baseName, locale, e);
            } catch (Error e) {
                cache.cleanUpConstructionList();
                throw e;
            }

            if (NOT_FOUND.equals(parent)) {
                throwResourceBundleException(true, baseName, locale, null);
            }

            return (ResourceBundle) parent;
        }

        /**
         * ��cache�в���bundle, ���factory��װ��bundle.  ����˷�������<code>null</code>, ������߱����Լ�����bundle,
         * ������<code>cache.put</code>����.
         *
         * @param factory       bundle����
         * @param bundleName    bundle����
         * @param defaultLocale ϵͳĬ�ϵ�locale
         * @param baseName      bundle������
         * @param parent        ��bundle, ���ڸ�bundle,  Ϊ<code>null</code>
         * @param NOT_FOUND     ���"δ�ҵ�"״̬�Ķ���
         *
         * @return resource bundle, ����<code>null</code>��ʾbundleδ�ҵ�
         *
         * @throws ResourceBundleCreateException bundle���ҵ�, �����첻�ɹ�
         */
        private static Object findBundle(ResourceBundleFactory factory, String bundleName,
                                         Locale defaultLocale, String baseName, Object parent,
                                         final Object NOT_FOUND)
                throws ResourceBundleCreateException {
            Object result = cache.getWait(factory, bundleName, defaultLocale);

            if (result != null) {
                return result;
            }


            // ���Դ�factory��װ��bundle.
            result = factory.createBundle(bundleName);

            if (result != null) {
                // �ڵ���factoryʱ, �п��ܵݹ�ص�����getBundle����, �������bundle�Ѿ���������.
                // ���������, bundleһ����cache��.  Ϊ��һ����, Ӧ����cache�е�bundle.
                Object otherBundle = cache.get(factory, bundleName, defaultLocale);

                if (otherBundle != null) {
                    result = otherBundle;
                } else {
                    // ����bundle�ĸ�bundle, �������ŵ�cache��.
                    final ResourceBundle bundle = (ResourceBundle) result;

                    if ((!NOT_FOUND.equals(parent)) && (bundle.getParent() == null)) {
                        bundle.setParent((ResourceBundle) parent);
                    }

                    bundle.setBaseName(baseName);
                    bundle.setLocale(baseName, bundleName);
                    cache.put(factory, bundleName, defaultLocale, result);
                }
            }

            return result;
        }

        /**
         * ȡ�ñ�ѡ��bundle��.
         *
         * @param baseName bundle�Ļ�����
         * @param locale   ��������
         *
         * @return ���б�ѡ��bundle��
         */
        private static List calculateBundleNames(String baseName, Locale locale) {
            final List   result         = new ArrayList(ResourceBundleConstant.MAX_BUNDLES_SEARCHED);
            final String language       = locale.getLanguage();
            final int    languageLength = language.length();
            final String country        = locale.getCountry();
            final int    countryLength  = country.length();
            final String variant        = locale.getVariant();
            final int    variantLength  = variant.length();

            // ���locale��("", "", "").
            if ((languageLength + countryLength + variantLength) == 0) {
                return result;
            }

            final StringBuffer buffer = new StringBuffer(baseName);


            // ����baseName_language
            buffer.append('_');
            buffer.append(language);

            if (languageLength > 0) {
                result.add(buffer.toString());
            }

            if ((countryLength + variantLength) == 0) {
                return result;
            }


            // ����baseName_language_country
            buffer.append('_');
            buffer.append(country);

            if (countryLength > 0) {
                result.add(buffer.toString());
            }

            if (variantLength == 0) {
                return result;
            }


            // ����baseName_language_country_variant
            buffer.append('_');
            buffer.append(variant);
            result.add(buffer.toString());

            return result;
        }

        /**
         * ����"resource bundleδ�ҵ�"���쳣.
         *
         * @param missing  ָ��bundleδ�ҵ�, ���Ǵ���bundle����
         * @param baseName δ�ҵ���bundle������
         * @param locale   δ�ҵ���bundle����������
         * @param cause    �쳣����
         */
        private static void throwResourceBundleException(boolean missing, String baseName,
                                                         Locale locale, Throwable cause) {
            String bundleName = baseName + "_" + locale;

            if (missing) {
                throw new ResourceBundleException(ResourceBundleConstant.RB_MISSING_RESOURCE_BUNDLE,
                                                  new Object[] {
                    baseName,
                    locale
                }, cause, bundleName, "");
            } else {
                throw new ResourceBundleException(ResourceBundleConstant.RB_FAILED_LOADING_RESOURCE_BUNDLE,
                                                  new Object[] {
                    baseName,
                    locale
                }, cause, bundleName, "");
            }
        }
    }

    /**
     * ��(factory, bundleName, defaultLocale)ӳ�䵽bundle�����cache��.
     */
    private static final class Cache extends SoftHashMap {
        /** ��̬��key, ������cache�в���bundle. ʹ�þ�̬�����Լ���GC�ĸ���. ʹ��cacheKey���������cache����ͬ��. */
        private static final CacheKey cacheKey = new CacheKey();

        /**
         * ���hash������ͬ������߳�, �Ա�ͬʱװ��ͬһ��bundle. ���hash������cacheKey��thread��ӳ��. ʹ�ô�hash����������cache����ͬ��.
         */
        private final Map underConstruction = new HashMap(
                                                      ResourceBundleConstant.MAX_BUNDLES_SEARCHED,
                                                      ResourceBundleConstant.CACHE_LOAD_FACTOR);

        /**
         * ����һ��cache.
         */
        public Cache() {
            super(ResourceBundleConstant.INITIAL_CACHE_SIZE,
                  ResourceBundleConstant.CACHE_LOAD_FACTOR);
        }

        /**
         * ��cache�в���bundle.
         *
         * @param factory       bundle����
         * @param bundleName    bundle����
         * @param defaultLocale ϵͳlocale
         *
         * @return ��cache��bundle. ���δ�ҵ�, �򷵻�<code>null</code>
         */
        public synchronized Object get(ResourceBundleFactory factory, String bundleName,
                                       Locale defaultLocale) {
            cacheKey.set(factory, bundleName, defaultLocale);

            Object result = get(cacheKey);

            cacheKey.clear();
            return result;
        }

        /**
         * ��cache�в���bundle, ���bundle������, ��������һ���߳����ڹ����bundle, ��ȴ�֮. ����˷�������<code>null</code>,
         * ������߱��븺�����<code>put</code>��<code>cleanUpConstructionList</code>����, �������߳̿��ܵȴ���, ���������.
         *
         * @param factory       bundle����
         * @param bundleName    bundle����
         * @param defaultLocale ϵͳlocale
         *
         * @return ��cache��bundle. ���δ�ҵ�, �򷵻�<code>null</code>
         */
        public synchronized Object getWait(ResourceBundleFactory factory, String bundleName,
                                           Locale defaultLocale) {
            Object result;


            // ���Ȳ���cache���Ƿ��Ѿ������bundle��, �����, ֱ�ӷ���.
            cacheKey.set(factory, bundleName, defaultLocale);
            result = get(cacheKey);

            if (result != null) {
                cacheKey.clear();
                return result;
            }

            // ����Dz��Ѿ�����һ��thread���ڴ������bundle.
            // ע��, �п��ܵݹ����getBundle����, ����, ��factory�е�����getBundle.
            // ���������, beingBuilt == false
            Thread  builder    = (Thread) underConstruction.get(cacheKey);
            boolean beingBuilt = (builder != null && builder != Thread.currentThread());

            // ����Ѿ�����һ��thread���ڴ������bundle.
            if (beingBuilt) {
                while (beingBuilt) {
                    cacheKey.clear();

                    try {
                        // �ȴ�, ֱ������̴߳������.
                        wait();
                    } catch (InterruptedException e) {
                    }

                    cacheKey.set(factory, bundleName, defaultLocale);
                    beingBuilt = underConstruction.containsKey(cacheKey);
                }


                // �����һ���̰߳����bundle��������, ��ֱ�ӷ��ؼ���
                result = get(cacheKey);

                if (result != null) {
                    cacheKey.clear();
                    return result;
                }
            }


            // ���bundle����cache��, ��׼�������bundle.
            // �����߱�����������put��cleanUpConstructionList����, ���򽫻�����.
            underConstruction.put(cacheKey.clone(), Thread.currentThread());

            cacheKey.clear();

            return null;
        }

        /**
         * ��bundle����cache, ���������еȴ����߳�.
         *
         * @param factory       bundle����
         * @param bundleName    bundle����
         * @param defaultLocale ϵͳlocale
         * @param bundle        ����cache��bundle����
         */
        public synchronized void put(ResourceBundleFactory factory, String bundleName,
                                     Locale defaultLocale, Object bundle) {
            cacheKey.set(factory, bundleName, defaultLocale);

            put(cacheKey.clone(), bundle);

            underConstruction.remove(cacheKey);

            cacheKey.clear();


            // ���������߳�
            notifyAll();
        }

        /**
         * ��"���ڹ���bundle"���̱߳��������ǰ�߳�. ���װ��bundleʧ��, ����Ҫ���ô˷���.
         */
        public synchronized void cleanUpConstructionList() {
            final Collection entries    = underConstruction.values();
            final Thread     thisThread = Thread.currentThread();

            while (entries.remove(thisThread)) {
            }


            // ���������߳�
            notifyAll();
        }
    }

    /**
     * ��bundle��Ӧ��cache key, ��bundle����, bundle����, ϵͳlocale�����ֶ����.
     */
    private static final class CacheKey implements Cloneable {
        private SoftReference factoryRef;
        private String        bundleName;
        private Locale        defaultLocale;
        private int           hashCode;

        /**
         * ����cache key.
         *
         * @param factory       bundle����
         * @param bundleName    bundle����
         * @param defaultLocale ϵͳlocale
         */
        public void set(ResourceBundleFactory factory, String bundleName, Locale defaultLocale) {
            this.bundleName    = bundleName;
            this.hashCode      = bundleName.hashCode();
            this.defaultLocale = defaultLocale;

            if (defaultLocale != null) {
                hashCode ^= defaultLocale.hashCode();
            }

            if (factory == null) {
                this.factoryRef = null;
            } else {
                factoryRef = new SoftReference(factory);
                hashCode ^= factory.hashCode();
            }
        }

        /**
         * ���cache key.
         */
        public void clear() {
            set(null, "", null);
        }

        /**
         * �������key�Ƿ�ƥ��.
         *
         * @param other  ��һ��cache key
         *
         * @return ���ƥ��, �򷵻�<code>true</code>
         */
        public boolean equals(Object other) {
            if (this == other) {
                return true;
            }

            try {
                final CacheKey otherKey = (CacheKey) other;

                // hashֵ��ͬ, ����������
                if (hashCode != otherKey.hashCode) {
                    return false;
                }

                // bundle�����Ƿ���ͬ?
                if (!eq(bundleName, otherKey.bundleName)) {
                    return false;
                }

                // locale�Ƿ���ͬ
                if (!eq(defaultLocale, otherKey.defaultLocale)) {
                    return false;
                }

                // factory�Ƿ���ͬ?
                if (factoryRef == null) {
                    return otherKey.factoryRef == null;
                } else {
                    return (otherKey.factoryRef != null)
                           && eq(factoryRef.get(), otherKey.factoryRef.get());
                }
            } catch (NullPointerException e) {
                return false;
            } catch (ClassCastException e) {
                return false;
            }
        }

        /**
         * �Ƚ����������Ƿ����.
         *
         * @param o1 ����1
         * @param o2 ����2
         *
         * @return ������, �򷵻�<code>true</code>
         */
        private boolean eq(Object o1, Object o2) {
            return (o1 == null) ? (o2 == null)
                                : o1.equals(o2);
        }

        /**
         * ȡ��hashֵ, ������������Ч, ��hashֵҲ���.
         *
         * @return hashֵ
         */
        public int hashCode() {
            return hashCode;
        }

        /**
         * ���ƶ���.
         *
         * @return cache key�ĸ���
         */
        public Object clone() {
            try {
                return super.clone();
            } catch (CloneNotSupportedException e) {
                throw new InternalError(MessageFormat.format(
                                                ResourceBundleConstant.RB_CLONE_NOT_SUPPORTED,
                                                new Object[] {
                    CacheKey.class.getName()
                }));
            }
        }

        /**
         * ȡ���ַ���ֵ��ʾ.
         *
         * @return �ַ�����ʾ
         */
        public String toString() {
            return new StringBuffer("CacheKey[factory=").append((factoryRef == null)
                                                                    ? "null"
                                                                    : factoryRef.get())
                                                        .append(", bundleName=").append(bundleName)
                                                        .append(", defaultLocale=")
                                                        .append(defaultLocale).append("]")
                                                        .toString();
        }
    }
}
TOP

Related Classes of com.alibaba.toolkit.util.resourcebundle.ResourceBundleFactory

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.