001/*
002 * $Id: Chapter.java 3373 2008-05-12 16:21:24Z xlv $
003 *
004 * This file is part of the iText (R) project.
005 * Copyright (c) 1998-2011 1T3XT BVBA
006 * Authors: Bruno Lowagie, Paulo Soares, et al.
007 *
008 * This program is free software; you can redistribute it and/or modify
009 * it under the terms of the GNU Affero General Public License version 3
010 * as published by the Free Software Foundation with the addition of the
011 * following permission added to Section 15 as permitted in Section 7(a):
012 * FOR ANY PART OF THE COVERED WORK IN WHICH THE COPYRIGHT IS OWNED BY 1T3XT,
013 * 1T3XT DISCLAIMS THE WARRANTY OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
014 *
015 * This program is distributed in the hope that it will be useful, but
016 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
017 * or FITNESS FOR A PARTICULAR PURPOSE.
018 * See the GNU Affero General Public License for more details.
019 * You should have received a copy of the GNU Affero General Public License
020 * along with this program; if not, see http://www.gnu.org/licenses or write to
021 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
022 * Boston, MA, 02110-1301 USA, or download the license from the following URL:
023 * http://itextpdf.com/terms-of-use/
024 *
025 * The interactive user interfaces in modified source and object code versions
026 * of this program must display Appropriate Legal Notices, as required under
027 * Section 5 of the GNU Affero General Public License.
028 *
029 * In accordance with Section 7(b) of the GNU Affero General Public License,
030 * a covered work must retain the producer line in every PDF that is created
031 * or manipulated using iText.
032 *
033 * You can be released from the requirements of the license by purchasing
034 * a commercial license. Buying such a license is mandatory as soon as you
035 * develop commercial activities involving the iText software without
036 * disclosing the source code of your own applications.
037 * These activities include: offering paid services to customers as an ASP,
038 * serving PDFs on the fly in a web application, shipping iText with a closed
039 * source product.
040 *
041 * For more information, please contact iText Software Corp. at this
042 * address: sales@itextpdf.com
043 */
044package com.itextpdf.text.error_messages;
045
046import java.io.BufferedReader;
047import java.io.IOException;
048import java.io.InputStream;
049import java.io.InputStreamReader;
050import java.io.Reader;
051import java.util.HashMap;
052
053import com.itextpdf.text.pdf.BaseFont;
054
055/**
056 * Localizes error messages. The messages are located in the package
057 * com.itextpdf.text.error_messages in the form language_country.lng.
058 * The internal file encoding is UTF-8 without any escape chars, it's not a
059 * normal property file. See en.lng for more information on the internal format.
060 * @author Paulo Soares (psoares@glintt.com)
061 */
062public final class MessageLocalization {
063    private static HashMap<String, String> defaultLanguage = new HashMap<String, String>();
064    private static HashMap<String, String> currentLanguage;
065    private static final String BASE_PATH = "com/itextpdf/text/l10n/error/";
066
067    private MessageLocalization() {
068    }
069
070    static {
071        try {
072            defaultLanguage = getLanguageMessages("en", null);
073        } catch (Exception ex) {
074            // do nothing
075        }
076        if (defaultLanguage == null)
077            defaultLanguage = new HashMap<String, String>();
078    }
079
080    /**
081     * Get a message without parameters.
082     * @param key the key to the message
083     * @return the message
084     */
085    public static String getMessage(String key) {
086        HashMap<String, String> cl = currentLanguage;
087        String val;
088        if (cl != null) {
089            val = cl.get(key);
090            if (val != null)
091                return val;
092        }
093        cl = defaultLanguage;
094        val = cl.get(key);
095        if (val != null)
096            return val;
097        return "No message found for " + key;
098    }
099
100
101
102    /**
103     * Get a message with one parameter as an primitive int. The parameter will replace the string
104     * "{1}" found in the message.
105     * @param key the key to the message
106     * @param p1 the parameter
107     * @return the message
108     */
109    public static String getComposedMessage(String key, int p1) {
110        return getComposedMessage(key, String.valueOf(p1), null, null, null);
111    }
112
113        /**
114         * Get a message with param.length parameters or none if param is null. In
115         * the message the "{1}", "{2}" to "{lenght of param array}" are replaced
116         * with the object.toString of the param array. (with param[0] being "{1}")
117         *
118         * @since iText 5.0.6
119         * @param key
120         *            the key to the message
121         * @param param array of parameter objects, (toString is used to add it to the message)
122         * @return the message
123         */
124        public static String getComposedMessage(final String key, final Object... param) {
125                String msg = getMessage(key);
126                if (null != param) {
127                        int i = 1;
128                        for (Object o : param) {
129                                if (null != o) {
130                                        msg = msg.replace("{" + i + "}", o.toString());
131                                }
132                                i++;
133                        }
134                }
135                return msg;
136        }
137
138    /**
139     * Sets the language to be used globally for the error messages. The language
140     * is a two letter lowercase country designation like "en" or "pt". The country
141     * is an optional two letter uppercase code like "US" or "PT".
142     * @param language the language
143     * @param country the country
144     * @return true if the language was found, false otherwise
145     * @throws IOException on error
146     */
147    public static boolean setLanguage(String language, String country) throws IOException {
148        HashMap<String, String> lang = getLanguageMessages(language, country);
149        if (lang == null)
150            return false;
151        currentLanguage = lang;
152        return true;
153    }
154
155    /**
156     * Sets the error messages directly from a Reader.
157     * @param r the Reader
158     * @throws IOException on error
159     */
160    public static void setMessages(Reader r) throws IOException {
161        currentLanguage = readLanguageStream(r);
162    }
163
164    private static HashMap<String, String> getLanguageMessages(String language, String country) throws IOException {
165        if (language == null)
166            throw new IllegalArgumentException("The language cannot be null.");
167        InputStream is = null;
168        try {
169            String file;
170            if (country != null)
171                file = language + "_" + country + ".lng";
172            else
173                file = language + ".lng";
174            is = BaseFont.getResourceStream(BASE_PATH + file, new MessageLocalization().getClass().getClassLoader());
175            if (is != null)
176                return readLanguageStream(is);
177            if (country == null)
178                return null;
179            file = language + ".lng";
180            is = BaseFont.getResourceStream(BASE_PATH + file, new MessageLocalization().getClass().getClassLoader());
181            if (is != null)
182                return readLanguageStream(is);
183            else
184                return null;
185        }
186        finally {
187            try {
188                if (null != is){
189                        is.close();
190                }
191            } catch (Exception exx) {
192            }
193            // do nothing
194        }
195    }
196
197    private static HashMap<String, String> readLanguageStream(InputStream is) throws IOException {
198        return readLanguageStream(new InputStreamReader(is, "UTF-8"));
199    }
200
201    private static HashMap<String, String> readLanguageStream(Reader r) throws IOException {
202        HashMap<String, String> lang = new HashMap<String, String>();
203        BufferedReader br = new BufferedReader(r);
204        String line;
205        while ((line = br.readLine()) != null) {
206            int idxeq = line.indexOf('=');
207            if (idxeq < 0)
208                continue;
209            String key = line.substring(0, idxeq).trim();
210            if (key.startsWith("#"))
211                continue;
212            lang.put(key, line.substring(idxeq + 1));
213        }
214        return lang;
215    }
216}