1 /* 2 * $Id: MessageFactory.java 19191 2010-08-25 21:05:23Z tcarlson $ 3 * -------------------------------------------------------------------------------------- 4 * Copyright (c) MuleSoft, Inc. All rights reserved. http://www.mulesoft.com 5 * 6 * The software in this package is published under the terms of the CPAL v1.0 7 * license, a copy of which has been included with this distribution in the 8 * LICENSE.txt file. 9 */ 10 11 package org.mule.config.i18n; 12 13 import java.text.MessageFormat; 14 import java.util.Locale; 15 import java.util.MissingResourceException; 16 import java.util.ResourceBundle; 17 18 import org.apache.commons.logging.Log; 19 import org.apache.commons.logging.LogFactory; 20 21 22 public abstract class MessageFactory 23 { 24 /** 25 * This error code is used for {@link Message} instances that are not read from a 26 * resource bundles but are created only with a string. 27 */ 28 private static final int STATIC_ERROR_CODE = -1; 29 private static final transient Object[] EMPTY_ARGS = new Object[]{}; 30 31 protected transient Log logger = LogFactory.getLog(getClass()); 32 // since java 6 only 33 //protected final ReloadControl control = new ReloadControl(); 34 35 /** 36 * Computes the bundle's full path 37 * (<code>META-INF/services/org/mule/i18n/<bundleName>-messages.properties</code>) from 38 * <code>bundleName</code>. 39 * 40 * @param bundleName Name of the bundle without the "messages" suffix and without 41 * file extension. 42 */ 43 protected static String getBundlePath(String bundleName) 44 { 45 return "META-INF.services.org.mule.i18n." + bundleName + "-messages"; 46 } 47 48 /** 49 * Factory method to create a new {@link Message} instance that is filled with the formatted 50 * message with id <code>code</code> from the resource bundle <code>bundlePath</code>. 51 * 52 * @param bundlePath complete path to the resource bundle for lookup 53 * @param code numeric code of the message 54 * @param arg 55 * @see #getBundlePath(String) 56 */ 57 protected Message createMessage(String bundlePath, int code, Object arg) 58 { 59 return createMessage(bundlePath, code, new Object[] {arg}); 60 } 61 62 /** 63 * Factory method to create a new {@link Message} instance that is filled with the formatted 64 * message with id <code>code</code> from the resource bundle <code>bundlePath</code>. 65 * 66 * @param bundlePath complete path to the resource bundle for lookup 67 * @param code numeric code of the message 68 * @param arg1 69 * @param arg2 70 * @see #getBundlePath(String) 71 */ 72 protected Message createMessage(String bundlePath, int code, Object arg1, Object arg2) 73 { 74 return createMessage(bundlePath, code, new Object[] {arg1, arg2}); 75 } 76 77 /** 78 * Factory method to create a new {@link Message} instance that is filled with the formatted 79 * message with id <code>code</code> from the resource bundle <code>bundlePath</code>. 80 * 81 * @param bundlePath complete path to the resource bundle for lookup 82 * @param code numeric code of the message 83 * @param arg1 84 * @param arg2 85 * @param arg3 86 * @see #getBundlePath(String) 87 */ 88 protected Message createMessage(String bundlePath, int code, Object arg1, Object arg2, 89 Object arg3) 90 { 91 return createMessage(bundlePath, code, new Object[] {arg1, arg2, arg3}); 92 } 93 94 /** 95 * Factory method to create a new {@link Message} instance that is filled with the formatted 96 * message with id <code>code</code> from the resource bundle <code>bundlePath</code>. 97 * 98 * <b>Attention:</b> do not confuse this method with 99 * <code>createMessage(String, int, Object)</code>. 100 * 101 * @param bundlePath complete path to the resource bundle for lookup 102 * @param code numeric code of the message 103 * @param arguments 104 * @see #getBundlePath(String) 105 */ 106 protected Message createMessage(String bundlePath, int code, Object... arguments) 107 { 108 String messageString = getString(bundlePath, code, arguments); 109 return new Message(messageString, code, arguments); 110 } 111 112 /** 113 * Factory method to create a new {@link Message} instance that is filled with the formatted 114 * message with id <code>code</code> from the resource bundle <code>bundlePath</code>. 115 * 116 * @param bundlePath complete path to the resource bundle for lookup 117 * @param code numeric code of the message 118 */ 119 protected Message createMessage(String bundlePath, int code) 120 { 121 String messageString = getString(bundlePath, code, null); 122 return new Message(messageString, code, EMPTY_ARGS); 123 } 124 125 /** 126 * Factory method to create a {@link Message} instance that is not read from a resource bundle. 127 * 128 * @param message Message's message text 129 * @return a Messsage instance that has an error code of -1 and no arguments. 130 */ 131 public static Message createStaticMessage(String message) 132 { 133 return new Message(message, STATIC_ERROR_CODE, EMPTY_ARGS); 134 } 135 136 /** 137 * Factory method to read the message with code <code>code</code> from the resource bundle. 138 * 139 * @param bundlePath complete path to the resource bundle for lookup 140 * @param code numeric code of the message 141 * @return formatted error message as {@link String} 142 */ 143 protected String getString(String bundlePath, int code) 144 { 145 return getString(bundlePath, code, null); 146 } 147 148 /** 149 * Factory method to read the message with code <code>code</code> from the resource bundle. 150 * 151 * @param bundlePath complete path to the resource bundle for lookup 152 * @param code numeric code of the message 153 * @param arg 154 * @return formatted error message as {@link String} 155 */ 156 protected String getString(String bundlePath, int code, Object arg) 157 { 158 Object[] arguments = new Object[] {arg}; 159 return getString(bundlePath, code, arguments); 160 } 161 162 /** 163 * Factory method to read the message with code <code>code</code> from the resource bundle. 164 * 165 * @param bundlePath complete path to the resource bundle for lookup 166 * @param code numeric code of the message 167 * @param arg1 168 * @param arg2 169 * @return formatted error message as {@link String} 170 */ 171 protected String getString(String bundlePath, int code, Object arg1, Object arg2) 172 { 173 Object[] arguments = new Object[] {arg1, arg2}; 174 return getString(bundlePath, code, arguments); 175 } 176 177 protected String getString(String bundlePath, int code, Object[] args) 178 { 179 // We will throw a MissingResourceException if the bundle name is invalid 180 // This happens if the code references a bundle name that just doesn't exist 181 ResourceBundle bundle = getBundle(bundlePath); 182 183 try 184 { 185 String m = bundle.getString(String.valueOf(code)); 186 if (m == null) 187 { 188 logger.error("Failed to find message for id " + code + " in resource bundle " + bundlePath); 189 return ""; 190 } 191 192 return MessageFormat.format(m, args); 193 } 194 catch (MissingResourceException e) 195 { 196 logger.error("Failed to find message for id " + code + " in resource bundle " + bundlePath); 197 return ""; 198 } 199 } 200 201 /** 202 * @throws MissingResourceException if resource is missing 203 */ 204 private ResourceBundle getBundle(String bundlePath) 205 { 206 Locale locale = Locale.getDefault(); 207 if (logger.isTraceEnabled()) 208 { 209 logger.trace("Loading resource bundle: " + bundlePath + " for locale " + locale); 210 } 211 ResourceBundle bundle = ResourceBundle.getBundle(bundlePath, locale, getClassLoader()); 212 return bundle; 213 } 214 215 /** 216 * Override this method to return the classloader for the bundle/module which 217 * contains the needed resource files. 218 */ 219 protected ClassLoader getClassLoader() 220 { 221 final ClassLoader ccl = Thread.currentThread().getContextClassLoader(); 222 // if there's a deployment classloader present, use it for finding resources 223 return ccl == null ? getClass().getClassLoader() : ccl; 224 } 225 226 // since java 6 only 227 /*static class ReloadControl extends ResourceBundle.Control 228 { 229 boolean needsReload = true; 230 231 @Override 232 public boolean needsReload(String baseName, Locale locale, String format, ClassLoader loader, ResourceBundle bundle, long loadTime) 233 { 234 // TODO always for now 235 return true; 236 } 237 238 @Override 239 public long getTimeToLive(String baseName, Locale locale) 240 { 241 if (needsReload) 242 { 243 // must be zero, as other 'DONT_CACHE' constant doesn't work here, and is -1 244 return 0; 245 } 246 247 return ResourceBundle.Control.TTL_NO_EXPIRATION_CONTROL; 248 } 249 }*/ 250 } 251 252