1 16 package org.directwebremoting.impl; 17 18 import java.lang.reflect.InvocationTargetException ; 19 import java.lang.reflect.Method ; 20 import java.lang.reflect.Modifier ; 21 import java.util.Collection ; 22 import java.util.Collections ; 23 import java.util.HashMap ; 24 import java.util.Iterator ; 25 import java.util.Map ; 26 27 import org.directwebremoting.AjaxFilter; 28 import org.directwebremoting.AjaxFilterChain; 29 import org.directwebremoting.WebContext; 30 import org.directwebremoting.WebContextFactory; 31 import org.directwebremoting.extend.AccessControl; 32 import org.directwebremoting.extend.AjaxFilterManager; 33 import org.directwebremoting.extend.Call; 34 import org.directwebremoting.extend.Calls; 35 import org.directwebremoting.extend.Converter; 36 import org.directwebremoting.extend.ConverterManager; 37 import org.directwebremoting.extend.Creator; 38 import org.directwebremoting.extend.CreatorManager; 39 import org.directwebremoting.extend.NamedConverter; 40 import org.directwebremoting.extend.Property; 41 import org.directwebremoting.extend.EnginePrivate; 42 import org.directwebremoting.extend.Remoter; 43 import org.directwebremoting.extend.Replies; 44 import org.directwebremoting.extend.Reply; 45 import org.directwebremoting.util.Continuation; 46 import org.directwebremoting.util.JavascriptUtil; 47 import org.directwebremoting.util.LocalUtil; 48 import org.directwebremoting.util.Logger; 49 50 55 public class DefaultRemoter implements Remoter 56 { 57 60 public String generateInterfaceScript(String scriptName, String path) throws SecurityException 61 { 62 String actualPath = path; 63 if (overridePath != null) 64 { 65 actualPath = overridePath; 66 } 67 68 StringBuffer buffer = new StringBuffer (); 69 70 Collection converterMatches = converterManager.getConverterMatchStrings(); 72 Iterator it = converterMatches.iterator(); 73 while (it.hasNext()) 74 { 75 String match = (String ) it.next(); 76 77 try 78 { 79 StringBuffer paramBuffer = new StringBuffer (); 80 81 Converter conv = converterManager.getConverterByMatchString(match); 82 if (conv instanceof NamedConverter) 84 { 85 NamedConverter boConv = (NamedConverter) conv; 86 String jsClassName = boConv.getJavascript(); 87 88 if (jsClassName != null && !jsClassName.equals("")) 90 { 91 if (match.indexOf("*") == -1) 93 { 94 paramBuffer.append('\n'); 95 96 paramBuffer.append("if (typeof " + jsClassName + " != \"function\") {\n"); 98 paramBuffer.append(" var " + jsClassName + " = function() {\n"); 99 100 Class mappedType; 102 try 103 { 104 mappedType = LocalUtil.classForName(match); 105 } 106 catch (ClassNotFoundException ex) 107 { 108 throw new IllegalArgumentException (ex.getMessage()); 109 } 110 111 Map properties = boConv.getPropertyMapFromClass(mappedType, true, true); 112 for (Iterator pit = properties.entrySet().iterator(); pit.hasNext();) 113 { 114 Map.Entry entry = (Map.Entry ) pit.next(); 115 String name = (String ) entry.getKey(); 116 Property property = (Property) entry.getValue(); 117 Class propType = property.getPropertyType(); 118 119 paramBuffer.append(" this." + name + " = "); 121 122 if (propType.isArray()) 124 { 125 paramBuffer.append("[]"); 126 } 127 else if (propType == boolean.class) 128 { 129 paramBuffer.append("false"); 130 } 131 else if (propType.isPrimitive()) 132 { 133 paramBuffer.append("0"); 134 } 135 else 136 { 137 paramBuffer.append("null"); 138 } 139 140 paramBuffer.append(";\n"); 141 } 142 143 paramBuffer.append(" }\n"); 144 paramBuffer.append("}\n"); 145 } 146 } 147 } 148 149 buffer.append(paramBuffer.toString()); 150 } 151 catch (Exception ex) 152 { 153 log.warn("Failed to create parameter declaration for " + match, ex); 154 buffer.append("// Missing parameter declaration for " + match + ". See the server logs for details."); 155 } 156 } 157 158 Creator creator = creatorManager.getCreator(scriptName); 159 160 buffer.append('\n'); 161 162 String init = EnginePrivate.getEngineInitScript(); 163 buffer.append(init); 164 165 buffer.append("if (" + scriptName + " == null) var " + scriptName + " = {};\n"); 166 buffer.append(scriptName + "._path = '" + actualPath + "';\n"); 167 168 Method [] methods = creator.getType().getMethods(); 169 for (int i = 0; i < methods.length; i++) 170 { 171 Method method = methods[i]; 172 String methodName = method.getName(); 173 174 try 178 { 179 accessControl.assertIsDisplayable(creator, scriptName, method); 180 } 181 catch (SecurityException ex) 182 { 183 if (!allowImpossibleTests) 184 { 185 continue; 186 } 187 } 188 189 if (JavascriptUtil.isReservedWord(methodName)) 191 { 192 continue; 193 } 194 195 String script; 198 if (!creator.isCacheable()) 199 { 200 script = getMethodJS(scriptName, method); 201 } 202 else 203 { 204 String key = scriptName + "." + method.getName(); 205 206 script = (String ) methodCache.get(key); 210 if (script == null) 211 { 212 script = getMethodJS(scriptName, method); 213 methodCache.put(key, script); 214 } 215 } 216 217 buffer.append(script); 218 } 219 220 return buffer.toString(); 221 } 222 223 229 private String getMethodJS(String scriptName, Method method) 230 { 231 StringBuffer buffer = new StringBuffer (); 232 233 String methodName = method.getName(); 234 buffer.append(scriptName + '.' + methodName + " = function("); 235 Class [] paramTypes = method.getParameterTypes(); 236 for (int j = 0; j < paramTypes.length; j++) 237 { 238 if (!LocalUtil.isServletClass(paramTypes[j])) 239 { 240 buffer.append("p" + j + ", "); 241 } 242 } 243 244 buffer.append("callback) {\n"); 245 246 String executeFunctionName = EnginePrivate.getExecuteFunctionName(); 247 buffer.append(" " + executeFunctionName + "(" + scriptName + "._path, '" + scriptName + "', '" + methodName + "\', "); 248 for (int j = 0; j < paramTypes.length; j++) 249 { 250 if (LocalUtil.isServletClass(paramTypes[j])) 251 { 252 buffer.append("false, "); 253 } 254 else 255 { 256 buffer.append("p" + j + ", "); 257 } 258 } 259 260 buffer.append("callback);\n"); 261 buffer.append("}\n"); 262 263 return buffer.toString(); 264 } 265 266 269 public Replies execute(Calls calls) 270 { 271 Replies replies = new Replies(calls.getBatchId()); 272 273 int callCount = calls.getCallCount(); 274 if (callCount > maxCallCount) 275 { 276 log.error("Call count for batch exceeds maxCallCount. Add an init-param of maxCallCount to increase this limit"); 277 throw new SecurityException ("Call count for batch is too high"); 278 } 279 280 for (int callNum = 0; callNum < callCount; callNum++) 281 { 282 Call call = calls.getCall(callNum); 283 Reply reply = execute(call); 284 replies.addReply(reply); 285 } 286 287 return replies; 288 } 289 290 295 public Reply execute(Call call) 296 { 297 try 298 { 299 Method method = call.getMethod(); 300 if (method == null || call.getException() != null) 301 { 302 return new Reply(call.getCallId(), null, call.getException()); 303 } 304 305 Creator creator = creatorManager.getCreator(call.getScriptName()); 309 310 accessControl.assertExecutionIsPossible(creator, call.getScriptName(), method); 314 315 Object object = null; 318 String scope = creator.getScope(); 319 boolean create = false; 320 321 if (!Modifier.isStatic(method.getModifiers())) 322 { 323 WebContext webcx = WebContextFactory.get(); 324 325 if (scope.equals(Creator.APPLICATION)) 327 { 328 object = webcx.getServletContext().getAttribute(call.getScriptName()); 329 } 330 else if (scope.equals(Creator.SESSION)) 331 { 332 object = webcx.getSession().getAttribute(call.getScriptName()); 333 } 334 else if (scope.equals(Creator.SCRIPT)) 335 { 336 object = webcx.getScriptSession().getAttribute(call.getScriptName()); 337 } 338 else if (scope.equals(Creator.REQUEST)) 339 { 340 object = webcx.getHttpServletRequest().getAttribute(call.getScriptName()); 341 } 342 344 if (object == null) 346 { 347 create = true; 348 object = creator.getInstance(); 349 } 350 351 if (create) 353 { 354 if (scope.equals(Creator.APPLICATION)) 355 { 356 webcx.getServletContext().setAttribute(call.getScriptName(), object); 359 } 360 else if (scope.equals(Creator.SESSION)) 361 { 362 webcx.getSession().setAttribute(call.getScriptName(), object); 363 } 364 else if (scope.equals(Creator.SCRIPT)) 365 { 366 webcx.getScriptSession().setAttribute(call.getScriptName(), object); 367 } 368 else if (scope.equals(Creator.REQUEST)) 369 { 370 webcx.getHttpServletRequest().setAttribute(call.getScriptName(), object); 371 } 372 } 374 } 375 376 log.info("Exec: " + call.getScriptName() + "." + call.getMethodName() + "()"); 378 if (log.isDebugEnabled()) 379 { 380 StringBuffer buffer = new StringBuffer (); 381 382 if (create) 383 { 384 buffer.append("--Object created, "); 385 if (!scope.equals(Creator.PAGE)) 386 { 387 buffer.append(" stored in "); 388 buffer.append(scope); 389 } 390 else 391 { 392 buffer.append(" not stored"); 393 } 394 } 395 else 396 { 397 buffer.append("--Object found in "); 398 buffer.append(scope); 399 } 400 buffer.append(". "); 401 402 415 buffer.append("id="); 416 buffer.append(call.getCallId()); 417 418 log.debug(buffer.toString()); 419 } 420 421 final Iterator it = ajaxFilterManager.getAjaxFilters(call.getScriptName()); 423 AjaxFilterChain chain = new AjaxFilterChain() 424 { 425 public Object doFilter(Object obj, Method meth, Object [] p) throws Exception 426 { 427 AjaxFilter next = (AjaxFilter) it.next(); 428 return next.doFilter(obj, meth, p, this); 429 } 430 }; 431 Object reply = chain.doFilter(object, method, call.getParameters()); 432 return new Reply(call.getCallId(), reply); 433 } 434 catch (InvocationTargetException ex) 435 { 436 Continuation.rethrowIfContinuation(ex); 438 439 log.warn("Method execution failed: ", ex.getTargetException()); 440 return new Reply(call.getCallId(), null, ex.getTargetException()); 441 } 442 catch (Exception ex) 443 { 444 Continuation.rethrowIfContinuation(ex); 446 447 log.warn("Method execution failed: ", ex); 448 return new Reply(call.getCallId(), null, ex); 449 } 450 } 451 452 456 public void setCreatorManager(CreatorManager creatorManager) 457 { 458 this.creatorManager = creatorManager; 459 } 460 461 465 public void setConverterManager(ConverterManager converterManager) 466 { 467 this.converterManager = converterManager; 468 } 469 470 474 public void setAccessControl(AccessControl accessControl) 475 { 476 this.accessControl = accessControl; 477 } 478 479 483 public void setAjaxFilterManager(AjaxFilterManager ajaxFilterManager) 484 { 485 this.ajaxFilterManager = ajaxFilterManager; 486 } 487 488 492 public void setOverridePath(String overridePath) 493 { 494 this.overridePath = overridePath; 495 } 496 497 501 public void setAllowImpossibleTests(boolean allowImpossibleTests) 502 { 503 this.allowImpossibleTests = allowImpossibleTests; 504 } 505 506 511 public void setMaxCallCount(int maxCallCount) 512 { 513 this.maxCallCount = maxCallCount; 514 } 515 516 519 private AjaxFilterManager ajaxFilterManager = null; 520 521 524 protected CreatorManager creatorManager = null; 525 526 529 protected ConverterManager converterManager = null; 530 531 534 protected AccessControl accessControl = null; 535 536 539 private String overridePath = null; 540 541 544 private boolean allowImpossibleTests = false; 545 546 550 private int maxCallCount = 20; 551 552 555 private Map methodCache = Collections.synchronizedMap(new HashMap ()); 556 557 560 private static final Logger log = Logger.getLogger(DefaultRemoter.class); 561 } 562 | Popular Tags |