EMMA Coverage Report (generated Wed Jun 28 22:15:27 PDT 2006)
[all classes][org.apache.derby.iapi.services.i18n]

COVERAGE SUMMARY FOR SOURCE FILE [MessageService.java]

nameclass, %method, %block, %line, %
MessageService.java100% (1/1)82%  (14/17)68%  (323/476)63%  (70.9/112)

COVERAGE BREAKDOWN BY CLASS AND METHOD

nameclass, %method, %block, %line, %
     
class MessageService100% (1/1)82%  (14/17)68%  (323/476)63%  (70.9/112)
<static initializer> 100% (1/1)100% (7/7)100% (1/1)
MessageService (): void 100% (1/1)100% (3/3)100% (1/1)
formatMessage (ResourceBundle, String, Object [], boolean): String 100% (1/1)50%  (42/84)51%  (13.9/27)
getBundle (String): ResourceBundle 100% (1/1)100% (16/16)100% (6/6)
getBundleForLocale (Locale, String): ResourceBundle 100% (1/1)80%  (12/15)33%  (1/3)
getBundleWithEnDefault (String, Locale): ResourceBundle 100% (1/1)100% (9/9)100% (3/3)
getCompleteMessage (String, Object []): String 100% (1/1)94%  (17/18)80%  (4/5)
getLocalizedMessage (Locale, String, Object []): String 0%   (0/1)0%   (0/25)0%   (0/8)
getLocalizedMessage (int, short, String, String, int, int, int, int, int, int... 100% (1/1)76%  (137/181)73%  (27/37)
getProperty (String, String): String 0%   (0/1)0%   (0/17)0%   (0/6)
getTextMessage (String): String 100% (1/1)100% (5/5)100% (1/1)
getTextMessage (String, Object): String 100% (1/1)100% (9/9)100% (1/1)
getTextMessage (String, Object, Object): String 100% (1/1)100% (13/13)100% (1/1)
getTextMessage (String, Object, Object, Object): String 100% (1/1)100% (17/17)100% (1/1)
getTextMessage (String, Object, Object, Object, Object): String 0%   (0/1)0%   (0/21)0%   (0/1)
hashString50 (String): int 100% (1/1)100% (29/29)100% (8/8)
setFinder (BundleFinder): Object 100% (1/1)100% (7/7)100% (2/2)

1/*
2 
3   Derby - Class org.apache.derby.iapi.services.i18n.MessageService
4 
5   Copyright 2000, 2004 The Apache Software Foundation or its licensors, as applicable.
6 
7   Licensed under the Apache License, Version 2.0 (the "License");
8   you may not use this file except in compliance with the License.
9   You may obtain a copy of the License at
10 
11      http://www.apache.org/licenses/LICENSE-2.0
12 
13   Unless required by applicable law or agreed to in writing, software
14   distributed under the License is distributed on an "AS IS" BASIS,
15   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16   See the License for the specific language governing permissions and
17   limitations under the License.
18 
19 */
20 
21package org.apache.derby.iapi.services.i18n;
22 
23import org.apache.derby.iapi.services.info.JVMInfo;
24import org.apache.derby.iapi.services.context.ShutdownException;
25 
26import java.util.Locale;
27import java.util.MissingResourceException;
28import java.util.ResourceBundle;
29import java.text.MessageFormat;
30 
31/**
32 *  Message Service implementation provides a mechanism for locating
33 * messages and substituting arguments for message parameters.
34 * It also provides a service for locating property values.
35 * <p>
36 * It uses the resource bundle mechanism for locating messages based on
37 * keys; the preferred form of resource bundle is a property file mapping
38 * keys to messages.
39 *
40 * @author ames
41 */
42public final class MessageService {
43 
44        private static final Locale EN = new Locale("en", "US");
45 
46        private static BundleFinder finder;
47 
48        private MessageService() {}
49 
50 
51        public static ResourceBundle getBundleForLocale(Locale locale, String msgId) {
52                try {
53                        return MessageService.getBundleWithEnDefault("org.apache.derby.loc.m"+hashString50(msgId), locale);
54                } catch (MissingResourceException mre) {
55                }
56                return null;
57        }
58 
59 
60        public static Object setFinder(BundleFinder theFinder) {
61                finder = theFinder;
62 
63                // Return an object for a caller to hang onto so
64                // Garbage collection doesn't GC this class.
65                return new MessageService().getClass();
66        }
67 
68        public static String getTextMessage(String messageID) {
69                return getCompleteMessage(messageID, (Object[]) null);
70        }
71        public static String getTextMessage(String messageID, Object a1) {
72 
73                return getCompleteMessage(messageID, new Object[]{a1});
74        }
75        public static String getTextMessage(String messageID, Object a1, Object a2) {
76                return getCompleteMessage(messageID, new Object[]{a1, a2});
77        }
78        public static String getTextMessage(String messageID, Object a1, Object a2, Object a3) {
79                return getCompleteMessage(messageID, new Object[]{a1, a2, a3});
80        }
81        public static String getTextMessage(String messageID, Object a1, Object a2, Object a3, Object a4) {
82                return getCompleteMessage(messageID, new Object[]{a1, a2, a3, a4});
83        }
84 
85        /**
86          Transform the message from messageID to the actual error, warning, or
87          info message using the correct locale.
88 
89          <P>
90          The arguments to the messages are passed via an object array, the objects
91          in the array WILL be changed by this class. The caller should NOT get the
92          object back from this array.
93 
94         */
95        public static String getCompleteMessage(String messageId, Object[] arguments) {
96 
97                try {
98                        return formatMessage(getBundle(messageId), messageId, arguments, true);
99                } catch (MissingResourceException mre) {
100                        // message does not exist in the requested locale or the default locale.
101                        // most likely it does exist in our fake base class _en, so try that.
102                } catch (ShutdownException se) {
103                }
104                return formatMessage(getBundleForLocale(EN, messageId), messageId, arguments, false);
105        }
106 
107        /**
108          Method used by Cloudscape Network Server to get localized message (original call
109          from jcc.
110 
111          @param sqlcode        sqlcode, not used.
112          @param errmcLen        sqlerrmc length
113          @param sqlerrmc        sql error message tokens, variable part of error message (ie.,
114                                                arguments) plus messageId, separated by separator.
115          @param sqlerrp        not used
116          @param errd0                not used
117          @param warn                not used
118          @param sqlState        5-char sql state
119          @param file                not used
120          @param localeStr        client locale in string
121          @param msg                OUTPUT parameter, localized error message
122          @param rc                        OUTPUT parameter, return code -- 0 for success
123         */
124        public static void getLocalizedMessage(int sqlcode, short errmcLen, String sqlerrmc,
125                                                                                String sqlerrp, int errd0, int errd1, int errd2,
126                                                                                int errd3, int errd4, int errd5, String warn,
127                                                                                String sqlState, String file, String localeStr,
128                                                                                String[] msg, int[] rc)
129        {
130                //figure out client locale from input locale string
131 
132                int _pos1 = localeStr.indexOf("_");                // "_" position
133                int _pos2 = localeStr.lastIndexOf("_");
134 
135                Locale locale = EN;                //default locale
136                if (_pos1 != -1)
137                {
138                        String language = localeStr.substring(0, _pos1);
139                        if (_pos2 == _pos1)
140                        {
141                                String country = localeStr.substring(_pos1 + 1);
142                                locale = new Locale(language, country);
143                        }
144                        else
145                        {
146                                String country = localeStr.substring(_pos1 + 1, _pos2);
147                                String variant = localeStr.substring(_pos2 + 1);
148                                locale = new Locale(language, country, variant);
149                        }
150                }
151 
152                // get messageId and arguments, messageId is necessary for us to look up
153                // localized message from property file.  messageId was sent as the last
154                // token in the sqlerrmc.
155 
156                String messageId = sqlState;         //use sqlState if we don't have messageId
157                Object[] arguments = null;
158                if (sqlerrmc != null && sqlerrmc.length() > 0)
159                {
160                        char [] sqlerrmc_chars = sqlerrmc.toCharArray();
161                        int numArgs = 0, lastSepIdx = -1; // last separator index
162                        for (int i = 0; i < sqlerrmc_chars.length; i++)
163                        {
164                                if (sqlerrmc_chars[i] == 20)        // separator
165                                {
166                                        numArgs++;
167                                        lastSepIdx = i;
168                                }
169                        }
170                        if (numArgs == 0)
171                                messageId = new String(sqlerrmc_chars); //no args, only messageId then
172                        else
173                        {
174                                messageId = new String(sqlerrmc_chars, lastSepIdx+1, sqlerrmc_chars.length-lastSepIdx-1);
175                                arguments = new Object[numArgs];
176                                for (int start = 0, arg = 0, i = 0; i < lastSepIdx + 1; i++)
177                                {
178                                        if (i == lastSepIdx || sqlerrmc_chars[i] == 20)        // delimiter 
179                                        {
180                                                arguments[arg++] = new String(sqlerrmc_chars, start, i - start);
181                                                start = i + 1;
182                                        }
183                                }
184                        }
185                }
186 
187                try {
188                        msg[0] = formatMessage(getBundleForLocale(locale, messageId), messageId, arguments, true);
189                        rc[0] = 0;
190                        return;
191                } catch (MissingResourceException mre) {
192                        // message does not exist in the requested locale
193                        // most likely it does exist in our fake base class _en, so try that.
194                } catch (ShutdownException se) {
195                }
196                msg[0] = formatMessage(getBundleForLocale(EN, messageId), messageId, arguments, false);
197                rc[0] = 0;
198        }
199        
200        /**
201          Method used by Cloudscape Network Server to get localized message 
202 
203          @param locale                locale
204          @param messageId        message id
205          @param args                message arguments
206         */
207        public static String getLocalizedMessage(Locale locale, String messageId, Object [] args)
208        {
209                String locMsg = null;
210 
211                try {
212                        locMsg = formatMessage(getBundleForLocale(locale, messageId), messageId, args, true);
213                        return locMsg;
214                } catch (MissingResourceException mre) {
215                        // message does not exist in the requested locale
216                        // most likely it does exist in our fake base class _en, so try that.
217                } catch (ShutdownException se) {
218                }
219                locMsg = formatMessage(getBundleForLocale(EN, messageId), messageId, args, false);
220                return locMsg;
221        }
222 
223        /**
224         */
225        public static String getProperty(String messageId, String propertyName) {
226 
227                ResourceBundle bundle = getBundle(messageId);
228 
229                try {
230                        if (bundle != null)
231                                return bundle.getString(messageId.concat(".").concat(propertyName));
232                } catch (MissingResourceException mre) {
233                }
234                return null;
235        }
236 
237        //
238        // class implementation
239        //
240        public static String formatMessage(ResourceBundle bundle, String messageId, Object[] arguments, boolean lastChance) {
241 
242                if (arguments == null)
243                        arguments = new Object[0];
244 
245                if (bundle != null) {
246 
247                        try {
248                                messageId = bundle.getString(messageId);
249 
250                                try {
251                                        return MessageFormat.format(messageId, arguments);
252                                }
253                                catch (IllegalArgumentException iae) {
254                                }
255                                catch (NullPointerException npe) {
256                                        //
257                                        //null arguments cause a NullPointerException. 
258                                        //This improves reporting.
259                                }
260 
261                        } catch (MissingResourceException mre) {
262                                // caller will try and handle the last chance
263                                if (lastChance)
264                                        throw mre;
265                        } 
266                }
267 
268                if (messageId == null)
269                        messageId = "UNKNOWN";
270 
271                
272                StringBuffer sb = new StringBuffer(messageId);
273 
274                sb.append(" : ");
275                int len = arguments.length;
276 
277                for (int i=0; i < len; i++) {
278                    // prepend a comma to all but the first
279                        if (i > 0)
280                                sb.append(", ");
281 
282                        sb.append('[');
283                        sb.append(i);
284                        sb.append("] ");
285                        if (arguments[i] == null)
286                                sb.append("null");
287                        else
288                                sb.append(arguments[i].toString());
289                }
290 
291                
292                return sb.toString();
293        }
294 
295        private static ResourceBundle getBundle(String messageId) {
296 
297                ResourceBundle bundle = null;
298 
299                if (finder != null)
300                        bundle = finder.getBundle(messageId);
301 
302                if (bundle == null) {
303                        bundle = MessageService.getBundleForLocale(Locale.getDefault(), messageId);
304                }
305 
306                return bundle;
307        }
308 
309        /**
310                Method to use instead of ResourceBundle.getBundle().
311                This method acts like ResourceBundle.getBundle() but if
312                the resource is not available in the requested locale,
313                default locale or base class the one for en_US is returned.
314        */
315 
316        public static ResourceBundle getBundleWithEnDefault(String resource, Locale locale) {
317 
318                try {
319                        return ResourceBundle.getBundle(resource, locale);
320                } catch (MissingResourceException mre) {
321 
322                        // This covers the case where neither the
323                        // requested locale or the default locale
324                        // have a resource.
325 
326                        return ResourceBundle.getBundle(resource, EN);
327                }
328        }
329 
330        /**
331                Hash function to split messages into 50 files based
332                upon the message identifier or SQLState. We don't use
333                String.hashCode() as it varies between releases and
334                doesn't provide an even distribution across the 50 files.
335 
336        */
337        public static int hashString50(String key) {
338                int hash = 0;
339                int len = key.length();
340                if (len > 5)
341                        len = 5;
342 
343                for (int i = 0; i < len; i++) {
344                        hash += key.charAt(i);
345                }
346                hash = hash % 50;
347                return hash;
348        }
349}

[all classes][org.apache.derby.iapi.services.i18n]
EMMA 2.0.5312 (C) Vladimir Roubtsov