1 16 package org.mortbay.http; 17 18 import java.io.Externalizable ; 19 import java.util.HashMap ; 20 import java.util.List ; 21 import java.util.Map ; 22 import java.util.Set ; 23 import java.util.StringTokenizer ; 24 25 import org.apache.commons.logging.Log; 26 import org.mortbay.log.LogFactory; 27 import org.mortbay.util.LazyList; 28 import org.mortbay.util.SingletonList; 29 import org.mortbay.util.StringMap; 30 31 32 62 public class PathMap extends HashMap implements Externalizable 63 { 64 private static Log log = LogFactory.getLog(PathMap.class); 65 66 67 private static String __pathSpecSeparators = 68 System.getProperty("org.mortbay.http.PathMap.separators",":,"); 69 70 71 78 public static void setPathSpecSeparators(String s) 79 { 80 __pathSpecSeparators=s; 81 } 82 83 84 StringMap _prefixMap=new StringMap(); 85 StringMap _suffixMap=new StringMap(); 86 StringMap _exactMap=new StringMap(); 87 88 List _defaultSingletonList=null; 89 Map.Entry _prefixDefault=null; 90 Map.Entry _default=null; 91 Set _entrySet; 92 boolean _nodefault=false; 93 94 95 97 public PathMap() 98 { 99 super(11); 100 _entrySet=entrySet(); 101 } 102 103 104 106 public PathMap(boolean nodefault) 107 { 108 super(11); 109 _entrySet=entrySet(); 110 _nodefault=nodefault; 111 } 112 113 114 116 public PathMap(int capacity) 117 { 118 super (capacity); 119 _entrySet=entrySet(); 120 } 121 122 123 125 public PathMap(Map m) 126 { 127 putAll(m); 128 _entrySet=entrySet(); 129 } 130 131 132 public void writeExternal(java.io.ObjectOutput out) 133 throws java.io.IOException 134 { 135 HashMap map = new HashMap (this); 136 out.writeObject(map); 137 } 138 139 140 public void readExternal(java.io.ObjectInput in) 141 throws java.io.IOException , ClassNotFoundException 142 { 143 HashMap map = (HashMap )in.readObject(); 144 this.putAll(map); 145 } 146 147 148 153 public synchronized Object put(Object pathSpec, Object object) 154 { 155 StringTokenizer tok = new StringTokenizer (pathSpec.toString(),__pathSpecSeparators); 156 Object old =null; 157 158 while (tok.hasMoreTokens()) 159 { 160 String spec=tok.nextToken(); 161 162 if (!spec.startsWith("/") && !spec.startsWith("*.")) 163 { 164 log.warn("PathSpec "+spec+". must start with '/' or '*.'"); 165 spec="/"+spec; 166 } 167 168 old = super.put(spec,object); 169 170 Entry entry = new Entry(spec,object); 172 173 if (entry.getKey().equals(spec)) 174 { 175 if (spec.equals("/*")) 176 _prefixDefault=entry; 177 else if (spec.endsWith("/*")) 178 { 179 _prefixMap.put(spec.substring(0,spec.length()-2),entry); 180 _exactMap.put(spec.substring(0,spec.length()-1),entry); 181 _exactMap.put(spec.substring(0,spec.length()-2),entry); 182 } 183 else if (spec.startsWith("*.")) 184 _suffixMap.put(spec.substring(2),entry); 185 else if (spec.equals("/")) 186 { 187 if (_nodefault) 188 _exactMap.put(spec,entry); 189 else 190 { 191 _default=entry; 192 _defaultSingletonList= 193 SingletonList.newSingletonList(_default); 194 } 195 } 196 else 197 _exactMap.put(spec,entry); 198 } 199 } 200 201 return old; 202 } 203 204 205 209 public Object match(String path) 210 { 211 Map.Entry entry = getMatch(path); 212 if (entry!=null) 213 return entry.getValue(); 214 return null; 215 } 216 217 218 219 223 public Map.Entry getMatch(String path) 224 { 225 Map.Entry entry; 226 227 if (path==null) 228 return null; 229 230 int l=path.indexOf(';'); 231 if (l<0) 232 { 233 l=path.indexOf('?'); 234 if (l<0) 235 l=path.length(); 236 } 237 238 entry=_exactMap.getEntry(path,0,l); 240 if (entry!=null) 241 return (Map.Entry ) entry.getValue(); 242 243 int i=l; 245 while((i=path.lastIndexOf('/',i-1))>=0) 246 { 247 entry=_prefixMap.getEntry(path,0,i); 248 if (entry!=null) 249 return (Map.Entry ) entry.getValue(); 250 } 251 252 if (_prefixDefault!=null) 254 return _prefixDefault; 255 256 i=0; 258 while ((i=path.indexOf('.',i+1))>0) 259 { 260 entry=_suffixMap.getEntry(path,i+1,l-i-1); 261 if (entry!=null) 262 return (Map.Entry ) entry.getValue(); 263 } 264 265 return _default; 267 } 268 269 270 275 public List getMatches(String path) 276 { 277 Map.Entry entry; 278 Object entries=null; 279 280 if (path==null) 281 return LazyList.getList(entries); 282 283 int l=path.indexOf(';'); 284 if (l<0) 285 { 286 l=path.indexOf('?'); 287 if (l<0) 288 l=path.length(); 289 } 290 291 entry=_exactMap.getEntry(path,0,l); 293 if (entry!=null) 294 entries=LazyList.add(entries,entry.getValue()); 295 296 int i=l-1; 298 while((i=path.lastIndexOf('/',i-1))>=0) 299 { 300 entry=_prefixMap.getEntry(path,0,i); 301 if (entry!=null) 302 entries=LazyList.add(entries,entry.getValue()); 303 } 304 305 if (_prefixDefault!=null) 307 entries=LazyList.add(entries,_prefixDefault); 308 309 i=0; 311 while ((i=path.indexOf('.',i+1))>0) 312 { 313 entry=_suffixMap.getEntry(path,i+1,l-i-1); 314 if (entry!=null) 315 entries=LazyList.add(entries,entry.getValue()); 316 } 317 318 if (_default!=null) 320 { 321 if (entries==null) 323 return _defaultSingletonList; 324 325 entries=LazyList.add(entries,_default); 326 } 327 328 return LazyList.getList(entries); 329 } 330 331 332 333 public synchronized Object remove(Object pathSpec) 334 { 335 if (pathSpec!=null) 336 { 337 String spec=(String ) pathSpec; 338 if (spec.equals("/*")) 339 _prefixDefault=null; 340 else if (spec.endsWith("/*")) 341 { 342 _prefixMap.remove(spec.substring(0,spec.length()-2)); 343 _exactMap.remove(spec.substring(0,spec.length()-1)); 344 _exactMap.remove(spec.substring(0,spec.length()-2)); 345 } 346 else if (spec.startsWith("*.")) 347 _suffixMap.remove(spec.substring(2)); 348 else if (spec.equals("/")) 349 { 350 _default=null; 351 _defaultSingletonList=null; 352 } 353 else 354 _exactMap.remove(spec); 355 } 356 return super.remove(pathSpec); 357 } 358 359 360 public void clear() 361 { 362 _exactMap=new StringMap(); 363 _prefixMap=new StringMap(); 364 _suffixMap=new StringMap(); 365 _default=null; 366 _defaultSingletonList=null; 367 super.clear(); 368 } 369 370 371 374 public static boolean match(String pathSpec, String path) 375 throws IllegalArgumentException 376 { 377 char c = pathSpec.charAt(0); 378 if (c=='/') 379 { 380 if (pathSpec.length()==1 || pathSpec.equals(path)) 381 return true; 382 383 if (pathSpec.endsWith("/*") && 384 pathSpec.regionMatches(0,path,0,pathSpec.length()-2)) 385 return true; 386 387 if (path.startsWith(pathSpec) && path.charAt(pathSpec.length())==';') 388 return true; 389 } 390 else if (c=='*') 391 return path.regionMatches(path.length()-pathSpec.length()+1, 392 pathSpec,1,pathSpec.length()-1); 393 return false; 394 } 395 396 397 400 public static boolean match(String pathSpec, String path, boolean noDefault) 401 throws IllegalArgumentException 402 { 403 char c = pathSpec.charAt(0); 404 if (c=='/') 405 { 406 if (!noDefault && pathSpec.length()==1 || pathSpec.equals(path)) 407 return true; 408 409 if (pathSpec.endsWith("/*") && 410 pathSpec.regionMatches(0,path,0,pathSpec.length()-2)) 411 return true; 412 413 if (path.startsWith(pathSpec) && path.charAt(pathSpec.length())==';') 414 return true; 415 } 416 else if (c=='*') 417 return path.regionMatches(path.length()-pathSpec.length()+1, 418 pathSpec,1,pathSpec.length()-1); 419 return false; 420 } 421 422 423 426 public static String pathMatch(String pathSpec, String path) 427 { 428 char c = pathSpec.charAt(0); 429 430 if (c=='/') 431 { 432 if (pathSpec.length()==1) 433 return path; 434 435 if (pathSpec.equals(path)) 436 return path; 437 438 if (pathSpec.endsWith("/*") && 439 pathSpec.regionMatches(0,path,0,pathSpec.length()-2)) 440 return path.substring(0,pathSpec.length()-2); 441 442 if (path.startsWith(pathSpec) && path.charAt(pathSpec.length())==';') 443 return path; 444 } 445 else if (c=='*') 446 { 447 if (path.regionMatches(path.length()-(pathSpec.length()-1), 448 pathSpec,1,pathSpec.length()-1)) 449 return path; 450 } 451 return null; 452 } 453 454 455 458 public static String pathInfo(String pathSpec, String path) 459 { 460 char c = pathSpec.charAt(0); 461 462 if (c=='/') 463 { 464 if (pathSpec.length()==1) 465 return null; 466 467 if (pathSpec.equals(path)) 468 return null; 469 470 if (pathSpec.endsWith("/*") && 471 pathSpec.regionMatches(0,path,0,pathSpec.length()-2)) 472 { 473 if (path.length()==pathSpec.length()-2) 474 return null; 475 return path.substring(pathSpec.length()-2); 476 } 477 } 478 return null; 479 } 480 481 482 483 489 public static String relativePath(String base, 490 String pathSpec, 491 String path ) 492 { 493 String info=pathInfo(pathSpec,path); 494 if (info==null) 495 info=path; 496 497 if( info.startsWith( "./")) 498 info = info.substring( 2); 499 if( base.endsWith( "/")) 500 if( info.startsWith( "/")) 501 path = base + info.substring(1); 502 else 503 path = base + info; 504 else 505 if( info.startsWith( "/")) 506 path = base + info; 507 else 508 path = base + "/" + info; 509 return path; 510 } 511 512 513 514 515 private static class Entry implements Map.Entry 516 { 517 private Object key; 518 private Object value; 519 private transient String string; 520 521 Entry(Object key, Object value) 522 { 523 this.key=key; 524 this.value=value; 525 } 526 527 public Object getKey() 528 { 529 return key; 530 } 531 532 public Object getValue() 533 { 534 return value; 535 } 536 537 public Object setValue(Object o) 538 { 539 throw new UnsupportedOperationException (); 540 } 541 542 public String toString() 543 { 544 if (string==null) 545 string=key+"="+value; 546 return string; 547 } 548 } 549 } 550 | Popular Tags |