1/* 2 * reserved comment block 3 * DO NOT REMOVE OR ALTER! 4 */ 5/* 6 * Licensed to the Apache Software Foundation (ASF) under one or more 7 * contributor license agreements. See the NOTICE file distributed with 8 * this work for additional information regarding copyright ownership. 9 * The ASF licenses this file to You under the Apache License, Version 2.0 10 * (the "License"); you may not use this file except in compliance with 11 * the License. You may obtain a copy of the License at 12 * 13 * http://www.apache.org/licenses/LICENSE-2.0 14 * 15 * Unless required by applicable law or agreed to in writing, software 16 * distributed under the License is distributed on an "AS IS" BASIS, 17 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 * See the License for the specific language governing permissions and 19 * limitations under the License. 20 */ 21 22package com.sun.org.apache.xml.internal.serializer.utils; 23 24import com.sun.org.apache.xalan.internal.utils.SecuritySupport; 25import java.util.ListResourceBundle; 26import java.util.Locale; 27import java.util.MissingResourceException; 28import java.util.ResourceBundle; 29 30/** 31 * A utility class for issuing error messages. 32 * 33 * A user of this class normally would create a singleton 34 * instance of this class, passing the name 35 * of the message class on the constructor. For example: 36 * <CODE> 37 * static Messages x = new Messages("org.package.MyMessages"); 38 * </CODE> 39 * Later the message is typically generated this way if there are no 40 * substitution arguments: 41 * <CODE> 42 * String msg = x.createMessage(org.package.MyMessages.KEY_ONE, null); 43 * </CODE> 44 * If there are arguments substitutions then something like this: 45 * <CODE> 46 * String filename = ...; 47 * String directory = ...; 48 * String msg = x.createMessage(org.package.MyMessages.KEY_TWO, 49 * new Object[] {filename, directory) ); 50 * </CODE> 51 * 52 * The constructor of an instance of this class must be given 53 * the class name of a class that extends java.util.ListResourceBundle 54 * ("org.package.MyMessages" in the example above). 55 * The name should not have any language suffix 56 * which will be added automatically by this utility class. 57 * 58 * The message class ("org.package.MyMessages") 59 * must define the abstract method getContents() that is 60 * declared in its base class, for example: 61 * <CODE> 62 * public Object[][] getContents() {return contents;} 63 * </CODE> 64 * 65 * It is suggested that the message class expose its 66 * message keys like this: 67 * <CODE> 68 * public static final String KEY_ONE = "KEY1"; 69 * public static final String KEY_TWO = "KEY2"; 70 * . . . 71 * </CODE> 72 * and used through their names (KEY_ONE ...) rather than 73 * their values ("KEY1" ...). 74 * 75 * The field contents (returned by getContents() 76 * should be initialized something like this: 77 * <CODE> 78 * public static final Object[][] contents = { 79 * { KEY_ONE, "Something has gone wrong!" }, 80 * { KEY_TWO, "The file ''{0}'' does not exist in directory ''{1}''." }, 81 * . . . 82 * { KEY_N, "Message N" } } 83 * </CODE> 84 * 85 * Where that section of code with the KEY to Message mappings 86 * (where the message classes 'contents' field is initialized) 87 * can have the Message strings translated in an alternate language 88 * in a errorResourceClass with a language suffix. 89 * 90 * 91 * This class is not a public API, it is only public because it is 92 * used in com.sun.org.apache.xml.internal.serializer. 93 * 94 * @xsl.usage internal 95 */ 96public final class Messages 97{ 98 /** The local object to use. */ 99 private final Locale m_locale = Locale.getDefault(); 100 101 /** The language specific resource object for messages. */ 102 private ListResourceBundle m_resourceBundle; 103 104 /** The class name of the error message string table with no language suffix. */ 105 private String m_resourceBundleName; 106 107 108 109 /** 110 * Constructor. 111 * @param resourceBundle the class name of the ListResourceBundle 112 * that the instance of this class is associated with and will use when 113 * creating messages. 114 * The class name is without a language suffix. If the value passed 115 * is null then loadResourceBundle(errorResourceClass) needs to be called 116 * explicitly before any messages are created. 117 * 118 * @xsl.usage internal 119 */ 120 Messages(String resourceBundle) 121 { 122 123 m_resourceBundleName = resourceBundle; 124 } 125 126 127 /** 128 * Get the Locale object that is being used. 129 * 130 * @return non-null reference to Locale object. 131 * @xsl.usage internal 132 */ 133 private Locale getLocale() 134 { 135 return m_locale; 136 } 137 138 /** 139 * Creates a message from the specified key and replacement 140 * arguments, localized to the given locale. 141 * 142 * @param msgKey The key for the message text. 143 * @param args The arguments to be used as replacement text 144 * in the message created. 145 * 146 * @return The formatted message string. 147 * @xsl.usage internal 148 */ 149 public final String createMessage(String msgKey, Object args[]) 150 { 151 if (m_resourceBundle == null) 152 m_resourceBundle = SecuritySupport.getResourceBundle(m_resourceBundleName); 153 154 if (m_resourceBundle != null) 155 { 156 return createMsg(m_resourceBundle, msgKey, args); 157 } 158 else 159 return "Could not load the resource bundles: "+ m_resourceBundleName; 160 } 161 162 /** 163 * Creates a message from the specified key and replacement 164 * arguments, localized to the given locale. 165 * 166 * @param errorCode The key for the message text. 167 * 168 * @param fResourceBundle The resource bundle to use. 169 * @param msgKey The message key to use. 170 * @param args The arguments to be used as replacement text 171 * in the message created. 172 * 173 * @return The formatted message string. 174 * @xsl.usage internal 175 */ 176 private final String createMsg( 177 ListResourceBundle fResourceBundle, 178 String msgKey, 179 Object args[]) //throws Exception 180 { 181 182 String fmsg = null; 183 boolean throwex = false; 184 String msg = null; 185 186 if (msgKey != null) 187 msg = fResourceBundle.getString(msgKey); 188 else 189 msgKey = ""; 190 191 if (msg == null) 192 { 193 throwex = true; 194 /* The message is not in the bundle . . . this is bad, 195 * so try to get the message that the message is not in the bundle 196 */ 197 try 198 { 199 200 msg = 201 java.text.MessageFormat.format( 202 MsgKey.BAD_MSGKEY, 203 new Object[] { msgKey, m_resourceBundleName }); 204 } 205 catch (Exception e) 206 { 207 /* even the message that the message is not in the bundle is 208 * not there ... this is really bad 209 */ 210 msg = 211 "The message key '" 212 + msgKey 213 + "' is not in the message class '" 214 + m_resourceBundleName+"'"; 215 } 216 } 217 else if (args != null) 218 { 219 try 220 { 221 // Do this to keep format from crying. 222 // This is better than making a bunch of conditional 223 // code all over the place. 224 int n = args.length; 225 226 for (int i = 0; i < n; i++) 227 { 228 if (null == args[i]) 229 args[i] = ""; 230 } 231 232 fmsg = java.text.MessageFormat.format(msg, args); 233 // if we get past the line above we have create the message ... hurray! 234 } 235 catch (Exception e) 236 { 237 throwex = true; 238 try 239 { 240 // Get the message that the format failed. 241 fmsg = 242 java.text.MessageFormat.format( 243 MsgKey.BAD_MSGFORMAT, 244 new Object[] { msgKey, m_resourceBundleName }); 245 fmsg += " " + msg; 246 } 247 catch (Exception formatfailed) 248 { 249 // We couldn't even get the message that the format of 250 // the message failed ... so fall back to English. 251 fmsg = 252 "The format of message '" 253 + msgKey 254 + "' in message class '" 255 + m_resourceBundleName 256 + "' failed."; 257 } 258 } 259 } 260 else 261 fmsg = msg; 262 263 if (throwex) 264 { 265 throw new RuntimeException(fmsg); 266 } 267 268 return fmsg; 269 } 270 271} 272