001/*
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements.  See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership.  The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the
007 * "License"); you may not use this file except in compliance
008 * with the License.  You may obtain a copy of the License at
009 *
010 *   https://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing,
013 * software distributed under the License is distributed on an
014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015 * KIND, either express or implied.  See the License for the
016 * specific language governing permissions and limitations
017 * under the License.
018 */
019
020/*
021 * THE FILE HAS BEEN AUTOGENERATED BY MSGTOOL TOOL.
022 * All changes made to this file manually will be overwritten
023 * if this tool runs again. Better make changes in the template file.
024 */
025
026package org.apache.commons.compress.harmony.archive.internal.nls;
027
028import java.security.AccessController;
029import java.security.PrivilegedAction;
030import java.util.Arrays;
031import java.util.Locale;
032import java.util.MissingResourceException;
033import java.util.Objects;
034import java.util.ResourceBundle;
035
036//import org.apache.commons.compress.harmony.kernel.vm.VM;
037
038/**
039 * This class retrieves strings from a resource bundle and returns them, formatting them with MessageFormat when required.
040 * <p>
041 * It is used by the system classes to provide national language support, by looking up messages in the {@code
042 *    org.apache.commons.compress.harmony.archive.internal.nls.messages
043 * } resource bundle. Note that if this file is not available, or an invalid key is looked up, or resource bundle support is not available, the key itself
044 * will be returned as the associated message. This means that the <em>KEY</em> should a reasonable human-readable (english) string.
045 */
046public class Messages {
047
048    // ResourceBundle holding the system messages.
049    private static ResourceBundle bundle;
050
051    static {
052        // Attempt to load the messages.
053        try {
054            bundle = setLocale(Locale.getDefault(), "org.apache.commons.compress.harmony.archive.internal.nls.messages"); //$NON-NLS-1$
055        } catch (final Throwable e) {
056            e.printStackTrace();
057        }
058    }
059
060    /**
061     * Generates a formatted text string given a source string containing "argument markers" of the form "{argNum}" where each argNum must be in the range 0..9.
062     * The result is generated by inserting the toString of each argument into the position indicated in the string.
063     * <p>
064     * To insert the "{" character into the output, use a single backslash character to escape it (i.e. "\{"). The "}" character does not need to be escaped.
065     *
066     * @param format String the format to use when printing.
067     * @param args   Object[] the arguments to use.
068     * @return String the formatted message.
069     */
070    public static String format(final String format, final Object[] args) {
071        final StringBuilder answer = new StringBuilder(format.length() + args.length * 20);
072        final String[] argStrings = new String[args.length];
073        Arrays.setAll(argStrings, i -> Objects.toString(args[i], "<null>")); //$NON-NLS-1$
074        int lastI = 0;
075        for (int i = format.indexOf('{', 0); i >= 0; i = format.indexOf('{', lastI)) {
076            if (i != 0 && format.charAt(i - 1) == '\\') {
077                // It's escaped, just print and loop.
078                if (i != 1) {
079                    answer.append(format.substring(lastI, i - 1));
080                }
081                answer.append('{');
082                lastI = i + 1;
083            } else // It's a format character.
084            if (i > format.length() - 3) {
085                // Bad format, just print and loop.
086                answer.append(format.substring(lastI));
087                lastI = format.length();
088            } else {
089                final int argnum = (byte) Character.digit(format.charAt(i + 1), 10);
090                if (argnum < 0 || format.charAt(i + 2) != '}') {
091                    // Bad format, just print and loop.
092                    answer.append(format.substring(lastI, i + 1));
093                    lastI = i + 1;
094                } else {
095                    // Got a good one!
096                    answer.append(format.substring(lastI, i));
097                    if (argnum >= argStrings.length) {
098                        answer.append("<missing argument>"); //$NON-NLS-1$
099                    } else {
100                        answer.append(argStrings[argnum]);
101                    }
102                    lastI = i + 3;
103                }
104            }
105        }
106        if (lastI < format.length()) {
107            answer.append(format.substring(lastI));
108        }
109        return answer.toString();
110    }
111
112    /**
113     * Gets a message which has no arguments.
114     *
115     * @param msg String the key to look up.
116     * @return String the message for that key in the system message bundle.
117     */
118    public static String getString(final String msg) {
119        if (bundle == null) {
120            return msg;
121        }
122        try {
123            return bundle.getString(msg);
124        } catch (final MissingResourceException e) {
125            return "Missing message: " + msg; //$NON-NLS-1$
126        }
127    }
128
129    /**
130     * Gets a message which takes 1 character argument.
131     *
132     * @param msg String the key to look up.
133     * @param arg char the character to insert in the formatted output.
134     * @return String the message for that key in the system message bundle.
135     */
136    public static String getString(final String msg, final char arg) {
137        return getString(msg, new Object[] { String.valueOf(arg) });
138    }
139
140    /**
141     * Gets a message which takes 1 integer argument.
142     *
143     * @param msg String the key to look up.
144     * @param arg int the integer to insert in the formatted output.
145     * @return String the message for that key in the system message bundle.
146     */
147    public static String getString(final String msg, final int arg) {
148        return getString(msg, new Object[] { Integer.toString(arg) });
149    }
150
151    /**
152     * Gets a message which takes 1 argument.
153     *
154     * @param msg String the key to look up.
155     * @param arg Object the object to insert in the formatted output.
156     * @return String the message for that key in the system message bundle.
157     */
158    public static String getString(final String msg, final Object arg) {
159        return getString(msg, new Object[] { arg });
160    }
161
162    /**
163     * Gets a message which takes 2 arguments.
164     *
165     * @param msg  String the key to look up.
166     * @param arg1 Object an object to insert in the formatted output.
167     * @param arg2 Object another object to insert in the formatted output.
168     * @return String the message for that key in the system message bundle.
169     */
170    public static String getString(final String msg, final Object arg1, final Object arg2) {
171        return getString(msg, new Object[] { arg1, arg2 });
172    }
173
174    /**
175     * Gets a message which takes several arguments.
176     *
177     * @param msg  String the key to look up.
178     * @param args Object[] the objects to insert in the formatted output.
179     * @return String the message for that key in the system message bundle.
180     */
181    public static String getString(final String msg, final Object[] args) {
182        String format = msg;
183
184        if (bundle != null) {
185            try {
186                format = bundle.getString(msg);
187            } catch (final MissingResourceException ignored) {
188                // ignored
189            }
190        }
191
192        return format(format, args);
193    }
194
195    /**
196     * Changes the locale of the messages.
197     *
198     * @param locale   Locale the locale to change to.
199     * @param resource resource name.
200     * @return The ResourceBundle.
201     */
202    public static ResourceBundle setLocale(final Locale locale, final String resource) {
203        try {
204            // VM.bootCallerClassLoader() returns null
205            final ClassLoader loader = null; // VM.bootCallerClassLoader();
206            return (ResourceBundle) AccessController.doPrivileged(
207                    (PrivilegedAction<Object>) () -> ResourceBundle.getBundle(resource, locale, loader != null ? loader : ClassLoader.getSystemClassLoader()));
208        } catch (final MissingResourceException ignored) {
209            // ignored
210        }
211        return null;
212    }
213}