1 29 30 package com.caucho.server.hmux; 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 import com.caucho.vfs.FilesystemPath; 38 import com.caucho.vfs.Path; 39 import com.caucho.vfs.ReadStream; 40 import com.caucho.vfs.StreamImpl; 41 import com.caucho.vfs.WriteStream; 42 import com.caucho.xml.XmlParser; 43 44 import org.xml.sax.Attributes ; 45 import org.xml.sax.SAXException ; 46 47 import java.io.IOException ; 48 import java.util.ArrayList ; 49 import java.util.Map ; 50 51 56 public class HmuxPath extends FilesystemPath { 57 protected static L10N L = new L10N(HmuxPath.class); 58 59 protected static LruCache<String ,CacheEntry> _cache = 60 new LruCache<String ,CacheEntry>(1024); 61 62 protected String _host; 63 protected int _port; 64 protected String _query; 65 66 protected String _virtualHost; 67 68 protected CacheEntry _cacheEntry; 69 70 76 public HmuxPath(String host, int port) 77 { 78 super(null, "/", "/"); 79 80 _root = this; 81 _host = host; 82 _port = port == 0 ? 80 : port; 83 } 84 85 94 HmuxPath(FilesystemPath root, 95 String userPath, Map <String ,Object > newAttributes, 96 String path, String query) 97 { 98 super(root, userPath, path); 99 100 _host = ((HmuxPath) root)._host; 101 _port = ((HmuxPath) root)._port; 102 _query = query; 103 104 if (newAttributes != null) { 105 _virtualHost = (String ) newAttributes.get("host"); 106 } 107 } 108 109 118 public Path lookupImpl(String userPath, Map <String ,Object > newAttributes) 119 { 120 String newPath; 121 122 if (userPath == null) 123 return _root.fsWalk(getPath(), newAttributes, "/"); 124 125 int length = userPath.length(); 126 int colon = userPath.indexOf(':'); 127 int slash = userPath.indexOf('/'); 128 129 if (colon != -1 && (colon < slash || slash == -1)) 131 return super.lookupImpl(userPath, newAttributes); 132 133 if (slash == 0 && length > 1 && userPath.charAt(1) == '/') 135 return schemeWalk(userPath, newAttributes, userPath, 0); 136 137 else if (slash == 0) 139 newPath = normalizePath("/", userPath, 0, '/'); 140 141 else 143 newPath = normalizePath(_pathname, userPath, 0, '/'); 144 145 return _root.fsWalk(userPath, newAttributes, newPath); 147 } 148 149 162 protected Path schemeWalk(String userPath, 163 Map <String ,Object > attributes, 164 String uri, 165 int offset) 166 { 167 int length = uri.length(); 168 169 if (length < 2 + offset || 170 uri.charAt(offset) != '/' || 171 uri.charAt(offset + 1) != '/') 172 throw new RuntimeException (L.l("bad scheme in `{0}'", uri)); 173 174 CharBuffer buf = CharBuffer.allocate(); 175 int i = 2 + offset; 176 int ch = 0; 177 for (; i < length && (ch = uri.charAt(i)) != ':' && ch != '/' && ch != '?'; 178 i++) { 179 buf.append((char) ch); 180 } 181 182 String host = buf.close(); 183 if (host.length() == 0) 184 throw new RuntimeException (L.l("bad host in `{0}'", uri)); 185 186 int port = 0; 187 if (ch == ':') { 188 for (i++; i < length && (ch = uri.charAt(i)) >= '0' && ch <= '9'; i++) { 189 port = 10 * port + uri.charAt(i) - '0'; 190 } 191 } 192 193 if (port == 0) 194 port = 80; 195 196 HmuxPath root = create(host, port); 197 198 return root.fsWalk(userPath, attributes, uri.substring(i)); 199 } 200 201 211 public Path fsWalk(String userPath, 212 Map <String ,Object > attributes, 213 String uri) 214 { 215 String path; 216 String query = null; 217 int queryIndex = uri.indexOf('?'); 218 if (queryIndex >= 0) { 219 path = uri.substring(0, queryIndex); 220 query = uri.substring(queryIndex + 1); 221 } else 222 path = uri; 223 224 if (path.length() == 0) 225 path = "/"; 226 227 return create(_root, userPath, attributes, path, query); 228 } 229 230 protected HmuxPath create(String host, int port) 231 { 232 return new HmuxPath(host, port); 233 } 234 235 protected HmuxPath create(FilesystemPath root, 236 String userPath, 237 Map <String ,Object > newAttributes, 238 String path, String query) 239 { 240 return new HmuxPath(root, userPath, newAttributes, path, query); 241 } 242 243 246 public String getScheme() 247 { 248 return "http"; 249 } 250 251 254 public String getURL() 255 { 256 int port = getPort(); 257 258 return (getScheme() + "://" + getHost() + 259 (port == 80 ? "" : ":" + getPort()) + 260 getPath() + 261 (_query == null ? "" : "?" + _query)); 262 } 263 264 267 public String getHost() 268 { 269 return _host; 270 } 271 272 275 public int getPort() 276 { 277 return _port; 278 } 279 280 283 public String getUserPath() 284 { 285 return _userPath; 286 } 287 288 291 public String getVirtualHost() 292 { 293 return _virtualHost; 294 } 295 296 299 public String getQuery() 300 { 301 return _query; 302 } 303 304 307 public long getLastModified() 308 { 309 return getCache().lastModified; 310 } 311 312 315 public long getLength() 316 { 317 return getCache().length; 318 } 319 320 323 public boolean exists() 324 { 325 return getCache().lastModified >= 0; 326 } 327 328 331 public boolean isFile() 332 { 333 return ! getPath().endsWith("/") && getCache().lastModified >= 0; 334 } 335 336 339 public boolean canRead() 340 { 341 return isFile(); 342 } 343 344 347 public boolean isDirectory() 348 { 349 return getPath().endsWith("/") && getCache().lastModified >= 0; 350 } 351 352 356 public String []list() throws IOException 357 { 358 try { 359 HmuxStream stream = (HmuxStream) openReadWriteImpl(); 360 stream.setMethod("PROPFIND"); 361 stream.setAttribute("Depth", "1"); 362 363 WriteStream os = new WriteStream(stream); 364 os.println("<?xml version=\"1.0\" encoding=\"utf-8\"?>"); 365 os.println("<propfind xmlns=\"DAV:\"><prop>"); 366 os.println("<resourcetype/>"); 367 os.println("</prop></propfind>"); 368 os.flush(); 369 370 ReadStream is = new ReadStream(stream); 371 372 ListHandler handler = new ListHandler(getPath()); 373 XmlParser parser = new XmlParser(); 374 parser.setContentHandler(handler); 375 376 parser.parse(is); 377 378 is.close(); 379 os.close(); 380 stream.close(); 381 382 ArrayList <String > names = handler.getNames(); 383 String []list = new String [names.size()]; 384 names.toArray(list); 385 386 return list; 387 } catch (Exception e) { 388 throw new IOException (L.l("list() is not supported by this server")); 389 } 390 } 391 392 protected CacheEntry getCache() 393 { 394 if (_cacheEntry == null) { 395 synchronized (_cache) { 396 _cacheEntry = _cache.get(getPath()); 397 if (_cacheEntry == null) { 398 _cacheEntry = new CacheEntry(); 399 _cache.put(getPath(), _cacheEntry); 400 } 401 } 402 } 403 404 long now = Alarm.getCurrentTime(); 405 synchronized (_cacheEntry) { 406 try { 407 if (_cacheEntry.expires > now) 408 return _cacheEntry; 409 410 HmuxStreamWrapper stream = (HmuxStreamWrapper) openReadImpl(); 411 stream.setHead(true); 412 stream.setSocketTimeout(120000); 413 414 String status = (String ) stream.getAttribute("status"); 415 if (status.equals("200")) { 416 String lastModified = (String ) stream.getAttribute("last-modified"); 417 418 _cacheEntry.lastModified = 0; 419 if (lastModified != null) { 420 QDate date = QDate.getGlobalDate(); 421 synchronized (date) { 422 _cacheEntry.lastModified = date.parseDate(lastModified); 423 } 424 } 425 426 String length = (String ) stream.getAttribute("content-length"); 427 _cacheEntry.length = 0; 428 if (length != null) { 429 _cacheEntry.length = Integer.parseInt(length); 430 } 431 } 432 else 433 _cacheEntry.lastModified = -1; 434 435 _cacheEntry.expires = now + 5000; 436 437 stream.close(); 438 return _cacheEntry; 439 } catch (Exception e) { 440 _cacheEntry.lastModified = -1; 441 _cacheEntry.expires = now + 5000; 442 443 return _cacheEntry; 444 } 445 } 446 } 447 448 449 452 public StreamImpl openReadImpl() throws IOException 453 { 454 return HmuxStream.openRead(this); 455 } 456 457 460 public StreamImpl openReadWriteImpl() throws IOException 461 { 462 return HmuxStream.openReadWrite(this); 463 } 464 465 @Override 466 protected Path cacheCopy() 467 { 468 return new HmuxPath(getRoot(), getUserPath(), 469 null, 470 getPath(), _query); 471 } 472 473 476 public String toString() 477 { 478 return getURL(); 479 } 480 481 484 public int hashCode() 485 { 486 return 65537 * super.hashCode() + 37 * _host.hashCode() + _port; 487 } 488 489 492 public boolean equals(Object o) 493 { 494 if (! (o instanceof HmuxPath)) 495 return false; 496 497 HmuxPath test = (HmuxPath) o; 498 499 if (! _host.equals(test._host)) 500 return false; 501 else if (_port != test._port) 502 return false; 503 else if (_query != null && ! _query.equals(test._query)) 504 return false; 505 else if (_query == null && test._query != null) 506 return false; 507 else 508 return true; 509 } 510 511 static class CacheEntry { 512 long lastModified; 513 long length; 514 boolean canRead; 515 long expires; 516 } 517 518 static class ListHandler extends org.xml.sax.helpers.DefaultHandler { 519 String _prefix; 520 ArrayList <String > _names = new ArrayList <String >(); 521 boolean _inHref; 522 523 ListHandler(String prefix) 524 { 525 _prefix = prefix; 526 } 527 528 ArrayList <String > getNames() 529 { 530 return _names; 531 } 532 533 public void startElement (String uri, String localName, 534 String qName, Attributes attributes) 535 { 536 if (localName.equals("href")) 537 _inHref = true; 538 } 539 540 public void characters(char []data, int offset, int length) 541 throws SAXException 542 { 543 if (! _inHref) 544 return; 545 546 String href = new String (data, offset, length).trim(); 547 if (! href.startsWith(_prefix)) 548 return; 549 550 href = href.substring(_prefix.length()); 551 if (href.startsWith("/")) 552 href = href.substring(1); 553 554 int p = href.indexOf('/'); 555 if (href.equals("") || p == 0) 556 return; 557 558 if (p < 0) 559 _names.add(href); 560 else 561 _names.add(href.substring(0, p)); 562 } 563 564 public void endElement (String uri, String localName, String qName) 565 throws SAXException 566 { 567 if (localName.equals("href")) 568 _inHref = false; 569 } 570 } 571 } 572 | Popular Tags |