KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > derby > iapi > services > i18n > MessageService


1 /*
2
3    Derby - Class org.apache.derby.iapi.services.i18n.MessageService
4
5    Licensed to the Apache Software Foundation (ASF) under one or more
6    contributor license agreements. See the NOTICE file distributed with
7    this work for additional information regarding copyright ownership.
8    The ASF licenses this file to you under the Apache License, Version 2.0
9    (the "License"); you may not use this file except in compliance with
10    the License. You may obtain a copy of the License at
11
12       http://www.apache.org/licenses/LICENSE-2.0
13
14    Unless required by applicable law or agreed to in writing, software
15    distributed under the License is distributed on an "AS IS" BASIS,
16    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17    See the License for the specific language governing permissions and
18    limitations under the License.
19
20  */

21
22 package org.apache.derby.iapi.services.i18n;
23
24 import org.apache.derby.iapi.services.info.JVMInfo;
25 import org.apache.derby.iapi.services.context.ShutdownException;
26
27 import java.util.Locale JavaDoc;
28 import java.util.MissingResourceException JavaDoc;
29 import java.util.ResourceBundle JavaDoc;
30 import java.text.MessageFormat JavaDoc;
31
32 /**
33  * Message Service implementation provides a mechanism for locating
34  * messages and substituting arguments for message parameters.
35  * It also provides a service for locating property values.
36  * <p>
37  * It uses the resource bundle mechanism for locating messages based on
38  * keys; the preferred form of resource bundle is a property file mapping
39  * keys to messages.
40  *
41  * @author ames
42  */

