1 18 package org.apache.beehive.netui.tags.databinding.invoke; 19 20 import org.apache.beehive.netui.util.internal.InternalStringBuilder; 21 22 import java.lang.reflect.InvocationTargetException ; 23 import java.lang.reflect.Method ; 24 import java.util.ArrayList ; 25 import java.util.List ; 26 import javax.servlet.jsp.JspException ; 27 28 import org.apache.beehive.netui.tags.AbstractClassicTag; 29 import org.apache.beehive.netui.util.Bundle; 30 import org.apache.beehive.netui.util.logging.Logger; 31 import org.apache.beehive.netui.util.type.TypeUtils; 32 33 47 public abstract class AbstractCallMethod 48 extends AbstractClassicTag { 49 50 private static final Logger LOGGER = Logger.getInstance(AbstractCallMethod.class); 51 52 private static final Object [] EMPTY_ARGS = new Object [0]; 53 private static final String EMPTY_STRING = ""; 54 private static final List EMPTY_LIST = new ArrayList (); 55 56 private List _parameters = null; 57 private String _method = null; 58 private boolean _failOnError = true; 59 private String _resultId = null; 60 private boolean _verifyTypes = false; 61 62 75 public void setResultId(String resultId) { 76 _resultId = resultId; 77 } 78 79 87 public void setFailOnError(boolean failOnError) { 88 _failOnError = failOnError; 89 } 90 91 99 public void setMethod(String method) { 100 _method = method; 101 } 102 103 112 public void addParameter(String type, Object parameter) { 113 if(_parameters == null) 114 _parameters = new ArrayList (); 115 116 if(type != null) _verifyTypes = true; 118 119 ParamNode pn = new ParamNode(); 120 pn.typeName = type; 121 pn.paramValue = parameter; 122 123 _parameters.add(pn); 124 } 125 126 133 public int doStartTag() 134 throws JspException { 135 return EVAL_BODY_BUFFERED; 136 } 137 138 160 public int doEndTag() 161 throws JspException { 162 Object object = null; 164 try { 165 object = resolveObject(); 166 } 167 catch(ObjectNotFoundException onf) { 168 Throwable cause = (onf.getCause() != null ? onf.getCause() : onf); 169 String msg = Bundle.getErrorString("Tags_AbstractCallMethod_noSuchObject", new Object []{getObjectName(), _method, cause}); 170 registerTagError(msg, null); 171 } 172 173 if(object == null) { 175 if(allowNullInvocationTarget()) { 176 handleReturnValue(null); 178 localRelease(); 179 return EVAL_PAGE; 180 } 181 else { 182 String msg = Bundle.getErrorString("Tags_AbstractCallMethod_objectIsNull", new Object []{getObjectName(), _method}); 183 registerTagError(msg, null); 184 } 185 } 186 187 if(hasErrors()) { 188 reportErrors(); 189 localRelease(); 190 return EVAL_PAGE; 191 } 192 193 Method m = findMethod(object, _method, _verifyTypes); 194 195 if(m == null) { 196 String msg = null; 197 if(_verifyTypes) { 198 String paramString = prettyPrintParameterTypes(_parameters); 199 msg = Bundle.getErrorString("Tags_AbstractCallMethod_noSuchMethodWithTypes", 200 new Object []{_method, 201 (_parameters != null ? new Integer (_parameters.size()) : new Integer (0)), 202 paramString, 203 getObjectName()}); 204 } 205 else 206 msg = Bundle.getErrorString("Tags_AbstractCallMethod_noSuchMethod", 207 new Object []{_method, 208 (_parameters != null ? new Integer (_parameters.size()) : new Integer (0)), 209 getObjectName()}); 210 211 registerTagError(msg, null); 212 reportErrors(); 213 localRelease(); 214 return EVAL_PAGE; 215 } 216 217 Object [] args = null; 218 try { 219 args = getArguments(m.getParameterTypes()); 220 } 221 catch(IllegalArgumentException iae) { 222 registerTagError(iae.getMessage(), null); 223 reportErrors(); 224 localRelease(); 225 return EVAL_PAGE; 226 } 227 228 Object result = null; 230 try { 231 if(LOGGER.isDebugEnabled()) { 232 LOGGER.debug("method: " + m.toString()); 233 for(int i = 0; i < args.length; i++) 234 LOGGER.debug("arg[" + i + "]: " + (args[i] != null ? args[i].getClass().getName() : "null")); 235 } 236 237 result = m.invoke(object, args); 238 } 239 catch(Exception e) { 240 assert e instanceof IllegalAccessException || e instanceof InvocationTargetException || e instanceof IllegalArgumentException ; 241 242 if(LOGGER.isErrorEnabled()) 243 LOGGER.error("Could not invoke method \"" + _method + "\" on the object named \"" + getObjectName() + "\" because: " + e, e); 244 245 if(_failOnError) { 246 String msg = Bundle.getErrorString("Tags_AbstractCallMethod_invocationError", new Object []{_method, getObjectName(), e}); 247 registerTagError(msg, null); 248 reportErrors(); 249 localRelease(); 250 return EVAL_PAGE; 251 } 252 } 253 254 if(LOGGER.isDebugEnabled()) { 255 LOGGER.debug((result != null ? 256 "return value is non-null and is of type \"" + result.getClass().getName() + "\"" : 257 "return value is null.")); 258 } 259 260 handleReturnValue(result); 262 263 localRelease(); 264 265 return EVAL_PAGE; 266 } 267 268 271 protected void localRelease() { 272 super.localRelease(); 273 _parameters = null; 274 _method = null; 275 _failOnError = true; 276 _resultId = null; 277 _verifyTypes = false; 278 } 279 280 293 protected abstract Object resolveObject() throws ObjectNotFoundException, JspException ; 294 295 301 protected abstract String getObjectName(); 302 303 310 protected boolean allowNullInvocationTarget() { 311 return false; 312 } 313 314 331 protected void handleReturnValue(Object result) { 332 if(_resultId != null) { 333 if(result != null) { 334 if(LOGGER.isInfoEnabled() && pageContext.getAttribute(_resultId) != null) 335 LOGGER.info("Overwriting attribute named \"" + _resultId + "\" in the PageContext with a new attribute of type \"" + 336 result.getClass().getName() + "\" returned from calling the method \"" + _method + "\" on an object named \"" + 337 getObjectName() + "\"."); 338 339 pageContext.setAttribute(_resultId, result); 340 } 341 else { 342 if(LOGGER.isInfoEnabled()) 343 LOGGER.info("Removing attribute named \"" + _resultId + "\" from the PageContext. " + 344 "The value returned from calling the method \"" + _method + "\" on an object named \"" + 345 getObjectName() + "\" is null."); 346 347 pageContext.removeAttribute(_resultId); 348 } 349 } 350 } 351 352 360 protected List getParameterNodes() { 361 if(_parameters != null) 362 return _parameters; 363 else 364 return EMPTY_LIST; 365 } 366 367 377 protected Method findMethod(Object target, String methodName, boolean verifyTypes) { 378 int paramCount = (_parameters != null ? _parameters.size() : 0); 379 Method [] methods = target.getClass().getMethods(); 380 381 for(int i = 0; i < methods.length; i++) { 382 if(methods[i].getName().equals(_method) && methods[i].getParameterTypes().length == paramCount) { 383 if(LOGGER.isDebugEnabled()) { 384 LOGGER.debug("found method: " + methods[i]); 385 LOGGER.debug("check types: " + verifyTypes); 386 } 387 388 if(verifyTypes) { 390 boolean match = true; 391 Class [] parameterTypes = methods[i].getParameterTypes(); 393 for(int j = 0; j < parameterTypes.length; j++) { 394 if(LOGGER.isDebugEnabled()) { 395 LOGGER.debug("parameterTypes[" + j + "]: " + parameterTypes[j]); 396 LOGGER.debug("paramNode[" + j + "]: " + ((ParamNode)_parameters.get(j)).typeName); 397 } 398 399 if(!parameterTypes[j].getName().equals(((ParamNode)_parameters.get(j)).typeName)) { 401 match = false; 402 break; 403 } 404 405 } 406 if(match) return methods[i]; 407 } 408 else 409 return methods[i]; 410 } 411 } 412 413 return null; 414 } 415 416 425 private final Object [] getArguments(Class [] paramTypes) { 426 if(_parameters == null) 427 return EMPTY_ARGS; 428 429 Object [] args = new Object [paramTypes.length]; 430 431 for(int i = 0; i < _parameters.size(); i++) { 432 ParamNode pn = (ParamNode)_parameters.get(i); 433 if(pn.paramValue == MethodParameter.NULL_ARG) 435 continue; 436 437 Object value = pn.paramValue; 438 try { 439 if(!(value instanceof String ) || value == null) 441 args[i] = value; 442 else 444 args[i] = TypeUtils.convertToObject((String )value, paramTypes[i]); 445 } 446 catch(Exception e) { 448 String msg = Bundle.getErrorString("Tags_AbstractCallMethod_parameterError", 449 new Object []{paramTypes[i], new Integer (i), value, e.toString()}); 450 throw new IllegalArgumentException (msg); 451 } 452 453 if(LOGGER.isDebugEnabled()) LOGGER.debug("argTypes[" + i + "]: " + paramTypes[i]); 454 } 455 456 return args; 457 } 458 459 466 private static final String prettyPrintParameterTypes(List parameters) { 467 InternalStringBuilder paramString = null; 468 if(parameters != null) { 469 paramString = new InternalStringBuilder(128); 470 paramString.append("("); 471 for(int i = 0; i < parameters.size(); i++) { 472 if(i > 0) 473 paramString.append(", "); 474 475 paramString.append(((ParamNode)parameters.get(i)).typeName); 476 } 477 paramString.append(")"); 478 479 return paramString.toString(); 480 } 481 else 482 return EMPTY_STRING; 483 } 484 485 493 protected class ParamNode { 494 495 499 public String typeName = null; 500 501 506 public Object paramValue = null; 507 508 public String toString() { 509 InternalStringBuilder buf = new InternalStringBuilder(32); 510 buf.append("typeName: ").append(typeName); 511 return buf.toString(); 512 } 513 } 514 } 515 | Popular Tags |