Source code: plugins/CsBeagle/CsBeagle.java
1 /*
2 This file is part of DeXter - Java Internet Communication Solution
3 Copyright (c) 2002 Tobias Riemer
4
5 This library 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 This library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public
16 License along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18 */
19
20 /*
21 * CsBeagle.java
22 *
23 * Created on 20. September 2002, 13:17
24 */
25
26 package plugins.CsBeagle;
27
28 import java.util.Vector;
29 import java.net.*;
30 import java.io.*;
31 import javax.swing.tree.DefaultMutableTreeNode;
32 import java.awt.event.ActionEvent;
33 import dexter.property.Property;
34
35 /**
36 *
37 * @author Tobias Riemer
38 */
39 public class CsBeagle extends dexter.core.DefaultService implements BuddyDataChangeListener, dexter.property.PropertyChangedListener {
40
41 private static ServerList servers;
42
43 protected int sCounter = 0;
44 protected boolean restart = true;
45 protected boolean favorite = true;
46 protected int dest = 0;
47 protected int time_out = 100;
48 protected static int server_finished = 0;
49 protected String fname = new String();
50 protected java.util.HashMap nodes = new java.util.HashMap();
51 private javax.swing.Action powerSearch = new plugins.CsBeagle.CsBeagle.PowerSearchAction();
52 private javax.swing.Action helpAction = new plugins.CsBeagle.CsBeagle.HelpAction();
53 private javax.swing.Action showServerInfoDlg = new plugins.CsBeagle.CsBeagle.ShowServerInfoDlgAction();
54 private javax.swing.Action showServerDlg = new plugins.CsBeagle.CsBeagle.ShowServerDlgAction();
55 private javax.swing.Action addIp = new plugins.CsBeagle.CsBeagle.AddIPAction();
56 private javax.swing.Action pingAction = new plugins.CsBeagle.CsBeagle.PingAction();
57
58 //Vector playerNodes = new Vector();
59 protected Vector players = new Vector();
60
61 Property pFavoriteDat = new Property("FavoriteDat",Property.STRING_VALUE,"C:\\SPIELE\\HALF-LIFE\\favsvrs.dat" , true);
62 Property pSleep = new Property("Sleep",Property.INT_VALUE,1000);
63 Property pBuddies = new Property("Buddies",Property.VECTOR_VALUE, true);
64 Property pPopup = new Property("Popup Notification",Property.BOOLEAN_VALUE);
65 Property pPowerSearch = new Property("Enable PS at Startup",Property.BOOLEAN_VALUE);
66 Property pPowerSearchThreads = new Property("Numbers PS Threads",Property.INT_VALUE, 10);
67
68 Property pPingExec = new Property("Executable",Property.STRING_VALUE,"ping" , false);
69 Property pPingParameters = new Property("Parameters",Property.STRING_VALUE,"-c 20" , false);
70
71 protected boolean powerThreadNeverStarted = true;
72 /** Creates a new instance of CsBeagle */
73 public CsBeagle() {
74 super("CsBeagle");
75
76 dexter.core.PluginMenu m1 = new dexter.core.PluginMenu("HELP", pluginMenu);
77 helpAction = new HelpAction();
78 m1.add(helpAction);
79 pluginMenu.add(m1);
80
81 setServiceName("CsBeagle");
82
83 propertyFile.setFileName(dexter.core.Dexter.getInstance().getHomeDir() + "csbeagle");
84 dexter.property.PropertyGroup pg = new dexter.property.PropertyGroup("General", new javax.swing.ImageIcon(getClass().getResource("/plugins/CsBeagle/images/cs.gif")));
85 propertyFile.addGroup(pg);
86 pg.addProperty(pFavoriteDat);
87 pFavoriteDat.setPropertyEditor(new dexter.property.FileChooserPropertyEditor());
88 pg.addProperty(pSleep);
89 pg.addProperty(pBuddies);
90 pg.addProperty(pPopup);
91
92 pg = new dexter.property.PropertyGroup("PowerSearch", new javax.swing.ImageIcon(getClass().getResource("/plugins/CsBeagle/images/search.gif")));
93 propertyFile.addGroup(pg);
94 pg.addProperty(pPowerSearch);
95 pg.addProperty(pPowerSearchThreads);
96
97 pg = new dexter.property.PropertyGroup("Ping", new javax.swing.ImageIcon(getClass().getResource("/plugins/CsBeagle/images/radar.gif")));
98 propertyFile.addGroup(pg);
99 pg.addProperty(pPingExec);
100 pg.addProperty(pPingParameters);
101
102 setIcon(new javax.swing.ImageIcon(getClass().getResource("/dexter/images/csbeagle.gif")));
103 Vector buddies = new Vector();
104 buddies.add(new Buddy("[ResDogs]2beers"));
105 buddies.add(new Buddy("[ResDogs]Mr.Ed"));
106 buddies.add(new Buddy("[ResDogs]Monokopfhoerer"));
107
108 pBuddies.setVector(buddies);
109 pBuddies.setClassName("plugins.CsBeagle.Buddy");
110 pBuddies.setDisplayType(Property.VECTOR_TEXTFIELD);
111
112 dexter.core.Dexter.getInstance().getEventDispatcher().addActionListener("grabberAction",
113 new dexter.events.ActionListener() {
114 public void actionPerformed(dexter.events.Event event) {
115 addIp(event);
116 }
117 });
118
119 }
120
121 protected void createPopupMenu() {
122
123 javax.swing.JMenuItem menuItem = new javax.swing.JMenuItem("PowerSearch");
124 menuItem.setAction(powerSearch);
125
126 popup.add(menuItem);
127
128 menuItem = new javax.swing.JMenuItem("Favorite Servers");
129 menuItem.addActionListener(new java.awt.event.ActionListener() {
130 public void actionPerformed(ActionEvent evt) {
131 viewFavoriteServers();
132 }
133 });
134 popup.add(menuItem);
135 }
136
137 public void initRun() {
138 super.initRun();
139 createPopupMenu();
140 pBuddies.addPropertyChangedListener(this);
141 pFavoriteDat.addPropertyChangedListener(this);
142 IPListener ipListener = new IPListener();
143 ipListener.start();
144 }
145
146 public void restart() {
147 restart = false;
148 servers = new ServerList();
149 servers.setFileName(getFavoriteDat());
150 try {
151 servers.loadList();
152
153 Vector result = new Vector();
154 int perc_old = -1;
155 int perc = 0;
156 int servercount;
157 if (favorite)
158 servercount = Server.getFavoriteCount();
159 else servercount = servers.size();
160
161 sCounter = 0;
162 createBuddyNodes();
163 } catch (Exception ex) {
164 ex.printStackTrace();
165 javax.swing.JOptionPane.showMessageDialog(null, "Cannot read " + getFavoriteDat(),"Error Message", javax.swing.JOptionPane.ERROR_MESSAGE);
166 }
167 fireNodeChanged(root);
168 }
169
170
171 public void doRun() {
172
173 if (restart) restart();
174 if (servers.size() > 0) {
175 if (sCounter >= servers.size()) sCounter = 0;
176
177 if ( (getPowerSearchAtStartup()) && (powerThreadNeverStarted)) {
178 powerThreadNeverStarted = false;
179 startPowerSearch();
180 }
181 Server server = (Server) servers.get(sCounter);
182
183 if ((!favorite) || server.isFavorite()) {
184
185
186 if (PowerSearchThread.activeThreads == 0) {
187 //setToolTipText(server.toString());
188 //fireNodeChanged(root);
189 server.setReceiving(true);
190 servers.fireDataChanged();
191 server.getData();
192 server.setReceiving(false);
193 servers.fireDataChanged();
194 }
195
196
197
198 if (server.getState() != Server.NOT_CONNECTED) {
199
200 //System.out.println("csBeagle: server " + server);
201 for (int i=0;i<getBuddies().size();i++) {
202 Buddy buddy = (Buddy) getBuddies().get(i);
203 buddy.refreshPlayers(server);
204 }
205 }
206 }
207 }
208 if (PowerSearchThread.activeThreads == 0) {
209 try {
210 thread.sleep(getSleep());
211 } catch (java.lang.InterruptedException e) { e.printStackTrace(); }
212 }
213 sCounter ++;
214
215 }
216
217 public void finalizeRun() {
218 super.finalizeRun();
219 try {
220 servers.saveList();
221 } catch (Exception ex) {
222 ex.printStackTrace();
223 javax.swing.JOptionPane.showMessageDialog(null, "Cannot save " + getFavoriteDat(),"Error Message", javax.swing.JOptionPane.ERROR_MESSAGE);
224 }
225 }
226
227 public void createBuddyNodes() {
228 nodes = new java.util.HashMap();
229 fireNodeRemoveAll(root);
230 for (int i=0;i<getBuddies().size();i++) {
231 BuddyEntry be = new BuddyEntry((Buddy)getBuddies().get(i));
232 be.setShowServerInfoDlgAction(showServerInfoDlg);
233 DefaultMutableTreeNode node = new DefaultMutableTreeNode(be);
234 nodes.put(((Buddy)getBuddies().get(i)).getName(),node);
235 fireNodeAdded(root,node);
236 ((Buddy)getBuddies().get(i)).addBuddyDataChangeListener(this);
237 }
238
239 }
240
241 public void propertyChanged(Property p) {
242 if (p==pFavoriteDat) {
243 restart = true;
244 }
245 if (p==pBuddies) {
246 createBuddyNodes();
247 }
248 }
249
250 public void startPowerSearch() {
251 //Vector threads = new Vector();
252 if (PowerSearchThread.activeThreads > 0) return ;
253 PowerSearchThread.serverIndex = 0;
254 PowerSearchThread.servers = servers;
255 for(int i=0;i<getPowerSearchThreads();i++) {
256 Thread thread = new PowerSearchThread();
257 thread.start();
258 }
259 }
260
261 public String getFavoriteDat() {
262 return pFavoriteDat.stringValue();
263 }
264
265 public int getSleep() {
266 return pSleep.intValue();
267 }
268
269 public Vector getBuddies() {
270 return pBuddies.getVector();
271 }
272
273 public boolean getPowerSearchAtStartup() {
274 return pPowerSearch.booleanValue();
275 }
276
277 public int getPowerSearchThreads() {
278 return pPowerSearchThreads.intValue();
279 }
280
281 public boolean getPopupNotification() {
282 return pPopup.booleanValue();
283 }
284
285 public String getPingExec() {
286 return pPingExec.stringValue();
287 }
288
289 public String getPingParameters() {
290 return pPingParameters.stringValue();
291 }
292
293 public void viewFavoriteServers() {
294 ServerDlg sd = new ServerDlg(getIcon());
295 sd.setServers(servers);
296 sd.setPowerSearchAction(powerSearch);
297 sd.setPingAction(pingAction);
298 sd.setAddIpAction(addIp);
299 sd.setShowServerInfoDlgAction(showServerInfoDlg);
300 sd.setVisible(true);
301 }
302
303 private void addIp(dexter.events.Event event) {
304 Vector v = (Vector) event.getValue();
305 if (v.size() < 2) return ;
306 if (v.get(0).toString().equals("ip")) {
307 try {
308 String ip = v.get(1).toString();
309 System.out.println("BEAGLE-ADD-IP: " + ip);
310 int port = 27015;
311 int i = ip.indexOf(':');
312 if (i != -1) {
313 port = Integer.decode(ip.substring(i+1)).intValue();
314 ip = ip.substring(0,i);
315 }
316 Server server = new Server(ip,port,true);
317 new AddIpThread(server).start();
318
319 } catch (NumberFormatException nex) {}
320 }
321 }
322
323 class AddIpThread extends Thread {
324
325 Server server;
326
327 public AddIpThread(Server server) {
328 this.server = server;
329 }
330
331 public void run() {
332 int trys = 0;
333 try {
334 while ((trys < 5) && ((server.getState() == Server.NOT_FOUND) ||
335 (server.getState() == Server.NOT_CONNECTED)) ) {
336 server.getData();
337 if (server.getState() != Server.NOT_FOUND) {
338 servers.add(server);
339 System.out.println("BEAGLE-ADD-SERVER: " + server);
340 return ;
341 }
342 sleep(200);
343 trys++;
344 }
345 } catch (Exception ex) {}
346 }
347 }
348
349 public void showServerInfoDlg(Server server) {
350 ServerInfoDlg sid = new ServerInfoDlg(getIcon(),pBuddies);
351 sid.setServer(server);
352 sid.setVisible(true);
353 }
354
355 public void addPlayer(Buddy b, Player p) {
356 DefaultMutableTreeNode node = (DefaultMutableTreeNode) nodes.get(b.getName());
357 PlayerEntry pe = new PlayerEntry(p);
358 pe.setShowServerInfoDlgAction(showServerInfoDlg);
359 fireNodeAdded(node,new DefaultMutableTreeNode(pe));
360 if (PowerSearchThread.activeThreads == 0) {
361 if (getPopupNotification()) {
362 dexter.swingExtensions.TimerFrame.showMessage(p.getName(), " plays CS on ", p.getServer().getName() , 3000);
363 }
364 }
365 }
366
367 public void removePlayer(Buddy b, Player p) {
368 //System.out.println("csBeage: removePlayer " + p + " from " + b);
369 DefaultMutableTreeNode node = (DefaultMutableTreeNode) nodes.get(b.getName());
370
371 DefaultMutableTreeNode pnode = findPlayerNode(node,p);
372 if (pnode != null)
373 fireNodeRemoved(pnode);
374 }
375
376 public void changePlayer(Buddy b, Player p) {
377 DefaultMutableTreeNode node = (DefaultMutableTreeNode) nodes.get(b.getName());
378
379 DefaultMutableTreeNode pnode = findPlayerNode(node,p);
380 if (pnode != null)
381 fireNodeChanged(pnode);
382 }
383
384 public DefaultMutableTreeNode findPlayerNode(DefaultMutableTreeNode node,Player p) {
385 int index = -1;
386 for(int i=0;i<node.getChildCount();i++) {
387 Player player = ((PlayerEntry) ((DefaultMutableTreeNode) node.getChildAt(i)).getUserObject()).getPlayer();
388 if (player.equals(p)) index = i;
389 }
390 if (index == -1) return null;
391 return (DefaultMutableTreeNode) node.getChildAt(index);
392 }
393
394 public class PowerSearchAction extends javax.swing.AbstractAction {
395
396 /**
397 * @todo Provide an Icon for Send
398 */
399 public PowerSearchAction() {
400 super("PowerSearch");
401 }
402
403 /** Invoked when an action occurs.
404 */
405 public void actionPerformed(ActionEvent e) {
406 startPowerSearch();
407 }
408 }
409
410 public class ShowServerInfoDlgAction extends javax.swing.AbstractAction {
411
412 /**
413 * @todo Provide an Icon for Send
414 */
415 public ShowServerInfoDlgAction() {
416 super("ShowServerInfoDlg");
417 }
418
419 /** Invoked when an action occurs.
420 */
421 public void actionPerformed(ActionEvent e) {
422 Server server = (Server)e.getSource();
423 showServerInfoDlg(server);
424 }
425 }
426
427 public class HelpAction extends javax.swing.AbstractAction {
428
429 /**
430 * @todo Provide an Icon for Send
431 */
432 public HelpAction() {
433 super("CsBeagle");
434 }
435
436 /** Invoked when an action occurs.
437 */
438 public void actionPerformed(ActionEvent e) {
439 dexter.swingExtensions.InternalBrowser ib = new dexter.swingExtensions.InternalBrowser();
440 try {
441 ib.setUrl(getClass().getResource("/plugins/CsBeagle/about.en.html"));
442 ib.show();
443 } catch (Exception ex) { ex.printStackTrace(); }
444 }
445 }
446
447
448 public class ShowServerDlgAction extends javax.swing.AbstractAction {
449
450 /**
451 * @todo Provide an Icon for Send
452 */
453 public ShowServerDlgAction() {
454 super("ShowServerDlg");
455 }
456
457 /** Invoked when an action occurs.
458 */
459 public void actionPerformed(ActionEvent e) {
460 viewFavoriteServers();
461 }
462 }
463
464 public class AddIPAction extends javax.swing.AbstractAction {
465
466 /**
467 * @todo Provide an Icon for Send
468 */
469 public AddIPAction() {
470 super("Add IP");
471 }
472
473 /** Invoked when an action occurs.
474 */
475 public void actionPerformed(ActionEvent e) {
476 AddIpDlg ipdlg = new AddIpDlg(getIcon());
477 ipdlg.setServerList(servers);
478 ipdlg.setVisible(true);
479 }
480 }
481
482 public class PingAction extends javax.swing.AbstractAction {
483
484 /**
485 * @todo Provide an Icon for Send
486 */
487 public PingAction() {
488 super("Ping Server");
489 }
490
491 /** Invoked when an action occurs.
492 */
493 public void actionPerformed(ActionEvent e) {
494 PingDlg pd = new PingDlg(getIcon(), ((Server) e.getSource()),getPingExec(),getPingParameters());
495 pd.setVisible(true);
496
497 }
498 }
499
500 class IPListener extends Thread {
501 boolean ipListenerStop = false;
502
503
504 public void run() {
505 ServerSocket serverSocket = null;
506 while ((!stop) && (!ipListenerStop)) {
507 try {
508 serverSocket = new ServerSocket(4444);
509 Socket clientSocket = null;
510
511 clientSocket = serverSocket.accept();
512
513 //PrintWriter out = new PrintWriter(clientSocket.getOutputStream(), true);
514 BufferedReader in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
515 String inputLine; //, outputLine;
516
517 if ((inputLine = in.readLine()) != null) {
518 System.out.println("IPListener: " + inputLine);
519 }
520
521 int index = inputLine.indexOf(':');
522 if (index != -1) {
523 String ip = inputLine.substring(0,index);
524 try {
525 int port = Integer.decode(inputLine.substring(index+1)).intValue();
526 Server server = new Server(ip,port,true);
527 server.getData();
528 servers.add(server);
529 } catch (NumberFormatException nex) {
530 nex.printStackTrace();
531 }
532 }
533 //out.close();
534 in.close();
535 clientSocket.close();
536 serverSocket.close();
537
538 } catch (IOException e) {
539 ipListenerStop = true;
540 try {
541 if (serverSocket != null) serverSocket.close();
542 } catch (IOException ex) {
543 ex.printStackTrace();
544 }
545 e.printStackTrace();
546 }
547 }
548 }
549 }
550
551 }