1 23 24 29 30 package com.sun.enterprise.webservice.monitoring; 31 32 import javax.servlet.*; 33 import javax.servlet.http.*; 34 35 import java.io.IOException ; 36 import java.io.PrintWriter ; 37 import java.io.ByteArrayOutputStream ; 38 import java.io.ByteArrayInputStream ; 39 import java.io.StringReader ; 40 import java.io.File ; 41 42 import java.util.Iterator ; 43 import java.util.List ; 44 import java.util.Arrays ; 45 import java.util.ArrayList ; 46 import java.util.Hashtable ; 47 import java.util.StringTokenizer ; 48 import java.lang.reflect.Method ; 49 import java.net.URLClassLoader ; 50 import java.net.URL ; 51 import java.net.URLDecoder ; 52 import java.net.MalformedURLException ; 53 54 import java.util.logging.Logger ; 55 import java.util.logging.Level ; 56 57 import javax.xml.soap.SOAPMessage ; 58 import javax.xml.namespace.QName ; 59 import com.sun.enterprise.deployment.WebServiceEndpoint; 60 import com.sun.enterprise.webservice.WsUtil; 61 import com.sun.xml.bind.api.JAXBRIContext; 62 import com.sun.enterprise.webservice.ServiceInterfaceGenerator; 63 import com.sun.enterprise.webservice.WsUtil; 64 65 import com.sun.enterprise.util.LocalStringManagerImpl; 66 67 import javax.xml.ws.Service; 69 import javax.jws.WebService; 70 import javax.xml.ws.WebEndpoint; 71 72 import com.sun.tools.ws.spi.WSToolsObjectFactory; 74 75 import javax.xml.transform.stream.StreamSource ; 76 import javax.xml.transform.stream.StreamResult ; 77 import javax.xml.transform.Transformer ; 78 import javax.xml.transform.TransformerFactory ; 79 import javax.xml.transform.OutputKeys ; 80 81 import javax.enterprise.deploy.shared.ModuleType ; 82 83 88 public class WebServiceTesterServlet extends HttpServlet implements MessageListener { 89 90 private static Logger logger = WsUtil.getDefaultLogger(); 91 private static Hashtable <String , Class > gsiClasses = new Hashtable <String , Class >(); 92 private static Hashtable <String , Object > ports = new Hashtable <String , Object >(); 93 private static LocalStringManagerImpl localStrings = 95 new LocalStringManagerImpl(WebServiceTesterServlet.class); 96 97 public static void invoke(HttpServletRequest request, 98 HttpServletResponse response, WebServiceEndpoint endpoint) { 99 100 try { 101 WebServiceTesterServlet servlet = new WebServiceTesterServlet(); 102 103 if (request.getMethod().equalsIgnoreCase("GET")) { 104 servlet.doGet(request, response); 105 } else { 106 servlet.doPost(request, response); 107 } 108 } catch(Exception e) { 109 try { 110 PrintWriter out = response.getWriter(); 111 out.print("<HTML><HEAD><TITLE>"+ 112 localStrings.getLocalString( 113 "enterprise.webservice.monitoring.methodInvocationException", 114 "Method invocation exception")+"</TITLE></HEAD>"); 115 out.print("<H3>" + 116 localStrings.getLocalString( 117 "enterprise.webservice.monitoring.ExceptionDetails", 118 "Exceptions details : {0}", 119 new Object [] {e.getMessage()}) + "</H3>"); 120 out.print("<HR>"); 121 e.printStackTrace(out); 122 out.print("<HR>"); 123 out.print("</HTML>"); 124 out.close(); 125 } catch(Exception ex) {}; 126 } 127 } 128 129 130 131 public WebServiceTesterServlet() { 132 } 133 134 public void doGet(HttpServletRequest req, HttpServletResponse res) 135 throws ServletException, IOException 136 { 137 res.setContentType("text/html"); 138 res.setHeader("pragma", "no-cache"); 139 PrintWriter out = res.getWriter(); 140 String requestURL = req.getRequestURL().toString(); 141 142 Endpoint myEndpoint = getEndpoint(requestURL); 143 String seiClassName = myEndpoint.getDescriptor().getServiceEndpointInterface(); 144 145 try { 147 Class seiClass = Thread.currentThread().getContextClassLoader().loadClass(seiClassName); 148 if(seiClass.getAnnotation(javax.jws.WebService.class) == null) { 149 testerNotSupportedError(myEndpoint.getDescriptor().getServiceName(), out); 150 return; 151 } 152 } catch (ClassNotFoundException clnfEx) { 153 classNotAccessibleError(Thread.currentThread().getContextClassLoader(), 154 seiClassName, out); 155 return; 156 } 157 158 initializePort(req); 159 Class clientSEI = gsiClasses.get(requestURL); 160 161 out.print("<HTML><HEAD><TITLE>"+ 162 myEndpoint.getDescriptor().getServiceName().getLocalPart()+" "+ 163 localStrings.getLocalString( 164 "enterprise.webservice.monitoring.title", 165 "Web Service Tester") + "</TITLE></HEAD>"); 166 out.print("<BODY><H1>"+ 167 myEndpoint.getDescriptor().getServiceName().getLocalPart()+" "+ 168 localStrings.getLocalString( 169 "enterprise.webservice.monitoring.title", 170 "Web Service Tester") + "</H1>"); 171 java.util.Enumeration <String > headers = req.getHeaderNames(); 172 173 boolean isInternetExplorer=false; 175 String userAgent = req.getHeader("user-agent"); 176 if (userAgent!=null) { 177 isInternetExplorer=userAgent.indexOf("MSIE")!=-1; 178 } 179 StringBuffer sb = new StringBuffer (URLDecoder.decode(requestURL)); 180 sb.append("?WSDL"); 181 182 out.print("<br>"); 183 out.print(localStrings.getLocalString( 184 "enterprise.webservice.monitoring.line1", 185 "This form will allow you to test your web service implementation (<A HREF=\"{0}\">WSDL File</A>)", 186 new Object [] {sb.toString()})); 187 out.print("<hr>"); 188 out.print(localStrings.getLocalString( 189 "enterprise.webservice.monitoring.line2", 190 "To invoke an operation, fill the method parameter(s) input boxes and click on the button labeled with the method name.")); 191 out.print(localStrings.getLocalString( 192 "enterprise.webservice.monitoring.methods", 193 "<H3>Methods :</H3>")); 194 195 Method [] methods = clientSEI.getMethods(); 196 197 for (Method m : methods) { 198 out.print("<FORM METHOD=\"POST\">"); 199 out.print(m.toString()); 200 out.print("<BR>"); 201 out.print("<INPUT TYPE=SUBMIT NAME=action value="+m.getName()+">"); 202 out.print(" ("); 204 Class [] parameters = m.getParameterTypes(); 205 for (int i=0;i<parameters.length;i++) { 206 out.print("<INPUT TYPE=TEXT NAME=PARAM"+ 207 m.getName()+i+">"); 208 if (i!=parameters.length-1) 209 out.print(","); 210 } 211 out.print(")"); 212 out.print("<BR>"); 213 out.print("<HR>"); 214 out.print("</FORM></BODY></HTML>"); 215 } 216 out.close(); 217 } 218 219 public void doPost(HttpServletRequest req, HttpServletResponse res) 220 throws ServletException, IOException 221 { 222 res.setContentType("text/html"); 223 res.setHeader("pragma", "no-cache"); 224 PrintWriter out = res.getWriter(); 225 String requestURL = req.getRequestURL().toString(); 226 227 out.print(localStrings.getLocalString( 228 "enterprise.webservice.monitoring.postTitle", 229 "<HTML><HEAD><TITLE>Method invocation trace</TITLE></HEAD>")); 230 231 String operationName = req.getParameter("action"); 232 233 try { 234 Endpoint myEndpoint = getEndpoint(requestURL); 235 236 Class clientSEI = gsiClasses.get(requestURL); 237 if (clientSEI==null) { 238 initializePort(req); 239 clientSEI = gsiClasses.get(requestURL); 240 } 241 Object port = ports.get(requestURL); 242 243 Method [] methods = clientSEI.getMethods(); 245 Method toInvoke = null; 246 for (Method m : methods) { 247 if (String.valueOf(m.getName()).equals(operationName)) { 248 toInvoke = m; 249 } 250 } 251 252 if (toInvoke==null) { 253 out.print("cannot find method " + operationName); 254 } else { 255 out.print(localStrings.getLocalString( 256 "enterprise.webservice.monitoring.methodInvocation", 257 "<H2><A> {0} </A> Method invocation</H2><BR><HR>", 258 new Object [] {toInvoke.getName()})); 259 260 myEndpoint.addListener(this); 262 263 Class [] parameterTypes = toInvoke.getParameterTypes(); 264 Object [] parameterValues= new Object [parameterTypes.length]; 265 out.print(localStrings.getLocalString( 266 "enterprise.webservice.monitoring.methodTrace", 267 "<h4>Method parameter(s)</h4>")); 268 out.print("<table border=\"1\">"); 269 out.print("<tr>"); 270 out.print("<th>Type</th>"); 271 out.print("<th>Value</th>"); 272 out.print("</tr>"); 273 for (int i=0;i<parameterTypes.length;i++) { 274 out.print("<tr>"); 275 String webValue = req.getParameter("PARAM"+ 276 toInvoke.getName()+i); 277 out.print("<td>" + parameterTypes[i].getName()+"</td>"); 278 out.print("<td>" + webValue + "</td>"); 279 parameterValues[i] = convertWebParam(parameterTypes[i],webValue); 280 out.print("</tr>"); 281 } 282 out.print("</table>"); 283 out.print("<HR>"); 284 out.print(localStrings.getLocalString( 285 "enterprise.webservice.monitoring.methodReturn", 286 "<h4>Method returned</h4>") 287 +toInvoke.getReturnType().getName() + " : \"<b>" 288 + toInvoke.invoke(port, parameterValues)+"</b>\""); 289 out.print("<HR>"); 290 if (request!=null) { 291 out.print(localStrings.getLocalString( 293 "enterprise.webservice.monitoring.soapReq", 294 "<h4>SOAP Request</h4>")); 295 dumpMessage(request, out); 296 } 297 if (toInvoke.getAnnotation(javax.jws.Oneway.class) == null && 298 response!=null) { 299 out.print(localStrings.getLocalString( 301 "enterprise.webservice.monitoring.soapResp", 302 "<h4>SOAP Response</h4>")); 303 dumpMessage(response, out); 304 } 305 myEndpoint.removeListener(this); 306 } 307 308 } catch(javax.xml.rpc.ServiceException e) { 309 throw new ServletException(e); 310 } catch(Exception e) { 311 throw new ServletException(e); 312 } 313 314 out.print("</HTML>"); 315 out.close(); 316 } 317 318 private void dumpMessage(MessageTrace message, PrintWriter out) throws Exception { 319 320 328 329 ByteArrayInputStream bais = new ByteArrayInputStream (message.getMessage(true).getBytes()); 331 StreamSource ss = new StreamSource (bais); 332 333 ByteArrayOutputStream baos = new ByteArrayOutputStream (); 334 StreamResult sr = new StreamResult (baos); 335 336 TransformerFactory factory = TransformerFactory.newInstance(); 337 Transformer transformer = factory.newTransformer(); 338 339 transformer.setOutputProperty(OutputKeys.METHOD, "xml"); 340 transformer.setOutputProperty(OutputKeys.INDENT, "yes"); 341 transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "4"); 342 transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8"); 343 transformer.transform(ss, sr); 344 345 346 out.print("<HR><blockquote><pre xml:lang>"); 347 String value = baos.toString(); 348 value = value.replaceAll("<", "<"); 349 value = value.replaceAll(">", ">"); 350 out.write(value); 351 352 out.print("</pre></blockquote><HR>"); 353 362 } 363 364 private MessageTrace request = null; 365 private MessageTrace response = null; 366 367 public void invocationProcessed(MessageTrace request, MessageTrace response) { 368 this.request = request; 369 this.response = response; 370 } 371 372 private Object convertWebParam(Class targetParamType, String webValue) { 373 374 Object convertedValue = null; 375 if (webValue==null || webValue.length()==0) { 376 return null; 377 } 378 if (String .class.equals(targetParamType)) { 379 convertedValue = webValue; 380 } else { 381 try { 382 if (int.class.equals(targetParamType) || 383 Integer .class.equals(targetParamType)) { 384 convertedValue = new Integer (webValue); 385 } 386 if (boolean.class.equals(targetParamType) || 387 Boolean .class.equals(targetParamType)) { 388 convertedValue = new Boolean (webValue); 389 } 390 if (char.class.equals(targetParamType) || 391 (Character .class.equals(targetParamType))) { 392 convertedValue = new Character (webValue.charAt(0)); 393 } 394 395 if (long.class.equals(targetParamType) || 396 (Long .class.equals(targetParamType))) { 397 convertedValue = new Long (webValue); 398 } 399 if (float.class.equals(targetParamType) || 400 (Float .class.equals(targetParamType))) { 401 convertedValue = new Float (webValue); 402 } 403 if (double.class.equals(targetParamType) || 404 (Double .class.equals(targetParamType))) { 405 convertedValue = new Double (webValue); 406 } 407 if (byte.class.equals(targetParamType) || 408 (Byte .class.equals(targetParamType))) { 409 convertedValue = new Byte (webValue); 410 } 411 if (short.class.equals(targetParamType) || 412 (Short .class.equals(targetParamType))) { 413 convertedValue = new Short (webValue); 414 } 415 if (StringBuffer .class.equals(targetParamType)) { 416 convertedValue = new StringBuffer (webValue); 417 } 418 } catch(NumberFormatException nfe) { 419 System.out.println("Cannot convert " + webValue + " in " + targetParamType); 420 } 421 } 422 return convertedValue; 423 } 424 425 private Endpoint getEndpoint(String url) { 426 427 WebServiceEngineImpl wsEngine = WebServiceEngineImpl.getInstance(); 428 String requestUriRaw; 429 if (url.indexOf("/Tester")!=-1) { 430 requestUriRaw = url.substring(0, url.indexOf("/Tester")); 431 } else { 432 requestUriRaw = url; 433 } 434 String requestUri = (requestUriRaw.charAt(0) == '/') ? 435 requestUriRaw.substring(1) : requestUriRaw; 436 437 return wsEngine.getEndpoint(requestUri); 438 439 } 440 441 private void classNotAccessibleError(ClassLoader cl, String className, PrintWriter out) { 442 443 out.print(localStrings.getLocalString( 444 "enterprise.webservice.monitoring.CNFTitle", 445 "<HTML><HEAD><TITLE>Method invocation exception</TITLE></HEAD>")); 446 if (cl==null) { 447 out.print(localStrings.getLocalString( 448 "enterprise.webservice.monitoring.CNFServerError", 449 "<H3>Internal server error, debugging is not available</H3>")); 450 } else { 451 out.print(localStrings.getLocalString( 452 "enterprise.webservice.monitoring.CNFerror2", 453 "<H3>Cannot load class {0} - Verify class presence in bundle</H3>", 454 new Object [] {className})); 455 } 456 out.print("<HR>"); 457 out.print("</HTML>"); 458 out.close(); 459 } 460 461 private void testerNotSupportedError(QName svcName, PrintWriter out) { 462 463 out.print(localStrings.getLocalString( 464 "enterprise.webservice.monitoring.TesterNSTitle", 465 "<HTML><HEAD><TITLE>Tester feature not supported</TITLE></HEAD>")); 466 out.print("<BODY>"); 467 out.print(localStrings.getLocalString( 468 "enterprise.webservice.monitoring.TesterNSerror2", 469 "Service {0} looks like a JAXRPC based webservice.", 470 new Object [] {svcName})); 471 out.print("<br><br>"); 472 out.print(localStrings.getLocalString( 473 "enterprise.webservice.monitoring.TesterNSdetail", 474 "Please note that the tester feature is supported for JAXWS based webservices only")); 475 out.print("</BODY>"); 476 out.print("</HTML>"); 477 out.close(); 478 } 479 480 private void initializePort(HttpServletRequest req) 481 throws ServletException, IOException { 482 483 String requestURL = req.getRequestURL().toString(); 484 Endpoint myEndpoint = getEndpoint(requestURL); 485 486 QName serviceName = 488 new QName (myEndpoint.getDescriptor().getWsdlPort().getNamespaceURI(), 489 myEndpoint.getDescriptor().getWebService().getName()); 490 491 StringBuffer sb = new StringBuffer (URLDecoder.decode(requestURL)); 493 sb.append("?WSDL"); 494 495 URL [] urls = new URL [1]; 496 String classesDir; 497 try { 498 URL wsdlUrl = new URL (sb.toString()); 499 classesDir = wsImport(wsdlUrl); 501 urls[0] = (new File (classesDir)).toURL(); 502 } catch(MalformedURLException mue) { 503 throw new ServletException(mue); 504 } 505 506 ClassLoader currentLoader = Thread.currentThread().getContextClassLoader(); 508 ClassLoader testerCL = new URLClassLoader (urls, currentLoader.getParent().getParent()); 515 try { 516 Thread.currentThread().setContextClassLoader(testerCL); 517 String serviceClassName = getServiceClass( 518 JAXBRIContext.mangleNameToClassName(serviceName.getLocalPart()), 519 classesDir); 520 if (serviceClassName==null) { 521 throw new RuntimeException ("Service Class not generated as expected"); 522 } 523 524 Class serviceClass = testerCL.loadClass(serviceClassName); 525 Service service = Service.create(new URL (sb.toString()), serviceName); 526 if (service==null) { 527 throw new RuntimeException ("Cannot load Service"); 528 } 529 530 String portClassName = getPortClass(myEndpoint, serviceClass); 532 if (portClassName==null) { 533 throw new RuntimeException ("Cannot find the correct port class."); 534 } 535 536 Class portClass = testerCL.loadClass(portClassName); 537 Object port = service.getPort(myEndpoint.getDescriptor().getWsdlPort(), portClass); 538 if (port==null) { 539 throw new RuntimeException ("Cannot find the correct port class."); 540 } 541 if (port!=null) { 542 ports.put(requestURL, port); 543 gsiClasses.put(requestURL, portClass); 544 } 545 } catch(Exception e) { 546 throw new ServletException(e); 547 } finally { 548 Thread.currentThread().setContextClassLoader(currentLoader); 550 deleteDir(new File (classesDir)); 552 } 553 } 554 555 private String wsImport(URL wsdlLocation) throws IOException { 556 557 File classesDir = new File (System.getProperty("java.io.tmpdir")); 558 classesDir = File.createTempFile("jax-ws", "tester", classesDir); 560 classesDir.delete(); 561 classesDir.mkdirs(); 562 563 String [] wsimportArgs = new String [4]; 564 wsimportArgs[0]="-d"; 565 wsimportArgs[1]=classesDir.getAbsolutePath(); 566 wsimportArgs[2]="-keep"; 567 wsimportArgs[3]=wsdlLocation.toExternalForm(); 568 WSToolsObjectFactory tools = WSToolsObjectFactory.newInstance(); 569 boolean success = tools.wsimport(System.out, wsimportArgs); 570 if (logger!=null) { 571 logger.log(Level.INFO, "Invoking wsimport with " + wsdlLocation); 572 } else { 573 System.out.println("Invoking wsimport with " + wsdlLocation); 574 } 575 576 if (success) { 577 if (logger!=null) 578 logger.log(Level.INFO, "wsimport successful"); 579 } else { 580 if (logger!=null) 581 logger.log(Level.SEVERE, "wsimport failed"); 582 return null; 583 } 584 return classesDir.getAbsolutePath(); 585 } 586 587 private String getServiceClass(String serviceClassName, String classesDirPath) { 588 File classesDir = new File (classesDirPath); 591 if (!classesDir.exists()) { 592 return null; 593 } 594 File [] classes = getListOfFiles(classesDir).toArray(new File [0]); 595 for (File f : classes) { 596 if (!f.getName().endsWith(serviceClassName+".class")) 597 continue; 598 String svcClass = f.getAbsolutePath().substring(classesDirPath.length()+1); 599 svcClass = svcClass.substring(0, svcClass.indexOf(".class")); 600 return svcClass.replaceAll("\\"+File.separator,"."); 601 } 602 return null; 603 } 604 605 private String getPortClass(Endpoint ep, Class serviceClass) 606 throws Exception { 607 String pkg = serviceClass.getPackage().getName(); 608 for(Method m : serviceClass.getMethods()) { 609 WebEndpoint webEP = (WebEndpoint) 610 m.getAnnotation(WebEndpoint.class); 611 if(webEP == null || webEP.name() == null || 612 webEP.name().length() == 0) { 613 continue; 614 } 615 String getPortMethodName = "get" + 616 JAXBRIContext.mangleNameToClassName(webEP.name()); 617 Method getPortMethod = 618 serviceClass.getMethod(getPortMethodName, null); 619 return getPortMethod.getReturnType().getName(); 620 } 621 return null; 622 } 623 624 private List <File > getListOfFiles(File path) { 625 626 File [] files = path.listFiles(); 627 List <File > result = new ArrayList <File >(); 628 for (File f : files) { 629 if (f.isDirectory()) { 630 result.addAll(getListOfFiles(f)); 631 } else { 632 result.add(f); 633 } 634 } 635 return result; 636 } 637 638 private void deleteDir(File path) { 639 640 File [] files = path.listFiles(); 641 for (File f : files) { 642 if (f.isDirectory()) { 643 deleteDir(f); 644 } 645 f.delete(); 646 } 647 path.delete(); 648 } 649 } 650 | Popular Tags |