43 public final class MessageService {
44
45     private static final Locale JavaDoc EN = new Locale JavaDoc("en", "US");
46
47     private static BundleFinder finder;
48
49     private MessageService() {}
50
51
52     public static ResourceBundle JavaDoc getBundleForLocale(Locale JavaDoc locale, String JavaDoc msgId) {
53         try {
54             return MessageService.getBundleWithEnDefault("org.apache.derby.loc.m"+hashString50(msgId), locale);
55         } catch (MissingResourceException JavaDoc mre) {
56         }
57         return null;
58     }
59
60
61     public static Object JavaDoc setFinder(BundleFinder theFinder) {
62         finder = theFinder;
63
64         // Return an object for a caller to hang onto so
65
// Garbage collection doesn't GC this class.
66
return new MessageService().getClass();
67     }
68
69     public static String JavaDoc getTextMessage(String JavaDoc messageID) {
70         return getCompleteMessage(messageID, (Object JavaDoc[]) null);
71     }
72     public static String JavaDoc getTextMessage(String JavaDoc messageID, Object JavaDoc a1) {
73
74         return getCompleteMessage(messageID, new Object JavaDoc[]{a1});
75     }
76     public static String JavaDoc getTextMessage(String JavaDoc messageID, Object JavaDoc a1, Object JavaDoc a2) {
77         return getCompleteMessage(messageID, new Object JavaDoc[]{a1, a2});
78     }
79     public static String JavaDoc getTextMessage(String JavaDoc messageID, Object JavaDoc a1, Object JavaDoc a2, Object JavaDoc a3) {
80         return getCompleteMessage(messageID, new Object JavaDoc[]{a1, a2, a3});
81     }
82     public static String JavaDoc getTextMessage(String JavaDoc messageID, Object JavaDoc a1, Object JavaDoc a2, Object JavaDoc a3, Object JavaDoc a4) {
83         return getCompleteMessage(messageID, new Object JavaDoc[]{a1, a2, a3, a4});
84     }
85
86     /**
87       Transform the message from messageID to the actual error, warning, or
88       info message using the correct locale.
89
90       <P>
91       The arguments to the messages are passed via an object array, the objects
92       in the array WILL be changed by this class. The caller should NOT get the
93       object back from this array.
94
95      */

96     public static String JavaDoc getCompleteMessage(String JavaDoc messageId, Object JavaDoc[] arguments) {
97
98         try {
99             return formatMessage(getBundle(messageId), messageId, arguments, true);
100         } catch (MissingResourceException JavaDoc mre) {
101             // message does not exist in the requested locale or the default locale.
102
// most likely it does exist in our fake base class _en, so try that.
103
} catch (ShutdownException se) {
104         }
105         return formatMessage(getBundleForLocale(EN, messageId), messageId, arguments, false);
106     }
107
108     /**
109       Method used by Cloudscape Network Server to get localized message (original call
110       from jcc.
111
112       @param sqlcode sqlcode, not used.
113       @param errmcLen sqlerrmc length
114       @param sqlerrmc sql error message tokens, variable part of error message (ie.,
115                         arguments) plus messageId, separated by separator.
116       @param sqlerrp not used
117       @param errd0 not used
118       @param warn not used
119       @param sqlState 5-char sql state
120       @param file not used
121       @param localeStr client locale in string
122       @param msg OUTPUT parameter, localized error message
123       @param rc OUTPUT parameter, return code -- 0 for success
124      */

125     public static void getLocalizedMessage(int sqlcode, short errmcLen, String JavaDoc sqlerrmc,
126                                         String JavaDoc sqlerrp, int errd0, int errd1, int errd2,
127                                         int errd3, int errd4, int errd5, String JavaDoc warn,
128                                         String JavaDoc sqlState, String JavaDoc file, String JavaDoc localeStr,
129                                         String JavaDoc[] msg, int[] rc)
130     {
131         //figure out client locale from input locale string
132

133         int _pos1 = localeStr.indexOf("_"); // "_" position
134
int _pos2 = localeStr.lastIndexOf("_");
135
136         Locale JavaDoc locale = EN; //default locale
137
if (_pos1 != -1)
138         {
139             String JavaDoc language = localeStr.substring(0, _pos1);
140             if (_pos2 == _pos1)
141             {
142                 String JavaDoc country = localeStr.substring(_pos1 + 1);
143                 locale = new Locale JavaDoc(language, country);
144             }
145             else
146             {
147                 String JavaDoc country = localeStr.substring(_pos1 + 1, _pos2);
148                 String JavaDoc variant = localeStr.substring(_pos2 + 1);
149                 locale = new Locale JavaDoc(language, country, variant);
150             }
151         }
152
153         // get messageId and arguments, messageId is necessary for us to look up
154
// localized message from property file. messageId was sent as the last
155
// token in the sqlerrmc.
156

157         String JavaDoc messageId = sqlState; //use sqlState if we don't have messageId
158
Object JavaDoc[] arguments = null;
159         if (sqlerrmc != null && sqlerrmc.length() > 0)
160         {
161             char [] sqlerrmc_chars = sqlerrmc.toCharArray();
162             int numArgs = 0, lastSepIdx = -1; // last separator index
163
for (int i = 0; i < sqlerrmc_chars.length; i++)
164             {
165                 if (sqlerrmc_chars[i] == 20) // separator
166
{
167                     numArgs++;
168                     lastSepIdx = i;
169                 }
170             }
171             if (numArgs == 0)
172                 messageId = new String JavaDoc(sqlerrmc_chars); //no args, only messageId then
173
else
174             {
175                 messageId = new String JavaDoc(sqlerrmc_chars, lastSepIdx+1, sqlerrmc_chars.length-lastSepIdx-1);
176                 arguments = new Object JavaDoc[numArgs];
177                 for (int start = 0, arg = 0, i = 0; i < lastSepIdx + 1; i++)
178                 {
179                     if (i == lastSepIdx || sqlerrmc_chars[i] == 20) // delimiter
180
{
181                         arguments[arg++] = new String JavaDoc(sqlerrmc_chars, start, i - start);
182                         start = i + 1;
183                     }
184                 }
185             }
186         }
187
188         try {
189             msg[0] = formatMessage(getBundleForLocale(locale, messageId), messageId, arguments, true);
190             rc[0] = 0;
191             return;
192         } catch (MissingResourceException JavaDoc mre) {
193             // message does not exist in the requested locale
194
// most likely it does exist in our fake base class _en, so try that.
195
} catch (ShutdownException se) {
196         }
197         msg[0] = formatMessage(getBundleForLocale(EN, messageId), messageId, arguments, false);
198         rc[0] = 0;
199     }
200     
201     /**
202       Method used by Cloudscape Network Server to get localized message
203
204       @param locale locale
205       @param messageId message id
206       @param args message arguments
207      */

208     public static String JavaDoc getLocalizedMessage(Locale JavaDoc locale, String JavaDoc messageId, Object JavaDoc [] args)
209     {
210         String JavaDoc locMsg = null;
211
212         try {
213             locMsg = formatMessage(getBundleForLocale(locale, messageId), messageId, args, true);
214             return locMsg;
215         } catch (MissingResourceException JavaDoc mre) {
216             // message does not exist in the requested locale
217
// most likely it does exist in our fake base class _en, so try that.
218
} catch (ShutdownException se) {
219         }
220         locMsg = formatMessage(getBundleForLocale(EN, messageId), messageId, args, false);
221         return locMsg;
222     }
223
224     /**
225      */

226     public static String JavaDoc getProperty(String JavaDoc messageId, String JavaDoc propertyName) {
227
228         ResourceBundle JavaDoc bundle = getBundle(messageId);
229
230         try {
231             if (bundle != null)
232                 return bundle.getString(messageId.concat(".").concat(propertyName));
233         } catch (MissingResourceException JavaDoc mre) {
234         }
235         return null;
236     }
237
238     //
239
// class implementation
240
//
241
public static String JavaDoc formatMessage(ResourceBundle JavaDoc bundle, String JavaDoc messageId, Object JavaDoc[] arguments, boolean lastChance) {
242
243         if (arguments == null)
244             arguments = new Object JavaDoc[0];
245
246         if (bundle != null) {
247
248             try {
249                 messageId = bundle.getString(messageId);
250
251                 try {
252                     return MessageFormat.format(messageId, arguments);
253                 }
254                 catch (IllegalArgumentException JavaDoc iae) {
255                 }
256                 catch (NullPointerException JavaDoc npe) {
257                     //
258
//null arguments cause a NullPointerException.
259
//This improves reporting.
260
}
261
262             } catch (MissingResourceException JavaDoc mre) {
263                 // caller will try and handle the last chance
264
if (lastChance)
265                     throw mre;
266             }
267         }
268
269         if (messageId == null)
270             messageId = "UNKNOWN";
271
272         
273         StringBuffer JavaDoc sb = new StringBuffer JavaDoc(messageId);
274
275         sb.append(" : ");
276         int len = arguments.length;
277
278         for (int i=0; i < len; i++) {
279             // prepend a comma to all but the first
280
if (i > 0)
281                 sb.append(", ");
282
283             sb.append('[');
284             sb.append(i);
285             sb.append("] ");
286             if (arguments[i] == null)
287                 sb.append("null");
288             else
289                 sb.append(arguments[i].toString());
290         }
291
292         
293         return sb.toString();
294     }
295
296     private static ResourceBundle JavaDoc getBundle(String JavaDoc messageId) {
297
298         ResourceBundle JavaDoc bundle = null;
299
300         if (finder != null)
301             bundle = finder.getBundle(messageId);
302
303         if (bundle == null) {
304             bundle = MessageService.getBundleForLocale(Locale.getDefault(), messageId);
305         }
306
307         return bundle;
308     }
309
310     /**
311         Method to use instead of ResourceBundle.getBundle().
312         This method acts like ResourceBundle.getBundle() but if
313         the resource is not available in the requested locale,
314         default locale or base class the one for en_US is returned.
315     */

316
317     public static ResourceBundle JavaDoc getBundleWithEnDefault(String JavaDoc resource, Locale JavaDoc locale) {
318
319         try {
320             return ResourceBundle.getBundle(resource, locale);
321         } catch (MissingResourceException JavaDoc mre) {
322
323             // This covers the case where neither the
324
// requested locale or the default locale
325
// have a resource.
326

327             return ResourceBundle.getBundle(resource, EN);
328         }
329     }
330
331     /**
332         Hash function to split messages into 50 files based
333         upon the message identifier or SQLState. We don't use
334         String.hashCode() as it varies between releases and
335         doesn't provide an even distribution across the 50 files.
336
337     */

338     public static int hashString50(String JavaDoc key) {
339         int hash = 0;
340         int len = key.length();
341         if (len > 5)
342             len = 5;
343
344         for (int i = 0; i < len; i++) {
345             hash += key.charAt(i);
346         }
347         hash = hash % 50;
348         return hash;
349     }
350 }
351
Popular Tags