001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * Portions Copyright Apache Software Foundation.
007: *
008: * The contents of this file are subject to the terms of either the GNU
009: * General Public License Version 2 only ("GPL") or the Common Development
010: * and Distribution License("CDDL") (collectively, the "License"). You
011: * may not use this file except in compliance with the License. You can obtain
012: * a copy of the License at https://glassfish.dev.java.net/public/CDDL+GPL.html
013: * or glassfish/bootstrap/legal/LICENSE.txt. See the License for the specific
014: * language governing permissions and limitations under the License.
015: *
016: * When distributing the software, include this License Header Notice in each
017: * file and include the License file at glassfish/bootstrap/legal/LICENSE.txt.
018: * Sun designates this particular file as subject to the "Classpath" exception
019: * as provided by Sun in the GPL Version 2 section of the License file that
020: * accompanied this code. If applicable, add the following below the License
021: * Header, with the fields enclosed by brackets [] replaced by your own
022: * identifying information: "Portions Copyrighted [year]
023: * [name of copyright owner]"
024: *
025: * Contributor(s):
026: *
027: * If you wish your version of this file to be governed by only the CDDL or
028: * only the GPL Version 2, indicate your decision by adding "[Contributor]
029: * elects to include this software in this distribution under the [CDDL or GPL
030: * Version 2] license." If you don't indicate a single choice of license, a
031: * recipient has the option to distribute your version of this file under
032: * either the CDDL, the GPL Version 2 or to extend the choice of license to
033: * its licensees as provided above. However, if you add GPL Version 2 code
034: * and therefore, elected the GPL Version 2 license, then the option applies
035: * only if the new code is made subject to such option by the copyright
036: * holder.
037: */
038:
039: package org.apache.taglibs.standard.tag.common.fmt;
040:
041: import java.io.IOException;
042: import java.text.MessageFormat;
043: import java.util.ArrayList;
044: import java.util.List;
045: import java.util.Locale;
046: import java.util.MissingResourceException;
047: import java.util.ResourceBundle;
048:
049: import javax.servlet.jsp.JspException;
050: import javax.servlet.jsp.JspTagException;
051: import javax.servlet.jsp.PageContext;
052: import javax.servlet.jsp.jstl.fmt.LocalizationContext;
053: import javax.servlet.jsp.tagext.BodyTagSupport;
054: import javax.servlet.jsp.tagext.Tag;
055:
056: import org.apache.taglibs.standard.tag.common.core.Util;
057:
058: /**
059: * Support for tag handlers for <message>, the message formatting tag
060: * in JSTL 1.0.
061: *
062: * @author Jan Luehe
063: */
064:
065: public abstract class MessageSupport extends BodyTagSupport {
066:
067: //*********************************************************************
068: // Public constants
069:
070: public static final String UNDEFINED_KEY = "???";
071:
072: //*********************************************************************
073: // Protected state
074:
075: protected String keyAttrValue; // 'key' attribute value
076: protected boolean keySpecified; // 'key' attribute specified
077: protected LocalizationContext bundleAttrValue; // 'bundle' attribute value
078: protected boolean bundleSpecified; // 'bundle' attribute specified?
079:
080: //*********************************************************************
081: // Private state
082:
083: private String var; // 'var' attribute
084: private int scope; // 'scope' attribute
085: private List params;
086:
087: //*********************************************************************
088: // Constructor and initialization
089:
090: public MessageSupport() {
091: super ();
092: params = new ArrayList();
093: init();
094: }
095:
096: private void init() {
097: var = null;
098: scope = PageContext.PAGE_SCOPE;
099: keyAttrValue = null;
100: keySpecified = false;
101: bundleAttrValue = null;
102: bundleSpecified = false;
103: }
104:
105: //*********************************************************************
106: // Tag attributes known at translation time
107:
108: public void setVar(String var) {
109: this .var = var;
110: }
111:
112: public void setScope(String scope) {
113: this .scope = Util.getScope(scope);
114: }
115:
116: //*********************************************************************
117: // Collaboration with subtags
118:
119: /**
120: * Adds an argument (for parametric replacement) to this tag's message.
121: *
122: * @see ParamSupport
123: */
124: public void addParam(Object arg) {
125: params.add(arg);
126: }
127:
128: //*********************************************************************
129: // Tag logic
130:
131: public int doStartTag() throws JspException {
132: params.clear();
133: return EVAL_BODY_BUFFERED;
134: }
135:
136: public int doEndTag() throws JspException {
137:
138: String key = null;
139: LocalizationContext locCtxt = null;
140:
141: // determine the message key by...
142: if (keySpecified) {
143: // ... reading 'key' attribute
144: key = keyAttrValue;
145: } else {
146: // ... retrieving and trimming our body
147: if (bodyContent != null && bodyContent.getString() != null)
148: key = bodyContent.getString().trim();
149: }
150:
151: if ((key == null) || key.equals("")) {
152: try {
153: pageContext.getOut().print("??????");
154: } catch (IOException ioe) {
155: throw new JspTagException(ioe.toString(), ioe);
156: }
157: return EVAL_PAGE;
158: }
159:
160: String prefix = null;
161: if (!bundleSpecified) {
162: Tag t = findAncestorWithClass(this , BundleSupport.class);
163: if (t != null) {
164: // use resource bundle from parent <bundle> tag
165: BundleSupport parent = (BundleSupport) t;
166: locCtxt = parent.getLocalizationContext();
167: prefix = parent.getPrefix();
168: } else {
169: locCtxt = BundleSupport
170: .getLocalizationContext(pageContext);
171: }
172: } else {
173: // localization context taken from 'bundle' attribute
174: locCtxt = bundleAttrValue;
175: if (locCtxt.getLocale() != null) {
176: SetLocaleSupport.setResponseLocale(pageContext, locCtxt
177: .getLocale());
178: }
179: }
180:
181: String message = UNDEFINED_KEY + key + UNDEFINED_KEY;
182: if (locCtxt != null) {
183: ResourceBundle bundle = locCtxt.getResourceBundle();
184: if (bundle != null) {
185: try {
186: // prepend 'prefix' attribute from parent bundle
187: if (prefix != null)
188: key = prefix + key;
189: message = bundle.getString(key);
190: // Perform parametric replacement if required
191: if (!params.isEmpty()) {
192: Object[] messageArgs = params.toArray();
193: MessageFormat formatter = new MessageFormat(""); // empty pattern, default Locale
194: if (locCtxt.getLocale() != null) {
195: formatter.setLocale(locCtxt.getLocale());
196: } else {
197: // For consistency with the <fmt:formatXXX> actions,
198: // we try to get a locale that matches the user's preferences
199: // as well as the locales supported by 'date' and 'number'.
200: //System.out.println("LOCALE-LESS LOCCTXT: GETTING FORMATTING LOCALE");
201: Locale locale = SetLocaleSupport
202: .getFormattingLocale(pageContext);
203: //System.out.println("LOCALE: " + locale);
204: if (locale != null) {
205: formatter.setLocale(locale);
206: }
207: }
208: formatter.applyPattern(message);
209: message = formatter.format(messageArgs);
210: }
211: } catch (MissingResourceException mre) {
212: message = UNDEFINED_KEY + key + UNDEFINED_KEY;
213: }
214: }
215: }
216:
217: if (var != null) {
218: pageContext.setAttribute(var, message, scope);
219: } else {
220: try {
221: pageContext.getOut().print(message);
222: } catch (IOException ioe) {
223: throw new JspTagException(ioe.toString(), ioe);
224: }
225: }
226:
227: return EVAL_PAGE;
228: }
229:
230: // Releases any resources we may have (or inherit)
231: public void release() {
232: init();
233: }
234: }
|