| 1 17 18 package org.apache.tomcat.util.http.mapper; 19 20 import javax.naming.NamingException ; 21 import javax.naming.directory.DirContext ; 22 23 import org.apache.tomcat.util.buf.CharChunk; 24 import org.apache.tomcat.util.buf.MessageBytes; 25 import org.apache.tomcat.util.buf.Ascii; 26 import java.util.List ; 27 import java.util.ArrayList ; 28 29 35 public final class Mapper { 36 37 38 private static org.apache.commons.logging.Log logger = 39 org.apache.commons.logging.LogFactory.getLog(Mapper.class); 40 42 43 46 protected Host[] hosts = new Host[0]; 47 48 49 52 protected String defaultHostName = null; 53 54 57 protected Context context = new Context (); 58 59 60 62 63 68 public String getDefaultHostName() { 69 return defaultHostName; 70 } 71 72 73 78 public void setDefaultHostName(String defaultHostName) { 79 this.defaultHostName = defaultHostName; 80 } 81 82 88 public synchronized void addHost(String name, String [] aliases, 89 Object host) { 90 Host[] newHosts = new Host[hosts.length + 1]; 91 Host newHost = new Host(); 92 ContextList contextList = new ContextList(); 93 newHost.name = name; 94 newHost.contextList = contextList; 95 newHost.object = host; 96 if (insertMap(hosts, newHosts, newHost)) { 97 hosts = newHosts; 98 } 99 for (int i = 0; i < aliases.length; i++) { 100 newHosts = new Host[hosts.length + 1]; 101 newHost = new Host(); 102 newHost.name = aliases[i]; 103 newHost.contextList = contextList; 104 newHost.object = host; 105 if (insertMap(hosts, newHosts, newHost)) { 106 hosts = newHosts; 107 } 108 } 109 } 110 111 112 117 public synchronized void removeHost(String name) { 118 int pos = find(hosts, name); 120 if (pos < 0) { 121 return; 122 } 123 Object host = hosts[pos].object; 124 Host[] newHosts = new Host[hosts.length - 1]; 125 if (removeMap(hosts, newHosts, name)) { 126 hosts = newHosts; 127 } 128 for (int i = 0; i < newHosts.length; i++) { 130 if (newHosts[i].object == host) { 131 Host[] newHosts2 = new Host[hosts.length - 1]; 132 if (removeMap(hosts, newHosts2, newHosts[i].name)) { 133 hosts = newHosts2; 134 } 135 } 136 } 137 } 138 139 public String [] getHosts() { 140 String hostN[] = new String [hosts.length]; 141 for( int i = 0; i < hosts.length; i++ ) { 142 hostN[i] = hosts[i].name; 143 } 144 return hostN; 145 } 146 147 148 154 public void setContext(String path, String [] welcomeResources, 155 javax.naming.Context resources) { 156 context.name = path; 157 context.welcomeResources = welcomeResources; 158 context.resources = resources; 159 } 160 161 162 171 public void addContext 172 (String hostName, String path, Object context, 173 String [] welcomeResources, javax.naming.Context resources) { 174 175 Host[] hosts = this.hosts; 176 int pos = find(hosts, hostName); 177 if( pos <0 ) { 178 addHost(hostName, new String [0], ""); 179 hosts = this.hosts; 180 pos = find(hosts, hostName); 181 } 182 if (pos < 0) { 183 logger.error("No host found: " + hostName); 184 } 185 Host host = hosts[pos]; 186 if (host.name.equals(hostName)) { 187 int slashCount = slashCount(path); 188 synchronized (host) { 189 Context [] contexts = host.contextList.contexts; 190 if (slashCount > host.contextList.nesting) { 192 host.contextList.nesting = slashCount; 193 } 194 Context [] newContexts = new Context [contexts.length + 1]; 195 Context newContext = new Context (); 196 newContext.name = path; 197 newContext.object = context; 198 newContext.welcomeResources = welcomeResources; 199 newContext.resources = resources; 200 if (insertMap(contexts, newContexts, newContext)) { 201 host.contextList.contexts = newContexts; 202 } 203 } 204 } 205 206 } 207 208 209 215 public void removeContext(String hostName, String path) { 216 Host[] hosts = this.hosts; 217 int pos = find(hosts, hostName); 218 if (pos < 0) { 219 return; 220 } 221 Host host = hosts[pos]; 222 if (host.name.equals(hostName)) { 223 synchronized (host) { 224 Context [] contexts = host.contextList.contexts; 225 if( contexts.length == 0 ){ 226 return; 227 } 228 Context [] newContexts = new Context [contexts.length - 1]; 229 if (removeMap(contexts, newContexts, path)) { 230 host.contextList.contexts = newContexts; 231 host.contextList.nesting = 0; 233 for (int i = 0; i < newContexts.length; i++) { 234 int slashCount = slashCount(newContexts[i].name); 235 if (slashCount > host.contextList.nesting) { 236 host.contextList.nesting = slashCount; 237 } 238 } 239 } 240 } 241 } 242 } 243 244 245 250 public String [] getContextNames() { 251 List list=new ArrayList (); 252 for( int i=0; i<hosts.length; i++ ) { 253 for( int j=0; j<hosts[i].contextList.contexts.length; j++ ) { 254 String cname=hosts[i].contextList.contexts[j].name; 255 list.add("//" + hosts[i].name + 256 (cname.startsWith("/") ? cname : "/")); 257 } 258 } 259 String res[] = new String [list.size()]; 260 return (String [])list.toArray(res); 261 } 262 263 264 272 public void addWrapper(String hostName, String contextPath, String path, 273 Object wrapper) { 274 addWrapper(hostName, contextPath, path, wrapper, false); 275 } 276 277 278 public void addWrapper(String hostName, String contextPath, String path, 279 Object wrapper, boolean jspWildCard) { 280 Host[] hosts = this.hosts; 281 int pos = find(hosts, hostName); 282 if (pos < 0) { 283 return; 284 } 285 Host host = hosts[pos]; 286 if (host.name.equals(hostName)) { 287 Context [] contexts = host.contextList.contexts; 288 int pos2 = find(contexts, contextPath); 289 if( pos2<0 ) { 290 logger.error("No context found: " + contextPath ); 291 return; 292 } 293 Context context = contexts[pos2]; 294 if (context.name.equals(contextPath)) { 295 addWrapper(context, path, wrapper, jspWildCard); 296 } 297 } 298 } 299 300 301 307 public void addWrapper(String path, Object wrapper) { 308 addWrapper(context, path, wrapper); 309 } 310 311 312 public void addWrapper(String path, Object wrapper, boolean jspWildCard) { 313 addWrapper(context, path, wrapper, jspWildCard); 314 } 315 316 317 protected void addWrapper(Context context, String path, Object wrapper) { 318 addWrapper(context, path, wrapper, false); 319 } 320 321 322 331 protected void addWrapper(Context context, String path, Object wrapper, 332 boolean jspWildCard) { 333 334 synchronized (context) { 335 Wrapper newWrapper = new Wrapper(); 336 newWrapper.object = wrapper; 337 newWrapper.jspWildCard = jspWildCard; 338 if (path.endsWith("/*")) { 339 newWrapper.name = path.substring(0, path.length() - 2); 341 Wrapper[] oldWrappers = context.wildcardWrappers; 342 Wrapper[] newWrappers = 343 new Wrapper[oldWrappers.length + 1]; 344 if (insertMap(oldWrappers, newWrappers, newWrapper)) { 345 context.wildcardWrappers = newWrappers; 346 int slashCount = slashCount(newWrapper.name); 347 if (slashCount > context.nesting) { 348 context.nesting = slashCount; 349 } 350 } 351 } else if (path.startsWith("*.")) { 352 newWrapper.name = path.substring(2); 354 Wrapper[] oldWrappers = context.extensionWrappers; 355 Wrapper[] newWrappers = 356 new Wrapper[oldWrappers.length + 1]; 357 if (insertMap(oldWrappers, newWrappers, newWrapper)) { 358 context.extensionWrappers = newWrappers; 359 } 360 } else if (path.equals("/")) { 361 newWrapper.name = ""; 363 context.defaultWrapper = newWrapper; 364 } else { 365 newWrapper.name = path; 367 Wrapper[] oldWrappers = context.exactWrappers; 368 Wrapper[] newWrappers = 369 new Wrapper[oldWrappers.length + 1]; 370 if (insertMap(oldWrappers, newWrappers, newWrapper)) { 371 context.exactWrappers = newWrappers; 372 } 373 } 374 } 375 } 376 377 378 383 public void removeWrapper(String path) { 384 removeWrapper(context, path); 385 } 386 387 388 395 public void removeWrapper 396 (String hostName, String contextPath, String path) { 397 Host[] hosts = this.hosts; 398 int pos = find(hosts, hostName); 399 if (pos < 0) { 400 return; 401 } 402 Host host = hosts[pos]; 403 if (host.name.equals(hostName)) { 404 Context [] contexts = host.contextList.contexts; 405 int pos2 = find(contexts, contextPath); 406 if (pos2 < 0) { 407 return; 408 } 409 Context context = contexts[pos2]; 410 if (context.name.equals(contextPath)) { 411 removeWrapper(context, path); 412 } 413 } 414 } 415 416 protected void removeWrapper(Context context, String path) { 417 synchronized (context) { 418 if (path.endsWith("/*")) { 419 String name = path.substring(0, path.length() - 2); 421 Wrapper[] oldWrappers = context.wildcardWrappers; 422 Wrapper[] newWrappers = 423 new Wrapper[oldWrappers.length - 1]; 424 if (removeMap(oldWrappers, newWrappers, name)) { 425 context.nesting = 0; 427 for (int i = 0; i < newWrappers.length; i++) { 428 int slashCount = slashCount(newWrappers[i].name); 429 if (slashCount > context.nesting) { 430 context.nesting = slashCount; 431 } 432 } 433 context.wildcardWrappers = newWrappers; 434 } 435 } else if (path.startsWith("*.")) { 436 String name = path.substring(2); 438 Wrapper[] oldWrappers = context.extensionWrappers; 439 Wrapper[] newWrappers = 440 new Wrapper[oldWrappers.length - 1]; 441 if (removeMap(oldWrappers, newWrappers, name)) { 442 context.extensionWrappers = newWrappers; 443 } 444 } else if (path.equals("/")) { 445 context.defaultWrapper = null; 447 } else { 448 String name = path; 450 Wrapper[] oldWrappers = context.exactWrappers; 451 Wrapper[] newWrappers = 452 new Wrapper[oldWrappers.length - 1]; 453 if (removeMap(oldWrappers, newWrappers, name)) { 454 context.exactWrappers = newWrappers; 455 } 456 } 457 } 458 } 459 460 public String getWrappersString( String host, String context ) { 461 String names[]=getWrapperNames(host, context); 462 StringBuffer sb=new StringBuffer (); 463 for( int i=0; i<names.length; i++ ) { 464 sb.append(names[i]).append(":"); 465 } 466 return sb.toString(); 467 } 468 469 public String [] getWrapperNames( String host, String context ) { 470 List list=new ArrayList (); 471 if( host==null ) host=""; 472 if( context==null ) context=""; 473 for( int i=0; i<hosts.length; i++ ) { 474 if( ! host.equals( hosts[i].name )) 475 continue; 476 for( int j=0; j<hosts[i].contextList.contexts.length; j++ ) { 477 if( ! context.equals( hosts[i].contextList.contexts[j].name)) 478 continue; 479 Context ctx=hosts[i].contextList.contexts[j]; 481 list.add( ctx.defaultWrapper.path); 482 for( int k=0; k<ctx.exactWrappers.length; k++ ) { 483 list.add( ctx.exactWrappers[k].path); 484 } 485 for( int k=0; k<ctx.wildcardWrappers.length; k++ ) { 486 list.add( ctx.wildcardWrappers[k].path + "*"); 487 } 488 for( int k=0; k<ctx.extensionWrappers.length; k++ ) { 489 list.add( "*." + ctx.extensionWrappers[k].path); 490 } 491 } 492 } 493 String res[]=new String [list.size()]; 494 return (String [])list.toArray(res); 495 } 496 497 498 499 507 public void map(MessageBytes host, MessageBytes uri, 508 MappingData mappingData) 509 throws Exception { 510 511 if (host.isNull()) { 512 host.getCharChunk().append(defaultHostName); 513 } 514 host.toChars(); 515 uri.toChars(); 516 internalMap(host.getCharChunk(), uri.getCharChunk(), mappingData); 517 518 } 519 520 521 529 public void map(MessageBytes uri, MappingData mappingData) 530 throws Exception { 531 532 uri.toChars(); 533 CharChunk uricc = uri.getCharChunk(); 534 uricc.setLimit(-1); 535 internalMapWrapper(context, uricc, mappingData); 536 537 } 538 539 540 542 543 546 private final void internalMap(CharChunk host, CharChunk uri, 547 MappingData mappingData) 548 throws Exception { 549 550 uri.setLimit(-1); 551 552 Context [] contexts = null; 553 Context context = null; 554 int nesting = 0; 555 556 if (mappingData.host == null) { 558 Host[] hosts = this.hosts; 559 int pos = findIgnoreCase(hosts, host); 560 if ((pos != -1) && (host.equalsIgnoreCase(hosts[pos].name))) { 561 mappingData.host = hosts[pos].object; 562 contexts = hosts[pos].contextList.contexts; 563 nesting = hosts[pos].contextList.nesting; 564 } else { 565 if (defaultHostName == null) { 566 return; 567 } 568 pos = find(hosts, defaultHostName); 569 if ((pos != -1) && (defaultHostName.equals(hosts[pos].name))) { 570 mappingData.host = hosts[pos].object; 571 contexts = hosts[pos].contextList.contexts; 572 nesting = hosts[pos].contextList.nesting; 573 } else { 574 return; 575 } 576 } 577 } 578 579 if (mappingData.context == null) { 581 int pos = find(contexts, uri); 582 if (pos == -1) { 583 return; 584 } 585 586 int lastSlash = -1; 587 int uriEnd = uri.getEnd(); 588 int length = -1; 589 boolean found = false; 590 while (pos >= 0) { 591 if (uri.startsWith(contexts[pos].name)) { 592 length = contexts[pos].name.length(); 593 if (uri.getLength() == length) { 594 found = true; 595 break; 596 } else if (uri.startsWithIgnoreCase("/", length)) { 597 found = true; 598 break; 599 } 600 } 601 if (lastSlash == -1) { 602 lastSlash = nthSlash(uri, nesting + 1); 603 } else { 604 lastSlash = lastSlash(uri); 605 } 606 uri.setEnd(lastSlash); 607 pos = find(contexts, uri); 608 } 609 uri.setEnd(uriEnd); 610 611 if (!found) { 612 if (contexts[0].name.equals("")) { 613 context = contexts[0]; 614 } 615 } else { 616 context = contexts[pos]; 617 } 618 if (context != null) { 619 mappingData.context = context.object; 620 mappingData.contextPath.setString(context.name); 621 } 622 } 623 624 if ((context != null) && (mappingData.wrapper == null)) { 626 internalMapWrapper(context, uri, mappingData); 627 } 628 629 } 630 631 632 635 private final void internalMapWrapper(Context context, CharChunk path, 636 MappingData mappingData) 637 throws Exception { 638 639 int pathOffset = path.getOffset(); 640 int pathEnd = path.getEnd(); 641 int servletPath = pathOffset; 642 boolean noServletPath = false; 643 644 int length = context.name.length(); 645 if (length != (pathEnd - pathOffset)) { 646 servletPath = pathOffset + length; 647 } else { 648 noServletPath = true; 649 path.append('/'); 650 pathOffset = path.getOffset(); 651 pathEnd = path.getEnd(); 652 servletPath = pathOffset+length; 653 } 654 655 path.setOffset(servletPath); 656 657 Wrapper[] exactWrappers = context.exactWrappers; 659 internalMapExactWrapper(exactWrappers, path, mappingData); 660 661 boolean checkJspWelcomeFiles = false; 663 Wrapper[] wildcardWrappers = context.wildcardWrappers; 664 if (mappingData.wrapper == null) { 665 internalMapWildcardWrapper(wildcardWrappers, context.nesting, 666 path, mappingData); 667 if (mappingData.wrapper != null && mappingData.jspWildCard) { 668 char[] buf = path.getBuffer(); 669 if (buf[pathEnd - 1] == '/') { 670 678 mappingData.wrapper = null; 679 checkJspWelcomeFiles = true; 680 } else { 681 mappingData.wrapperPath.setChars(buf, path.getStart(), 683 path.getLength()); 684 mappingData.pathInfo.recycle(); 685 } 686 } 687 } 688 689 if(mappingData.wrapper == null && noServletPath) { 690 mappingData.redirectPath.setChars 692 (path.getBuffer(), pathOffset, pathEnd); 693 path.setEnd(pathEnd - 1); 694 return; 695 } 696 697 Wrapper[] extensionWrappers = context.extensionWrappers; 699 if (mappingData.wrapper == null && !checkJspWelcomeFiles) { 700 internalMapExtensionWrapper(extensionWrappers, path, mappingData); 701 } 702 703 if (mappingData.wrapper == null) { 705 boolean checkWelcomeFiles = checkJspWelcomeFiles; 706 if (!checkWelcomeFiles) { 707 char[] buf = path.getBuffer(); 708 checkWelcomeFiles = (buf[pathEnd - 1] == '/'); 709 } 710 if (checkWelcomeFiles) { 711 for (int i = 0; (i < context.welcomeResources.length) 712 && (mappingData.wrapper == null); i++) { 713 path.setOffset(pathOffset); 714 path.setEnd(pathEnd); 715 path.append(context.welcomeResources[i], 0, 716 context.welcomeResources[i].length()); 717 path.setOffset(servletPath); 718 719 internalMapExactWrapper(exactWrappers, path, mappingData); 721 722 if (mappingData.wrapper == null) { 724 internalMapWildcardWrapper 725 (wildcardWrappers, context.nesting, 726 path, mappingData); 727 } 728 729 if (mappingData.wrapper == null 732 && context.resources != null) { 733 Object file = null; 734 String pathStr = path.toString(); 735 try { 736 file = context.resources.lookup(pathStr); 737 } catch(NamingException nex) { 738 } 740 if (file != null && !(file instanceof DirContext ) ) { 741 internalMapExtensionWrapper(extensionWrappers, 742 path, mappingData); 743 if (mappingData.wrapper == null 744 && context.defaultWrapper != null) { 745 mappingData.wrapper = 746 context.defaultWrapper.object; 747 mappingData.requestPath.setChars 748 (path.getBuffer(), path.getStart(), 749 path.getLength()); 75
|