1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.xnap.plugin.overnet;
21
22 import java.awt.event.KeyEvent;
23 import java.io.File;
24 import java.io.IOException;
25 import java.util.List;
26 import javax.help.HelpSet;
27 import javax.swing.Action;
28 import javax.swing.Icon;
29 import javax.swing.JComponent;
30 import javax.swing.JMenu;
31 import org.apache.log4j.Logger;
32 import org.xnap.XNap;
33 import org.xnap.XNapFacade;
34 import org.xnap.action.AbstractXNapAction;
35 import org.xnap.event.StateEvent;
36 import org.xnap.event.StateListener;
37 import org.xnap.gui.AbstractPreferencesDialog;
38 import org.xnap.gui.DefaultPrefsWizardDialog;
39 import org.xnap.gui.StatusBar;
40 import org.xnap.gui.XNapFrame;
41 import org.xnap.gui.action.FocusAction;
42 import org.xnap.gui.component.XNapMenu;
43 import org.xnap.gui.component.XNapMenuItem;
44 import org.xnap.gui.event.AbstractPreferencesDialogListener;
45 import org.xnap.gui.shortcut.ActionShortcut;
46 import org.xnap.gui.shortcut.ShortcutManager;
47 import org.xnap.gui.util.GUIHelper;
48 import org.xnap.gui.util.IconHelper;
49 import org.xnap.plugin.AbstractPlugin;
50 import org.xnap.plugin.overnet.gui.OvernetPanel;
51 import org.xnap.plugin.overnet.gui.OvernetPreferencesPanel;
52 import org.xnap.plugin.overnet.gui.OvernetStatusPanel;
53 import org.xnap.plugin.overnet.gui.action.ConnectAction;
54 import org.xnap.plugin.overnet.gui.action.DisconnectAction;
55 import org.xnap.plugin.overnet.gui.action.DownloadLinkAction;
56 import org.xnap.plugin.overnet.net.DownloadTable;
57 import org.xnap.plugin.overnet.net.OvernetCore;
58 import org.xnap.plugin.overnet.net.OvernetSearch;
59 import org.xnap.plugin.overnet.net.UploadTable;
60 import org.xnap.plugin.overnet.net.msg.MessageHandler;
61 import org.xnap.plugin.overnet.net.msg.client.StopMessage;
62 import org.xnap.plugin.overnet.util.OvernetPreferences;
63 import org.xnap.search.MediaType;
64 import org.xnap.search.Search;
65 import org.xnap.search.SearchFilter;
66 import org.xnap.search.SearchManager;
67 import org.xnap.search.SearchProvider;
68 import org.xnap.util.State;
69 import org.xnap.util.VersionParser;
70
71 /***
72 * Provides a plugin that can control an overnet core.
73 *
74 * <p>OvernetPlugin follows the singleton pattern.
75 */
76 public class OvernetPlugin extends AbstractPlugin
77 implements SearchProvider, StateListener
78 {
79
80
81
82 public static final String ICON_FILENAME = "toolbar-overnet-logo.png";
83
84 public static final Icon ICON_16 = IconHelper.getIcon(ICON_FILENAME, 16,
85 false);
86
87 public static final String NEW_COMMANDLINE_VERSION = "overnet0.51.2";
88
89 public static final String OLD_COMMANDLINE_OPTION = "-";
90
91 public static final String NEW_COMMANDLINE_OPTION = "-g";
92
93 /***
94 * The plugin's instance.
95 */
96 private static OvernetPlugin instance = null;
97 /***
98 * Handles Messagelisteners.
99 */
100 private MessageHandler messageHandler;
101 /***
102 * Used plugin-internally to map status messages to the corresponding
103 * uploads.
104 */
105 private UploadTable uploadTable;
106 /***
107 * Used plugin-internally to map status messages to the corresponding
108 * downloads.
109 */
110 private DownloadTable downloadTable;
111 /***
112 * Holds the connection to the core. Does all the sending and receiving of
113 * messages.
114 */
115 private OvernetCore core;
116 /***
117 * Holds the core process if the core was started from within the plugin.
118 */
119 private Process coreProcess = null;
120 /***
121 * Is notified when the preferences dialog becomes visible and adds the
122 * plugin's dialog.
123 */
124 private PreferencesDialogListener listener;
125 /***
126 * Menu plugged into XNap's plugins menu.
127 */
128 private JMenu jmOvernet;
129 /***
130 * The overnet gui panel.
131 */
132 private OvernetPanel jpOvernet;
133 /***
134 * The overnet status panel.
135 */
136 private OvernetStatusPanel spOvernet;
137 /***
138 * Overnet's manual helpset. Not used yet.
139 */
140 private HelpSet hs;
141 /***
142 * The shortcut for switching to the overnet panel.
143 */
144 private ActionShortcut focusShortcut;
145
146 private static Logger logger = Logger.getLogger(OvernetPlugin.class);
147
148
149
150 public OvernetPlugin()
151 {
152 }
153
154
155
156 public OvernetCore getCore()
157 {
158 return core;
159 }
160
161 public static OvernetPlugin getInstance()
162 {
163 return instance;
164 }
165
166 public String getName()
167 {
168 return getInfo().getName();
169 }
170
171 public void start()
172 {
173 instance = this;
174 messageHandler = new MessageHandler();
175 downloadTable = new DownloadTable();
176 uploadTable = new UploadTable();
177
178 OvernetPreferences.getInstance();
179
180 core = new OvernetCore(messageHandler);
181 core.addStateListener(this);
182
183 startCoreConnection();
184 }
185
186 public void startGUI()
187 {
188 listener = new PreferencesDialogListener();
189 XNapFacade.addPluginPreferencesDialogListener(listener);
190
191 initializeMenu();
192 XNapFrame.getInstance().getMainMenuBar().addPluginMenu(jmOvernet);
193
194 jpOvernet = new OvernetPanel();
195 jpOvernet.setName("overnet");
196 XNapFrame.getInstance().insertTab
197 (getName(), IconHelper.getListIcon(ICON_FILENAME), jpOvernet);
198
199 spOvernet = new OvernetStatusPanel();
200 core.addStateListener(spOvernet);
201 StatusBar.getInstance().addComponent(spOvernet);
202
203
204 FocusAction fa = new FocusAction();
205 fa.putValue(Action.NAME, XNap.tr("Overnet"));
206 fa.putValue(Action.SHORT_DESCRIPTION,
207 XNap.tr("Switches to Overnet panel"));
208 fa.putValue(Action.ACTION_COMMAND_KEY, "overnet");
209 fa.putValue(IconHelper.XNAP_ICON, ICON_FILENAME);
210 fa.putValue(AbstractXNapAction.DEFAULT_KEYSTROKE,
211 GUIHelper.getMenuKeyStroke(KeyEvent.VK_O));
212 focusShortcut = ShortcutManager.getInstance().add
213 (fa, (JComponent)XNapFrame.getInstance().getContentPane(),
214 OvernetPreferences.getInstance());
215
216
217
218 if (!OvernetPreferences.getInstance().getBoolean("seenStartupWizard")) {
219 DefaultPrefsWizardDialog dfd
220 = new DefaultPrefsWizardDialog(OvernetPreferences.getInstance(),
221 "seenStartupWizard");
222 dfd.addPanel(new OvernetPreferencesPanel());
223 dfd.pack();
224 dfd.show(XNapFrame.getInstance());
225 }
226
227
228
229 }
230
231 /***
232 * Starts a core process if the core command is specified in the
233 * preferences.
234 */
235 private void startCoreConnection()
236 {
237 OvernetPreferences prefs = OvernetPreferences.getInstance();
238 String command = prefs.getCoreCommand();
239
240 if (prefs.getStartCore() && command.length() > 0) {
241 String[] args = new String[]
242 { command,
243 prefs.getUseCustomCommandLineOption() ?
244 prefs.getCommandLineOption()
245 : getCommandLineOptions(command) };
246 try {
247 logger.debug("launching core " + command + " " + args[1]);
248 coreProcess = Runtime.getRuntime().exec
249 (args, null, (new File(command)).getParentFile());
250 }
251 catch (IOException ie) {
252 logger.debug("Could not launch core", ie);
253 }
254 }
255
256
257 core.connect(prefs.getStartCore() ? 5 * 1000 : 0);
258 }
259
260 public static String getCommandLineOptions(String command)
261 {
262 String core = new File(command).getName();
263 return VersionParser.compare(core, NEW_COMMANDLINE_VERSION) < 0 ?
264 OLD_COMMANDLINE_OPTION : NEW_COMMANDLINE_OPTION;
265 }
266
267 /***
268 * Closes the core connection and kills the core process if it was started
269 * from within the plugin.
270 */
271 private void stopCoreConnection()
272 {
273 if (coreProcess != null) {
274 if (core.getState() == State.CONNECTED) {
275 OvernetCore.send(new StopMessage());
276 }
277 core.stop();
278 coreProcess.destroy();
279 coreProcess = null;
280 }
281 else {
282 core.stop();
283 }
284
285 core.removeStateListener(this);
286 core = null;
287 }
288
289 private void initializeMenu()
290 {
291 jmOvernet = new XNapMenu(getName());
292 jmOvernet.setIcon(IconHelper.getMenuIcon(ICON_FILENAME));
293 jmOvernet.add(new XNapMenuItem(new ConnectAction()));
294 jmOvernet.add(new XNapMenuItem(new DisconnectAction()));
295 jmOvernet.addSeparator();
296 jmOvernet.add(new XNapMenuItem(new DownloadLinkAction()));
297 }
298
299 public static MessageHandler getMessageHandler()
300 {
301 return instance.messageHandler;
302 }
303
304 /***
305 * Implements the {@link StateListener} interface.
306 */
307 public void stateChanged(StateEvent event)
308 {
309 if (core.getState() == State.DISCONNECTED) {
310 disposeTransfers();
311 }
312 }
313
314 private void disposeTransfers()
315 {
316 downloadTable.dispose();
317 uploadTable.dispose();
318 }
319
320 public void stop()
321 {
322 stopCoreConnection();
323
324 disposeTransfers();
325
326
327
328
329 OvernetPreferences.disposeInstance();
330
331
332 }
333
334 public void stopGUI()
335 {
336 listener.dispose();
337 XNapFacade.removePluginPreferencesDialogListener(listener);
338 listener = null;
339
340 XNapFrame.getInstance().getMainMenuBar().removePluginMenu(jmOvernet);
341 jmOvernet = null;
342
343 XNapFrame.getInstance().removeTab(jpOvernet);
344 jpOvernet.dispose();
345 jpOvernet = null;
346
347 StatusBar.getInstance().removeComponent(spOvernet);
348 core.removeStateListener(spOvernet);
349 spOvernet = null;
350
351 ShortcutManager.getInstance().remove
352 (focusShortcut, (JComponent)XNapFrame.getInstance().getContentPane());
353
354
355
356 }
357
358 public MediaType[] getSupportedMediaTypes()
359 {
360 return new MediaType[] { SearchManager.MEDIA_ANYTHING };
361 }
362
363 public Search search(SearchFilter filter)
364 {
365 return new OvernetSearch(filter);
366 }
367
368
369
370 private class PreferencesDialogListener
371 extends AbstractPreferencesDialogListener
372 {
373 public void addPanels(AbstractPreferencesDialog dialog, List panels)
374 {
375 OvernetPreferencesPanel opp = new OvernetPreferencesPanel();
376 panels.add(opp);
377 panels.add(dialog.addPanel(opp, ICON_FILENAME));
378 }
379 }
380 }
381
382