1 /* 2 * $Id: ValueExpressionValueBindingAdapter.java,v 1.7 2007/04/27 22:00:12 ofung 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 package javax.faces.component; 42 43 import javax.el.ValueExpression; 44 import javax.el.ELException; 45 import javax.el.ELContext; 46 import javax.faces.el.ValueBinding; 47 import javax.faces.context.FacesContext; 48 import javax.faces.component.StateHolder; 49 50 import java.io.Serializable; 51 52 /** 53 * <p>Wrap a ValueBinding instance and expose it as a 54 * ValueExpression.</p> 55 */ 56 57 class ValueExpressionValueBindingAdapter extends ValueExpression implements Serializable, StateHolder { 58 59 private static final long serialVersionUID = 2388977392466671243L; 60 61 public ValueExpressionValueBindingAdapter() {} 62 63 private ValueBinding binding = null; 64 65 ValueExpressionValueBindingAdapter(ValueBinding binding) { 66 assert(null != binding); 67 this.binding = binding; 68 } 69 70 // 71 // Methods from ValueExpression 72 // 73 74 public Object getValue(ELContext context) throws ELException { 75 assert(null != binding); 76 if (context == null) { 77 throw new NullPointerException("ELContext -> null"); 78 } 79 Object result = null; 80 FacesContext facesContext = (FacesContext) 81 context.getContext(FacesContext.class); 82 assert(null != facesContext); 83 try { 84 result = binding.getValue(facesContext); 85 } 86 catch (Throwable e) { 87 throw new ELException(e); 88 } 89 return result; 90 } 91 92 public void setValue(ELContext context, Object value) throws ELException { 93 assert(null != binding); 94 if (context == null) { 95 throw new NullPointerException("ELContext -> null"); 96 } 97 FacesContext facesContext = (FacesContext) 98 context.getContext(FacesContext.class); 99 assert(null != facesContext); 100 try { 101 binding.setValue(facesContext, value); 102 } 103 catch (Throwable e) { 104 throw new ELException(e); 105 } 106 } 107 108 109 public boolean isReadOnly(ELContext context) throws ELException { 110 assert(null != binding); 111 if (context == null) { 112 throw new NullPointerException("ELContext -> null"); 113 } 114 boolean result = false; 115 FacesContext facesContext = (FacesContext) 116 context.getContext(FacesContext.class); 117 assert(null != facesContext); 118 try { 119 result = binding.isReadOnly(facesContext); 120 } 121 catch (Throwable e) { 122 throw new ELException(e); 123 } 124 return result; 125 } 126 127 public Class<?> getType(ELContext context) throws ELException { 128 assert(null != binding); 129 if (context == null) { 130 throw new NullPointerException("ELContext -> null"); 131 } 132 Class result = null; 133 FacesContext facesContext = (FacesContext) 134 context.getContext(FacesContext.class); 135 assert(null != facesContext); 136 try { 137 result = binding.getType(facesContext); 138 } 139 catch (Throwable e) { 140 throw new ELException(e); 141 } 142 return result; 143 } 144 145 /** 146 * <p>Always return <code>false</code> since we can't possibly know 147 * if this is a literal text binding or not.</p> 148 */ 149 150 public boolean isLiteralText() { 151 return false; 152 } 153 154 public Class<?> getExpectedType() { 155 assert(null != binding); 156 Class result = null; 157 FacesContext context = FacesContext.getCurrentInstance(); 158 try { 159 Object value = binding.getValue(context); 160 result = value.getClass(); 161 } 162 catch (Throwable e) { 163 result = null; 164 } 165 return result; 166 } 167 168 public String getExpressionString() { 169 assert(null != binding); 170 return binding.getExpressionString(); 171 172 } 173 174 public boolean equals(Object other) { 175 176 if (other == this) { 177 return true; 178 } 179 180 if (other instanceof ValueExpressionValueBindingAdapter) { 181 ValueBinding vb = 182 ((ValueExpressionValueBindingAdapter) other).getWrapped(); 183 return (binding.equals(vb)); 184 } else if (other instanceof ValueExpression) { 185 FacesContext context = FacesContext.getCurrentInstance(); 186 ValueExpression otherVE = (ValueExpression) other; 187 Class type = binding.getType(context); 188 if (type != null) { 189 return type.equals(otherVE.getType(context.getELContext())); 190 } 191 } 192 return false; 193 194 } 195 196 public int hashCode() { 197 assert(null != binding); 198 199 return binding.hashCode(); 200 } 201 202 public String getDelimiterSyntax() { 203 // PENDING (visvan) Implementation 204 return ""; 205 } 206 207 // 208 // Methods from StateHolder 209 // 210 211 212 213 public Object saveState(FacesContext context) { 214 if (context == null) { 215 throw new NullPointerException(); 216 } 217 Object result = null; 218 if (!tranzient) { 219 if (binding instanceof StateHolder) { 220 Object [] stateStruct = new Object[2]; 221 222 // save the actual state of our wrapped binding 223 stateStruct[0] = ((StateHolder)binding).saveState(context); 224 // save the class name of the binding impl 225 stateStruct[1] = binding.getClass().getName(); 226 227 result = stateStruct; 228 } 229 else { 230 result = binding; 231 } 232 } 233 234 return result; 235 } 236 237 public void restoreState(FacesContext context, Object state) { 238 if (context == null) { 239 throw new NullPointerException(); 240 } 241 // if we have state 242 if (null == state) { 243 return; 244 } 245 246 if (!(state instanceof ValueBinding)) { 247 Object [] stateStruct = (Object []) state; 248 Object savedState = stateStruct[0]; 249 String className = stateStruct[1].toString(); 250 ValueBinding result = null; 251 252 Class toRestoreClass = null; 253 if (null != className) { 254 try { 255 toRestoreClass = loadClass(className, this); 256 } 257 catch (ClassNotFoundException e) { 258 throw new IllegalStateException(e.getMessage()); 259 } 260 261 if (null != toRestoreClass) { 262 try { 263 result = 264 (ValueBinding) toRestoreClass.newInstance(); 265 } 266 catch (InstantiationException e) { 267 throw new IllegalStateException(e.getMessage()); 268 } 269 catch (IllegalAccessException a) { 270 throw new IllegalStateException(a.getMessage()); 271 } 272 } 273 274 if (null != result && null != savedState) { 275 // don't need to check transient, since that was 276 // done on the saving side. 277 ((StateHolder)result).restoreState(context, savedState); 278 } 279 binding = result; 280 } 281 } 282 else { 283 binding = (ValueBinding) state; 284 } 285 } 286 287 private boolean tranzient = false; 288 289 public boolean isTransient() { 290 return tranzient; 291 } 292 293 public void setTransient(boolean newTransientValue) { 294 tranzient = newTransientValue; 295 } 296 297 // 298 // Helper methods for StateHolder 299 // 300 301 private static Class loadClass(String name, 302 Object fallbackClass) throws ClassNotFoundException { 303 ClassLoader loader = 304 Thread.currentThread().getContextClassLoader(); 305 if (loader == null) { 306 loader = fallbackClass.getClass().getClassLoader(); 307 } 308 return Class.forName(name, true, loader); 309 } 310 311 312 // 313 // methods used by classes aware of this class's wrapper nature 314 // 315 316 public ValueBinding getWrapped() { 317 return binding; 318 } 319 320 }