|
@@ -23,6 +23,7 @@
|
23
|
23
|
package com.dmdirc;
|
24
|
24
|
|
25
|
25
|
import com.dmdirc.config.profiles.Profile;
|
|
26
|
+import com.dmdirc.events.FrameClosingEvent;
|
26
|
27
|
import com.dmdirc.events.ServerConnectErrorEvent;
|
27
|
28
|
import com.dmdirc.events.ServerConnectedEvent;
|
28
|
29
|
import com.dmdirc.events.ServerConnectingEvent;
|
|
@@ -49,9 +50,7 @@ import com.dmdirc.parser.interfaces.ProtocolDescription;
|
49
|
50
|
import com.dmdirc.parser.interfaces.SecureParser;
|
50
|
51
|
import com.dmdirc.parser.interfaces.StringConverter;
|
51
|
52
|
import com.dmdirc.tls.CertificateManager;
|
52
|
|
-import com.dmdirc.ui.core.components.WindowComponent;
|
53
|
53
|
import com.dmdirc.ui.input.TabCompletionType;
|
54
|
|
-import com.dmdirc.ui.messages.BackBufferFactory;
|
55
|
54
|
import com.dmdirc.ui.messages.ColourManager;
|
56
|
55
|
import com.dmdirc.ui.messages.Formatter;
|
57
|
56
|
import com.dmdirc.ui.messages.HighlightManager;
|
|
@@ -63,7 +62,6 @@ import java.net.URI;
|
63
|
62
|
import java.net.URISyntaxException;
|
64
|
63
|
import java.net.UnknownHostException;
|
65
|
64
|
import java.util.ArrayList;
|
66
|
|
-import java.util.Arrays;
|
67
|
65
|
import java.util.Collection;
|
68
|
66
|
import java.util.Collections;
|
69
|
67
|
import java.util.Map;
|
|
@@ -83,6 +81,8 @@ import javax.net.ssl.SSLException;
|
83
|
81
|
import org.slf4j.Logger;
|
84
|
82
|
import org.slf4j.LoggerFactory;
|
85
|
83
|
|
|
84
|
+import net.engio.mbassy.listener.Handler;
|
|
85
|
+
|
86
|
86
|
import static com.dmdirc.util.LogUtils.APP_ERROR;
|
87
|
87
|
import static com.google.common.base.Preconditions.checkNotNull;
|
88
|
88
|
|
|
@@ -90,7 +90,7 @@ import static com.google.common.base.Preconditions.checkNotNull;
|
90
|
90
|
* The Server class represents the client's view of a server. It maintains a list of all channels,
|
91
|
91
|
* queries, etc, and handles parser callbacks pertaining to the server.
|
92
|
92
|
*/
|
93
|
|
-public class Server extends FrameContainer implements Connection {
|
|
93
|
+public class Server implements Connection {
|
94
|
94
|
|
95
|
95
|
private static final Logger LOG = LoggerFactory.getLogger(Server.class);
|
96
|
96
|
/** The name of the general domain. */
|
|
@@ -163,6 +163,7 @@ public class Server extends FrameContainer implements Connection {
|
163
|
163
|
private final HighlightManager highlightManager;
|
164
|
164
|
/** Listener to use for config changes. */
|
165
|
165
|
private final ConfigChangeListener configListener = (domain, key) -> updateTitle();
|
|
166
|
+ private final WindowModel windowModel;
|
166
|
167
|
/** The future used when a reconnect timer is scheduled. */
|
167
|
168
|
private ScheduledFuture<?> reconnectTimerFuture;
|
168
|
169
|
|
|
@@ -170,30 +171,19 @@ public class Server extends FrameContainer implements Connection {
|
170
|
171
|
* Creates a new server which will connect to the specified URL with the specified profile.
|
171
|
172
|
*/
|
172
|
173
|
public Server(
|
|
174
|
+ final WindowModel windowModel,
|
173
|
175
|
final ConfigProviderMigrator configMigrator,
|
174
|
176
|
final ParserFactory parserFactory,
|
175
|
177
|
final IdentityFactory identityFactory,
|
176
|
178
|
final QueryFactory queryFactory,
|
177
|
|
- final DMDircMBassador eventBus,
|
178
|
179
|
final MessageEncoderFactory messageEncoderFactory,
|
179
|
180
|
final ConfigProvider userSettings,
|
180
|
181
|
final GroupChatManagerImplFactory groupChatManagerFactory,
|
181
|
182
|
final ScheduledExecutorService executorService,
|
182
|
183
|
@Nonnull final URI uri,
|
183
|
184
|
@Nonnull final Profile profile,
|
184
|
|
- final BackBufferFactory backBufferFactory,
|
185
|
185
|
final UserManager userManager) {
|
186
|
|
- super("server-disconnected",
|
187
|
|
- getHost(uri),
|
188
|
|
- getHost(uri),
|
189
|
|
- configMigrator.getConfigProvider(),
|
190
|
|
- backBufferFactory,
|
191
|
|
- eventBus,
|
192
|
|
- Arrays.asList(
|
193
|
|
- WindowComponent.TEXTAREA.getIdentifier(),
|
194
|
|
- WindowComponent.INPUTFIELD.getIdentifier(),
|
195
|
|
- WindowComponent.CERTIFICATE_VIEWER.getIdentifier()));
|
196
|
|
-
|
|
186
|
+ this.windowModel = windowModel;
|
197
|
187
|
this.parserFactory = parserFactory;
|
198
|
188
|
this.identityFactory = identityFactory;
|
199
|
189
|
this.configMigrator = configMigrator;
|
|
@@ -206,7 +196,7 @@ public class Server extends FrameContainer implements Connection {
|
206
|
196
|
this.inviteManager = new InviteManagerImpl(this);
|
207
|
197
|
|
208
|
198
|
awayMessage = Optional.empty();
|
209
|
|
- eventHandler = new ServerEventHandler(this, groupChatManager, getEventBus());
|
|
199
|
+ eventHandler = new ServerEventHandler(this, groupChatManager, windowModel.getEventBus());
|
210
|
200
|
|
211
|
201
|
this.address = uri;
|
212
|
202
|
this.profile = profile;
|
|
@@ -214,14 +204,14 @@ public class Server extends FrameContainer implements Connection {
|
214
|
204
|
|
215
|
205
|
updateIcon();
|
216
|
206
|
|
217
|
|
- getConfigManager().addChangeListener("formatter", "serverName", configListener);
|
218
|
|
- getConfigManager().addChangeListener("formatter", "serverTitle", configListener);
|
|
207
|
+ windowModel.getConfigManager().addChangeListener("formatter", "serverName", configListener);
|
|
208
|
+ windowModel.getConfigManager().addChangeListener("formatter", "serverTitle", configListener);
|
219
|
209
|
|
220
|
|
- initBackBuffer();
|
221
|
|
- this.highlightManager = new HighlightManager(getConfigManager(),
|
222
|
|
- new ColourManager(getConfigManager()));
|
|
210
|
+ this.highlightManager = new HighlightManager(windowModel.getConfigManager(),
|
|
211
|
+ new ColourManager(windowModel.getConfigManager()));
|
223
|
212
|
highlightManager.init();
|
224
|
|
- getEventBus().subscribe(highlightManager);
|
|
213
|
+ windowModel.getEventBus().subscribe(highlightManager);
|
|
214
|
+ windowModel.getEventBus().subscribe(this);
|
225
|
215
|
}
|
226
|
216
|
|
227
|
217
|
/**
|
|
@@ -278,7 +268,8 @@ public class Server extends FrameContainer implements Connection {
|
278
|
268
|
return;
|
279
|
269
|
case CONNECTED:
|
280
|
270
|
case CONNECTING:
|
281
|
|
- disconnect(getConfigManager().getOption(DOMAIN_GENERAL, "quitmessage"));
|
|
271
|
+ disconnect(windowModel.getConfigManager()
|
|
272
|
+ .getOption(DOMAIN_GENERAL, "quitmessage"));
|
282
|
273
|
case DISCONNECTING:
|
283
|
274
|
while (!myState.getState().isDisconnected()) {
|
284
|
275
|
try {
|
|
@@ -313,7 +304,7 @@ public class Server extends FrameContainer implements Connection {
|
313
|
304
|
parser = Optional.ofNullable(buildParser());
|
314
|
305
|
|
315
|
306
|
if (!parser.isPresent()) {
|
316
|
|
- getEventBus().publishAsync(
|
|
307
|
+ windowModel.getEventBus().publishAsync(
|
317
|
308
|
new ServerUnknownProtocolEvent(this, address.getScheme()));
|
318
|
309
|
return;
|
319
|
310
|
}
|
|
@@ -338,7 +329,7 @@ public class Server extends FrameContainer implements Connection {
|
338
|
329
|
}
|
339
|
330
|
}
|
340
|
331
|
|
341
|
|
- getEventBus().publish(new ServerConnectingEvent(this, address));
|
|
332
|
+ windowModel.getEventBus().publish(new ServerConnectingEvent(this, address));
|
342
|
333
|
}
|
343
|
334
|
|
344
|
335
|
@Override
|
|
@@ -356,12 +347,12 @@ public class Server extends FrameContainer implements Connection {
|
356
|
347
|
|
357
|
348
|
@Override
|
358
|
349
|
public void reconnect() {
|
359
|
|
- reconnect(getConfigManager().getOption(DOMAIN_GENERAL, "reconnectmessage"));
|
|
350
|
+ reconnect(windowModel.getConfigManager().getOption(DOMAIN_GENERAL, "reconnectmessage"));
|
360
|
351
|
}
|
361
|
352
|
|
362
|
353
|
@Override
|
363
|
354
|
public void disconnect() {
|
364
|
|
- disconnect(getConfigManager().getOption(DOMAIN_GENERAL, "quitmessage"));
|
|
355
|
+ disconnect(windowModel.getConfigManager().getOption(DOMAIN_GENERAL, "quitmessage"));
|
365
|
356
|
}
|
366
|
357
|
|
367
|
358
|
@Override
|
|
@@ -403,7 +394,8 @@ public class Server extends FrameContainer implements Connection {
|
403
|
394
|
parserLock.readLock().unlock();
|
404
|
395
|
}
|
405
|
396
|
|
406
|
|
- if (getConfigManager().getOptionBool(DOMAIN_GENERAL, "closequeriesonquit")) {
|
|
397
|
+ if (windowModel.getConfigManager()
|
|
398
|
+ .getOptionBool(DOMAIN_GENERAL, "closequeriesonquit")) {
|
407
|
399
|
closeQueries();
|
408
|
400
|
}
|
409
|
401
|
}
|
|
@@ -423,9 +415,10 @@ public class Server extends FrameContainer implements Connection {
|
423
|
415
|
}
|
424
|
416
|
|
425
|
417
|
final int delay = Math.max(1000,
|
426
|
|
- getConfigManager().getOptionInt(DOMAIN_GENERAL, "reconnectdelay"));
|
|
418
|
+ windowModel.getConfigManager().getOptionInt(DOMAIN_GENERAL, "reconnectdelay"));
|
427
|
419
|
|
428
|
|
- getEventBus().publishAsync(new ServerReconnectScheduledEvent(this, delay / 1000));
|
|
420
|
+ windowModel.getEventBus().publishAsync(
|
|
421
|
+ new ServerReconnectScheduledEvent(this, delay / 1000));
|
429
|
422
|
|
430
|
423
|
reconnectTimerFuture = executorService.schedule(() -> {
|
431
|
424
|
synchronized (myStateLock) {
|
|
@@ -483,7 +476,8 @@ public class Server extends FrameContainer implements Connection {
|
483
|
476
|
if (!getState().isDisconnected()) {
|
484
|
477
|
newQuery.reregister();
|
485
|
478
|
}
|
486
|
|
- getInputModel().get().getTabCompleter().addEntry(TabCompletionType.QUERY_NICK, nick);
|
|
479
|
+ windowModel.getInputModel().get().getTabCompleter()
|
|
480
|
+ .addEntry(TabCompletionType.QUERY_NICK, nick);
|
487
|
481
|
queries.put(lnick, newQuery);
|
488
|
482
|
}
|
489
|
483
|
|
|
@@ -492,8 +486,10 @@ public class Server extends FrameContainer implements Connection {
|
492
|
486
|
|
493
|
487
|
@Override
|
494
|
488
|
public void updateQuery(final Query query, final String oldNick, final String newNick) {
|
495
|
|
- getInputModel().get().getTabCompleter().removeEntry(TabCompletionType.QUERY_NICK, oldNick);
|
496
|
|
- getInputModel().get().getTabCompleter().addEntry(TabCompletionType.QUERY_NICK, newNick);
|
|
489
|
+ windowModel.getInputModel().get().getTabCompleter()
|
|
490
|
+ .removeEntry(TabCompletionType.QUERY_NICK, oldNick);
|
|
491
|
+ windowModel.getInputModel().get().getTabCompleter()
|
|
492
|
+ .addEntry(TabCompletionType.QUERY_NICK, newNick);
|
497
|
493
|
|
498
|
494
|
queries.put(converter.toLowerCase(newNick), query);
|
499
|
495
|
queries.remove(converter.toLowerCase(oldNick));
|
|
@@ -506,7 +502,7 @@ public class Server extends FrameContainer implements Connection {
|
506
|
502
|
|
507
|
503
|
@Override
|
508
|
504
|
public void delQuery(final Query query) {
|
509
|
|
- getInputModel().get().getTabCompleter().removeEntry(
|
|
505
|
+ windowModel.getInputModel().get().getTabCompleter().removeEntry(
|
510
|
506
|
TabCompletionType.QUERY_NICK, query.getNickname());
|
511
|
507
|
queries.remove(converter.toLowerCase(query.getNickname()));
|
512
|
508
|
}
|
|
@@ -518,26 +514,6 @@ public class Server extends FrameContainer implements Connection {
|
518
|
514
|
new ArrayList<>(queries.values()).forEach(Query::close);
|
519
|
515
|
}
|
520
|
516
|
|
521
|
|
- /**
|
522
|
|
- * Retrieves the host component of the specified URI, or throws a relevant exception if this is
|
523
|
|
- * not possible.
|
524
|
|
- *
|
525
|
|
- * @param uri The URI to be processed
|
526
|
|
- *
|
527
|
|
- * @return The URI's host component, as returned by {@link URI#getHost()}.
|
528
|
|
- *
|
529
|
|
- * @throws NullPointerException If <code>uri</code> is null
|
530
|
|
- * @throws IllegalArgumentException If the specified URI has no host
|
531
|
|
- * @since 0.6.4
|
532
|
|
- */
|
533
|
|
- private static String getHost(final URI uri) {
|
534
|
|
- if (uri.getHost() == null) {
|
535
|
|
- throw new IllegalArgumentException("URIs must have hosts");
|
536
|
|
- }
|
537
|
|
-
|
538
|
|
- return uri.getHost();
|
539
|
|
- }
|
540
|
|
-
|
541
|
517
|
/**
|
542
|
518
|
* Builds an appropriately configured {@link Parser} for this server.
|
543
|
519
|
*
|
|
@@ -545,7 +521,8 @@ public class Server extends FrameContainer implements Connection {
|
545
|
521
|
*/
|
546
|
522
|
@Nullable
|
547
|
523
|
private Parser buildParser() {
|
548
|
|
- final Parser myParser = parserFactory.getParser(profile, address, getConfigManager())
|
|
524
|
+ final Parser myParser = parserFactory
|
|
525
|
+ .getParser(profile, address, windowModel.getConfigManager())
|
549
|
526
|
.orElse(null);
|
550
|
527
|
|
551
|
528
|
if (myParser != null) {
|
|
@@ -554,8 +531,8 @@ public class Server extends FrameContainer implements Connection {
|
554
|
531
|
|
555
|
532
|
if (myParser instanceof SecureParser) {
|
556
|
533
|
final CertificateManager certificateManager =
|
557
|
|
- new CertificateManager(this, address.getHost(), getConfigManager(),
|
558
|
|
- userSettings, getEventBus());
|
|
534
|
+ new CertificateManager(this, address.getHost(), windowModel.getConfigManager(),
|
|
535
|
+ userSettings, windowModel.getEventBus());
|
559
|
536
|
final SecureParser secureParser = (SecureParser) myParser;
|
560
|
537
|
secureParser.setTrustManagers(certificateManager);
|
561
|
538
|
secureParser.setKeyManagers(certificateManager.getKeyManager());
|
|
@@ -582,7 +559,7 @@ public class Server extends FrameContainer implements Connection {
|
582
|
559
|
final String icon = myState.getState() == ServerState.CONNECTED
|
583
|
560
|
? protocolDescription.get().isSecure(address)
|
584
|
561
|
? "secure-server" : "server" : "server-disconnected";
|
585
|
|
- setIcon(icon);
|
|
562
|
+ windowModel.setIcon(icon);
|
586
|
563
|
}
|
587
|
564
|
|
588
|
565
|
/**
|
|
@@ -726,37 +703,38 @@ public class Server extends FrameContainer implements Connection {
|
726
|
703
|
return myState;
|
727
|
704
|
}
|
728
|
705
|
|
729
|
|
- @Override
|
730
|
|
- public void close() {
|
731
|
|
- synchronized (myStateLock) {
|
732
|
|
- eventHandler.unregisterCallbacks();
|
733
|
|
- getConfigManager().removeListener(configListener);
|
734
|
|
- highlightManager.stop();
|
735
|
|
- getEventBus().unsubscribe(highlightManager);
|
736
|
|
- executorService.shutdown();
|
|
706
|
+ @Handler
|
|
707
|
+ private void handleClose(final FrameClosingEvent event) {
|
|
708
|
+ if (event.getContainer() == windowModel) {
|
|
709
|
+ synchronized (myStateLock) {
|
|
710
|
+ eventHandler.unregisterCallbacks();
|
|
711
|
+ windowModel.getConfigManager().removeListener(configListener);
|
|
712
|
+ highlightManager.stop();
|
|
713
|
+ windowModel.getEventBus().unsubscribe(highlightManager);
|
|
714
|
+ executorService.shutdown();
|
737
|
715
|
|
738
|
|
- disconnect();
|
|
716
|
+ disconnect();
|
739
|
717
|
|
740
|
|
- myState.transition(ServerState.CLOSING);
|
741
|
|
- }
|
742
|
|
-
|
743
|
|
- groupChatManager.closeAll();
|
744
|
|
- closeQueries();
|
745
|
|
- inviteManager.removeInvites();
|
|
718
|
+ myState.transition(ServerState.CLOSING);
|
|
719
|
+ }
|
746
|
720
|
|
747
|
|
- super.close();
|
|
721
|
+ groupChatManager.closeAll();
|
|
722
|
+ closeQueries();
|
|
723
|
+ inviteManager.removeInvites();
|
|
724
|
+ windowModel.getEventBus().unsubscribe(this);
|
|
725
|
+ }
|
748
|
726
|
}
|
749
|
727
|
|
750
|
728
|
@Override
|
751
|
729
|
public WindowModel getWindowModel() {
|
752
|
|
- return this;
|
|
730
|
+ return windowModel;
|
753
|
731
|
}
|
754
|
732
|
|
755
|
733
|
@Override
|
756
|
734
|
public void sendCTCPReply(final String source, final String type, final String args) {
|
757
|
735
|
if ("VERSION".equalsIgnoreCase(type)) {
|
758
|
736
|
parser.get().sendCTCPReply(source, "VERSION",
|
759
|
|
- "DMDirc " + getConfigManager().getOption("version", "version") +
|
|
737
|
+ "DMDirc " + windowModel.getConfigManager().getOption("version", "version") +
|
760
|
738
|
" - https://www.dmdirc.com/");
|
761
|
739
|
} else if ("PING".equalsIgnoreCase(type)) {
|
762
|
740
|
parser.get().sendCTCPReply(source, "PING", args);
|
|
@@ -765,11 +743,6 @@ public class Server extends FrameContainer implements Connection {
|
765
|
743
|
}
|
766
|
744
|
}
|
767
|
745
|
|
768
|
|
- @Override
|
769
|
|
- public Optional<Connection> getConnection() {
|
770
|
|
- return Optional.of(this);
|
771
|
|
- }
|
772
|
|
-
|
773
|
746
|
@Override
|
774
|
747
|
public void updateTitle() {
|
775
|
748
|
synchronized (myStateLock) {
|
|
@@ -785,9 +758,9 @@ public class Server extends FrameContainer implements Connection {
|
785
|
758
|
getLocalUser().map(User::getNickname).orElse("Unknown")
|
786
|
759
|
};
|
787
|
760
|
|
788
|
|
- setName(Formatter.formatMessage(getConfigManager(),
|
|
761
|
+ windowModel.setName(Formatter.formatMessage(windowModel.getConfigManager(),
|
789
|
762
|
"serverName", arguments));
|
790
|
|
- setTitle(Formatter.formatMessage(getConfigManager(),
|
|
763
|
+ windowModel.setTitle(Formatter.formatMessage(windowModel.getConfigManager(),
|
791
|
764
|
"serverTitle", arguments));
|
792
|
765
|
} finally {
|
793
|
766
|
parserLock.readLock().unlock();
|
|
@@ -808,7 +781,7 @@ public class Server extends FrameContainer implements Connection {
|
808
|
781
|
return;
|
809
|
782
|
}
|
810
|
783
|
|
811
|
|
- getEventBus().publish(new ServerDisconnectedEvent(this));
|
|
784
|
+ windowModel.getEventBus().publish(new ServerDisconnectedEvent(this));
|
812
|
785
|
|
813
|
786
|
eventHandler.unregisterCallbacks();
|
814
|
787
|
|
|
@@ -837,14 +810,16 @@ public class Server extends FrameContainer implements Connection {
|
837
|
810
|
|
838
|
811
|
updateIcon();
|
839
|
812
|
|
840
|
|
- if (getConfigManager().getOptionBool(DOMAIN_GENERAL, "closequeriesondisconnect")) {
|
|
813
|
+ if (windowModel.getConfigManager()
|
|
814
|
+ .getOptionBool(DOMAIN_GENERAL, "closequeriesondisconnect")) {
|
841
|
815
|
closeQueries();
|
842
|
816
|
}
|
843
|
817
|
|
844
|
818
|
inviteManager.removeInvites();
|
845
|
819
|
updateAwayState(Optional.empty());
|
846
|
820
|
|
847
|
|
- if (getConfigManager().getOptionBool(DOMAIN_GENERAL, "reconnectondisconnect")
|
|
821
|
+ if (windowModel.getConfigManager()
|
|
822
|
+ .getOptionBool(DOMAIN_GENERAL, "reconnectondisconnect")
|
848
|
823
|
&& myState.getState() == ServerState.TRANSIENTLY_DISCONNECTED) {
|
849
|
824
|
doDelayedReconnect();
|
850
|
825
|
}
|
|
@@ -884,10 +859,11 @@ public class Server extends FrameContainer implements Connection {
|
884
|
859
|
|
885
|
860
|
updateIcon();
|
886
|
861
|
|
887
|
|
- getEventBus().publish(new ServerConnectErrorEvent(this, getErrorDescription
|
888
|
|
- (errorInfo)));
|
|
862
|
+ windowModel.getEventBus().publish(new ServerConnectErrorEvent(this,
|
|
863
|
+ getErrorDescription(errorInfo)));
|
889
|
864
|
|
890
|
|
- if (getConfigManager().getOptionBool(DOMAIN_GENERAL, "reconnectonconnectfailure")) {
|
|
865
|
+ if (windowModel.getConfigManager()
|
|
866
|
+ .getOptionBool(DOMAIN_GENERAL, "reconnectonconnectfailure")) {
|
891
|
867
|
doDelayedReconnect();
|
892
|
868
|
}
|
893
|
869
|
}
|
|
@@ -949,7 +925,7 @@ public class Server extends FrameContainer implements Connection {
|
949
|
925
|
groupChatManager.handleConnected();
|
950
|
926
|
}
|
951
|
927
|
|
952
|
|
- getEventBus().publish(new ServerConnectedEvent(this));
|
|
928
|
+ windowModel.getEventBus().publish(new ServerConnectedEvent(this));
|
953
|
929
|
}
|
954
|
930
|
|
955
|
931
|
@Override
|
|
@@ -960,7 +936,7 @@ public class Server extends FrameContainer implements Connection {
|
960
|
936
|
@Override
|
961
|
937
|
public void updateIgnoreList() {
|
962
|
938
|
ignoreList.clear();
|
963
|
|
- ignoreList.addAll(getConfigManager().getOptionList("network", "ignorelist"));
|
|
939
|
+ ignoreList.addAll(windowModel.getConfigManager().getOptionList("network", "ignorelist"));
|
964
|
940
|
}
|
965
|
941
|
|
966
|
942
|
@Override
|