| 1 7 package javax.swing; 8 9 import java.awt.*; 10 import java.awt.event.*; 11 import java.net.*; 12 import java.util.*; 13 import java.io.*; 14 import java.util.*; 15 16 import javax.swing.plaf.*; 17 import javax.swing.text.*; 18 import javax.swing.event.*; 19 import javax.swing.text.html.*; 20 import javax.accessibility.*; 21 22 166 public class JEditorPane extends JTextComponent { 167 168 172 public JEditorPane() { 173 super(); 174 setFocusCycleRoot(true); 175 setFocusTraversalPolicy(new LayoutFocusTraversalPolicy () { 176 public Component getComponentAfter(Container focusCycleRoot, 177 Component aComponent) { 178 if (focusCycleRoot != JEditorPane.this || 179 (!isEditable() && getComponentCount() > 0)) { 180 return super.getComponentAfter(focusCycleRoot, 181 aComponent); 182 } else { 183 Container rootAncestor = getFocusCycleRootAncestor(); 184 return (rootAncestor != null) 185 ? rootAncestor.getFocusTraversalPolicy(). 186 getComponentAfter(rootAncestor, 187 JEditorPane.this) 188 : null; 189 } 190 } 191 public Component getComponentBefore(Container focusCycleRoot, 192 Component aComponent) { 193 if (focusCycleRoot != JEditorPane.this || 194 (!isEditable() && getComponentCount() > 0)) { 195 return super.getComponentBefore(focusCycleRoot, 196 aComponent); 197 } else { 198 Container rootAncestor = getFocusCycleRootAncestor(); 199 return (rootAncestor != null) 200 ? rootAncestor.getFocusTraversalPolicy(). 201 getComponentBefore(rootAncestor, 202 JEditorPane.this) 203 : null; 204 } 205 } 206 public Component getDefaultComponent(Container focusCycleRoot) 207 { 208 return (focusCycleRoot != JEditorPane.this || 209 (!isEditable() && getComponentCount() > 0)) 210 ? super.getDefaultComponent(focusCycleRoot) 211 : null; 212 } 213 protected boolean accept(Component aComponent) { 214 return (aComponent != JEditorPane.this) 215 ? super.accept(aComponent) 216 : false; 217 } 218 }); 219 LookAndFeel.installProperty(this, 220 "focusTraversalKeysForward", 221 JComponent. 222 getManagingFocusForwardTraversalKeys()); 223 LookAndFeel.installProperty(this, 224 "focusTraversalKeysBackward", 225 JComponent. 226 getManagingFocusBackwardTraversalKeys()); 227 } 228 229 236 public JEditorPane(URL initialPage) throws IOException { 237 this(); 238 setPage(initialPage); 239 } 240 241 249 public JEditorPane(String url) throws IOException { 250 this(); 251 setPage(url); 252 } 253 254 264 public JEditorPane(String type, String text) { 265 this(); 266 setContentType(type); 267 setText(text); 268 } 269 270 276 public synchronized void addHyperlinkListener(HyperlinkListener listener) { 277 listenerList.add(HyperlinkListener.class, listener); 278 } 279 280 285 public synchronized void removeHyperlinkListener(HyperlinkListener listener) { 286 listenerList.remove(HyperlinkListener.class, listener); 287 } 288 289 297 public synchronized HyperlinkListener[] getHyperlinkListeners() { 298 return (HyperlinkListener[])listenerList.getListeners( 299 HyperlinkListener.class); 300 } 301 302 313 public void fireHyperlinkUpdate(HyperlinkEvent e) { 314 Object [] listeners = listenerList.getListenerList(); 316 for (int i = listeners.length-2; i>=0; i-=2) { 319 if (listeners[i]==HyperlinkListener.class) { 320 ((HyperlinkListener)listeners[i+1]).hyperlinkUpdate(e); 321 } 322 } 323 } 324 325 326 391 public void setPage(URL page) throws IOException { 392 if (page == null) { 393 throw new IOException("invalid url"); 394 } 395 URL loaded = getPage(); 396 397 398 if (!page.equals(loaded) && page.getRef() == null) { 400 scrollRectToVisible(new Rectangle(0,0,1,1)); 401 } 402 boolean reloaded = false; 403 if ((loaded == null) || (! loaded.sameFile(page))) { 404 405 InputStream in = getStream(page); 407 if (kit != null) { 408 Document doc = kit.createDefaultDocument(); 409 if (pageProperties != null) { 410 for (Enumeration e = pageProperties.keys(); e.hasMoreElements() ;) { 413 Object key = e.nextElement(); 414 doc.putProperty(key, pageProperties.get(key)); 415 } 416 pageProperties.clear(); 417 } 418 if (doc.getProperty(Document.StreamDescriptionProperty) == null) { 419 doc.putProperty(Document.StreamDescriptionProperty, page); 420 } 421 422 synchronized(this) { 427 if (loading != null) { 428 loading.cancel(); 431 loading = null; 432 } 433 } 434 if (doc instanceof AbstractDocument) { 435 AbstractDocument adoc = (AbstractDocument) doc; 436 int p = adoc.getAsynchronousLoadPriority(); 437 if (p >= 0) { 438 setDocument(doc); 440 synchronized(this) { 441 loading = new PageStream(in); 442 Thread pl = new PageLoader(doc, loading, p, loaded, page); 443 pl.start(); 444 } 445 return; 446 } 447 } 448 read(in, doc); 449 setDocument(doc); 450 reloaded = true; 451 } 452 } 453 final String reference = page.getRef(); 454 if (reference != null) { 455 if (!reloaded) { 456 scrollToReference(reference); 457 } 458 else { 459 SwingUtilities.invokeLater(new Runnable () { 461 public void run() { 462 scrollToReference(reference); 463 } 464 }); 465 } 466 getDocument().putProperty(Document.StreamDescriptionProperty, page); 467 } 468 firePropertyChange("page", loaded, page); 469 } 470 471 472 487 public void read(InputStream in, Object desc) throws IOException { 488 489 if (desc instanceof HTMLDocument && 490 kit instanceof HTMLEditorKit) { 491 HTMLDocument hdoc = (HTMLDocument) desc; 492 setDocument(hdoc); 493 read(in, hdoc); 494 } else { 495 String charset = (String ) getClientProperty("charset"); 496 Reader r = (charset != null) ? new InputStreamReader(in, charset) : 497 new InputStreamReader(in); 498 super.read(r, desc); 499 } 500 } 501 502 503 514 void read(InputStream in, Document doc) throws IOException { 515 try { 516 String charset = (String ) getClientProperty("charset"); 517 Reader r = (charset != null) ? new InputStreamReader(in, charset) : 518 new InputStreamReader(in); 519 kit.read(r, doc, 0); 520 } catch (BadLocationException e) { 521 throw new IOException(e.getMessage()); 522 } catch (ChangedCharSetException e1) { 523 String charSetSpec = e1.getCharSetSpec(); 524 if (e1.keyEqualsCharSet()) { 525 putClientProperty("charset", charSetSpec); 526 } else { 527 setCharsetFromContentTypeParameters(charSetSpec); 528 } 529 in.close(); 530 URL url = (URL)doc.getProperty(Document.StreamDescriptionProperty); 531 URLConnection conn = url.openConnection(); 532 in = conn.getInputStream(); 533 try { 534 doc.remove(0, doc.getLength()); 535 } catch (BadLocationException e) {} 536 doc.putProperty("IgnoreCharsetDirective", Boolean.valueOf(true)); 537 read(in, doc); 538 } 539 } 540 541 542 545 class PageLoader extends Thread { 546 547 550 PageLoader(Document doc, InputStream in, int priority, URL old, 551 URL page) { 552 setPriority(priority); 553 this.in = in; 554 this.old = old; 555 this.page = page; 556 this.doc = doc; 557 } 558 559 564 public void run() { 565 try { 566 read(in, doc); 567 synchronized(JEditorPane.this) { 568 loading = null; 569 } 570 URL page = (URL) doc.getProperty(Document.StreamDescriptionProperty); 571 String reference = page.getRef(); 572 if (reference != null) { 573 Runnable callScrollToReference = new Runnable () { 577 public void run() { 578 URL u = (URL) getDocument().getProperty 579 (Document.StreamDescriptionProperty); 580 String ref = u.getRef(); 581 scrollToReference(ref); 582 } 583 }; 584 SwingUtilities.invokeLater(callScrollToReference); 585 } 586 } catch (IOException ioe) { 587 UIManager.getLookAndFeel().provideErrorFeedback(JEditorPane.this); 588 } finally { 589 SwingUtilities.invokeLater(new Runnable () { 590 public void run() { 591 firePropertyChange("page", old, page); 592 } 593 }); 594 } 595 } 596 597 600 InputStream in; 601 602 605 URL old; 606 607 610 URL page; 611 612 617 Document doc; 618 } 619 620 static class PageStream extends FilterInputStream { 621 622 boolean canceled; 623 624 public PageStream(InputStream i) { 625 super(i); 626 canceled = false; 627 } 628 629 633 public synchronized void cancel() { 634 canceled = true; 635 } 636 637 protected synchronized void checkCanceled() throws IOException { 638 if (canceled) { 639 throw new IOException("page canceled"); 640 } 641 } 642 643 public int read() throws IOException { 644 checkCanceled(); 645 return super.read(); 646 } 647 648 public long skip(long n) throws IOException { 649 checkCanceled(); 650 return super.skip(n); 651 } 652 653 public int available() throws IOException { 654 checkCanceled(); 655 return super.available(); 656 } 657 658 public void reset() throws IOException { 659 checkCanceled(); 660 super.reset(); 661 } 662 663 } 664 665 684 protected InputStream getStream(URL page) throws IOException { 685 URLConnection conn = page.openConnection(); 686 if (conn instanceof HttpURLConnection) { 687 HttpURLConnection hconn = (HttpURLConnection) conn; 688 hconn.setInstanceFollowRedirects(false); 689 int response = hconn.getResponseCode(); 690 boolean redirect = (response >= 300 && response <= 399); 691 692 696 if (redirect) { 697 String loc = conn.getHeaderField("Location"); 698 if (loc.startsWith("http", 0)) { 699 page = new URL(loc); 700 } else { 701 page = new URL(page, loc); 702 } 703 return getStream(page); 704 } 705 } 706 if (pageProperties == null) { 707 pageProperties = new Hashtable(); 708 } 709 String type = conn.getContentType(); 710 if (type != null) { 711 setContentType(type); 712 pageProperties.put("content-type", type); 713 } 714 pageProperties.put(Document.StreamDescriptionProperty, page); 715 String enc = conn.getContentEncoding(); 716 if (enc != null) { 717 pageProperties.put("content-encoding", enc); 718 } 719 InputStream in = conn.getInputStream(); 720 return in; 721 } 722 723 738 public void scrollToReference(String reference) { 739 Document d = getDocument(); 740 if (d instanceof HTMLDocument) { 741 HTMLDocument doc = (HTMLDocument) d; 742 HTMLDocument.Iterator iter = doc.getIterator(HTML.Tag.A); 743 for (; iter.isValid(); iter.next()) { 744 AttributeSet a = iter.getAttributes(); 745 String nm = (String ) a.getAttribute(HTML.Attribute.NAME); 746 if ((nm != null) && nm.equals(reference)) { 747 try { 749 Rectangle r = modelToView(iter.getStartOffset()); 750 if (r != null) { 751 Rectangle vis = getVisibleRect(); 754 r.height = vis.height; 756 scrollRectToVisible(r); 757 } 758 } catch (BadLocationException ble) { 759 UIManager.getLookAndFeel().provideErrorFeedback(JEditorPane.this); 760 } 761 } 762 } 763 } 764 } 765 766 774 public URL getPage() { 775 return (URL) getDocument().getProperty(Document.StreamDescriptionProperty); 776 } 777 778 785 public void setPage(String url) throws IOException { 786 if (url == null) { 787 throw new IOException("invalid url"); 788 } 789 URL page = new URL(url); 790 setPage(page); 791 } 792 793 800 public String getUIClassID() { 801 return uiClassID; 802 } 803 804 810 protected EditorKit createDefaultEditorKit() { 811 return new PlainEditorKit(); 812 } 813 814 821 public EditorKit getEditorKit() { 822 if (kit == null) { 823 kit = createDefaultEditorKit(); 824 } 825 return kit; 826 } 827 828 836 public final String getContentType() { 837 return (kit != null) ? kit.getContentType() : null; 838 } 839 840 869 public final void setContentType(String type) { 870 int parm = type.indexOf(";"); 874 if (parm > -1) { 875 String paramList = type.substring(parm); 877 type = type.substring(0, parm).trim(); 879 if (type.toLowerCase().startsWith("text/")) { 880 setCharsetFromContentTypeParameters(paramList); 881 } 882 } 883 if ((kit == null) || (! type.equals(kit.getContentType()))) { 884 EditorKit k = getEditorKitForContentType(type); 885 if (k != null) { 886 setEditorKit(k); 887 } 888 } 889 } 890 891 895 private void setCharsetFromContentTypeParameters(String paramlist) { 896 String charset = null; 897 try { 898 int semi = paramlist.indexOf(';'); 900 if (semi > -1 && semi < paramlist.length()-1) { 901 paramlist = paramlist.substring(semi + 1); 902 } 903 904 if (paramlist.length() > 0) { 905 HeaderParser hdrParser = new HeaderParser(paramlist); 908 charset = hdrParser.findValue("charset"); 909 if (charset != null) { 910 putClientProperty("charset", charset); 911 } 912 } 913 } 914 catch (IndexOutOfBoundsException e) { 915 } 917 catch (NullPointerException e) { 918 } 920 catch (Exception e) { 921 System.err.println("JEditorPane.getCharsetFromContentTypeParameters failed on: " + paramlist); 923 e.printStackTrace(); 924 } 925 } 926 927 928 952 public void setEditorKit(EditorKit kit) { 953 EditorKit old = this.kit; 954 if (old != null) { 955 old.deinstall(this); 956 } 957 this.kit = kit; 958 if (this.kit != null) { 959 this.kit.install(this); 960 setDocument(this.kit.createDefaultDocument()); 961 } 962 firePropertyChange("editorKit", old, kit); 963 } 964 965 984 public EditorKit getEditorKitForContentType(String type) { 985 if (typeHandlers == null) { 986 typeHandlers = new Hashtable(3); 987 |