1 16 17 package org.apache.axis.transport.http; 18 19 import org.apache.axis.AxisFault; 20 import org.apache.axis.Constants; 21 import org.apache.axis.Message; 22 import org.apache.axis.MessageContext; 23 import org.apache.axis.components.logger.LogFactory; 24 import org.apache.axis.description.OperationDesc; 25 import org.apache.axis.description.ServiceDesc; 26 import org.apache.axis.encoding.Base64; 27 import org.apache.axis.message.SOAPEnvelope; 28 import org.apache.axis.message.SOAPFault; 29 import org.apache.axis.server.AxisServer; 30 import org.apache.axis.utils.Messages; 31 import org.apache.axis.utils.XMLUtils; 32 import org.apache.axis.utils.NetworkUtils; 33 import org.apache.commons.logging.Log; 34 import org.w3c.dom.Document ; 35 36 import javax.xml.namespace.QName ; 37 import javax.xml.soap.MimeHeader ; 38 import javax.xml.soap.MimeHeaders ; 39 import javax.xml.soap.SOAPMessage ; 40 41 import java.io.OutputStream ; 42 import java.io.ByteArrayInputStream ; 43 import java.net.Socket ; 44 import java.util.ArrayList ; 45 import java.util.Iterator ; 46 47 48 public class SimpleAxisWorker implements Runnable { 49 protected static Log log = 50 LogFactory.getLog(SimpleAxisWorker.class.getName()); 51 52 private SimpleAxisServer server; 53 private Socket socket; 54 55 private static String transportName = "SimpleHTTP"; 57 58 private static byte OK[] = ("200 " + Messages.getMessage("ok00")).getBytes(); 60 private static byte NOCONTENT[] = ("202 " + Messages.getMessage("ok00") + "\n\n").getBytes(); 61 private static byte UNAUTH[] = ("401 " + Messages.getMessage("unauth00")).getBytes(); 62 private static byte SENDER[] = "400".getBytes(); 63 private static byte ISE[] = ("500 " + Messages.getMessage("internalError01")).getBytes(); 64 65 private static byte HTTP[] = "HTTP/1.0 ".getBytes(); 67 68 private static byte XML_MIME_STUFF[] = 70 ("\r\nContent-Type: text/xml; charset=utf-8\r\n" + 71 "Content-Length: ").getBytes(); 72 73 private static byte HTML_MIME_STUFF[] = 75 ("\r\nContent-Type: text/html; charset=utf-8\r\n" + 76 "Content-Length: ").getBytes(); 77 78 private static byte SEPARATOR[] = "\r\n\r\n".getBytes(); 80 81 89 private static final byte[] toLower = new byte[256]; 91 92 static { 93 for (int i = 0; i < 256; i++) { 94 toLower[i] = (byte) i; 95 } 96 97 for (int lc = 'a'; lc <= 'z'; lc++) { 98 toLower[lc + 'A' - 'a'] = (byte) lc; 99 } 100 } 101 102 private static final int BUFSIZ = 4096; 104 105 private static final byte lenHeader[] = "content-length: ".getBytes(); 107 private static final int lenLen = lenHeader.length; 108 109 private static final byte typeHeader[] = (HTTPConstants.HEADER_CONTENT_TYPE.toLowerCase() + ": ").getBytes(); 111 private static final int typeLen = typeHeader.length; 112 113 private static final byte locationHeader[] = (HTTPConstants.HEADER_CONTENT_LOCATION.toLowerCase() + ": ").getBytes(); 115 private static final int locationLen = locationHeader.length; 116 117 private static final byte actionHeader[] = "soapaction: ".getBytes(); 119 private static final int actionLen = actionHeader.length; 120 121 private static final byte cookieHeader[] = "cookie: ".getBytes(); 123 private static final int cookieLen = cookieHeader.length; 124 125 private static final byte cookie2Header[] = "cookie2: ".getBytes(); 127 private static final int cookie2Len = cookie2Header.length; 128 129 private static final byte authHeader[] = "authorization: ".getBytes(); 131 private static final int authLen = authHeader.length; 132 133 private static final byte getHeader[] = "GET".getBytes(); 135 136 private static final byte postHeader[] = "POST".getBytes(); 138 139 private static final byte headerEnder[] = ": ".getBytes(); 141 142 private static final byte basicAuth[] = "basic ".getBytes(); 144 145 public SimpleAxisWorker(SimpleAxisServer server, Socket socket) { 146 this.server = server; 147 this.socket = socket; 148 } 149 150 153 public void run() { 154 try { 155 execute(); 156 } finally { 157 SimpleAxisServer.getPool().workerDone(this, false); 158 } 159 } 160 161 164 public void execute () { 165 byte buf[] = new byte[BUFSIZ]; 166 AxisServer engine = server.getAxisServer(); 168 169 MessageContext msgContext = new MessageContext(engine); 171 Message requestMsg = null; 172 173 NonBlockingBufferedInputStream is = 175 new NonBlockingBufferedInputStream(); 176 177 StringBuffer soapAction = new StringBuffer (); 179 StringBuffer httpRequest = new StringBuffer (); 180 StringBuffer fileName = new StringBuffer (); 181 StringBuffer cookie = new StringBuffer (); 182 StringBuffer cookie2 = new StringBuffer (); 183 StringBuffer authInfo = new StringBuffer (); 184 StringBuffer contentType = new StringBuffer (); 185 StringBuffer contentLocation = new StringBuffer (); 186 187 Message responseMsg = null; 188 189 msgContext.setTransportName(transportName); 197 198 responseMsg = null; 199 200 try { 201 byte[] status = OK; 203 204 boolean doWsdl = false; 206 207 String cooky = null; 209 210 String methodName = null; 211 212 try { 213 if (server.isSessionUsed()) { 215 cookie.delete(0, cookie.length()); 216 cookie2.delete(0, cookie2.length()); 217 } 218 authInfo.delete(0, authInfo.length()); 219 220 is.setInputStream(socket.getInputStream()); 222 MimeHeaders requestHeaders = new MimeHeaders (); 224 int contentLength = parseHeaders(is, buf, contentType, 225 contentLocation, soapAction, 226 httpRequest, fileName, 227 cookie, cookie2, authInfo, requestHeaders); 228 is.setContentLength(contentLength); 229 230 int paramIdx = fileName.toString().indexOf('?'); 231 if (paramIdx != -1) { 232 String params = fileName.substring(paramIdx + 1); 234 fileName.setLength(paramIdx); 235 236 log.debug(Messages.getMessage("filename00", 237 fileName.toString())); 238 log.debug(Messages.getMessage("params00", 239 params)); 240 241 if ("wsdl".equalsIgnoreCase(params)) 242 doWsdl = true; 243 244 if (params.startsWith("method=")) { 245 methodName = params.substring(7); 246 } 247 } 248 249 msgContext.setProperty(Constants.MC_REALPATH, 252 fileName.toString()); 253 msgContext.setProperty(Constants.MC_RELATIVE_PATH, 254 fileName.toString()); 255 msgContext.setProperty(Constants.MC_JWS_CLASSDIR, 256 "jwsClasses"); 257 msgContext.setProperty(Constants.MC_HOME_DIR, "."); 258 259 String url = "http://" + getLocalHost() + ":" + 261 server.getServerSocket().getLocalPort() + "/" + 262 fileName.toString(); 263 msgContext.setProperty(MessageContext.TRANS_URL, url); 264 265 String filePart = fileName.toString(); 266 if (filePart.startsWith("axis/services/")) { 267 String servicePart = filePart.substring(14); 268 int separator = servicePart.indexOf('/'); 269 if (separator > -1) { 270 msgContext.setProperty("objectID", 271 servicePart.substring(separator + 1)); 272 servicePart = servicePart.substring(0, separator); 273 } 274 msgContext.setTargetService(servicePart); 275 } 276 277 if (authInfo.length() > 0) { 278 byte[] decoded = Base64.decode(authInfo.toString()); 281 StringBuffer userBuf = new StringBuffer (); 282 StringBuffer pwBuf = new StringBuffer (); 283 StringBuffer authBuf = userBuf; 284 for (int i = 0; i < decoded.length; i++) { 285 if ((char) (decoded[i] & 0x7f) == ':') { 286 authBuf = pwBuf; 287 continue; 288 } 289 authBuf.append((char) (decoded[i] & 0x7f)); 290 } 291 292 if (log.isDebugEnabled()) { 293 log.debug(Messages.getMessage("user00", 294 userBuf.toString())); 295 } 296 297 msgContext.setUsername(userBuf.toString()); 298 msgContext.setPassword(pwBuf.toString()); 299 } 300 301 if (httpRequest.toString().equals("GET")) { 303 304 OutputStream out = socket.getOutputStream(); 305 out.write(HTTP); 306 if(fileName.length()==0) { 307 out.write("301 Redirect\nLocation: /axis/\n\n".getBytes()); 308 out.flush(); 309 return; 310 } 311 out.write(status); 312 313 if (methodName != null) { 314 String body = 315 "<" + methodName + ">" + 316 "</" + methodName + ">"; 318 String msgtxt = 319 "<SOAP-ENV:Envelope" + 320 " xmlns:SOAP-ENV=\"" + Constants.URI_SOAP12_ENV + "\">" + 321 "<SOAP-ENV:Body>" + body + "</SOAP-ENV:Body>" + 322 "</SOAP-ENV:Envelope>"; 323 324 ByteArrayInputStream istream = 325 new ByteArrayInputStream (msgtxt.getBytes()); 326 requestMsg = new Message(istream); 327 } else if (doWsdl) { 328 engine.generateWSDL(msgContext); 329 330 Document doc = (Document ) msgContext.getProperty("WSDL"); 331 if (doc != null) { 332 XMLUtils.normalize(doc.getDocumentElement()); 333 String response = XMLUtils.PrettyDocumentToString(doc); 334 byte[] respBytes = response.getBytes(); 335 336 out.write(XML_MIME_STUFF); 337 putInt(buf, out, respBytes.length); 338 out.write(SEPARATOR); 339 out.write(respBytes); 340 out.flush(); 341 return; 342 } 343 } else { 344 StringBuffer sb = new StringBuffer (); 345 sb.append("<h2>And now... Some Services</h2>\n"); 346 Iterator i = engine.getConfig().getDeployedServices(); 347 sb.append("<ul>\n"); 348 while (i.hasNext()) { 349 ServiceDesc sd = (ServiceDesc)i.next(); 350 sb.append("<li>\n"); 351 sb.append(sd.getName()); 352 sb.append(" <a HREF=\"services/"); 353 sb.append(sd.getName()); 354 sb.append("?wsdl\"><i>(wsdl)</i></a></li>\n"); 355 ArrayList operations = sd.getOperations(); 356 if (!operations.isEmpty()) { 357 sb.append("<ul>\n"); 358 for (Iterator it = operations.iterator(); it.hasNext();) { 359 OperationDesc desc = (OperationDesc) it.next(); 360 sb.append("<li>" + desc.getName()); 361 } 362 sb.append("</ul>\n"); 363 } 364 } 365 sb.append("</ul>\n"); 366 367 byte [] bytes = sb.toString().getBytes(); 368 369 out.write(HTML_MIME_STUFF); 370 putInt(buf, out, bytes.length); 371 out.write(SEPARATOR); 372 out.write(bytes); 373 out.flush(); 374 return; 375 } 376 } else { 377 378 String soapActionString = soapAction.toString(); 381 if (soapActionString != null) { 382 msgContext.setUseSOAPAction(true); 383 msgContext.setSOAPActionURI(soapActionString); 384 } 385 requestMsg = new Message(is, 386 false, 387 contentType.toString(), 388 contentLocation.toString() 389 ); 390 } 391 392 MimeHeaders requestMimeHeaders = requestMsg.getMimeHeaders(); 394 for (Iterator i = requestHeaders.getAllHeaders(); i.hasNext(); ) { 395 MimeHeader requestHeader = (MimeHeader ) i.next(); 396 requestMimeHeaders.addHeader(requestHeader.getName(), requestHeader.getValue()); 397 } 398 msgContext.setRequestMessage(requestMsg); 399 String requestEncoding = (String ) requestMsg.getProperty(SOAPMessage.CHARACTER_SET_ENCODING); 402 if (requestEncoding != null) { 403 msgContext.setProperty(SOAPMessage.CHARACTER_SET_ENCODING, requestEncoding); 404 } 405 406 if (server.isSessionUsed()) { 408 if (cookie.length() > 0) { 410 cooky = cookie.toString().trim(); 411 } else if (cookie2.length() > 0) { 412 cooky = cookie2.toString().trim(); 413 } 414 415 if (cooky == null) { 417 int i = SimpleAxisServer.sessionIndex++; 421 cooky = "" + i; 422 } 423 424 msgContext.setSession(server.createSession(cooky)); 425 } 426 427 engine.invoke(msgContext); 429 430 responseMsg = msgContext.getResponseMessage(); 432 433 if (responseMsg == null) { 434 status = NOCONTENT; 435 } 436 } catch (Exception e) { 437 AxisFault af; 438 if (e instanceof AxisFault) { 439 af = (AxisFault) e; 440 log.debug(Messages.getMessage("serverFault00"), af); 441 QName faultCode = af.getFaultCode(); 442 if (Constants.FAULT_SOAP12_SENDER.equals(faultCode)) { 443 status = SENDER; 444 } else if ("Server.Unauthorized".equals(af.getFaultCode().getLocalPart())) { 445 status = UNAUTH; } else { 447 status = ISE; } 449 } else { 450 status = ISE; af = AxisFault.makeFault(e); 452 } 453 454 responseMsg = msgContext.getResponseMessage(); 458 if (responseMsg == null) { 459 responseMsg = new Message(af); 460 responseMsg.setMessageContext(msgContext); 461 } else { 462 try { 463 SOAPEnvelope env = responseMsg.getSOAPEnvelope(); 464 env.clearBody(); 465 env.addBodyElement(new SOAPFault((AxisFault) e)); 466 } catch (AxisFault fault) { 467 } 469 } 470 } 471 472 String responseEncoding = (String ) msgContext.getProperty(SOAPMessage.CHARACTER_SET_ENCODING); 474 if (responseEncoding != null && responseMsg != null) { 475 responseMsg.setProperty(SOAPMessage.CHARACTER_SET_ENCODING, responseEncoding); 476 } 477 OutputStream out = socket.getOutputStream(); 479 out.write(HTTP); 480 out.write(status); 481 482 if (responseMsg != null) { 483 if (server.isSessionUsed() && null != cooky && 484 0 != cooky.trim().length()) { 485 StringBuffer cookieOut = new StringBuffer (); 489 cookieOut.append("\r\nSet-Cookie: ") 490 .append(cooky) 491 .append("\r\nSet-Cookie2: ") 492 .append(cooky); 493 out.write(cookieOut.toString().getBytes()); 495 } 496 497 out.write(("\r\n" + HTTPConstants.HEADER_CONTENT_TYPE + ": " + responseMsg.getContentType(msgContext.getSOAPConstants())).getBytes()); 499 503 for (Iterator i = responseMsg.getMimeHeaders().getAllHeaders(); i.hasNext(); ) { 505 MimeHeader responseHeader = (MimeHeader ) i.next(); 506 out.write('\r'); 507 out.write('\n'); 508 out.write(responseHeader.getName().getBytes()); 509 out.write(headerEnder); 510 out.write(responseHeader.getValue().getBytes()); 511 } 512 513 out.write(SEPARATOR); 514 responseMsg.writeTo(out); 515 } 516 517 out.flush(); 519 } catch (Exception e) { 520 log.info(Messages.getMessage("exception00"), e); 521 } finally { 522 try { 523 if (socket != null) socket.close(); 524 } catch (Exception e) { 525 } 526 } 527 if (msgContext.getProperty(MessageContext.QUIT_REQUESTED) != null) { 528 try { 530 server.stop(); 531 } catch (Exception e) { 532 } 533 } 534 535 } 536 537 protected void invokeMethodFromGet(String methodName, String args) throws Exception { 538 539 } 540 541 554 private int parseHeaders(NonBlockingBufferedInputStream is, 555 byte buf[], 556 StringBuffer contentType, 557 StringBuffer contentLocation, 558 StringBuffer soapAction, 559 StringBuffer httpRequest, 560 StringBuffer fileName, 561 StringBuffer cookie, 562 StringBuffer cookie2, 563 StringBuffer authInfo, 564 MimeHeaders headers) 565 throws java.io.IOException { 566 int n; 567 int len = 0; 568 569 n = this.readLine(is, buf, 0, buf.length); 571 if (n < 0) { 572 throw new java.io.IOException (Messages.getMessage("unexpectedEOS00")); 574 } 575 576 httpRequest.delete(0, httpRequest.length()); 578 fileName.delete(0, fileName.length()); 579 contentType.delete(0, contentType.length()); 580 contentLocation.delete(0, contentLocation.length()); 581 582 if (buf[0] == getHeader[0]) { 583 httpRequest.append("GET"); 584 for (int i = 0; i < n - 5; i++) { 585 char c = (char) (buf[i + 5] & 0x7f); 586 if (c == ' ') 587 break; 588 fileName.append(c); 589 } 590 log.debug(Messages.getMessage("filename01", "SimpleAxisServer", fileName.toString())); 591 return 0; 592 } else if (buf[0] == postHeader[0]) { 593 httpRequest.append("POST"); 594 for (int i = 0; i < n - 6; i++) { 595 char c = (char) (buf[i + 6] & 0x7f); 596 if (c == ' ') 597 break; 598 fileName.append(c); 599 } 600 log.debug(Messages.getMessage("filename01", "SimpleAxisServer", fileName.toString())); 601 } else { 602 throw new java.io.IOException (Messages.getMessage("badRequest00")); 603 } 604 605 while ((n = readLine(is, buf, 0, buf.length)) > 0) { 606 607 if ((n <= 2) && (buf[0] == '\n' || buf[0] == '\r') && (len > 0)) break; 608 609 614 int endHeaderIndex = 0; 616 while (endHeaderIndex < n && toLower[buf[endHeaderIndex]] != headerEnder[0]) { 617 endHeaderIndex++; 618 } 619 endHeaderIndex += 2; 620 623 int i = endHeaderIndex - 1; 625 626 if (endHeaderIndex == lenLen && matches(buf, lenHeader)) { 628 630 while ((++i < n) && (buf[i] >= '0') && (buf[i] <= '9')) { 631 len = (len * 10) + (buf[i] - '0'); 632 } 633 headers.addHeader(HTTPConstants.HEADER_CONTENT_LENGTH, String.valueOf(len)); 634 635 } else if (endHeaderIndex == actionLen 636 && matches(buf, actionHeader)) { 637 638 soapAction.delete(0, soapAction.length()); 639 i++; 641 while ((++i < n) && (buf[i] != '"')) { 642 soapAction.append((char) (buf[i] & 0x7f)); 643 } 644 headers.addHeader(HTTPConstants.HEADER_SOAP_ACTION, "\"" + soapAction.toString() + "\""); 645 646 } else if (server.isSessionUsed() && endHeaderIndex == cookieLen 647 && matches(buf, cookieHeader)) { 648 649 while ((++i < n) && (buf[i] != ';') && (buf[i] != '\r') && (buf[i] != '\n')) { 651 cookie.append((char) (buf[i] & 0x7f)); 652 } 653 headers.addHeader("Set-Cookie", cookie.toString()); 654 655 } else if (server.isSessionUsed() && endHeaderIndex == cookie2Len 656 && matches(buf, cookie2Header)) { 657 658 while ((++i < n) && (buf[i] != ';') && (buf[i] != '\r') && (buf[i] != '\n')) { 660 cookie2.append((char) (buf[i] & 0x7f)); 661 } 662 headers.addHeader("Set-Cookie2", cookie.toString()); 663 664 } else if (endHeaderIndex == authLen && matches(buf, authHeader)) { 665 if (matches(buf, endHeaderIndex, basicAuth)) { 666 i += basicAuth.length; 667 while (++i < n && (buf[i] != '\r') && (buf[i] != '\n')) { 668 if (buf[i] == ' ') continue; 669 authInfo.append((char) (buf[i] & 0x7f)); 670 } 671 headers.addHeader(HTTPConstants.HEADER_AUTHORIZATION, new String (basicAuth) + authInfo.toString()); 672 } else { 673 throw new java.io.IOException ( 674 Messages.getMessage("badAuth00")); 675 } 676 } else if (endHeaderIndex == locationLen && matches(buf, locationHeader)) { 677 while (++i < n && (buf[i] != '\r') && (buf[i] != '\n')) { 678 if (buf[i] == ' ') continue; 679 contentLocation.append((char) (buf[i] & 0x7f)); 680 } 681 headers.addHeader(HTTPConstants.HEADER_CONTENT_LOCATION, contentLocation.toString()); 682 } else if (endHeaderIndex == typeLen && matches(buf, typeHeader)) { 683 while (++i < n && (buf[i] != '\r') && (buf[i] != '\n')) { 684 if (buf[i] == ' ') continue; 685 contentType.append((char) (buf[i] & 0x7f)); 686 } 687 headers.addHeader(HTTPConstants.HEADER_CONTENT_TYPE, contentLocation.toString()); 688 } else { 689 String customHeaderName = new String (buf, 0, endHeaderIndex - 2); 690 StringBuffer customHeaderValue = new StringBuffer (); 691 while (++i < n && (buf[i] != '\r') && (buf[i] != '\n')) { 692 if (buf[i] == ' ') continue; 693 customHeaderValue.append((char) (buf[i] & 0x7f)); 694 } 695 headers.addHeader(customHeaderName, customHeaderValue.toString()); 696 } 697 698 } 699 return len; 700 } 701 702 705 public boolean matches(byte[] buf, byte[] target) { 706 for (int i = 0; i < target.length; i++) { 707 if (toLower[buf[i]] != target[i]) { 708 return false; 709 } 710 } 711 return true; 712 } 713 714 718 public boolean matches(byte[] buf, int bufIdx, byte[] target) { 719 for (int i = 0; i < target.length; i++) { 720 if (toLower[buf[bufIdx + i]] != target[i]) { 721 return false; 722 } 723 } 724 return true; 725 } 726 727 732 private void putInt(byte buf[], OutputStream out, int value) 733 throws java.io.IOException { 734 int len = 0; 735 int offset = buf.length; 736 737 if (value < 0) { 739 buf[--offset] = (byte) '-'; 740 value = -value; 741 len++; 742 } 743 744 if (value == 0) { 746 buf[--offset] = (byte) '0'; 747 len++; 748 } 749 750 while (value > 0) { 752 buf[--offset] = (byte) (value % 10 + '0'); 753 value = value / 10; 754 len++; 755 } 756 757 out.write(buf, offset, len); 759 } 760 761 768 private int readLine(NonBlockingBufferedInputStream is, byte[] b, int off, int len) 769 throws java.io.IOException { 770 int count = 0, c; 771 772 while ((c = is.read()) != -1) { 773 if (c != '\n' && c != '\r') { 774 b[off++] = (byte) c; 775 count++; 776 } 777 if (count == len) break; 778 if ('\n' == c) { 779 int peek = is.peek(); if (peek != ' ' && peek != '\t') break; 781 } 782 } 783 return count > 0 ? count : -1; 784 } 785 786 789 public static String getLocalHost() { 790 return NetworkUtils.getLocalHostname(); 791 } 792 } 793 | Popular Tags |