1 16 package org.directwebremoting.impl; 17 18 import java.io.BufferedReader ; 19 import java.io.IOException ; 20 import java.io.InputStream ; 21 import java.io.InputStreamReader ; 22 import java.lang.reflect.Method ; 23 import java.util.Arrays ; 24 import java.util.Collection ; 25 import java.util.Collections ; 26 import java.util.HashMap ; 27 import java.util.Iterator ; 28 import java.util.Map ; 29 30 import org.directwebremoting.extend.AccessControl; 31 import org.directwebremoting.extend.ConverterManager; 32 import org.directwebremoting.extend.Creator; 33 import org.directwebremoting.extend.CreatorManager; 34 import org.directwebremoting.extend.DebugPageGenerator; 35 import org.directwebremoting.extend.DwrConstants; 36 import org.directwebremoting.servlet.EngineHandler; 37 import org.directwebremoting.servlet.PathConstants; 38 import org.directwebremoting.servlet.UtilHandler; 39 import org.directwebremoting.util.JavascriptUtil; 40 import org.directwebremoting.util.LocalUtil; 41 import org.directwebremoting.util.Logger; 42 import org.directwebremoting.util.Messages; 43 44 48 public class DefaultDebugPageGenerator implements DebugPageGenerator 49 { 50 53 public String generateIndexPage(final String root) throws SecurityException 54 { 55 if (!creatorManager.isDebug()) 56 { 57 log.warn("Failed attempt to access test pages outside of debug mode. Set the debug init-parameter to true to enable."); 58 throw new SecurityException (Messages.getString("DefaultDebugPageGenerator.AccessDenied")); 59 } 60 61 StringBuffer buffer = new StringBuffer (); 62 63 buffer.append("<html>\n"); 64 buffer.append("<head><title>DWR Test Index</title></head>\n"); 65 buffer.append("<body>\n"); 66 67 buffer.append("<h2>Classes known to DWR:</h2>\n"); 68 buffer.append("<ul>\n"); 69 for (Iterator it = creatorManager.getCreatorNames().iterator(); it.hasNext();) 70 { 71 String name = (String ) it.next(); 72 Creator creator = creatorManager.getCreator(name); 73 74 buffer.append("<li><a HREF='"); 75 buffer.append(root); 76 buffer.append(testHandlerUrl); 77 buffer.append(name); 78 buffer.append("'>"); 79 buffer.append(name); 80 buffer.append("</a> ("); 81 buffer.append(creator.getType().getName()); 82 buffer.append(")</li>\n"); 83 } 84 buffer.append("</ul>\n"); 85 86 buffer.append("</body></html>\n"); 87 88 return buffer.toString(); 89 } 90 91 94 public String generateTestPage(final String root, final String scriptName) throws SecurityException 95 { 96 if (!creatorManager.isDebug()) 97 { 98 log.warn("Failed attempt to access test pages outside of debug mode. Set the debug init-parameter to true to enable."); 99 throw new SecurityException (Messages.getString("DefaultAccessControl.AccessDenied")); 100 } 101 102 String interfaceURL = root + interfaceHandlerUrl + scriptName + PathConstants.EXTENSION_JS; 103 String engineURL = root + engineHandlerUrl; 104 String utilURL = root + utilHandlerUrl; 105 106 String proxyInterfaceURL = PATH_UP + interfaceHandlerUrl + scriptName + PathConstants.EXTENSION_JS; 107 String proxyEngineURL = PATH_UP + engineHandlerUrl; 108 String proxyUtilURL = PATH_UP + utilHandlerUrl; 109 110 Creator creator = creatorManager.getCreator(scriptName); 111 Method [] methods = creator.getType().getMethods(); 112 StringBuffer buffer = new StringBuffer (); 113 114 buffer.append("<html>\n"); 115 buffer.append("<head>\n"); 116 buffer.append(" <title>DWR Test</title>\n"); 117 buffer.append(" <!-- These paths use .. so that they still work behind a path mapping proxy. The fully qualified version is more cut and paste friendly. -->\n"); 118 buffer.append(" <script type='text/javascript' SRC='" + proxyInterfaceURL + "'></script>\n"); 119 buffer.append(" <script type='text/javascript' SRC='" + proxyEngineURL + "'></script>\n"); 120 buffer.append(" <script type='text/javascript' SRC='" + proxyUtilURL + "'></script>\n"); 121 buffer.append(" <script type='text/javascript'>\n"); 122 buffer.append(" function objectEval(text)\n"); 123 buffer.append(" {\n"); 124 buffer.append(" // eval() breaks when we use it to get an object using the { a:42, b:'x' }\n"); 125 buffer.append(" // syntax because it thinks that { and } surround a block and not an object\n"); 126 buffer.append(" // So we wrap it in an array and extract the first element to get around\n"); 127 buffer.append(" // this.\n"); 128 buffer.append(" // This code is only needed for interpreting the parameter input fields,\n"); 129 buffer.append(" // so you can ignore this for normal use.\n"); 130 buffer.append(" // The regex = [start of line][whitespace]{[stuff]}[whitespace][end of line]\n"); 131 buffer.append(" text = text.replace(/\\n/g, ' ');\n"); 132 buffer.append(" text = text.replace(/\\r/g, ' ');\n"); 133 buffer.append(" if (text.match(/^\\s*\\{.*\\}\\s*$/))\n"); 134 buffer.append(" {\n"); 135 buffer.append(" text = '[' + text + '][0]';\n"); 136 buffer.append(" }\n"); 137 buffer.append(" return eval(text);\n"); 138 buffer.append(" }\n"); 139 buffer.append(" </script>\n"); 140 buffer.append(" <style>\n"); 141 buffer.append(" input.itext { font-size: smaller; background: #E4E4E4; border: 0; }\n"); 142 buffer.append(" input.ibutton { font-size: xx-small; border: 1px outset; margin: 0px; padding: 0px; }\n"); 143 buffer.append(" span.reply { background: #ffffdd; white-space: pre; }\n"); 144 buffer.append(" span.warning { font-size: smaller; color: red; }\n"); 145 buffer.append(" </style>\n"); 146 buffer.append("</head>\n"); 147 buffer.append("<body onload='dwr.util.useLoadingMessage()'>\n"); 148 buffer.append(BLANK); 149 150 buffer.append("<h2>Methods For: " + scriptName + " (" + creator.getType().getName() + ")</h2>\n"); 151 buffer.append("<p>To use this class in your javascript you will need the following script includes:</p>\n"); 152 buffer.append("<pre>\n"); 153 buffer.append(" <script type='text/javascript' SRC='<a HREF='" + interfaceURL + "'>" + interfaceURL + "</a>'></script>\n"); 154 buffer.append(" <script type='text/javascript' SRC='<a HREF='" + engineURL + "'>" + engineURL + "</a>'></script>\n"); 155 buffer.append("</pre>\n"); 156 157 buffer.append("<p>In addition there is an optional utility script:</p>\n"); 158 buffer.append("<pre>\n"); 159 buffer.append(" <script type='text/javascript' SRC='<a HREF='" + utilURL + "'>" + utilURL + "</a>'></script>\n"); 160 buffer.append("</pre>\n"); 161 162 buffer.append("<p>Replies from DWR are shown with a yellow background if they are simple or in an alert box otherwise.<br/>\n"); 163 buffer.append("The inputs are evaluated as Javascript so strings must be quoted before execution.</p>\n"); 164 165 buffer.append("<p>There are " + methods.length + " declared methods:</p><ul>\n"); 166 167 for (int i = 0; i < methods.length; i++) 168 { 169 Method method = methods[i]; 170 String methodName = method.getName(); 171 172 if (JavascriptUtil.isReservedWord(methodName)) 174 { 175 buffer.append(BLANK); 176 buffer.append("<li style='color: #88A;'>" + methodName + "() is not available because it is a reserved word.</li>\n"); 177 continue; 178 } 179 180 buffer.append(BLANK); 181 buffer.append("<li>\n"); 182 buffer.append(" " + methodName + '('); 183 184 Class [] paramTypes = method.getParameterTypes(); 185 for (int j = 0; j < paramTypes.length; j++) 186 { 187 Class paramType = paramTypes[j]; 188 189 if (LocalUtil.isServletClass(paramType)) 191 { 192 buffer.append("AUTO"); 193 } 194 else 195 { 196 String value = BLANK; 197 if (paramType == String .class) 198 { 199 value = "\"\""; 200 } 201 else if (paramType == Boolean .class || paramType == Boolean.TYPE) 202 { 203 value = "true"; 204 } 205 else if (paramType == Integer .class || paramType == Integer.TYPE || paramType == Short .class || paramType == Short.TYPE 206 || paramType == Long .class || paramType == Long.TYPE || paramType == Byte .class || paramType == Byte.TYPE) 207 { 208 value = "0"; 209 } 210 else if (paramType == Float .class || paramType == Float.TYPE || paramType == Double .class || paramType == Double.TYPE) 211 { 212 value = "0.0"; 213 } 214 else if (paramType.isArray() || Collection .class.isAssignableFrom(paramType)) 215 { 216 value = "[]"; 217 } 218 else if (Map .class.isAssignableFrom(paramType)) 219 { 220 value = "{}"; 221 } 222 223 buffer.append(" <input class='itext' type='text' size='10' value='" + value + "' id='p" + i + j + "' title='Will be converted to: " + paramType.getName() + "'/>"); 224 } 225 226 buffer.append(j == paramTypes.length - 1 ? BLANK : ", \n"); 227 } 228 buffer.append(" );\n"); 229 230 String onclick = scriptName + '.' + methodName + "("; 231 for (int j = 0; j < paramTypes.length; j++) 232 { 233 if (!LocalUtil.isServletClass(paramTypes[j])) 234 { 235 onclick += "objectEval($(\"p" + i + j + "\").value), "; 236 } 237 } 238 onclick += "reply" + i + ");"; 239 240 buffer.append(" <input class='ibutton' type='button' onclick='" + onclick + "' value='Execute' title='Calls " + scriptName + '.' + methodName + "(). View source for details.'/>\n"); 241 242 buffer.append(" <script type='text/javascript'>\n"); 243 buffer.append(" var reply" + i + " = function(data)\n"); 244 buffer.append(" {\n"); 245 buffer.append(" if (data != null && typeof data == 'object') alert(dwr.util.toDescriptiveString(data, 2));\n"); 246 buffer.append(" else dwr.util.setValue('d" + i + "', dwr.util.toDescriptiveString(data, 1));\n"); 247 buffer.append(" }\n"); 248 buffer.append(" </script>\n"); 249 buffer.append(" <span id='d" + i + "' class='reply'></span>\n"); 250 251 boolean overloaded = false; 253 for (int j = 0; j < methods.length; j++) 254 { 255 if (j != i && methods[j].getName().equals(methodName)) 256 { 257 overloaded = true; 258 } 259 } 260 if (overloaded) 261 { 262 buffer.append("<br/><span class='warning'>(Warning: overloaded methods are not recommended. See <a HREF='#overloadedMethod'>below</a>)</span>\n"); 263 } 264 265 for (int j = 0; j < paramTypes.length; j++) 267 { 268 if (!converterManager.isConvertable(paramTypes[j])) 269 { 270 buffer.append("<br/><span class='warning'>(Warning: No Converter for " + paramTypes[j].getName() + ". See <a HREF='#missingConverter'>below</a>)</span>\n"); 271 } 272 } 273 274 if (!converterManager.isConvertable(method.getReturnType())) 275 { 276 buffer.append("<br/><span class='warning'>(Warning: No Converter for " + method.getReturnType().getName() + ". See <a HREF='#missingConverter'>below</a>)</span>\n"); 277 } 278 279 try 281 { 282 accessControl.assertIsDisplayable(creator, scriptName, method); 283 } 284 catch (SecurityException ex) 285 { 286 buffer.append("<br/><span class='warning'>(Warning: " + methodName + "() is excluded: " + ex.getMessage() + ". See <a HREF='#excludedMethod'>below</a>)</span>\n"); 287 } 288 289 293 buffer.append("</li>\n"); 294 } 295 296 buffer.append(BLANK); 297 buffer.append("</ul>\n"); 298 299 buffer.append("<h2>Other Links</h2>\n"); 300 buffer.append("<ul>\n"); 301 buffer.append("<li>Back to <a HREF='" + root + "/'>class index</a>.</li>\n"); 302 buffer.append("</ul>\n"); 303 304 synchronized (scriptCache) 305 { 306 String output = (String ) scriptCache.get(PathConstants.FILE_HELP); 307 if (output == null) 308 { 309 InputStream raw = getClass().getResourceAsStream(DwrConstants.PACKAGE + PathConstants.FILE_HELP); 310 if (raw == null) 311 { 312 log.error(Messages.getString("DefaultProcessor.MissingHelp", PathConstants.FILE_HELP)); 313 output = "<p>Failed to read help text from resource file. Check dwr.jar is built to include html files.</p>"; 314 } 315 else 316 { 317 StringBuffer fileBuffer = new StringBuffer (); 318 319 BufferedReader in = new BufferedReader (new InputStreamReader (raw)); 320 while (true) 321 { 322 try 323 { 324 String line = in.readLine(); 325 if (line == null) 326 { 327 break; 328 } 329 330 fileBuffer.append(line); 331 fileBuffer.append('\n'); 332 } 333 catch (IOException ex) 334 { 335 fileBuffer.append(ex.toString()); 336 fileBuffer.append('\n'); 337 break; 338 } 339 } 340 341 output = fileBuffer.toString(); 342 } 343 344 scriptCache.put(PathConstants.FILE_HELP, output); 345 } 346 347 buffer.append(output); 348 } 349 350 buffer.append("</body></html>\n"); 351 352 return buffer.toString(); 353 } 354 355 358 public String generateInterfaceUrl(String root, String scriptName) 359 { 360 return root + interfaceHandlerUrl + scriptName + PathConstants.EXTENSION_JS; 361 } 362 363 366 public String generateEngineUrl(String root) 367 { 368 return root + engineHandlerUrl; 369 } 370 371 374 public String generateLibraryUrl(String root, String library) 375 { 376 return root + library; 377 } 378 379 382 public Collection getAvailableLibraries() 383 { 384 if (availableLibraries == null) 385 { 386 availableLibraries = Collections.unmodifiableCollection(Arrays.asList(new String [] { utilHandlerUrl })); 387 } 388 389 return availableLibraries; 390 } 391 392 396 public void setConverterManager(ConverterManager converterManager) 397 { 398 this.converterManager = converterManager; 399 } 400 401 405 public void setCreatorManager(CreatorManager creatorManager) 406 { 407 this.creatorManager = creatorManager; 408 } 409 410 414 public void setAccessControl(AccessControl accessControl) 415 { 416 this.accessControl = accessControl; 417 } 418 419 422 public void setEngineHandlerUrl(String engineHandlerUrl) 423 { 424 this.engineHandlerUrl = engineHandlerUrl; 425 } 426 427 430 public void setUtilHandlerUrl(String utilHandlerUrl) 431 { 432 this.utilHandlerUrl = utilHandlerUrl; 433 } 434 435 438 public void setTestHandlerUrl(String testHandlerUrl) 439 { 440 this.testHandlerUrl = testHandlerUrl; 441 } 442 443 447 public void setInterfaceHandlerUrl(String interfaceHandlerUrl) 448 { 449 this.interfaceHandlerUrl = interfaceHandlerUrl; 450 } 451 452 455 protected String engineHandlerUrl; 456 457 460 protected String utilHandlerUrl; 461 462 465 protected String testHandlerUrl; 466 467 470 protected String interfaceHandlerUrl; 471 472 475 protected ConverterManager converterManager = null; 476 477 480 protected CreatorManager creatorManager = null; 481 482 485 protected AccessControl accessControl = null; 486 487 490 protected final Map scriptCache = new HashMap (); 491 492 496 private Collection availableLibraries = null; 497 498 501 private static final String PATH_UP = ".."; 502 503 506 public static final String BLANK = ""; 507 508 511 private static final Logger log = Logger.getLogger(DefaultDebugPageGenerator.class); 512 } 513 | Popular Tags |