1 /*****************************************************/
2 /* This java file is a part of the */
4 /* - Plouf's Java IRC Client - */
6 /* Copyright (C) 2002 - 2005 Philippe Detournay */
8 /* All contacts : theplouf@yahoo.com */
10 /* PJIRC is free software; you can redistribute */
11 /* it and/or modify it under the terms of the GNU */
12 /* General Public License as published by the */
13 /* Free Software Foundation; version 2 or later of */
16 /* PJIRC is distributed in the hope that it will */
17 /* be useful, but WITHOUT ANY WARRANTY; without */
18 /* even the implied warranty of MERCHANTABILITY or */
19 /* FITNESS FOR A PARTICULAR PURPOSE. See the GNU */
20 /* General Public License for more details. */
22 /* You should have received a copy of the GNU */
23 /* General Public License along with PJIRC; if */
24 /* not, write to the Free Software Foundation, */
25 /* Inc., 59 Temple Place, Suite 330, Boston, */
26 /* MA 02111-1307 USA */
28 /*****************************************************/
32 import irc.gui.GUISource;
33 import irc.gui.IRCInterface;
34 import irc.gui.IRCInterfaceListener;
35 import irc.ident.IdentListener;
36 import irc.ident.IdentWrapper;
37 import irc.plugin.Plugin;
39 import java.awt.Button;
40 import java.awt.Container;
41 import java.awt.FlowLayout;
43 import java.awt.Frame;
44 import java.awt.GridLayout;
45 import java.awt.TextField;
46 import java.awt.event.ActionEvent;
47 import java.awt.event.ActionListener;
48 import java.awt.event.WindowEvent;
49 import java.awt.event.WindowListener;
51 import java.util.Enumeration;
52 import java.util.Hashtable;
53 import java.util.Vector;
56 * The IRC Application. This is the main class of PJIRC.
58 public class IRCApplication extends IRCObject implements ServerListener, ServerManager, IdentListener,
59 IRCInterfaceListener, WindowListener, ActionListener, PluginManager {
60 private DefaultSource _defaultSource;
62 private Interpretor _inter;
64 private IdentWrapper _ident;
66 private StartupConfiguration _start;
68 private IRCInterface _interface;
69 private Vector _plugins;
70 private Hashtable _pluginsTable;
73 private Container _container;
75 private Hashtable _servers;
77 private Object _nickLock = new Object();
80 * Create a new IRCApplication.
83 * the IRC configuration.
84 * @param startupConfig
85 * the startup configuration.
87 * a container in wich the application will display. Maybe null. If
88 * null, a new Frame will be opened.
90 public IRCApplication(IRCConfiguration config, StartupConfiguration startupConfig, Container source) {
93 _start = startupConfig;
94 _plugins = new Vector();
95 _pluginsTable = new Hashtable();
97 String gui = config.getS("gui");
99 Class cl = Class.forName("irc.gui." + gui + ".Interface");
100 java.lang.reflect.Constructor ctr = cl.getDeclaredConstructor(new Class[] { config.getClass() });
101 _interface = (IRCInterface) ctr.newInstance(new Object[] { config });
102 } catch (java.lang.reflect.InvocationTargetException iex) {
103 iex.getTargetException().printStackTrace();
104 throw new Error("Unable to load interface " + gui + " : " + iex.getTargetException());
105 } catch (Throwable ex) {
106 ex.printStackTrace();
107 throw new Error("Unable to load interface " + gui + " : " + ex);
110 _servers = new Hashtable();
111 _defaultSource = new DefaultSource(_ircConfiguration);
112 DefaultInterpretor defaultInter = new DefaultInterpretor(_ircConfiguration, _start, this, this);
113 _defaultSource.setInterpretor(defaultInter);
117 * Init the application.
119 public synchronized void init() {
120 loadPlugin(_interface);
122 String[] plugins = _start.getPlugins();
123 for (int i = 0; i < plugins.length; i++)
124 loadPlugin(plugins[i]);
126 _interface.addIRCInterfaceListener(this);
127 if (_container == null) {
128 _frame = new Frame();
129 _frame.addWindowListener(this);
130 if (_interface.getComponent() != null)
131 _frame.add(_interface.getComponent());
132 _frame.setFont(new Font("", Font.PLAIN, 12));
133 _frame.setSize(640, 400);
137 _container.removeAll();
138 _container.setLayout(new GridLayout(1, 1));
139 if (_interface.getComponent() != null)
140 _container.add(_interface.getComponent());
143 _inter = new CTCPInterpretor(_ircConfiguration, _defaultSource.getInterpretor(), this);
144 _inter.addLast(_interface.getInterpretor());
146 if (_ircConfiguration.getB("useidentserver")) {
148 _ident = new IdentWrapper(_ircConfiguration);
149 Exception e = _ident.start(_start.getName(), this);
151 _defaultSource.report("\3" + "6" + "*** " + getText(IRCTextProvider.IDENT_FAILED_LAUNCH, e.getMessage()));
153 } catch (Throwable ex) {
154 _ircConfiguration.internalError("ident error", ex, "plouf@pjirc.com");
160 String[] init = _ircConfiguration.getInitialization();
161 for (int i = 0; i < init.length; i++)
162 _defaultSource.sendString(init[i]);
164 IRCServer server = new IRCServer(_ircConfiguration, this, _start.getNick(), _start.getAltNick(), _start.getName(),
166 server.setServers(_start.getHost(), _start.getPort(), _start.getPass());
168 newServer(server, _ircConfiguration.getB("autoconnection"));
170 requestSourceFocus();
174 * Get the IRC interface.
176 * @return the IRC interface.
178 public IRCInterface getIRCInterface() {
183 public void newServer(Server server, boolean connect) {
184 server.addServerListener(this);
185 _servers.put(server, server);
187 Enumeration enum1 = _plugins.elements();
188 while (enum1.hasMoreElements()) {
189 Plugin plugin = (Plugin) enum1.nextElement();
190 plugin.serverCreated(server);
193 server.enumerateSourcesAsCreated(this);
199 * Uninit the application.
201 public synchronized void uninit() {
202 Enumeration en = _servers.keys();
203 while (en.hasMoreElements()) {
204 Server s = (Server) en.nextElement();
210 _interface.removeIRCInterfaceListener(this);
213 _frame.removeWindowListener(this);
216 while (_plugins.size() > 0) {
217 unloadPlugin((Plugin) _plugins.elementAt(_plugins.size() - 1));
219 _pluginsTable = new Hashtable();
221 if (_container != null)
222 _container.removeAll();
224 EventDispatcher.clearCache();
228 public boolean loadPlugin(String str) {
229 if (_pluginsTable.get(str) != null)
233 Class cl = Class.forName("irc.plugin." + str);
234 java.lang.reflect.Constructor ctr = cl.getDeclaredConstructor(new Class[] { _ircConfiguration.getClass() });
235 plugin = (Plugin) ctr.newInstance(new Object[] { _ircConfiguration });
237 } catch (Throwable ex) {
238 ex.printStackTrace();
241 _pluginsTable.put(str, plugin);
246 public boolean unloadPlugin(String str) {
247 Plugin plugin = (Plugin) _pluginsTable.get(str);
250 _pluginsTable.remove(str);
251 unloadPlugin(plugin);
255 private void loadPlugin(Plugin plugin) {
256 class addHandler implements ServerListener {
257 private Plugin _plugin;
260 * Create a new addHandler
265 public addHandler(Plugin plug) {
270 public void serverConnected(Server s) {/* ... */
274 public void serverDisconnected(Server s) {/* ... */
278 public void serverLeft(Server s) {/* ... */
282 public String[] cannotUseRequestedNicknames(Server s) {
287 public void sourceCreated(Source source, Server server, Boolean bring) {
288 _plugin.sourceCreated(source, bring);
292 public void sourceRemoved(Source source, Server server) {/* ... */
296 public Object specialServerRequest(String request, Server server, Object[] params) {
301 plugin.setIRCApplication(this);
303 _plugins.insertElementAt(plugin, _plugins.size());
304 plugin.sourceCreated(_defaultSource, Boolean.TRUE);
306 Enumeration en = _servers.keys();
307 while (en.hasMoreElements()) {
308 Server s = (Server) en.nextElement();
309 plugin.serverCreated(s);
311 s.enumerateSourcesAsCreated(new addHandler(plugin));
316 private void unloadPlugin(Plugin plugin) {
317 class removeHandler implements ServerListener {
318 private Plugin _plugin;
321 * Create a new removeHandler
326 public removeHandler(Plugin plug) {
331 public void serverConnected(Server s) {/* ... */
335 public void serverDisconnected(Server s) {/* ... */
339 public void serverLeft(Server s) {/* ... */
343 public String[] cannotUseRequestedNicknames(Server s) {
348 public void sourceCreated(Source source, Server server, Boolean bring) {/* ... */
352 public void sourceRemoved(Source source, Server server) {
353 _plugin.sourceRemoved(source);
357 public Object specialServerRequest(String request, Server server, Object[] params) {
362 for (int i = 0; i < _plugins.size(); i++) {
363 if (_plugins.elementAt(i) == plugin) {
364 _plugins.removeElementAt(i);
365 Enumeration en = _servers.keys();
366 while (en.hasMoreElements()) {
367 Server s = (Server) en.nextElement();
368 s.enumerateSourcesAsRemoved(new removeHandler(plugin));
369 plugin.serverRemoved(s);
371 plugin.sourceRemoved(_defaultSource);
379 public void sourceCreated(Source source, Server server, Boolean bring) {
380 source.getInterpretor().addLast(_inter);
381 Enumeration enum1 = _plugins.elements();
382 while (enum1.hasMoreElements()) {
383 Plugin plugin = (Plugin) enum1.nextElement();
384 plugin.sourceCreated(source, bring);
389 public void sourceRemoved(Source source, Server server) {
390 Enumeration enum1 = _plugins.elements();
391 while (enum1.hasMoreElements()) {
392 Plugin plugin = (Plugin) enum1.nextElement();
393 plugin.sourceRemoved(source);
398 public void serverLeft(Server s) {
399 Enumeration enum1 = _plugins.elements();
400 while (enum1.hasMoreElements()) {
401 Plugin plugin = (Plugin) enum1.nextElement();
402 plugin.serverRemoved(s);
405 s.removeServerListener(this);
408 private Frame getParentFrame() {
411 Container ans = _container;
412 while (ans != null) {
413 if (ans instanceof Frame)
415 ans = ans.getParent();
421 * Get the application's parent container. The GUI instance will be added into
422 * this container or one of its children.
424 * @return application's parent container.
426 public Container getContainer() {
433 public Object specialServerRequest(String request, Server s, Object[] params) {
434 if (request.equals("DCCFileRequest")) {
435 File f = _ircConfiguration.getSecurityProvider().getSaveFile(params[1].toString(),
436 getText(IRCTextProvider.FILE_SAVEAS) + " [" + params[1] + "]");
438 } else if (request.equals("DCCChatRequest")) {
439 boolean accept = _ircConfiguration.getSecurityProvider().confirm(getParentFrame(),
440 getText(IRCTextProvider.GUI_DCC_CHAT_WARNING_TITLE),
441 getText(IRCTextProvider.GUI_DCC_CHAT_WARNING_TEXT, (String) params[0]));
442 return new Boolean(accept);
444 _ircConfiguration.internalError("Unknown request : " + request, null, "plouf@pjirc.com");
450 public void serverConnected(Server server) {
451 for (int i = 0; i < _start.getCommands().length; i++) {
452 String cmd = _start.getCommands()[i];
453 if ((cmd.startsWith("/")) && (server instanceof IRCServer))
454 ((IRCServer) server).getStatus().sendString(_start.getCommands()[i]);
456 server.execute(_start.getCommands()[i]);
459 Enumeration enum1 = _plugins.elements();
460 while (enum1.hasMoreElements()) {
461 Plugin plugin = (Plugin) enum1.nextElement();
462 plugin.serverConnected(server);
468 public void serverDisconnected(Server s) {
469 Enumeration enum1 = _plugins.elements();
470 while (enum1.hasMoreElements()) {
471 Plugin plugin = (Plugin) enum1.nextElement();
472 plugin.serverDisconnected(s);
477 public void identRequested(String source, Integer result, String reply) {
478 _defaultSource.report("\3" + "6" + "*** " + getText(IRCTextProvider.IDENT_REQUEST, source));
480 switch (result.intValue()) {
481 case IdentListener.IDENT_ERROR:
482 s = getText(IRCTextProvider.IDENT_ERROR);
484 case IdentListener.IDENT_OK:
485 s = getText(IRCTextProvider.IDENT_REPLIED, reply);
487 case IdentListener.IDENT_DEFAULT:
488 s = getText(IRCTextProvider.IDENT_REPLIED, getText(IRCTextProvider.IDENT_DEFAULT_USER) + " : " + reply);
490 case IdentListener.IDENT_NOT_FOUND:
491 s = getText(IRCTextProvider.IDENT_NO_USER);
494 s = getText(IRCTextProvider.IDENT_UNDEFINED);
497 _defaultSource.report("\3" + "6" + "*** " + s);
502 public void identRunning(Integer port) {
503 _defaultSource.report("\3" + "6" + "*** " + getText(IRCTextProvider.IDENT_RUNNING_ON_PORT, port + ""));
507 public void identLeaving(String message) {
508 _defaultSource.report("\3" + "6" + "*** " + getText(IRCTextProvider.IDENT_LEAVING, message));
512 public void activeChanged(GUISource source, IRCInterface inter) {
513 if (source != null) {
514 if (source.getSource().mayDefault())
515 source.getSource().getServer().setDefaultSource(source.getSource());
517 _frame.setTitle(source.getTitle());
522 public void windowActivated(WindowEvent e) {
527 public void windowClosed(WindowEvent e) {
528 if (e.getSource() == _frame) {
529 EventDispatcher.dispatchEventAsync(this, "uninit", new Object[0]);
534 public void windowClosing(WindowEvent e) {
535 ((Frame) e.getSource()).hide();
536 ((Frame) e.getSource()).dispose();
540 public void windowDeactivated(WindowEvent e) {
545 public void windowDeiconified(WindowEvent e) {
550 public void windowIconified(WindowEvent e) {
555 public void windowOpened(WindowEvent e) {
559 private GUISource getActiveSource() {
560 return _interface.getActive();
563 private Source getSource(String serverName, String type, String name) {
564 Enumeration e = _servers.keys();
565 while (e.hasMoreElements()) {
566 Server s = (Server) e.nextElement();
567 String sname = s.getServerName();
568 if (sname.equals(serverName) || serverName.length() == 0) {
569 Enumeration f = s.getSources();
570 while (f.hasMoreElements()) {
571 Source src = (Source) f.nextElement();
572 if (src.getType().equals(type) && src.getName().equals(name))
581 * Request the active source to gain focus.
583 public void requestSourceFocus() {
584 GUISource current = getActiveSource();
587 current.requestFocus();
591 * Request the given source to gain focus.
594 * the source's server name, or an empty string if no server
595 * filtering needs to be done.
601 public void requestSourceFocus(String serverName, String type, String name) {
602 Source source = getSource(serverName, type, name);
603 if (source != null) {
604 GUISource gui = _interface.getGUISource(source);
606 _interface.setActive(gui);
611 * Send the given command to the given source interpretor.
614 * the source's server name, or an empty string if no server
615 * filtering needs to be done.
621 * the command to send.
623 public void sendString(String serverName, String type, String name, String cmd) {
624 Source source = getSource(serverName, type, name);
626 source.sendString(cmd);
630 * Send the given string to the current source interpretor.
633 * string to send to the interpretor.
635 public void sendString(String str) {
636 GUISource current = getActiveSource();
639 current.getSource().sendString(str);
643 * Set the current textfield text.
646 * new textfield text.
648 public void setFieldText(String txt) {
649 GUISource current = getActiveSource();
652 current.setFieldText(txt);
656 * Get the current textfield text.
658 * @return the current textfield text.
660 public String getFieldText() {
661 GUISource current = getActiveSource();
664 return current.getFieldText();
668 * Validate the current textfield text, as if user pressed return key.
670 public void validateText() {
671 GUISource current = getActiveSource();
674 current.validateText();
678 * Send the given event value to the given plugin.
683 * the event value to be sent.
685 public void sendPluginEvent(String pluginName, Object event) {
686 Plugin plugin = (Plugin) _pluginsTable.get(pluginName);
689 plugin.externalEvent(event);
693 * Get the plugin value from the given plugin name.
699 * @return the returned plugin value, or null if the plugin is not found.
701 public Object getPluginValue(String pluginName, Object valueName) {
702 Plugin plugin = (Plugin) _pluginsTable.get(pluginName);
705 return plugin.getValue(valueName);
709 public String[] cannotUseRequestedNicknames(Server s) {
710 synchronized (_nickLock) {
711 if (_interface.getComponent() != null)
712 _interface.getComponent().setEnabled(false);
714 _frame.setEnabled(false);
715 Frame f = new Frame();
716 f.setLayout(new FlowLayout());
718 f.setTitle(getText(IRCTextProvider.GUI_CHANGE_NICK));
719 TextField field = new TextField(_start.getNick());
720 Button b = new Button("Ok");
721 b.addActionListener(this);
727 } catch (InterruptedException ex) {
734 String[] ans = new String[1];
735 ans[0] = field.getText();
737 _frame.setEnabled(true);
738 if (_interface.getComponent() != null)
739 _interface.getComponent().setEnabled(true);
745 public void actionPerformed(ActionEvent evt) {
746 synchronized (_nickLock) {
747 _nickLock.notifyAll();
751 private static void usage() {
752 System.out.println("Usage :");
753 System.out.println(" java irc.IRCApplication -f configfile");
754 System.out.println("or java irc.IRCApplication -p nick fullname host gui");
755 System.out.println("");
756 System.out.println("Without any parameter, '-f pjirc.cfg' parameters are assumed.");
760 * Actual entry point.
763 * application parameters.
765 public static void go(String[] args) {
766 FileHandler file = new LocalFileHandler();
767 IRCConfiguration ircConfiguration;
768 StartupConfiguration startupConfiguration;
772 if ((args.length == 0) || ((args.length >= 2) && (args[0].equals("-f")))) {
773 String f = "pjirc.cfg";
774 if (args.length >= 2)
776 StreamParameterProvider provider = new StreamParameterProvider(file.getInputStream(f));
777 ConfigurationLoader loader = new ConfigurationLoader(provider, new NullURLHandler(), new AWTImageLoader(),
778 new NullSoundHandler(), file);
779 ircConfiguration = loader.loadIRCConfiguration();
780 startupConfiguration = loader.loadStartupConfiguration();
781 } else if ((args.length >= 5) && (args[0].equals("-p"))) {
782 StreamParameterProvider provider = new StreamParameterProvider(null);
783 ConfigurationLoader loader = new ConfigurationLoader(provider, new NullURLHandler(), new AWTImageLoader(),
784 new NullSoundHandler(), file);
785 ircConfiguration = loader.loadIRCConfiguration();
786 ircConfiguration.set("gui", args[4]);
787 startupConfiguration = new StartupConfiguration(args[1], "", args[2], new String[] { "" },
788 new String[] { args[3] }, new int[] { 6667 }, "", new String[] {}, new String[] {});
794 IRCApplication application = new IRCApplication(ircConfiguration, startupConfiguration, null);
795 EventDispatcher.dispatchEventAsyncAndWaitEx(application, "init", new Object[0]);
796 } catch (Throwable ex) {
797 System.out.println("Error : " + ex.getMessage());
798 ex.printStackTrace();
806 * application parameters.
808 public static void main(String[] args) {