1 /*
2 * $Id: HtmlBasicInputRenderer.java,v 1.39.4.3 2008/07/09 18:16:00 rlubke Exp $
3 */
4
5 /*
6 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
7 *
8 * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
9 *
10 * The contents of this file are subject to the terms of either the GNU
11 * General Public License Version 2 only ("GPL") or the Common Development
12 * and Distribution License("CDDL") (collectively, the "License"). You
13 * may not use this file except in compliance with the License. You can obtain
14 * a copy of the License at https://glassfish.dev.java.net/public/CDDL+GPL.html
15 * or glassfish/bootstrap/legal/LICENSE.txt. See the License for the specific
16 * language governing permissions and limitations under the License.
17 *
18 * When distributing the software, include this License Header Notice in each
19 * file and include the License file at glassfish/bootstrap/legal/LICENSE.txt.
20 * Sun designates this particular file as subject to the "Classpath" exception
21 * as provided by Sun in the GPL Version 2 section of the License file that
22 * accompanied this code. If applicable, add the following below the License
23 * Header, with the fields enclosed by brackets [] replaced by your own
24 * identifying information: "Portions Copyrighted [year]
25 * [name of copyright owner]"
26 *
27 * Contributor(s):
28 *
29 * If you wish your version of this file to be governed by only the CDDL or
30 * only the GPL Version 2, indicate your decision by adding "[Contributor]
31 * elects to include this software in this distribution under the [CDDL or GPL
32 * Version 2] license." If you don't indicate a single choice of license, a
33 * recipient has the option to distribute your version of this file under
34 * either the CDDL, the GPL Version 2 or to extend the choice of license to
35 * its licensees as provided above. However, if you add GPL Version 2 code
36 * and therefore, elected the GPL Version 2 license, then the option applies
37 * only if the new code is made subject to such option by the copyright
38 * holder.
39 */
40
41 // HtmlBasicInputRenderer.java
42
43 package com.sun.faces.renderkit.html_basic;
44
45 import java.util.logging.Level;
46
47 import javax.el.ValueExpression;
48 import javax.faces.application.Application;
49 import javax.faces.component.UIComponent;
50 import javax.faces.component.UIInput;
51 import javax.faces.component.ValueHolder;
52 import javax.faces.context.FacesContext;
53 import javax.faces.convert.Converter;
54 import javax.faces.convert.ConverterException;
55
56 import com.sun.faces.util.MessageFactory;
57 import com.sun.faces.util.MessageUtils;
58 import com.sun.faces.util.RequestStateManager;
59
60 /**
61 * <B>HtmlBasicInputRenderer</B> is a base class for implementing renderers
62 * that support UIInput type components
63 */
64
65 public abstract class HtmlBasicInputRenderer extends HtmlBasicRenderer {
66
67
68 private boolean hasStringConverter = false;
69
70 private boolean hasStringConverterSet = false;
71
72 // ---------------------------------------------------------- Public Methods
73
74
75 @Override
76 public Object getConvertedValue(FacesContext context, UIComponent component,
77 Object submittedValue)
78 throws ConverterException {
79
80 String newValue = (String) submittedValue;
81 // if we have no local value, try to get the valueExpression.
82 ValueExpression valueExpression = component.getValueExpression("value");
83 Converter converter = null;
84
85 // If there is a converter attribute, use it to to ask application
86 // instance for a converter with this identifer.
87 if (component instanceof ValueHolder) {
88 converter = ((ValueHolder) component).getConverter();
89 }
90
91 if (null == converter && null != valueExpression) {
92 Class converterType = valueExpression.getType(context.getELContext());
93 // if converterType is null, assume the modelType is "String".
94 if (converterType == null ||
95 converterType == Object.class) {
96 if (logger.isLoggable(Level.FINE)) {
97 logger.log(Level.FINE,
98 "No conversion necessary for value {0} of component {1}",
99 new Object[]{
100 submittedValue,
101 component.getId() });
102 }
103 return newValue;
104 }
105
106 // If the converterType is a String, and we don't have a
107 // converter-for-class for java.lang.String, assume the type is
108 // "String".
109 if (converterType == String.class && !hasStringConverter(context)) {
110 if (logger.isLoggable(Level.FINE)) {
111 logger.log(Level.FINE,
112 "No conversion necessary for value {0} of component {1}",
113 new Object[]{
114 submittedValue,
115 component.getId()});
116 }
117 return newValue;
118 }
119 // if getType returns a type for which we support a default
120 // conversion, acquire an appropriate converter instance.
121
122 try {
123 Application application = context.getApplication();
124 converter = application.createConverter(converterType);
125 if (logger.isLoggable(Level.FINE)) {
126 logger.log(Level.FINE,
127 "Created converter ({0}) for type {1} for component {2}.",
128 new Object[] {
129 converter.getClass().getName(),
130 converterType.getClass().getName(),
131 component.getId() });
132 }
133 } catch (Exception e) {
134 if (logger.isLoggable(Level.SEVERE)) {
135 logger.log(Level.SEVERE,
136 "Could not instantiate converter for type {0}: {1}",
137 new Object[] {
138 converterType,
139 e.toString() });
140 }
141 return (null);
142 }
143 } else if (converter == null) {
144 // if there is no valueExpression and converter attribute set,
145 // assume the modelType as "String" since we have no way of
146 // figuring out the type. So for the selectOne and
147 // selectMany, converter has to be set if there is no
148 // valueExpression attribute set on the component.
149 if (logger.isLoggable(Level.FINE)) {
150 logger.log(Level.FINE,
151 "No conversion necessary for value {0} of component {1}",
152 new Object[] {
153 submittedValue,
154 component.getId() });
155 logger.fine(" since there is no explicitly registered converter "
156 + "and the component value is not bound to a model property");
157 }
158 return newValue;
159 }
160
161 if (converter != null) {
162 // If the conversion eventually falls to needing to use EL type coercion,
163 // make sure our special ConverterPropertyEditor knows about this value.
164 RequestStateManager.set(context,
165 RequestStateManager.TARGET_COMPONENT_ATTRIBUTE_NAME,
166 component);
167 return converter.getAsObject(context, component, newValue);
168 } else {
169 // throw converter exception.
170 Object[] params = {
171 newValue,
172 "null Converter"
173 };
174
175 throw new ConverterException(MessageFactory.getMessage(
176 context, MessageUtils.CONVERSION_ERROR_MESSAGE_ID, params));
177 }
178
179 }
180
181
182 @Override
183 public void setSubmittedValue(UIComponent component, Object value) {
184
185 if (component instanceof UIInput) {
186 ((UIInput) component).setSubmittedValue(value);
187 if (logger.isLoggable(Level.FINE)) {
188 logger.fine("Set submitted value " + value + " on component ");
189 }
190 }
191
192 }
193
194 // ------------------------------------------------------- Protected Methods
195
196
197 @Override
198 protected Object getValue(UIComponent component) {
199
200 if (component instanceof ValueHolder) {
201 Object value = ((ValueHolder) component).getValue();
202 if (logger.isLoggable(Level.FINE)) {
203 logger.fine("component.getValue() returned " + value);
204 }
205 return value;
206 }
207
208 return null;
209
210 }
211
212 // --------------------------------------------------------- Private Methods
213
214
215 private boolean hasStringConverter(FacesContext context) {
216
217 if (!hasStringConverterSet) {
218 hasStringConverter = (null !=
219 context.getApplication()
220 .createConverter(String.class));
221 hasStringConverterSet = true;
222 }
223 return hasStringConverter;
224
225 }
226
227 } // end of class HtmlBasicInputRenderer