1 29 30 package com.caucho.vfs; 31 32 import com.caucho.util.Alarm; 33 import com.caucho.util.CharBuffer; 34 import com.caucho.util.L10N; 35 import com.caucho.util.LruCache; 36 import com.caucho.util.QDate; 37 38 import org.xml.sax.Attributes ; 39 import org.xml.sax.SAXException ; 40 41 import java.io.IOException ; 42 import java.util.ArrayList ; 43 import java.util.Map ; 44 45 50 public class HttpPath extends FilesystemPath { 51 protected static L10N L = new L10N(HttpPath.class); 52 53 protected static LruCache<String ,CacheEntry> _cache = 54 new LruCache<String ,CacheEntry>(1024); 55 56 protected String _host; 57 protected int _port; 58 protected String _query; 59 60 protected String _virtualHost; 61 62 protected CacheEntry _cacheEntry; 63 64 70 public HttpPath(String host, int port) 71 { 72 super(null, "/", "/"); 73 74 _root = this; 75 _host = host; 76 _port = port == 0 ? 80 : port; 77 } 78 79 88 HttpPath(FilesystemPath root, 89 String userPath, Map <String ,Object > newAttributes, 90 String path, String query) 91 { 92 super(root, userPath, path); 93 94 _host = ((HttpPath) root)._host; 95 _port = ((HttpPath) root)._port; 96 _query = query; 97 98 if (newAttributes != null) { 99 _virtualHost = (String ) newAttributes.get("host"); 100 } 101 } 102 103 112 public Path lookupImpl(String userPath, Map <String ,Object > newAttributes) 113 { 114 String newPath; 115 116 if (userPath == null) 117 return _root.fsWalk(getPath(), newAttributes, "/"); 118 119 int length = userPath.length(); 120 int colon = userPath.indexOf(':'); 121 int slash = userPath.indexOf('/'); 122 123 if (colon != -1 && (colon < slash || slash == -1)) 125 return super.lookupImpl(userPath, newAttributes); 126 127 if (slash == 0 && length > 1 && userPath.charAt(1) == '/') 129 return schemeWalk(userPath, newAttributes, userPath, 0); 130 131 else if (slash == 0) 133 newPath = normalizePath("/", userPath, 0, '/'); 134 135 else 137 newPath = normalizePath(_pathname, userPath, 0, '/'); 138 139 return _root.fsWalk(userPath, newAttributes, newPath); 141 } 142 143 156 protected Path schemeWalk(String userPath, 157 Map <String ,Object > attributes, 158 String uri, 159 int offset) 160 { 161 int length = uri.length(); 162 163 if (length < 2 + offset || 164 uri.charAt(offset) != '/' || 165 uri.charAt(offset + 1) != '/') 166 throw new RuntimeException (L.l("bad scheme in `{0}'", uri)); 167 168 CharBuffer buf = CharBuffer.allocate(); 169 int i = 2 + offset; 170 int ch = 0; 171 for (; i < length && (ch = uri.charAt(i)) != ':' && ch != '/' && ch != '?'; 172 i++) { 173 buf.append((char) ch); 174 } 175 176 String host = buf.close(); 177 if (host.length() == 0) 178 throw new RuntimeException (L.l("bad host in `{0}'", uri)); 179 180 int port = 0; 181 if (ch == ':') { 182 for (i++; i < length && (ch = uri.charAt(i)) >= '0' && ch <= '9'; i++) { 183 port = 10 * port + uri.charAt(i) - '0'; 184 } 185 } 186 187 if (port == 0) 188 port = 80; 189 190 HttpPath root = create(host, port); 191 192 return root.fsWalk(userPath, attributes, uri.substring(i)); 193 } 194 195 205 public Path fsWalk(String userPath, 206 Map <String ,Object > attributes, 207 String uri) 208 { 209 String path; 210 String query = null; 211 int queryIndex = uri.indexOf('?'); 212 if (queryIndex >= 0) { 213 path = uri.substring(0, queryIndex); 214 query = uri.substring(queryIndex + 1); 215 } else 216 path = uri; 217 218 if (path.length() == 0) 219 path = "/"; 220 221 return create(_root, userPath, attributes, path, query); 222 } 223 224 protected HttpPath create(String host, int port) 225 { 226 return new HttpPath(host, port); 227 } 228 229 protected HttpPath create(FilesystemPath root, 230 String userPath, 231 Map <String ,Object > newAttributes, 232 String path, String query) 233 { 234 return new HttpPath(root, userPath, newAttributes, path, query); 235 } 236 237 240 public String getScheme() 241 { 242 return "http"; 243 } 244 245 248 public String getURL() 249 { 250 int port = getPort(); 251 252 return (getScheme() + "://" + getHost() + 253 (port == 80 ? "" : ":" + getPort()) + 254 getPath() + 255 (_query == null ? "" : "?" + _query)); 256 } 257 258 261 public String getHost() 262 { 263 return _host; 264 } 265 266 269 public int getPort() 270 { 271 return _port; 272 } 273 274 277 public String getUserPath() 278 { 279 return _userPath; 280 } 281 282 285 public String getVirtualHost() 286 { 287 return _virtualHost; 288 } 289 290 293 public String getQuery() 294 { 295 return _query; 296 } 297 298 301 public long getLastModified() 302 { 303 return getCache().lastModified; 304 } 305 306 309 public long getLength() 310 { 311 return getCache().length; 312 } 313 314 317 public boolean exists() 318 { 319 return getCache().lastModified >= 0; 320 } 321 322 325 public boolean isFile() 326 { 327 return ! getPath().endsWith("/") && getCache().lastModified >= 0; 328 } 329 330 333 public boolean canRead() 334 { 335 return isFile(); 336 } 337 338 341 public boolean isDirectory() 342 { 343 return getPath().endsWith("/") && getCache().lastModified >= 0; 344 } 345 346 350 387 388 protected CacheEntry getCache() 389 { 390 if (_cacheEntry == null) { 391 synchronized (_cache) { 392 _cacheEntry = _cache.get(getPath()); 393 if (_cacheEntry == null) { 394 _cacheEntry = new CacheEntry(); 395 _cache.put(getPath(), _cacheEntry); 396 } 397 } 398 } 399 400 long now = Alarm.getCurrentTime(); 401 synchronized (_cacheEntry) { 402 try { 403 if (_cacheEntry.expires > now) 404 return _cacheEntry; 405 406 HttpStreamWrapper stream = (HttpStreamWrapper) openReadImpl(); 407 stream.setHead(true); 408 stream.setSocketTimeout(120000); 409 410 String status = (String ) stream.getAttribute("status"); 411 if (status.equals("200")) { 412 String lastModified = (String ) stream.getAttribute("last-modified"); 413 414 _cacheEntry.lastModified = 0; 415 if (lastModified != null) { 416 QDate date = QDate.getGlobalDate(); 417 synchronized (date) { 418 _cacheEntry.lastModified = date.parseDate(lastModified); 419 } 420 } 421 422 String length = (String ) stream.getAttribute("content-length"); 423 _cacheEntry.length = 0; 424 if (length != null) { 425 _cacheEntry.length = Integer.parseInt(length); 426 } 427 } 428 else 429 _cacheEntry.lastModified = -1; 430 431 _cacheEntry.expires = now + 5000; 432 433 stream.close(); 434 return _cacheEntry; 435 } catch (Exception e) { 436 _cacheEntry.lastModified = -1; 437 _cacheEntry.expires = now + 5000; 438 439 return _cacheEntry; 440 } 441 } 442 } 443 444 445 448 public StreamImpl openReadImpl() throws IOException 449 { 450 return HttpStream.openRead(this); 451 } 452 453 456 public StreamImpl openReadWriteImpl() throws IOException 457 { 458 return HttpStream.openReadWrite(this); 459 } 460 461 @Override 462 protected Path cacheCopy() 463 { 464 return new HttpPath(getRoot(), getUserPath(), 465 null, 466 getPath(), _query); 467 } 468 469 472 public String toString() 473 { 474 return getURL(); 475 } 476 477 480 public int hashCode() 481 { 482 return 65537 * super.hashCode() + 37 * _host.hashCode() + _port; 483 } 484 485 488 public boolean equals(Object o) 489 { 490 if (! (o instanceof HttpPath)) 491 return false; 492 493 HttpPath test = (HttpPath) o; 494 495 if (! _host.equals(test._host)) 496 return false; 497 else if (_port != test._port) 498 return false; 499 else if (_query != null && ! _query.equals(test._query)) 500 return false; 501 else if (_query == null && test._query != null) 502 return false; 503 else 504 return true; 505 } 506 507 static class CacheEntry { 508 long lastModified; 509 long length; 510 boolean canRead; 511 long expires; 512 } 513 514 static class ListHandler extends org.xml.sax.helpers.DefaultHandler { 515 String _prefix; 516 ArrayList <String > _names = new ArrayList <String >(); 517 boolean _inHref; 518 519 ListHandler(String prefix) 520 { 521 _prefix = prefix; 522 } 523 524 ArrayList <String > getNames() 525 { 526 return _names; 527 } 528 529 public void startElement (String uri, String localName, 530 String qName, Attributes attributes) 531 { 532 if (localName.equals("href")) 533 _inHref = true; 534 } 535 536 public void characters(char []data, int offset, int length) 537 throws SAXException 538 { 539 if (! _inHref) 540 return; 541 542 String href = new String (data, offset, length).trim(); 543 if (! href.startsWith(_prefix)) 544 return; 545 546 href = href.substring(_prefix.length()); 547 if (href.startsWith("/")) 548 href = href.substring(1); 549 550 int p = href.indexOf('/'); 551 if (href.equals("") || p == 0) 552 return; 553 554 if (p < 0) 555 _names.add(href); 556 else 557 _names.add(href.substring(0, p)); 558 } 559 560 public void endElement (String uri, String localName, String qName) 561 throws SAXException 562 { 563 if (localName.equals("href")) 564 _inHref = false; 565 } 566 } 567 } 568 | Popular Tags |