Source code: com/fm/gui/fmHyperlinkRouter.java
1 /****************************************************************************
2 * Copyright (c) 2003 Andrew Duka | aduka@users.sourceforge.net
3 * All right reserved.
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
9 *
10 ****************************************************************************/
11 package com.fm.gui;
12
13 import javax.swing.event.HyperlinkListener;
14 import javax.swing.event.HyperlinkEvent;
15 import javax.swing.*;
16 import java.io.IOException;
17 import java.net.UnknownHostException;
18 import java.util.ResourceBundle;
19 import java.util.HashMap;
20 import java.util.Iterator;
21
22 /**
23 * Entities of class handle hyperlink events within GUI components.
24 *
25 * <p>The <code>fmHyperlinkRouter</code> serves as a hyperlink event router.
26 * Entities of the class handle link update event, then scan own table of
27 * prefix handlers and if URL starts with one of prefixes defined in this table
28 * the event is routed to appropriate prefix handler handler. If no prefix
29 * handler is defined the URL will be served by external or internal
30 * browser respectively.</p>
31 *
32 * <p>The prefix handler is a <code>HyperLinkListener</code> entity, which
33 * performs some specific operations with link which starts with handler
34 * specific prefix.</p>
35 *
36 * <p>It's assumed that only one handler for the prefix exists in the router
37 * configuration. This is done to avoid overlapped actions of handlers of the
38 * same type</p>
39 *
40 */
41 public class fmHyperlinkRouter implements HyperlinkListener
42 {
43 private String browserCmd;
44 private HashMap prefixHandlers;
45
46 /**
47 * Constructor.
48 *
49 * <p>If extCmd is null then editor component will handle URL by using
50 * <code>setPage</code> method of the <code>JEditorPane</code> component.</p>
51 *
52 * @param extCmd
53 */
54 public fmHyperlinkRouter(String extCmd)
55 {
56 browserCmd = extCmd;
57 prefixHandlers = new HashMap();
58 }
59
60 /**
61 * Constructor.
62 *
63 * <p>If extCmd is null then editor component will handle URL by using
64 * <code>setPage</code> method of the <code>JEditorPane</code> component.</p>
65 *
66 * @param extCmd
67 * @param handlers HashMap with protocol handlers
68 */
69 public fmHyperlinkRouter(String extCmd, HashMap handlers)
70 {
71 browserCmd = extCmd;
72 prefixHandlers = handlers;
73 }
74
75 /**
76 * Called when a hypertext link is updated.
77 *
78 * @param e the event responsible for the update
79 */
80 public void hyperlinkUpdate(HyperlinkEvent e)
81 {
82 if (e.getEventType() == HyperlinkEvent.EventType.ACTIVATED)
83 {
84 ResourceBundle locals = fmUITheme.getLocalizedStrings();
85
86 // Do nothing on empty URL
87 if (e.getURL() == null)
88 {
89 JOptionPane.showMessageDialog(null,
90 locals.getString("msg.cant_display_page") +
91 ": " + locals.getString("msg.undefined"),
92 locals.getString("label.error"),
93 JOptionPane.ERROR_MESSAGE);
94 return;
95 }
96
97 // looking for handlers
98 String url = e.getURL().toString();
99 // Situation then one prefix is overlapped by longer prefix is surely
100 // possible. To avoid missunderstandings the longest matched prefix
101 // will be used as a key
102 String pretender = new String("");
103 String t;
104 for (Iterator i = prefixHandlers.keySet().iterator(); i.hasNext();)
105 {
106 t = (String) i.next();
107 if (url.startsWith(t) && (t.length() > pretender.length()))
108 pretender = t;
109 }
110 // Routing event if handler is found
111 if (pretender.length() > 0) {
112 HyperlinkListener l = (HyperlinkListener)prefixHandlers.get(pretender);
113 l.hyperlinkUpdate(e);
114 return;
115 }
116
117 // redirecting to browsers
118 try
119 {
120 if (browserCmd == null) { // use external handling
121 ((JEditorPane)e.getSource()).setPage(e.getURL());
122 }
123 else {
124 try {
125 String resCmd = browserCmd.replaceAll("%url",e.getURL().toString());
126 Runtime.getRuntime().exec(resCmd);
127
128 }
129 catch (IOException ioe) {
130 ioe.printStackTrace();
131
132 JOptionPane.showMessageDialog(null,
133 locals.getString("msg.cant_run_external_browser"),
134 locals.getString("label.error"),
135 JOptionPane.ERROR_MESSAGE);
136 }
137 }
138 }
139 catch (UnknownHostException uhe)
140 {
141 uhe.printStackTrace();
142 JOptionPane.showMessageDialog(null,
143 locals.getString("msg.cant_resolve_host") +
144 ": " + ((e.getURL().getHost() == null) ? locals.getString("msg.undefined") :
145 e.getURL().getHost()),
146 locals.getString("label.error"),
147 JOptionPane.ERROR_MESSAGE);
148 }
149 catch (IOException ioe)
150 {
151 ioe.printStackTrace();
152
153 JOptionPane.showMessageDialog(null,
154 locals.getString("msg.cant_display_page") +
155 ": " + ((e.getURL() == null) ?
156 locals.getString("msg.undefined") : e.getURL().toString()),
157 locals.getString("label.error"),
158 JOptionPane.ERROR_MESSAGE);
159 }
160 }
161 }
162
163 /**
164 * Set handler for prefix
165 *
166 * <p>Note tha new handler always replaces existing if any.</p>
167 *
168 * @param prefix Prefix string (e.g. http://import/, ftp://)
169 * @param handler HyperlinkListener entity which will handle specified proto
170 */
171 public void setPrefixHandler(String prefix, HyperlinkListener handler)
172 {
173 prefixHandlers.put(prefix, handler);
174 }
175
176 /**
177 * Set browser's command
178 *
179 * @param brCmd New browser command
180 */
181 public void setBrowserCommand(String brCmd)
182 {
183 browserCmd = brCmd;
184 }
185 }