001: /*
002: * ====================================================================
003: * JAFFA - Java Application Framework For All
004: *
005: * Copyright (C) 2002 JAFFA Development Group
006: *
007: * This library is free software; you can redistribute it and/or
008: * modify it under the terms of the GNU Lesser General Public
009: * License as published by the Free Software Foundation; either
010: * version 2.1 of the License, or (at your option) any later version.
011: *
012: * This library is distributed in the hope that it will be useful,
013: * but WITHOUT ANY WARRANTY; without even the implied warranty of
014: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
015: * Lesser General Public License for more details.
016: *
017: * You should have received a copy of the GNU Lesser General Public
018: * License along with this library; if not, write to the Free Software
019: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
020: *
021: * Redistribution and use of this software and associated documentation ("Software"),
022: * with or without modification, are permitted provided that the following conditions are met:
023: * 1. Redistributions of source code must retain copyright statements and notices.
024: * Redistributions must also contain a copy of this document.
025: * 2. Redistributions in binary form must reproduce the above copyright notice,
026: * this list of conditions and the following disclaimer in the documentation
027: * and/or other materials provided with the distribution.
028: * 3. The name "JAFFA" must not be used to endorse or promote products derived from
029: * this Software without prior written permission. For written permission,
030: * please contact mail to: jaffagroup@yahoo.com.
031: * 4. Products derived from this Software may not be called "JAFFA" nor may "JAFFA"
032: * appear in their names without prior written permission.
033: * 5. Due credit should be given to the JAFFA Project (http://jaffa.sourceforge.net).
034: *
035: * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
036: * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
037: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
038: * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
039: * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
040: * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
041: * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
042: * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
043: * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
044: * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
045: * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
046: * SUCH DAMAGE.
047: * ====================================================================
048: */
049:
050: package org.jaffa.util;
051:
052: import java.util.StringTokenizer;
053: import java.util.Locale;
054: import org.apache.struts.util.MessageResources;
055: import org.apache.struts.Globals;
056: import org.apache.log4j.Logger;
057: import javax.servlet.jsp.PageContext;
058: import java.lang.reflect.Method;
059: import java.lang.reflect.Modifier;
060: import org.jaffa.metadata.FieldMetaData;
061: import java.lang.reflect.InvocationTargetException;
062: import org.jaffa.presentation.portlet.session.LocaleContext;
063:
064: /** This is a helper class for getting messages from the Resource. It also performs token replacement
065: *
066: * @author GautamJ
067: */
068: public class MessageHelper {
069:
070: private static final String TOKEN_BEGIN_MARKER = "[";
071: private static final String TOKEN_END_MARKER = "]";
072: private static final Logger log = Logger
073: .getLogger(MessageHelper.class);
074:
075: /**
076: * Gets the message for the input key from the default resources, as specified in the 'framework.messageResources.bundle' property of framework.properties files.
077: * A null will be returned in case an invalid or if no ResourceBundle is specified in the 'framework.messageResources.bundle' property of framework.properties file.
078: * It uses the locale for the user from the thread variable, if available, else it uses the default locale for the JVM.
079: * It will also perform token replacement.
080: * @param key The key of the the message to be looked up.
081: * @param args An array of arguments to be added to the message.
082: * @return the message with the tokens replaced.
083: */
084: public static String findMessage(String key, Object[] args) {
085: return findMessage(LocaleContext.getLocale(), key, args);
086: }
087:
088: /**
089: * Gets the message for the input key from the default resources, as specified in the 'framework.messageResources.bundle' property of framework.properties files.
090: * A null will be returned in case an invalid or if no ResourceBundle is specified in the 'framework.messageResources.bundle' property of framework.properties file.
091: * It will also perform token replacement.
092: * @param locale the Locale to be used when looking up the ResourceBundle.
093: * @param key The key of the the message to be looked up.
094: * @param args An array of arguments to be added to the message.
095: * @return the message with the tokens replaced.
096: */
097: public static String findMessage(Locale locale, String key,
098: Object[] args) {
099: if (PropertyMessageResourcesFactory
100: .getDefaultMessageResources() != null)
101: return findMessage(PropertyMessageResourcesFactory
102: .getDefaultMessageResources(), locale, key, args);
103: else
104: return null;
105: }
106:
107: /**
108: * Gets the message for the input key from the resources (an attribute in the request stream). It will also perform token replacement.
109: * This uses the default struts MessageResources and Locale.
110: * @param pageContext The servlet pageContext we are processing.
111: * @param key The key of the the message to be looked up.
112: * @param args An array of arguments to be added to the message.
113: * @return the message with the tokens replaced.
114: */
115: public static String findMessage(PageContext pageContext,
116: String key, Object[] args) {
117: return findMessage(pageContext, null, null, key, args);
118: }
119:
120: /**
121: * Gets the message for the input key from the resources (an attribute in the request stream). It will also perform token replacement.
122: * @param pageContext The servlet pageContext we are processing.
123: * @param resources The key that identifies that the MessageResources object in the pageContext
124: * @param locale The key that identifies that the Locale object in the pageContext
125: * @param key The key of the the message to be looked up.
126: * @param args An array of arguments to be added to the message.
127: * @return the message with the tokens replaced.
128: */
129: public static String findMessage(PageContext pageContext,
130: String resources, String locale, String key, Object[] args) {
131: return findMessage(
132: findMessageResources(pageContext, resources),
133: findLocale(pageContext, locale), key, args);
134: }
135:
136: /**
137: * Gets the message for the input key from the resources. It will also perform token replacement.
138: * @param resources The underlying resource bundle to look at.
139: * @param locale The requested message Locale.
140: * @param key The key of the the message to be looked up.
141: * @param args An array of arguments to be added to the message.
142: * @return the message with the tokens replaced.
143: */
144: public static String findMessage(MessageResources resources,
145: Locale locale, String key, Object[] args) {
146: // Get the message
147: if (log.isDebugEnabled())
148: log.debug("Looking up the ResourceBundle for the key - "
149: + key);
150:
151: if (key == null)
152: return null;
153:
154: String message = null;
155: if (args == null)
156: message = resources.getMessage(locale, key);
157: else
158: message = resources.getMessage(locale, key, args);
159:
160: // now perform token replacement
161: if (message != null)
162: message = replaceTokens(resources, locale, message);
163:
164: return message;
165: }
166:
167: /**
168: * Replace the tokens in the input message with appropriate values from the default resources, as specified in the 'framework.messageResources.bundle' property of framework.properties files.
169: * A null will be returned in case an invalid or if no ResourceBundle is specified in the 'framework.messageResources.bundle' property of framework.properties file.
170: * It uses the locale for the user from the thread variable, if available, else it uses the default locale for the JVM.
171: * If the value for a token, is again a token, then it will recursively find the value.
172: * @param message Message to be looked up for token replacement.
173: * @return the message with the tokens replaced.
174: */
175: public static String replaceTokens(String message) {
176: return replaceTokens(LocaleContext.getLocale(), message);
177: }
178:
179: /**
180: * Replace the tokens in the input message with appropriate values from the default resources, as specified in the 'framework.messageResources.bundle' property of framework.properties files.
181: * A null will be returned in case an invalid or if no ResourceBundle is specified in the 'framework.messageResources.bundle' property of framework.properties file.
182: * If the value for a token, is again a token, then it will recursively find the value.
183: * @param locale the Locale to be used when looking up the ResourceBundle.
184: * @param message Message to be looked up for token replacement.
185: * @return the message with the tokens replaced.
186: */
187: public static String replaceTokens(Locale locale, String message) {
188: if (PropertyMessageResourcesFactory
189: .getDefaultMessageResources() != null)
190: return replaceTokens(PropertyMessageResourcesFactory
191: .getDefaultMessageResources(), locale, message);
192: else
193: return null;
194: }
195:
196: /**
197: * Replace the tokens in the input message with appropriate values from the resources (an attribute in the request stream).
198: * This uses the default struts MessageResources and Locale.
199: * If the value for a token, is again a token, then it will recursively find the value.
200: * @param pageContext The servlet pageContext we are processing.
201: * @param message Message to be looked up for token replacement.
202: * @return the message with the tokens replaced.
203: */
204: public static String replaceTokens(PageContext pageContext,
205: String message) {
206: return replaceTokens(pageContext, null, null, message);
207: }
208:
209: /**
210: * Replace the tokens in the input message with appropriate values from the resources (an attribute in the request stream).
211: * If the value for a token, is again a token, then it will recursively find the value.
212: * @param pageContext The servlet pageContext we are processing.
213: * @param resources The key that identifies that the MessageResources object in the pageContext
214: * @param locale The key that identifies that the Locale object in the pageContext
215: * @param message Message to be looked up for token replacement.
216: * @return the message with the tokens replaced.
217: */
218: public static String replaceTokens(PageContext pageContext,
219: String resources, String locale, String message) {
220: return replaceTokens(findMessageResources(pageContext,
221: resources), findLocale(pageContext, locale), message);
222: }
223:
224: /**
225: * Replace the tokens in the input message with appropriate values from the resources.
226: * If the value for a token, is again a token, then it will recursively find the value.
227: * Note: Ensure that are no cyclic references from one token to another to the first token.
228: * @param resources The underlying resource bundle to look at.
229: * @param locale The requested message Locale.
230: * @param message Message to be looked up for token replacement.
231: * @return the message with the tokens replaced.
232: */
233: public static String replaceTokens(MessageResources resources,
234: Locale locale, String message) {
235: String out = null;
236: if (message == null
237: || message.length() <= (TOKEN_BEGIN_MARKER + TOKEN_END_MARKER)
238: .length()) {
239: // no need for token-replacement
240: out = message;
241: } else {
242: StringBuffer buf = new StringBuffer();
243: StringTokenizer strngTknzr = new StringTokenizer(message,
244: TOKEN_BEGIN_MARKER + TOKEN_END_MARKER, true);
245: while (strngTknzr.hasMoreTokens()) {
246: String str = strngTknzr.nextToken();
247: if (str.equals(TOKEN_BEGIN_MARKER)) {
248: if (strngTknzr.hasMoreTokens()) {
249: boolean foundTokenEnd = false;
250: StringBuffer tokenName = new StringBuffer();
251: String tokenReplacement = null;
252: while (strngTknzr.hasMoreTokens()) {
253: String subStr = strngTknzr.nextToken();
254: if (subStr.equals(TOKEN_END_MARKER)) {
255: foundTokenEnd = true;
256: if (log.isDebugEnabled())
257: log
258: .debug("Looking up the ResourceBundle for the key - "
259: + tokenName
260: .toString());
261: tokenReplacement = resources
262: .getMessage(locale, tokenName
263: .toString());
264: if (tokenReplacement == null) {
265: // no error will be raised.. just return with TOKEN_MARKERS around the token name
266: tokenReplacement = tokenize(tokenName
267: .toString());
268: } else if (!tokenReplacement
269: .equals(tokenize(tokenName
270: .toString()))) {
271: // perform token-replacement recursively
272: tokenReplacement = replaceTokens(
273: resources, locale,
274: tokenReplacement);
275: }
276: break;
277: } else {
278: tokenName.append(subStr);
279: }
280: }
281: if (tokenReplacement != null) {
282: buf.append(tokenReplacement);
283: } else {
284: buf.append(TOKEN_BEGIN_MARKER);
285: buf.append(tokenName.toString());
286: if (foundTokenEnd)
287: buf.append(TOKEN_END_MARKER);
288: }
289: } else {
290: buf.append(TOKEN_BEGIN_MARKER);
291: }
292: } else {
293: buf.append(str);
294: }
295: }
296: out = buf.toString();
297: }
298: return out;
299: }
300:
301: /** This will add the Token Markers around the input String.
302: * @param input the string to be tokenized.
303: * @return the string with the Token Markers around it. A null is returned if the input is null. If the input begins or ends with the token marker, then it will be returned as is.
304: */
305: public static String tokenize(String input) {
306: if (input == null)
307: return null;
308: else if (input.startsWith(TOKEN_BEGIN_MARKER)
309: || input.endsWith(TOKEN_END_MARKER))
310: return input;
311: else
312: return TOKEN_BEGIN_MARKER + input + TOKEN_END_MARKER;
313: }
314:
315: /** Returns a true if the input String consists of a tokenized string.
316: * @param input the string to be checked for presence of tokens
317: * @return a true if the input String consists of a tokenized string.
318: */
319: public static boolean hasTokens(String input) {
320: boolean result = false;
321: if (input != null) {
322: int i = input.indexOf(TOKEN_BEGIN_MARKER);
323: if (i >= 0 && input.indexOf(TOKEN_END_MARKER) > i)
324: result = true;
325: }
326: return result;
327: }
328:
329: /** This is a convenience method to remove the token markers from the input string.
330: * This method will remove the markers at the beginning and at the end of the string only.
331: * Otherwise it'll simply return the input as is.
332: * @param input The string from which the token markers are to be removed.
333: * @return The input string minus its outer token markers, if any.
334: */
335: public static String removeTokenMarkers(String input) {
336: String output = input;
337: if (input != null && input.startsWith(TOKEN_BEGIN_MARKER)
338: && input.endsWith(TOKEN_END_MARKER))
339: output = input.substring(TOKEN_BEGIN_MARKER.length(), input
340: .length()
341: - TOKEN_END_MARKER.length());
342: return output;
343: }
344:
345: /** This returns the Struts MessageResources.*/
346: private static MessageResources findMessageResources(
347: PageContext pageContext, String resources) {
348: return (MessageResources) pageContext
349: .findAttribute((resources != null ? resources
350: : Globals.MESSAGES_KEY));
351: }
352:
353: /** This returns the Locale set by the Struts framework in the Session object.*/
354: private static Locale findLocale(PageContext pageContext,
355: String locale) {
356: return (Locale) pageContext
357: .findAttribute((locale != null ? locale
358: : Globals.LOCALE_KEY));
359: }
360:
361: }
|