001    //$HeadURL: svn+ssh://jwilden@svn.wald.intevation.org/deegree/base/branches/2.5_testing/src/org/deegree/i18n/Messages.java $
002    /*----------------------------------------------------------------------------
003     This file is part of deegree, http://deegree.org/
004     Copyright (C) 2001-2009 by:
005     Department of Geography, University of Bonn
006     and
007     lat/lon GmbH
008    
009     This library is free software; you can redistribute it and/or modify it under
010     the terms of the GNU Lesser General Public License as published by the Free
011     Software Foundation; either version 2.1 of the License, or (at your option)
012     any later version.
013     This library is distributed in the hope that it will be useful, but WITHOUT
014     ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
015     FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
016     details.
017     You should have received a copy of the GNU Lesser General Public License
018     along with this library; if not, write to the Free Software Foundation, Inc.,
019     59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
020    
021     Contact information:
022    
023     lat/lon GmbH
024     Aennchenstr. 19, 53177 Bonn
025     Germany
026     http://lat-lon.de/
027    
028     Department of Geography, University of Bonn
029     Prof. Dr. Klaus Greve
030     Postfach 1147, 53001 Bonn
031     Germany
032     http://www.geographie.uni-bonn.de/deegree/
033    
034     e-mail: info@deegree.org
035     ----------------------------------------------------------------------------*/
036    package org.deegree.i18n;
037    
038    import java.io.IOException;
039    import java.io.InputStream;
040    import java.text.MessageFormat;
041    import java.util.Enumeration;
042    import java.util.HashMap;
043    import java.util.Iterator;
044    import java.util.Locale;
045    import java.util.Map;
046    import java.util.Properties;
047    
048    import org.deegree.framework.log.ILogger;
049    import org.deegree.framework.log.LoggerFactory;
050    import org.deegree.framework.util.BootLogger;
051    
052    /**
053     * Responsible for the access to messages that are visible to the user.
054     * <p>
055     * Messages are read from the properties file <code>messages_LANG.properties</code> (LANG is always a lowercased ISO 639
056     * code), so internationalization is supported. If a certain property (or the property file) for the specific default
057     * language of the system is not found, the message is taken from <code>messages_en.properties</code>.
058     * 
059     * @see Locale#getLanguage()
060     * 
061     * @author <a href="mailto:poth@lat-lon.de">Andreas Poth</a>
062     * @author <a href="mailto:taddei@lat-lon.de">Ugo Taddei</a>
063     * @author <a href="mailto:schneider@lat-lon.de">Markus Schneider</a>
064     * @author last edited by: $Author: apoth $
065     * 
066     * @version $Revision: 26673 $, $Date: 2010-09-10 12:58:10 +0200 (Fr, 10 Sep 2010) $
067     */
068    public class Messages {
069    
070        private static final ILogger LOG = LoggerFactory.getLogger( Messages.class );
071    
072        /* This definition allows Eclipse to display the content of referenced message keys. */
073        @SuppressWarnings("unused")
074        private static final String BUNDLE_NAME = "org.deegree.i18n.messages_en";
075    
076        private static Properties defaultProps = new Properties();
077    
078        private static Map<Locale, Properties> props = new HashMap<Locale, Properties>();
079    
080        private static String lang;
081    
082        /**
083         * Initialization done at class loading time.
084         */
085        static {
086            try {
087                // load all messages from default file ("org/deegree/i18n/message_en.properties")
088                String fileName = "messages_en.properties";
089                InputStream is = Messages.class.getResourceAsStream( fileName );
090                if ( is == null ) {
091                    BootLogger.log( "Error while initializing " + Messages.class.getName() + " : "
092                                    + " default message file: '" + fileName + " not found." );
093                }
094                is = Messages.class.getResourceAsStream( fileName );
095                defaultProps.load( is );
096                is.close();
097    
098                // override messages using file "/message_en.properties"
099                fileName = "/messages_en.properties";
100                overrideMessages( fileName, defaultProps );
101    
102                lang = Locale.getDefault().getLanguage();
103                if ( !"".equals( lang ) && !"en".equals( lang ) ) {
104                    // override messages using file "org/deegree/i18n/message_LANG.properties"
105                    fileName = "messages_" + lang + ".properties";
106                    overrideMessages( fileName, defaultProps );
107                    // override messages using file "/message_LANG.properties"
108                    fileName = "/messages_" + lang + ".properties";
109                    overrideMessages( fileName, defaultProps );
110                }
111            } catch ( IOException e ) {
112                BootLogger.logError( "Error while initializing " + Messages.class.getName() + " : " + e.getMessage(), e );
113            }
114        }
115    
116        private static void overrideMessages( String propertiesFile, Properties props )
117                                throws IOException {
118            InputStream is = Messages.class.getResourceAsStream( propertiesFile );
119            if ( is != null ) {
120                // override default messages
121                Properties overrideProps = new Properties();
122                overrideProps.load( is );
123                is.close();
124                Iterator<?> iter = overrideProps.keySet().iterator();
125                while ( iter.hasNext() ) {
126                    String key = (String) iter.next();
127                    props.put( key, overrideProps.get( key ) );
128                }
129            }
130        }
131    
132        private static String get( Properties props, String key, Object... args ) {
133            String s = (String) props.get( key );
134            if ( s != null ) {
135                return MessageFormat.format( s, args );
136            }
137    
138            return "$Message with key: " + key + " not found$";
139        }
140    
141        /**
142         * @param loc
143         *            the locale to be used
144         * @param key
145         *            to get
146         * @param arguments
147         *            to fill in the message
148         * @return the localized message
149         */
150        public static synchronized String get( Locale loc, String key, Object... arguments ) {
151            if ( loc.getLanguage().equals( lang ) ) {
152                return get( key, arguments );
153            }
154    
155            if ( !props.containsKey( loc ) ) {
156                Properties p = new Properties();
157    
158                String l = loc.getLanguage();
159    
160                if ( !"".equals( l ) ) {
161                    try {
162                        // override messages in this order:
163                        // messages_en.properties
164                        // /messages_en.properties
165                        // messages_lang.properties
166                        // /messages_lang.properties
167                        String fileName = "messages_en.properties";
168                        overrideMessages( fileName, p );
169                        fileName = "/messages_en.properties";
170                        overrideMessages( fileName, p );
171                        fileName = "messages_" + l + ".properties";
172                        overrideMessages( fileName, p );
173                        fileName = "/messages_" + l + ".properties";
174                        overrideMessages( fileName, p );
175                    } catch ( IOException e ) {
176                        LOG.logError( "Error loading language file for language '" + l + "': ", e );
177                    }
178                }
179    
180                props.put( loc, p );
181            }
182    
183            return get( props.get( loc ), key, arguments );
184        }
185    
186        /**
187         * 
188         * @param locale
189         * @return copy of complete list of properties
190         */
191        public static synchronized Properties getProperties( Locale locale ) {
192            if ( locale == null ) {
193                locale = Locale.getDefault();
194            }
195            if ( !props.containsKey( locale ) ) {
196                Properties p = new Properties();
197    
198                String l = locale.getLanguage();
199    
200                if ( !"".equals( l ) ) {
201                    try {
202                        // override messages in this order:
203                        // messages_en.properties
204                        // /messages_en.properties
205                        // messages_lang.properties
206                        // /messages_lang.properties
207                        String fileName = "messages_en.properties";
208                        overrideMessages( fileName, p );
209                        fileName = "/messages_en.properties";
210                        overrideMessages( fileName, p );
211                        fileName = "messages_" + l + ".properties";
212                        overrideMessages( fileName, p );
213                        fileName = "/messages_" + l + ".properties";
214                        overrideMessages( fileName, p );
215                    } catch ( IOException e ) {
216                        LOG.logError( "Error loading language file for language '" + l + "': ", e );
217                    }
218                }
219    
220                props.put( locale, p );
221            }
222            Properties p1 = props.get( locale );
223            Properties p2 = new Properties(  );
224            Enumeration<Object> keys = p1.keys();
225            while ( keys.hasMoreElements() ) {
226                String key = (String) keys.nextElement();
227                String value = p1.getProperty( key );
228                p2.put( key, value );
229                
230            }
231            return p2;
232        }
233    
234        /**
235         * Alias for #getMessage.
236         * 
237         * @param key
238         * @param arguments
239         * @return the message
240         */
241        public static String get( String key, Object... arguments ) {
242            return getMessage( key, arguments );
243        }
244    
245        /**
246         * Returns the message assigned to the passed key. If no message is assigned, an error message will be returned that
247         * indicates the missing key.
248         * 
249         * @see MessageFormat for conventions on string formatting and escape characters.
250         * 
251         * @param key
252         * @param arguments
253         * @return the message assigned to the passed key
254         */
255        public static String getMessage( String key, Object... arguments ) {
256            return get( defaultProps, key, arguments );
257        }
258    }