1 18 package org.apache.batik.apps.svgbrowser; 19 20 import java.awt.Dimension ; 21 import java.awt.event.ActionEvent ; 22 import java.awt.Font ; 23 import java.io.BufferedReader ; 24 import java.io.File ; 25 import java.io.FileWriter ; 26 import java.io.InputStreamReader ; 27 import java.io.IOException ; 28 import java.io.Reader ; 29 import java.io.UnsupportedEncodingException ; 30 import java.io.Writer ; 31 import java.net.Authenticator ; 32 import java.net.URLDecoder ; 33 import java.net.URLEncoder ; 34 import java.util.HashMap ; 35 import java.util.Iterator ; 36 import java.util.LinkedList ; 37 import java.util.List ; 38 import java.util.Locale ; 39 import java.util.Map ; 40 import java.util.ResourceBundle ; 41 import java.util.StringTokenizer ; 42 import java.util.Vector ; 43 44 import javax.swing.AbstractAction ; 45 import javax.swing.Action ; 46 import javax.swing.ImageIcon ; 47 import javax.swing.JOptionPane ; 48 import javax.swing.JProgressBar ; 49 import javax.swing.UIManager ; 50 import javax.swing.plaf.FontUIResource ; 51 52 import org.apache.batik.swing.JSVGCanvas; 53 import org.apache.batik.swing.gvt.GVTTreeRendererAdapter; 54 import org.apache.batik.swing.gvt.GVTTreeRendererEvent; 55 import org.apache.batik.swing.svg.GVTTreeBuilderAdapter; 56 import org.apache.batik.swing.svg.GVTTreeBuilderEvent; 57 import org.apache.batik.swing.svg.SVGDocumentLoaderAdapter; 58 import org.apache.batik.swing.svg.SVGDocumentLoaderEvent; 59 import org.apache.batik.util.ApplicationSecurityEnforcer; 60 import org.apache.batik.util.ParsedURL; 61 import org.apache.batik.util.SVGConstants; 62 import org.apache.batik.util.XMLResourceDescriptor; 63 import org.apache.batik.util.gui.resource.ResourceManager; 64 65 71 public class Main implements Application { 72 77 public static final String UNKNOWN_SCRIPT_TYPE_LOAD_KEY_EXTENSION 78 = ".load"; 79 80 83 public static final String PROPERTY_USER_HOME = "user.home"; 84 85 88 public static final String PROPERTY_JAVA_SECURITY_POLICY 89 = "java.security.policy"; 90 91 94 public static final String BATIK_CONFIGURATION_SUBDIRECTORY = ".batik"; 95 96 99 public static final String SQUIGGLE_CONFIGURATION_FILE = "preferences.xml"; 100 101 104 public static final String SQUIGGLE_POLICY_FILE = "__svgbrowser.policy"; 105 106 109 public static final String POLICY_GRANT_SCRIPT_NETWORK_ACCESS 110 = "grant {\n permission java.net.SocketPermission \"*\", \"listen, connect, resolve, accept\";\n};\n\n"; 111 112 115 public static final String POLICY_GRANT_SCRIPT_FILE_ACCESS 116 = "grant {\n permission java.io.FilePermission \"<<ALL FILES>>\", \"read\";\n};\n\n"; 117 118 121 public static final String PREFERENCE_KEY_VISITED_URI_LIST 122 = "preference.key.visited.uri.list"; 123 124 127 public static final String PREFERENCE_KEY_VISITED_URI_LIST_LENGTH 128 = "preference.key.visited.uri.list.length"; 129 130 134 public static final String URI_SEPARATOR = " "; 135 136 139 public static final String DEFAULT_DEFAULT_FONT_FAMILY 140 = "Arial, Helvetica, sans-serif"; 141 142 146 public static final String SVG_INITIALIZATION = "resources/init.svg"; 147 148 151 protected String svgInitializationURI; 152 153 157 public static void main(String [] args) { 158 new Main(args); 159 } 160 161 164 public final static String RESOURCES = 165 "org.apache.batik.apps.svgbrowser.resources.Main"; 166 167 170 public static final String SQUIGGLE_SECURITY_POLICY 171 = "org/apache/batik/apps/svgbrowser/resources/svgbrowser.policy"; 172 173 176 protected static ResourceBundle bundle; 177 178 181 protected static ResourceManager resources; 182 static { 183 bundle = ResourceBundle.getBundle(RESOURCES, Locale.getDefault()); 184 resources = new ResourceManager(bundle); 185 } 186 187 190 protected static ImageIcon frameIcon = new ImageIcon 191 (Main.class.getResource(resources.getString("Frame.icon"))); 192 193 196 protected XMLPreferenceManager preferenceManager; 197 198 201 public static final int MAX_VISITED_URIS = 10; 202 203 206 protected Vector lastVisited = new Vector (); 207 208 211 protected int maxVisitedURIs = MAX_VISITED_URIS; 212 213 216 protected String [] arguments; 217 218 224 protected boolean overrideSecurityPolicy = false; 225 226 230 protected ApplicationSecurityEnforcer securityEnforcer; 231 232 235 protected Map handlers = new HashMap (); 236 { 237 handlers.put("-font-size", new FontSizeHandler()); 238 } 239 240 243 protected List viewerFrames = new LinkedList (); 244 245 248 protected PreferenceDialog preferenceDialog; 249 250 254 public Main(String [] args) { 255 arguments = args; 256 257 Map defaults = new HashMap (11); 261 262 defaults.put(PreferenceDialog.PREFERENCE_KEY_LANGUAGES, 263 Locale.getDefault().getLanguage()); 264 defaults.put(PreferenceDialog.PREFERENCE_KEY_SHOW_RENDERING, 265 Boolean.FALSE); 266 defaults.put(PreferenceDialog.PREFERENCE_KEY_AUTO_ADJUST_WINDOW, 267 Boolean.TRUE); 268 defaults.put(PreferenceDialog.PREFERENCE_KEY_SELECTION_XOR_MODE, 269 Boolean.FALSE); 270 defaults.put(PreferenceDialog.PREFERENCE_KEY_ENABLE_DOUBLE_BUFFERING, 271 Boolean.TRUE); 272 defaults.put(PreferenceDialog.PREFERENCE_KEY_SHOW_DEBUG_TRACE, 273 Boolean.FALSE); 274 defaults.put(PreferenceDialog.PREFERENCE_KEY_PROXY_HOST, 275 ""); 276 defaults.put(PreferenceDialog.PREFERENCE_KEY_PROXY_PORT, 277 ""); 278 defaults.put(PreferenceDialog.PREFERENCE_KEY_CSS_MEDIA, 279 "screen"); 280 defaults.put(PreferenceDialog.PREFERENCE_KEY_DEFAULT_FONT_FAMILY, 281 DEFAULT_DEFAULT_FONT_FAMILY); 282 defaults.put(PreferenceDialog.PREFERENCE_KEY_IS_XML_PARSER_VALIDATING, 283 Boolean.FALSE); 284 defaults.put(PreferenceDialog.PREFERENCE_KEY_ENFORCE_SECURE_SCRIPTING, 285 Boolean.TRUE); 286 defaults.put(PreferenceDialog.PREFERENCE_KEY_GRANT_SCRIPT_FILE_ACCESS, 287 Boolean.FALSE); 288 defaults.put(PreferenceDialog.PREFERENCE_KEY_GRANT_SCRIPT_NETWORK_ACCESS, 289 Boolean.FALSE); 290 defaults.put(PreferenceDialog.PREFERENCE_KEY_LOAD_JAVA, 291 Boolean.TRUE); 292 defaults.put(PreferenceDialog.PREFERENCE_KEY_LOAD_ECMASCRIPT, 293 Boolean.TRUE); 294 defaults.put(PreferenceDialog.PREFERENCE_KEY_ALLOWED_SCRIPT_ORIGIN, 295 new Integer (ResourceOrigin.DOCUMENT)); 296 defaults.put(PreferenceDialog.PREFERENCE_KEY_ALLOWED_EXTERNAL_RESOURCE_ORIGIN, 297 new Integer (ResourceOrigin.ANY)); 298 defaults.put(PREFERENCE_KEY_VISITED_URI_LIST, 299 ""); 300 defaults.put(PREFERENCE_KEY_VISITED_URI_LIST_LENGTH, 301 new Integer (MAX_VISITED_URIS)); 302 303 securityEnforcer 304 = new ApplicationSecurityEnforcer(this.getClass(), 305 SQUIGGLE_SECURITY_POLICY); 306 307 try { 308 preferenceManager = new XMLPreferenceManager(SQUIGGLE_CONFIGURATION_FILE, 309 defaults); 310 String dir = System.getProperty(PROPERTY_USER_HOME); 311 File f = new File (dir, BATIK_CONFIGURATION_SUBDIRECTORY); 312 f.mkdir(); 313 XMLPreferenceManager.setPreferenceDirectory(f.getCanonicalPath()); 314 preferenceManager.load(); 315 setPreferences(); 316 initializeLastVisited(); 317 Authenticator.setDefault(new JAuthenticator()); 318 } catch (Exception e) { 319 e.printStackTrace(); 320 } 321 322 final AboutDialog initDialog = new AboutDialog(); 326 final JProgressBar pb = new JProgressBar (0, 3); 327 initDialog.getContentPane().add("South", pb); 328 329 Dimension ss = initDialog.getToolkit().getScreenSize(); 331 Dimension ds = initDialog.getPreferredSize(); 332 333 initDialog.setLocation((ss.width - ds.width) / 2, 334 (ss.height - ds.height) / 2); 335 336 initDialog.setSize(ds); 337 initDialog.setVisible(true); 338 339 final JSVGViewerFrame v = new JSVGViewerFrame(this); 340 JSVGCanvas c = v.getJSVGCanvas(); 341 c.addSVGDocumentLoaderListener(new SVGDocumentLoaderAdapter() { 342 public void documentLoadingStarted(SVGDocumentLoaderEvent e) { 343 pb.setValue(1); 344 } 345 public void documentLoadingCompleted(SVGDocumentLoaderEvent e) { 346 pb.setValue(2); 347 } 348 }); 349 c.addGVTTreeBuilderListener(new GVTTreeBuilderAdapter() { 350 public void gvtBuildCompleted(GVTTreeBuilderEvent e) { 351 pb.setValue(3); 352 } 353 }); 354 c.addGVTTreeRendererListener(new GVTTreeRendererAdapter() { 355 public void gvtRenderingCompleted(GVTTreeRendererEvent e) { 356 initDialog.dispose(); 357 v.dispose(); 358 System.gc(); 359 run(); 360 } 361 }); 362 363 c.setSize(100, 100); 364 svgInitializationURI = Main.class.getResource(SVG_INITIALIZATION).toString(); 365 c.loadSVGDocument(svgInitializationURI); 366 } 367 368 372 public void installCustomPolicyFile() throws IOException { 373 String securityPolicyProperty 374 = System.getProperty(PROPERTY_JAVA_SECURITY_POLICY); 375 376 if (overrideSecurityPolicy 377 || 378 securityPolicyProperty == null 379 || 380 "".equals(securityPolicyProperty)) { 381 ParsedURL policyURL = new ParsedURL(securityEnforcer.getPolicyURL()); 383 384 String dir = System.getProperty(PROPERTY_USER_HOME); 386 File batikConfigDir = new File (dir, BATIK_CONFIGURATION_SUBDIRECTORY); 387 File policyFile = new File (batikConfigDir, SQUIGGLE_POLICY_FILE); 388 389 Reader r = new BufferedReader (new InputStreamReader (policyURL.openStream())); 391 Writer w = new FileWriter (policyFile); 392 393 char[] buf = new char[1024]; 394 int n = 0; 395 while ( (n=r.read(buf, 0, buf.length)) != -1 ) { 396 w.write(buf, 0, n); 397 } 398 399 r.close(); 400 401 boolean grantScriptNetworkAccess 404 = preferenceManager.getBoolean 405 (PreferenceDialog.PREFERENCE_KEY_GRANT_SCRIPT_NETWORK_ACCESS); 406 boolean grantScriptFileAccess 407 = preferenceManager.getBoolean 408 (PreferenceDialog.PREFERENCE_KEY_GRANT_SCRIPT_FILE_ACCESS); 409 410 if (grantScriptNetworkAccess) { 411 w.write(POLICY_GRANT_SCRIPT_NETWORK_ACCESS); 412 } 413 414 if (grantScriptFileAccess) { 415 w.write(POLICY_GRANT_SCRIPT_FILE_ACCESS); 416 } 417 418 w.close(); 419 420 overrideSecurityPolicy = true; 423 424 System.setProperty(PROPERTY_JAVA_SECURITY_POLICY, 425 policyFile.toURL().toString()); 426 427 } 428 } 429 430 433 public void run() { 434 try { 435 int i = 0; 436 437 for (; i < arguments.length; i++) { 438 OptionHandler oh = (OptionHandler)handlers.get(arguments[i]); 439 if (oh == null) { 440 break; 441 } 442 i = oh.handleOption(i); 443 } 444 445 JSVGViewerFrame frame = createAndShowJSVGViewerFrame(); 446 while (i < arguments.length) { 447 if (arguments[i].length() == 0) { 448 i++; 449 continue; 450 } 451 452 File file = new File (arguments[i]); 453 String uri = null; 454 455 try{ 456 if (file.canRead()) { 457 uri = file.toURL().toString(); 458 } 459 }catch(SecurityException se){ 460 } 462 463 if(uri == null){ 464 uri = arguments[i]; 465 ParsedURL purl = null; 466 purl = new ParsedURL(arguments[i]); 467 468 if (!purl.complete()) 469 uri = null; 471 } 472 473 if (uri != null) { 474 if (frame == null) 475 frame = createAndShowJSVGViewerFrame(); 476 477 frame.showSVGDocument(uri); 478 frame = null; 479 } else { 480 483 486 JOptionPane.showMessageDialog 490 (frame, 491 resources.getString("Error.skipping.file") 492 + arguments[i]); 493 } 494 i++; 495 } 496 } catch (Exception e) { 497 e.printStackTrace(); 498 printUsage(); 499 } 500 } 501 502 505 protected void printUsage() { 506 System.out.println(); 507 508 System.out.println(resources.getString("Command.header")); 509 System.out.println(resources.getString("Command.syntax")); 510 System.out.println(); 511 System.out.println(resources.getString("Command.options")); 512 Iterator it = handlers.keySet().iterator(); 513 while (it.hasNext()) { 514 String s = (String )it.next(); 515 System.out.println(((OptionHandler)handlers.get(s)).getDescription()); 516 } 517 } 518 519 522 protected interface OptionHandler { 523 527 int handleOption(int i); 528 529 532 String getDescription(); 533 } 534 535 538 protected class FontSizeHandler implements OptionHandler { 539 public int handleOption(int i) { 540 int size = Integer.parseInt(arguments[++i]); 541 542 Font font = new Font ("Dialog", Font.PLAIN, size); 543 FontUIResource fontRes = new FontUIResource (font); 544 UIManager.put("CheckBox.font", fontRes); 545 UIManager.put("PopupMenu.font", fontRes); 546 UIManager.put("TextPane.font", fontRes); 547 UIManager.put("MenuItem.font", fontRes); 548 UIManager.put("ComboBox.font", fontRes); 549 UIManager.put("Button.font", fontRes); 550 UIManager.put("Tree.font", fontRes); 551 UIManager.put("ScrollPane.font", fontRes); 552 UIManager.put("TabbedPane.font", fontRes); 553 UIManager.put("EditorPane.font", fontRes); 554 UIManager.put("TitledBorder.font", fontRes); 555 UIManager.put("Menu.font", fontRes); 556 UIManager.put("TextArea.font", fontRes); 557 UIManager.put("OptionPane.font", fontRes); 558 UIManager.put("DesktopIcon.font", fontRes); 559 UIManager.put("MenuBar.font", fontRes); 560 UIManager.put("ToolBar.font", fontRes); 561 UIManager.put("RadioButton.font", fontRes); 562 UIManager.put("RadioButtonMenuItem.font", fontRes); 563 UIManager.put("ToggleButton.font", fontRes); 564 UIManager.put("ToolTip.font", fontRes); 565 UIManager.put("ProgressBar.font", fontRes); 566 UIManager.put("TableHeader.font", fontRes); 567 UIManager.put("Panel.font", fontRes); 568 UIManager.put("List.font", fontRes); 569 UIManager.put("ColorChooser.font", fontRes); 570 UIManager.put("PasswordField.font", fontRes); 571 UIManager.put("TextField.font", fontRes); 572 UIManager.put("Table.font", fontRes); 573 UIManager.put("Label.font", fontRes); 574 UIManager.put("InternalFrameTitlePane.font", fontRes); 575 UIManager.put("CheckBoxMenuItem.font", fontRes); 576 577 return i; 578 } 579 public String getDescription() { 580 return resources.getString("Command.font-size"); 581 } 582 } 583 584 586 589 public JSVGViewerFrame createAndShowJSVGViewerFrame() { 590 JSVGViewerFrame mainFrame = new JSVGViewerFrame(this); 591 mainFrame.setSize(resources.getInteger("Frame.width"), 592 resources.getInteger("Frame.height")); 593 mainFrame.setIconImage(frameIcon.getImage()); 594 mainFrame.setTitle(resources.getString("Frame.title")); 595 mainFrame.setVisible(true); 596 viewerFrames.add(mainFrame); 597 setPreferences(mainFrame); 598 return mainFrame; 599 } 600 601 604 public void closeJSVGViewerFrame(JSVGViewerFrame f) { 605 f.getJSVGCanvas().stopProcessing(); 606 viewerFrames.remove(f); 607 if (viewerFrames.size() == 0) { 608 System.exit(0); 609 } 610 f.dispose(); 611 } 612 613 616 public Action createExitAction(JSVGViewerFrame vf) { 617 return new AbstractAction () { 618 public void actionPerformed(ActionEvent e) { 619 System.exit(0); 620 } 621 }; 622 } 623 624 627 public void openLink(String url) { 628 JSVGViewerFrame f = createAndShowJSVGViewerFrame(); 629 f.getJSVGCanvas().loadSVGDocument(url); 630 } 631 632 635 public String getXMLParserClassName() { 636 return XMLResourceDescriptor.getXMLParserClassName(); 637 } 638 639 643 public boolean isXMLParserValidating() { 644 return preferenceManager.getBoolean 645 (PreferenceDialog.PREFERENCE_KEY_IS_XML_PARSER_VALIDATING); 646 } 647 648 651 public void showPreferenceDialog(JSVGViewerFrame f) { 652 if (preferenceDialog == null) { 653 preferenceDialog = new PreferenceDialog(preferenceManager); 654 } 655 if (preferenceDialog.showDialog() == PreferenceDialog.OK_OPTION) { 656 try { 657 preferenceManager.save(); 658 setPreferences(); 659 } catch (Exception e) { 660 } 661 } 662 } 663 664 private void setPreferences() throws IOException { 665 Iterator it = viewerFrames.iterator(); 666 while (it.hasNext()) { 667 setPreferences((JSVGViewerFrame)it.next()); 668 } 669 670 System.setProperty("proxyHost", preferenceManager.getString 671 (PreferenceDialog.PREFERENCE_KEY_PROXY_HOST)); 672 System.setProperty("proxyPort", preferenceManager.getString 673 (PreferenceDialog.PREFERENCE_KEY_PROXY_PORT)); 674 675 installCustomPolicyFile(); 676 677 securityEnforcer.enforceSecurity 678 (preferenceManager.getBoolean 679 (PreferenceDialog.PREFERENCE_KEY_ENFORCE_SECURE_SCRIPTING) 680 ); 681 682 } 683 684 private void setPreferences(JSVGViewerFrame vf) { 685 boolean db = preferenceManager.getBoolean 686 (PreferenceDialog.PREFERENCE_KEY_ENABLE_DOUBLE_BUFFERING); 687 vf.getJSVGCanvas().setDoubleBufferedRendering(db); 688 boolean sr = preferenceManager.getBoolean 689 (PreferenceDialog.PREFERENCE_KEY_SHOW_RENDERING); 690 vf.getJSVGCanvas().setProgressivePaint(sr); 691 boolean d = preferenceManager.getBoolean 692 (PreferenceDialog.PREFERENCE_KEY_SHOW_DEBUG_TRACE); 693 vf.setDebug(d); 694 boolean aa = preferenceManager.getBoolean 695 (PreferenceDialog.PREFERENCE_KEY_AUTO_ADJUST_WINDOW); 696 vf.setAutoAdjust(aa); 697 boolean dd = preferenceManager.getBoolean 698 (PreferenceDialog.PREFERENCE_KEY_SELECTION_XOR_MODE); 699 vf.getJSVGCanvas().setSelectionOverlayXORMode(dd); 700 } 701 702 705 public String getLanguages() { 706 String s = preferenceManager.getString 707 (PreferenceDialog.PREFERENCE_KEY_LANGUAGES); 708 return (s == null) 709 ? Locale.getDefault().getLanguage() 710 : s; 711 } 712 713 717 public String getUserStyleSheetURI() { 718 return preferenceManager.getString 719 (PreferenceDialog.PREFERENCE_KEY_USER_STYLESHEET); 720 } 721 722 726 public String getDefaultFontFamily() { 727 return preferenceManager.getString 728 (PreferenceDialog.PREFERENCE_KEY_DEFAULT_FONT_FAMILY); 729 } 730 731 735 public String getMedia() { 736 String s = preferenceManager.getString 737 (PreferenceDialog.PREFERENCE_KEY_CSS_MEDIA); 738 return (s == null) ? "screen" : s; 739 } 740 741 745 public boolean isSelectionOverlayXORMode() { 746 return preferenceManager.getBoolean 747 (PreferenceDialog.PREFERENCE_KEY_SELECTION_XOR_MODE); 748 } 749 750 754 public boolean canLoadScriptType(String scriptType){ 755 if (SVGConstants.SVG_SCRIPT_TYPE_ECMASCRIPT.equals(scriptType)){ 756 return preferenceManager.getBoolean 757 (PreferenceDialog.PREFERENCE_KEY_LOAD_ECMASCRIPT); 758 } else if (SVGConstants.SVG_SCRIPT_TYPE_JAVA.equals(scriptType)){ 759 return preferenceManager.getBoolean 760 (PreferenceDialog.PREFERENCE_KEY_LOAD_JAVA); 761 } else { 762 return preferenceManager.getBoolean 763 (scriptType + UNKNOWN_SCRIPT_TYPE_LOAD_KEY_EXTENSION); 764 } 765 } 766 767 771 public int getAllowedScriptOrigin() { 772 int ret = preferenceManager.getInteger 773 (PreferenceDialog.PREFERENCE_KEY_ALLOWED_SCRIPT_ORIGIN); 774 775 return ret; 776 } 777 778 783 public int getAllowedExternalResourceOrigin() { 784 int ret = preferenceManager.getInteger 785 (PreferenceDialog.PREFERENCE_KEY_ALLOWED_EXTERNAL_RESOURCE_ORIGIN); 786 787 return ret; 788 } 789 790 793 public void addVisitedURI(String uri) { 794 if(svgInitializationURI.equals(uri)) { 795 return; 796 } 797 798 int maxVisitedURIs = 799 preferenceManager.getInteger 800 (PREFERENCE_KEY_VISITED_URI_LIST_LENGTH); 801 802 if (maxVisitedURIs < 0) { 803 maxVisitedURIs = 0; 804 } 805 806 if (lastVisited.contains(uri)) { 807 lastVisited.removeElement(uri); 808 } 809 810 while (lastVisited.size() > 0 && lastVisited.size() > (maxVisitedURIs-1)) { 811 lastVisited.removeElementAt(0); 812 } 813 814 if (maxVisitedURIs > 0) { 815 lastVisited.addElement(uri); 816 } 817 818 StringBuffer lastVisitedBuffer = new StringBuffer (); 820 821 for (int i=0; i<lastVisited.size(); i++) { 822 lastVisitedBuffer.append 823 (URLEncoder.encode(lastVisited.elementAt(i).toString())); 824 lastVisitedBuffer.append(URI_SEPARATOR); 825 } 826 827 preferenceManager.setString 828 (PREFERENCE_KEY_VISITED_URI_LIST, 829 lastVisitedBuffer.toString()); 830 831 try { 832 preferenceManager.save(); 833 } catch (Exception e) { 834 } 836 } 837 838 841 public String [] getVisitedURIs() { 842 String [] visitedURIs = new String [lastVisited.size()]; 843 lastVisited.copyInto(visitedURIs); 844 return visitedURIs; 845 } 846 847 850 protected void initializeLastVisited(){ 851 String lastVisitedStr 852 = preferenceManager.getString(PREFERENCE_KEY_VISITED_URI_LIST); 853 854 StringTokenizer st 855 = new StringTokenizer (lastVisitedStr, 856 URI_SEPARATOR); 857 858 int n = st.countTokens(); 859 860 int maxVisitedURIs 861 = preferenceManager.getInteger 862 (PREFERENCE_KEY_VISITED_URI_LIST_LENGTH); 863 864 if (n > maxVisitedURIs) { 865 n = maxVisitedURIs; 866 } 867 868 for (int i=0; i<n; i++) { 869 lastVisited.addElement(URLDecoder.decode(st.nextToken())); 870 } 871 } 872 } 873 | Popular Tags |