View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements. See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache license, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License. You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the license for the specific language governing permissions and
15   * limitations under the license.
16   */
17  package org.apache.logging.log4j.message;
18  
19  import org.apache.logging.log4j.status.StatusLogger;
20  
21  import java.io.IOException;
22  import java.io.ObjectInputStream;
23  import java.util.Locale;
24  import java.util.MissingResourceException;
25  import java.util.ResourceBundle;
26  
27  /**
28   * This class is not the recommended way to Localize messages. It is provided to provide some level
29   * of compatibility with Log4j 1.x.
30   *
31   * The recommended way to localize messages is to simply log a message id. Log events should
32   * then be recorded without formatting into some kind of data store. The application that is
33   * used to read the events and display them to the user should also localize and format the
34   * messages for the end user.
35   */
36  public class LocalizedMessage extends ParameterizedMessage implements LoggerNameAwareMessage
37  {
38      private static final long serialVersionUID = 3893703791567290742L;
39  
40      private String bundleId;
41  
42      private transient ResourceBundle bundle;
43  
44      private Locale locale;
45  
46      private transient StatusLogger logger = StatusLogger.getLogger();
47  
48      private String loggerName;
49  
50      public LocalizedMessage(String messagePattern, String[] stringArgs, Throwable throwable) {
51          super(messagePattern, stringArgs, throwable);
52          setup(null, null, null);
53      }
54  
55  
56      public LocalizedMessage(String bundleId, String key, String[] stringArgs,
57                              Throwable throwable) {
58          super(key, stringArgs, throwable);
59          setup(bundleId, null, null);
60      }
61  
62      public LocalizedMessage(ResourceBundle bundle, String key, String[] stringArgs,
63                              Throwable throwable) {
64          super(key, stringArgs, throwable);
65          setup(null, bundle, null);
66      }
67  
68      public LocalizedMessage(String bundleId, Locale locale, String key, String[] stringArgs,
69                              Throwable throwable) {
70          super(key, stringArgs, throwable);
71          setup(bundleId, null, locale);
72      }
73  
74      public LocalizedMessage(ResourceBundle bundle, Locale locale, String key, String[] stringArgs,
75                              Throwable throwable) {
76          super(key, stringArgs, throwable);
77          setup(null, bundle, locale);
78      }
79  
80      public LocalizedMessage(Locale locale, String key, String[] stringArgs, Throwable throwable) {
81          super(key, stringArgs, throwable);
82          setup(null, null, locale);
83      }
84  
85  
86      /**
87       * <p>This method returns a LocalizedMessage which contains the arguments converted to String
88       * as well as an optional Throwable.</p>
89       * <p/>
90       * <p>If the last argument is a Throwable and is NOT used up by a placeholder in the message
91       * pattern it is returned in LocalizedMessage.getThrowable() and won't be contained in the
92       * created String[].<br/>
93       * If it is used up ParameterizedMessage.getThrowable() will return null even if the last
94       * argument was a Throwable!</p>
95       *
96       * @param messagePattern the message pattern that to be checked for placeholders.
97       * @param arguments      the argument array to be converted.
98       */
99      public LocalizedMessage(String messagePattern, Object[] arguments) {
100         super(messagePattern, arguments);
101         setup(null, null, null);
102     }
103 
104     public LocalizedMessage(String bundleId, String key, Object[] arguments) {
105         super(key, arguments);
106         setup(bundleId, null, null);
107     }
108 
109     public LocalizedMessage(ResourceBundle bundle, String key, Object[] arguments) {
110         super(key, arguments);
111         setup(null, bundle, null);
112     }
113 
114     public LocalizedMessage(String bundleId, Locale locale, String key, Object[] arguments) {
115         super(key, arguments);
116         setup(bundleId, null, locale);
117     }
118 
119     public LocalizedMessage(ResourceBundle bundle, Locale locale, String key, Object[] arguments) {
120         super(key, arguments);
121         setup(null, bundle, locale);
122     }
123 
124     public LocalizedMessage(Locale locale, String key, Object[] arguments) {
125         super(key, arguments);
126         setup(null, null, locale);
127     }
128 
129     public LocalizedMessage(String messagePattern, Object arg) {
130         super(messagePattern, arg);
131         setup(null, null, null);
132     }
133 
134     public LocalizedMessage(String bundleId, String key, Object arg) {
135         super(key, arg);
136         setup(bundleId, null, null);
137     }
138 
139     public LocalizedMessage(ResourceBundle bundle, String key, Object arg) {
140         super(key, arg);
141         setup(null, bundle, null);
142     }
143 
144     public LocalizedMessage(String bundleId, Locale locale, String key, Object arg) {
145         super(key, arg);
146         setup(bundleId, null, locale);
147     }
148 
149     public LocalizedMessage(ResourceBundle bundle, Locale locale, String key, Object arg) {
150         super(key, arg);
151         setup(null, bundle, locale);
152     }
153 
154     public LocalizedMessage(Locale locale, String key, Object arg) {
155         super(key, arg);
156         setup(null, null, locale);
157     }
158 
159     public LocalizedMessage(String messagePattern, Object arg1, Object arg2) {
160         super(messagePattern, arg1, arg2);
161         setup(null, null, null);
162     }
163 
164     public LocalizedMessage(String bundleId, String key, Object arg1, Object arg2) {
165         super(key, arg1, arg2);
166         setup(bundleId, null, null);
167     }
168 
169     public LocalizedMessage(ResourceBundle bundle, String key, Object arg1, Object arg2) {
170         super(key, arg1, arg2);
171         setup(null, bundle, null);
172     }
173 
174     public LocalizedMessage(String bundleId, Locale locale, String key, Object arg1, Object arg2) {
175         super(key, arg1, arg2);
176         setup(bundleId, null, locale);
177     }
178 
179     public LocalizedMessage(ResourceBundle bundle, Locale locale, String key, Object arg1,
180                             Object arg2) {
181         super(key, arg1, arg2);
182         setup(null, bundle, locale);
183     }
184 
185     public LocalizedMessage(Locale locale, String key, Object arg1, Object arg2) {
186         super(key, arg1, arg2);
187         setup(null, null, locale);
188     }
189 
190     /**
191      * Set the name of the Logger.
192      * @param name The name of the Logger.
193      */
194     public void setLoggerName(String name) {
195         this.loggerName = name;
196     }
197 
198     /**
199      * Returns the name of the Logger.
200      * @return the name of the Logger.
201      */
202     public String getLoggerName() {
203         return this.loggerName;
204     }
205 
206     private void setup(String bundleId, ResourceBundle bundle, Locale locale) {
207         this.bundleId = bundleId;
208         this.bundle = bundle;
209         this.locale = locale;
210     }
211 
212     /**
213      * Returns the formatted message after looking up the format in the resource bundle.
214      * @param messagePattern The key for the resource bundle or the pattern if the bundle doesn't contain the key.
215      * @param args The parameters.
216      * @return The formatted message String.
217      */
218     @Override
219     public String formatMessage(String messagePattern, String[] args) {
220         ResourceBundle bundle = this.bundle;
221         if (bundle == null) {
222             if (bundleId != null) {
223                 bundle = getBundle(bundleId, locale, false);
224             } else {
225                 bundle = getBundle(loggerName, locale, true);
226             }
227         }
228         String msgPattern = (bundle == null || !bundle.containsKey(messagePattern)) ?
229             messagePattern : bundle.getString(messagePattern);
230         return format(msgPattern, args);
231     }
232 
233     /**
234      * Override this to use a ResourceBundle.Control in Java 6
235      * @param key The key to the bundle.
236      * @param locale The locale to use when formatting the message.
237      * @param loop If true the key will be treated as a package or class name and a resource bundle will
238      * be located based on all or part of the package name. If false the key is expected to be the exact bundle id.
239      * @return The ResourceBundle.
240      */
241     protected ResourceBundle getBundle(String key, Locale locale, boolean loop) {
242         ResourceBundle rb = null;
243 
244         if (key == null) {
245             return null;
246         }
247         try {
248             if (locale != null) {
249                 rb = ResourceBundle.getBundle(key, locale);
250             } else {
251                 rb = ResourceBundle.getBundle(key);
252             }
253         } catch (MissingResourceException ex) {
254             if (!loop) {
255                 logger.debug("Unable to locate ResourceBundle " + key);
256                 return null;
257             }
258         }
259 
260         String substr = key;
261         int i;
262         while (rb == null && (i = substr.lastIndexOf('.')) > 0) {
263             substr = substr.substring(0, i);
264             try {
265                 if (locale != null) {
266                     rb = ResourceBundle.getBundle(substr, locale);
267                 } else {
268                     rb = ResourceBundle.getBundle(substr);
269                 }
270             } catch (MissingResourceException ex) {
271                 logger.debug("Unable to locate ResourceBundle " + substr);
272             }
273         }
274         return rb;
275     }
276 
277     private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException {
278         stream.defaultReadObject();
279         bundle = null;
280         logger = StatusLogger.getLogger();
281     }
282 }