Browse Source

DI the logging plugin.

Change-Id: I7b8fd7a83d4431dcf551a171fbb23caeb6100c2e
Reviewed-on: http://gerrit.dmdirc.com/3179
Automatic-Compile: DMDirc Build Manager
Reviewed-by: Greg Holmes <greg@dmdirc.com>
tags/0.8
Chris Smith 10 years ago
parent
commit
652abcd527

+ 11
- 11
src/com/dmdirc/addons/logging/LoggingCommand.java View File

@@ -32,8 +32,10 @@ import com.dmdirc.commandparser.commands.context.CommandContext;
32 32
 import com.dmdirc.interfaces.CommandController;
33 33
 import com.dmdirc.ui.input.AdditionalTabTargets;
34 34
 
35
+import javax.inject.Inject;
36
+
35 37
 /**
36
- * The dcop command retrieves information from a dcop application.
38
+ * The logging command retrieves information from a dcop application.
37 39
  */
38 40
 public class LoggingCommand extends Command implements IntelligentCommand {
39 41
 
@@ -41,20 +43,21 @@ public class LoggingCommand extends Command implements IntelligentCommand {
41 43
     private static final String LOGGING = "logging";
42 44
     /** A command info object for this command. */
43 45
     public static final BaseCommandInfo INFO = new BaseCommandInfo(LOGGING,
44
-            "logging - <set|help> [parameters]",
46
+            "logging <history|help> - view logging related information",
45 47
             CommandType.TYPE_SERVER);
46
-    /** Logging plugin. */
47
-    private final LoggingPlugin plugin;
48
+    /** Logging manager. */
49
+    private final LoggingManager manager;
48 50
 
49 51
     /**
50 52
      * Creates a new instance of this command.
51 53
      *
52 54
      * @param controller The controller to use for command information.
53
-     * @param plugin     The plugin providing logging services.
55
+     * @param manager    The manager providing logging services.
54 56
      */
55
-    public LoggingCommand(final CommandController controller, final LoggingPlugin plugin) {
57
+    @Inject
58
+    public LoggingCommand(final CommandController controller, final LoggingManager manager) {
56 59
         super(controller);
57
-        this.plugin = plugin;
60
+        this.manager = manager;
58 61
     }
59 62
 
60 63
     /** {@inheritDoc} */
@@ -63,13 +66,11 @@ public class LoggingCommand extends Command implements IntelligentCommand {
63 66
             final CommandArguments args, final CommandContext context) {
64 67
         if (args.getArguments().length > 0) {
65 68
             if (args.getArguments()[0].equalsIgnoreCase("history")) {
66
-                if (!plugin.showHistory(origin)) {
69
+                if (!manager.showHistory(origin)) {
67 70
                     sendLine(origin, args.isSilent(), FORMAT_ERROR,
68 71
                             "Unable to open history for this window.");
69 72
                 }
70 73
             } else if (args.getArguments()[0].equalsIgnoreCase("help")) {
71
-                sendLine(origin, args.isSilent(), FORMAT_OUTPUT, LOGGING
72
-                        + " reload           - Reload the logging plugin.");
73 74
                 sendLine(origin, args.isSilent(), FORMAT_OUTPUT, LOGGING
74 75
                         + " history          - Open the history of this window, if available.");
75 76
                 sendLine(origin, args.isSilent(), FORMAT_OUTPUT, LOGGING
@@ -90,7 +91,6 @@ public class LoggingCommand extends Command implements IntelligentCommand {
90 91
             final IntelligentCommandContext context) {
91 92
         final AdditionalTabTargets res = new AdditionalTabTargets();
92 93
         if (arg == 0) {
93
-            res.add("reload");
94 94
             res.add("history");
95 95
             res.add("help");
96 96
             res.excludeAll();

+ 858
- 0
src/com/dmdirc/addons/logging/LoggingManager.java View File

@@ -0,0 +1,858 @@
1
+/*
2
+ * Copyright (c) 2006-2014 DMDirc Developers
3
+ *
4
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
5
+ * of this software and associated documentation files (the "Software"), to deal
6
+ * in the Software without restriction, including without limitation the rights
7
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ * copies of the Software, and to permit persons to whom the Software is
9
+ * furnished to do so, subject to the following conditions:
10
+ *
11
+ * The above copyright notice and this permission notice shall be included in
12
+ * all copies or substantial portions of the Software.
13
+ *
14
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20
+ * SOFTWARE.
21
+ */
22
+
23
+package com.dmdirc.addons.logging;
24
+
25
+import com.dmdirc.Channel;
26
+import com.dmdirc.ClientModule.GlobalConfig;
27
+import com.dmdirc.FrameContainer;
28
+import com.dmdirc.Query;
29
+import com.dmdirc.actions.CoreActionType;
30
+import com.dmdirc.addons.logging.LoggingModule.LoggingDomain;
31
+import com.dmdirc.commandline.CommandLineOptionsModule.Directory;
32
+import com.dmdirc.interfaces.ActionController;
33
+import com.dmdirc.interfaces.ActionListener;
34
+import com.dmdirc.interfaces.Connection;
35
+import com.dmdirc.interfaces.actions.ActionType;
36
+import com.dmdirc.interfaces.config.AggregateConfigProvider;
37
+import com.dmdirc.interfaces.config.ConfigChangeListener;
38
+import com.dmdirc.logger.ErrorLevel;
39
+import com.dmdirc.logger.Logger;
40
+import com.dmdirc.parser.interfaces.ChannelClientInfo;
41
+import com.dmdirc.parser.interfaces.ChannelInfo;
42
+import com.dmdirc.parser.interfaces.ClientInfo;
43
+import com.dmdirc.parser.interfaces.Parser;
44
+import com.dmdirc.ui.WindowManager;
45
+import com.dmdirc.ui.messages.Styliser;
46
+import com.dmdirc.util.URLBuilder;
47
+import com.dmdirc.util.io.ReverseFileReader;
48
+import com.dmdirc.util.io.StreamUtils;
49
+
50
+import java.awt.Color;
51
+import java.io.BufferedWriter;
52
+import java.io.File;
53
+import java.io.FileWriter;
54
+import java.io.IOException;
55
+import java.math.BigInteger;
56
+import java.security.MessageDigest;
57
+import java.security.NoSuchAlgorithmException;
58
+import java.text.DateFormat;
59
+import java.text.SimpleDateFormat;
60
+import java.util.ArrayList;
61
+import java.util.Collection;
62
+import java.util.Collections;
63
+import java.util.Date;
64
+import java.util.HashMap;
65
+import java.util.Map;
66
+import java.util.Stack;
67
+import java.util.Timer;
68
+import java.util.TimerTask;
69
+
70
+import javax.inject.Inject;
71
+import javax.inject.Provider;
72
+import javax.inject.Singleton;
73
+
74
+/**
75
+ * Manages logging activities.
76
+ */
77
+@Singleton
78
+public class LoggingManager implements ActionListener, ConfigChangeListener {
79
+
80
+    /** Date format used for "File Opened At" log. */
81
+    private static final DateFormat OPENED_AT_FORMAT = new SimpleDateFormat(
82
+            "EEEE MMMM dd, yyyy - HH:mm:ss");
83
+    /** This plugin's plugin info. */
84
+    private final String domain;
85
+    /** The action controller to use. */
86
+    private final ActionController actionController;
87
+    /** Global config. */
88
+    private final AggregateConfigProvider config;
89
+    /** The manager to add history windows to. */
90
+    private final WindowManager windowManager;
91
+    /** Map of open files. */
92
+    private final Map<String, OpenFile> openFiles = Collections.synchronizedMap(
93
+            new HashMap<String, OpenFile>());
94
+    private final URLBuilder urlBuilder;
95
+    private final Provider<String> directoryProvider;
96
+    /** Timer used to close idle files. */
97
+    private Timer idleFileTimer;
98
+    /** Cached boolean settings. */
99
+    private boolean networkfolders;
100
+    private boolean filenamehash;
101
+    private boolean addtime;
102
+    private boolean stripcodes;
103
+    private boolean channelmodeprefix;
104
+    private boolean autobackbuffer;
105
+    private boolean backbufferTimestamp;
106
+    private boolean usedate;
107
+    /** Cached string settings. */
108
+    private String timestamp;
109
+    private String usedateformat;
110
+    private String colour;
111
+    /** Cached int settings. */
112
+    private int historyLines;
113
+    private int backbufferLines;
114
+
115
+    @Inject
116
+    public LoggingManager(
117
+            @LoggingDomain final String domain,
118
+            final ActionController actionController,
119
+            @GlobalConfig final AggregateConfigProvider globalConfig,
120
+            final WindowManager windowManager,
121
+            final URLBuilder urlBuilder,
122
+            @Directory(LoggingModule.LOGS_DIRECTORY) final Provider<String> directoryProvider) {
123
+        this.domain = domain;
124
+        this.actionController = actionController;
125
+        this.config = globalConfig;
126
+        this.windowManager = windowManager;
127
+        this.urlBuilder = urlBuilder;
128
+        this.directoryProvider = directoryProvider;
129
+    }
130
+
131
+    public void load() {
132
+        setCachedSettings();
133
+
134
+        final File dir = new File(directoryProvider.get());
135
+        if (dir.exists()) {
136
+            if (!dir.isDirectory()) {
137
+                Logger.userError(ErrorLevel.LOW,
138
+                        "Unable to create logging dir (file exists instead)");
139
+            }
140
+        } else {
141
+            if (!dir.mkdirs()) {
142
+                Logger.userError(ErrorLevel.LOW, "Unable to create logging dir");
143
+            }
144
+        }
145
+
146
+        config.addChangeListener(domain, this);
147
+
148
+        actionController.registerListener(this,
149
+                CoreActionType.CHANNEL_OPENED,
150
+                CoreActionType.CHANNEL_CLOSED,
151
+                CoreActionType.CHANNEL_MESSAGE,
152
+                CoreActionType.CHANNEL_SELF_MESSAGE,
153
+                CoreActionType.CHANNEL_ACTION,
154
+                CoreActionType.CHANNEL_SELF_ACTION,
155
+                CoreActionType.CHANNEL_GOTTOPIC,
156
+                CoreActionType.CHANNEL_TOPICCHANGE,
157
+                CoreActionType.CHANNEL_JOIN,
158
+                CoreActionType.CHANNEL_PART,
159
+                CoreActionType.CHANNEL_QUIT,
160
+                CoreActionType.CHANNEL_KICK,
161
+                CoreActionType.CHANNEL_NICKCHANGE,
162
+                CoreActionType.CHANNEL_MODECHANGE,
163
+                CoreActionType.QUERY_OPENED,
164
+                CoreActionType.QUERY_CLOSED,
165
+                CoreActionType.QUERY_MESSAGE,
166
+                CoreActionType.QUERY_SELF_MESSAGE,
167
+                CoreActionType.QUERY_ACTION,
168
+                CoreActionType.QUERY_SELF_ACTION);
169
+
170
+        // Close idle files every hour.
171
+        idleFileTimer = new Timer("LoggingPlugin Timer");
172
+        idleFileTimer.schedule(new TimerTask() {
173
+            /** {@inheritDoc} */
174
+            @Override
175
+            public void run() {
176
+                timerTask();
177
+            }
178
+        }, 3600000);
179
+    }
180
+
181
+    public void unload() {
182
+        if (idleFileTimer != null) {
183
+            idleFileTimer.cancel();
184
+            idleFileTimer.purge();
185
+        }
186
+
187
+        actionController.unregisterListener(this);
188
+
189
+        synchronized (openFiles) {
190
+            for (OpenFile file : openFiles.values()) {
191
+                StreamUtils.close(file.writer);
192
+            }
193
+            openFiles.clear();
194
+        }
195
+    }
196
+
197
+    /**
198
+     * What to do every hour when the timer fires.
199
+     */
200
+    protected void timerTask() {
201
+        // Oldest time to allow
202
+        final long oldestTime = System.currentTimeMillis() - 3480000;
203
+
204
+        synchronized (openFiles) {
205
+            final Collection<String> old = new ArrayList<>(openFiles.size());
206
+            for (Map.Entry<String, OpenFile> entry : openFiles.entrySet()) {
207
+                if (entry.getValue().lastUsedTime < oldestTime) {
208
+                    StreamUtils.close(entry.getValue().writer);
209
+                    old.add(entry.getKey());
210
+                }
211
+            }
212
+
213
+            openFiles.keySet().removeAll(old);
214
+        }
215
+    }
216
+
217
+    /**
218
+     * Log a query-related event.
219
+     *
220
+     * @param type      The type of the event to process
221
+     * @param format    Format of messages that are about to be sent. (May be null)
222
+     * @param arguments The arguments for the event
223
+     */
224
+    protected void handleQueryEvent(final CoreActionType type, final StringBuffer format,
225
+            final Object... arguments) {
226
+        final Query query = (Query) arguments[0];
227
+        if (query.getConnection() == null) {
228
+            Logger.appError(ErrorLevel.MEDIUM, "Query object has no server (" + type.toString()
229
+                    + ")", new Exception("Query object has no server (" + type.toString() + ")"));
230
+            return;
231
+        }
232
+
233
+        final Parser parser = query.getConnection().getParser();
234
+        ClientInfo client;
235
+
236
+        if (parser == null) {
237
+            // Without a parser object, we might not be able to find the file to log this to.
238
+            if (networkfolders) {
239
+                // We *wont* be able to, so rather than logging to an incorrect file we just won't log.
240
+                return;
241
+            }
242
+            client = null;
243
+        } else {
244
+            client = parser.getClient(query.getHost());
245
+        }
246
+
247
+        final String filename = getLogFile(client);
248
+
249
+        switch (type) {
250
+            case QUERY_OPENED:
251
+                if (autobackbuffer) {
252
+                    showBackBuffer(query, filename);
253
+                }
254
+
255
+                appendLine(filename, "*** Query opened at: %s", OPENED_AT_FORMAT.format(new Date()));
256
+                appendLine(filename, "*** Query with User: %s", query.getHost());
257
+                appendLine(filename, "");
258
+                break;
259
+            case QUERY_CLOSED:
260
+                appendLine(filename, "*** Query closed at: %s", OPENED_AT_FORMAT.format(new Date()));
261
+                if (openFiles.containsKey(filename)) {
262
+                    StreamUtils.close(openFiles.get(filename).writer);
263
+                    openFiles.remove(filename);
264
+                }
265
+                break;
266
+            case QUERY_MESSAGE:
267
+            case QUERY_SELF_MESSAGE:
268
+            case QUERY_ACTION:
269
+            case QUERY_SELF_ACTION:
270
+                final boolean isME = (type == CoreActionType.QUERY_SELF_MESSAGE || type
271
+                        == CoreActionType.QUERY_SELF_ACTION);
272
+                final String overrideNick = isME ? getDisplayName(parser.getLocalClient()) : "";
273
+
274
+                if (type == CoreActionType.QUERY_MESSAGE || type
275
+                        == CoreActionType.QUERY_SELF_MESSAGE) {
276
+                    appendLine(filename, "<%s> %s", getDisplayName(client, overrideNick),
277
+                            arguments[2]);
278
+                } else {
279
+                    appendLine(filename, "* %s %s", getDisplayName(client, overrideNick),
280
+                            arguments[2]);
281
+                }
282
+                break;
283
+        }
284
+    }
285
+
286
+    /**
287
+     * Log a channel-related event.
288
+     *
289
+     * @param type      The type of the event to process
290
+     * @param format    Format of messages that are about to be sent. (May be null)
291
+     * @param arguments The arguments for the event
292
+     */
293
+    protected void handleChannelEvent(final CoreActionType type, final StringBuffer format,
294
+            final Object... arguments) {
295
+        final Channel chan = ((Channel) arguments[0]);
296
+        final ChannelInfo channel = chan.getChannelInfo();
297
+        final String filename = getLogFile(channel);
298
+
299
+        final ChannelClientInfo channelClient = (arguments.length > 1
300
+                && arguments[1] instanceof ChannelClientInfo) ? (ChannelClientInfo) arguments[1]
301
+                : null;
302
+        final ClientInfo client = channelClient == null ? null : channelClient.getClient();
303
+
304
+        final String message = (arguments.length > 2 && arguments[2] instanceof String)
305
+                ? (String) arguments[2] : null;
306
+
307
+        switch (type) {
308
+            case CHANNEL_OPENED:
309
+                if (autobackbuffer) {
310
+                    showBackBuffer(chan, filename);
311
+                }
312
+
313
+                appendLine(filename, "*** Channel opened at: %s", OPENED_AT_FORMAT.
314
+                        format(new Date()));
315
+                appendLine(filename, "");
316
+                break;
317
+            case CHANNEL_CLOSED:
318
+                appendLine(filename, "*** Channel closed at: %s", OPENED_AT_FORMAT.
319
+                        format(new Date()));
320
+                if (openFiles.containsKey(filename)) {
321
+                    StreamUtils.close(openFiles.get(filename).writer);
322
+                    openFiles.remove(filename);
323
+                }
324
+                break;
325
+            case CHANNEL_MESSAGE:
326
+            case CHANNEL_SELF_MESSAGE:
327
+            case CHANNEL_ACTION:
328
+            case CHANNEL_SELF_ACTION:
329
+                if (type == CoreActionType.CHANNEL_MESSAGE || type
330
+                        == CoreActionType.CHANNEL_SELF_MESSAGE) {
331
+                    appendLine(filename, "<%s> %s", getDisplayName(client), message);
332
+                } else {
333
+                    appendLine(filename, "* %s %s", getDisplayName(client), message);
334
+                }
335
+                break;
336
+            case CHANNEL_GOTTOPIC:
337
+                // ActionManager.processEvent(CoreActionType.CHANNEL_GOTTOPIC, this);
338
+                final DateFormat timeFormat = new SimpleDateFormat("HH:mm:ss");
339
+                final DateFormat dateFormat = new SimpleDateFormat("dd/MM/yyyy");
340
+
341
+                appendLine(filename, "*** Topic is: %s", channel.getTopic());
342
+                appendLine(filename, "*** Set at: %s on %s by %s", timeFormat.format(1000 * channel.
343
+                        getTopicTime()), dateFormat.format(1000 * channel.getTopicTime()), channel.
344
+                        getTopicSetter());
345
+                break;
346
+            case CHANNEL_TOPICCHANGE:
347
+                appendLine(filename, "*** %s Changed the topic to: %s",
348
+                        getDisplayName(channelClient), message);
349
+                break;
350
+            case CHANNEL_JOIN:
351
+                appendLine(filename, "*** %s (%s) joined the channel", getDisplayName(channelClient),
352
+                        client.toString());
353
+                break;
354
+            case CHANNEL_PART:
355
+                if (message.isEmpty()) {
356
+                    appendLine(filename, "*** %s (%s) left the channel", getDisplayName(
357
+                            channelClient), client.toString());
358
+                } else {
359
+                    appendLine(filename, "*** %s (%s) left the channel (%s)", getDisplayName(
360
+                            channelClient), client.toString(), message);
361
+                }
362
+                break;
363
+            case CHANNEL_QUIT:
364
+                if (message.isEmpty()) {
365
+                    appendLine(filename, "*** %s (%s) Quit IRC", getDisplayName(channelClient),
366
+                            client.toString());
367
+                } else {
368
+                    appendLine(filename, "*** %s (%s) Quit IRC (%s)", getDisplayName(channelClient),
369
+                            client.toString(), message);
370
+                }
371
+                break;
372
+            case CHANNEL_KICK:
373
+                final String kickReason = (String) arguments[3];
374
+                final ChannelClientInfo kickedClient = (ChannelClientInfo) arguments[2];
375
+
376
+                if (kickReason.isEmpty()) {
377
+                    appendLine(filename, "*** %s was kicked by %s", getDisplayName(kickedClient),
378
+                            getDisplayName(channelClient));
379
+                } else {
380
+                    appendLine(filename, "*** %s was kicked by %s (%s)",
381
+                            getDisplayName(kickedClient), getDisplayName(channelClient), kickReason);
382
+                }
383
+                break;
384
+            case CHANNEL_NICKCHANGE:
385
+                appendLine(filename, "*** %s is now %s", getDisplayName(channelClient, message),
386
+                        getDisplayName(channelClient));
387
+                break;
388
+            case CHANNEL_MODECHANGE:
389
+                if (channelClient.getClient().getNickname().isEmpty()) {
390
+                    appendLine(filename, "*** Channel modes are: %s", message);
391
+                } else {
392
+                    appendLine(filename, "*** %s set modes: %s", getDisplayName(channelClient),
393
+                            message);
394
+                }
395
+                break;
396
+        }
397
+    }
398
+
399
+    /**
400
+     * Process an event of the specified type.
401
+     *
402
+     * @param type      The type of the event to process
403
+     * @param format    Format of messages that are about to be sent. (May be null)
404
+     * @param arguments The arguments for the event
405
+     */
406
+    @Override
407
+    public void processEvent(final ActionType type, final StringBuffer format,
408
+            final Object... arguments) {
409
+        if (type instanceof CoreActionType) {
410
+            final CoreActionType thisType = (CoreActionType) type;
411
+
412
+            switch (thisType) {
413
+                case CHANNEL_OPENED:
414
+                case CHANNEL_CLOSED:
415
+                case CHANNEL_MESSAGE:
416
+                case CHANNEL_SELF_MESSAGE:
417
+                case CHANNEL_ACTION:
418
+                case CHANNEL_SELF_ACTION:
419
+                case CHANNEL_GOTTOPIC:
420
+                case CHANNEL_TOPICCHANGE:
421
+                case CHANNEL_JOIN:
422
+                case CHANNEL_PART:
423
+                case CHANNEL_QUIT:
424
+                case CHANNEL_KICK:
425
+                case CHANNEL_NICKCHANGE:
426
+                case CHANNEL_MODECHANGE:
427
+                    handleChannelEvent(thisType, format, arguments);
428
+                    break;
429
+                case QUERY_OPENED:
430
+                case QUERY_CLOSED:
431
+                case QUERY_MESSAGE:
432
+                case QUERY_SELF_MESSAGE:
433
+                case QUERY_ACTION:
434
+                case QUERY_SELF_ACTION:
435
+                    handleQueryEvent(thisType, format, arguments);
436
+                    break;
437
+                default:
438
+                    break;
439
+            }
440
+        }
441
+    }
442
+
443
+    /** {@inheritDoc} */
444
+    @Override
445
+    public void configChanged(final String domain, final String key) {
446
+        setCachedSettings();
447
+    }
448
+
449
+    /**
450
+     * Add a backbuffer to a frame.
451
+     *
452
+     * @param frame    The frame to add the backbuffer lines to
453
+     * @param filename File to get backbuffer from
454
+     */
455
+    protected void showBackBuffer(final FrameContainer frame, final String filename) {
456
+        if (frame == null) {
457
+            Logger.userError(ErrorLevel.LOW, "Given a null frame");
458
+            return;
459
+        }
460
+
461
+        final File testFile = new File(filename);
462
+        if (testFile.exists()) {
463
+            try {
464
+                final ReverseFileReader file = new ReverseFileReader(testFile);
465
+                // Because the file includes a newline char at the end, an empty line
466
+                // is returned by getLines. To counter this, we call getLines(1) and do
467
+                // nothing with the output.
468
+                file.getLines(1);
469
+                final Stack<String> lines = file.getLines(backbufferLines);
470
+                while (!lines.empty()) {
471
+                    frame.addLine(getColouredString(colour, lines.pop()), backbufferTimestamp);
472
+                }
473
+                file.close();
474
+                frame.addLine(getColouredString(colour, "--- End of backbuffer\n"),
475
+                        backbufferTimestamp);
476
+            } catch (IOException | SecurityException e) {
477
+                Logger.userError(ErrorLevel.LOW, "Unable to show backbuffer (Filename: " + filename
478
+                        + "): " + e.getMessage());
479
+            }
480
+        }
481
+    }
482
+
483
+    /**
484
+     * Get a coloured String. If colour is invalid, IRC Colour 14 will be used.
485
+     *
486
+     * @param colour The colour the string should be (IRC Colour or 6-digit hex colour)
487
+     * @param line   the line to colour
488
+     *
489
+     * @return The given line with the appropriate irc codes appended/prepended to colour it.
490
+     */
491
+    protected static String getColouredString(final String colour, final String line) {
492
+        String res = null;
493
+        if (colour.length() < 3) {
494
+            int num;
495
+
496
+            try {
497
+                num = Integer.parseInt(colour);
498
+            } catch (NumberFormatException ex) {
499
+                num = -1;
500
+            }
501
+
502
+            if (num >= 0 && num <= 15) {
503
+                res = String.format("%c%02d%s%1$c", Styliser.CODE_COLOUR, num, line);
504
+            }
505
+        } else if (colour.length() == 6) {
506
+            try {
507
+                Color.decode("#" + colour);
508
+                res = String.format("%c%s%s%1$c", Styliser.CODE_HEXCOLOUR, colour, line);
509
+            } catch (NumberFormatException ex) { /* Do Nothing */ }
510
+        }
511
+
512
+        if (res == null) {
513
+            res = String.format("%c%02d%s%1$c", Styliser.CODE_COLOUR, 14, line);
514
+        }
515
+        return res;
516
+    }
517
+
518
+    /**
519
+     * Add a line to a file.
520
+     *
521
+     * @param filename Name of file to write to
522
+     * @param format   Format of line to add. (NewLine will be added Automatically)
523
+     * @param args     Arguments for format
524
+     *
525
+     * @return true on success, else false.
526
+     */
527
+    protected boolean appendLine(final String filename, final String format, final Object... args) {
528
+        return appendLine(filename, String.format(format, args));
529
+    }
530
+
531
+    /**
532
+     * Add a line to a file.
533
+     *
534
+     * @param filename Name of file to write to
535
+     * @param line     Line to add. (NewLine will be added Automatically)
536
+     *
537
+     * @return true on success, else false.
538
+     */
539
+    protected boolean appendLine(final String filename, final String line) {
540
+        final StringBuffer finalLine = new StringBuffer();
541
+
542
+        if (addtime) {
543
+            String dateString;
544
+            try {
545
+                final DateFormat dateFormat = new SimpleDateFormat(timestamp);
546
+                dateString = dateFormat.format(new Date()).trim();
547
+            } catch (IllegalArgumentException iae) {
548
+                // Default to known good format
549
+                final DateFormat dateFormat = new SimpleDateFormat("[dd/MM/yyyy HH:mm:ss]");
550
+                dateString = dateFormat.format(new Date()).trim();
551
+
552
+                Logger.userError(ErrorLevel.LOW, "Dateformat String '" + timestamp
553
+                        + "' is invalid. For more information: http://java.sun.com/javase/6/docs/api/java/text/SimpleDateFormat.html");
554
+            }
555
+            finalLine.append(dateString);
556
+            finalLine.append(' ');
557
+        }
558
+
559
+        if (stripcodes) {
560
+            finalLine.append(Styliser.stipControlCodes(line));
561
+        } else {
562
+            finalLine.append(line);
563
+        }
564
+
565
+        BufferedWriter out;
566
+        try {
567
+            if (openFiles.containsKey(filename)) {
568
+                final OpenFile of = openFiles.get(filename);
569
+                of.lastUsedTime = System.currentTimeMillis();
570
+                out = of.writer;
571
+            } else {
572
+                out = new BufferedWriter(new FileWriter(filename, true));
573
+                openFiles.put(filename, new OpenFile(out));
574
+            }
575
+            out.write(finalLine.toString());
576
+            out.newLine();
577
+            out.flush();
578
+            return true;
579
+        } catch (IOException e) {
580
+            /*
581
+             * Do Nothing
582
+             *
583
+             * Makes no sense to keep adding errors to the logger when we can't write to the file,
584
+             * as chances are it will happen on every incomming line.
585
+             */
586
+        }
587
+        return false;
588
+    }
589
+
590
+    /**
591
+     * Get the name of the log file for a specific object.
592
+     *
593
+     * @param obj Object to get name for
594
+     *
595
+     * @return the name of the log file to use for this object.
596
+     */
597
+    protected String getLogFile(final Object obj) {
598
+        final StringBuffer directory = new StringBuffer();
599
+        final StringBuffer file = new StringBuffer();
600
+        String md5String = "";
601
+
602
+        directory.append(directoryProvider.get());
603
+        if (directory.charAt(directory.length() - 1) != File.separatorChar) {
604
+            directory.append(File.separatorChar);
605
+        }
606
+
607
+        if (obj == null) {
608
+            file.append("null.log");
609
+        } else if (obj instanceof ChannelInfo) {
610
+            final ChannelInfo channel = (ChannelInfo) obj;
611
+            if (channel.getParser() != null) {
612
+                addNetworkDir(directory, file, channel.getParser().getNetworkName());
613
+            }
614
+            file.append(sanitise(channel.getName().toLowerCase()));
615
+            md5String = channel.getName();
616
+        } else if (obj instanceof ClientInfo) {
617
+            final ClientInfo client = (ClientInfo) obj;
618
+            if (client.getParser() != null) {
619
+                addNetworkDir(directory, file, client.getParser().getNetworkName());
620
+            }
621
+            file.append(sanitise(client.getNickname().toLowerCase()));
622
+            md5String = client.getNickname();
623
+        } else {
624
+            file.append(sanitise(obj.toString().toLowerCase()));
625
+            md5String = obj.toString();
626
+        }
627
+
628
+        if (usedate) {
629
+            final String dateFormat = usedateformat;
630
+            final String dateDir = new SimpleDateFormat(dateFormat).format(new Date());
631
+            directory.append(dateDir);
632
+            if (directory.charAt(directory.length() - 1) != File.separatorChar) {
633
+                directory.append(File.separatorChar);
634
+            }
635
+
636
+            if (!new File(directory.toString()).exists() && !(new File(directory.toString())).
637
+                    mkdirs()) {
638
+                Logger.userError(ErrorLevel.LOW, "Unable to create date dirs");
639
+            }
640
+        }
641
+
642
+        if (filenamehash) {
643
+            file.append('.');
644
+            file.append(md5(md5String));
645
+        }
646
+        file.append(".log");
647
+
648
+        return directory.toString() + file.toString();
649
+    }
650
+
651
+    /**
652
+     * This function adds the networkName to the log file. It first tries to create a directory for
653
+     * each network, if that fails it will prepend the networkName to the filename instead.
654
+     *
655
+     * @param directory   Current directory name
656
+     * @param file        Current file name
657
+     * @param networkName Name of network
658
+     */
659
+    protected void addNetworkDir(final StringBuffer directory, final StringBuffer file,
660
+            final String networkName) {
661
+        if (!networkfolders) {
662
+            return;
663
+        }
664
+
665
+        final String network = sanitise(networkName.toLowerCase());
666
+
667
+        boolean prependNetwork = false;
668
+
669
+        // Check dir exists
670
+        final File dir = new File(directory.toString() + network + System.getProperty(
671
+                "file.separator"));
672
+        if (dir.exists() && !dir.isDirectory()) {
673
+            Logger.userError(ErrorLevel.LOW,
674
+                    "Unable to create networkfolders dir (file exists instead)");
675
+            // Prepend network name to file instead.
676
+            prependNetwork = true;
677
+        } else if (!dir.exists() && !dir.mkdirs()) {
678
+            Logger.userError(ErrorLevel.LOW, "Unable to create networkfolders dir");
679
+            prependNetwork = true;
680
+        }
681
+
682
+        if (prependNetwork) {
683
+            file.insert(0, " -- ");
684
+            file.insert(0, network);
685
+        } else {
686
+            directory.append(network);
687
+            directory.append(System.getProperty("file.separator"));
688
+        }
689
+    }
690
+
691
+    /**
692
+     * Sanitise a string to be used as a filename.
693
+     *
694
+     * @param name String to sanitise
695
+     *
696
+     * @return Sanitised version of name that can be used as a filename.
697
+     */
698
+    protected static String sanitise(final String name) {
699
+        // Replace illegal chars with
700
+        return name.replaceAll("[^\\w\\.\\s\\-\\#\\&\\_]", "_");
701
+    }
702
+
703
+    /**
704
+     * Get the md5 hash of a string.
705
+     *
706
+     * @param string String to hash
707
+     *
708
+     * @return md5 hash of given string
709
+     */
710
+    protected static String md5(final String string) {
711
+        try {
712
+            final MessageDigest m = MessageDigest.getInstance("MD5");
713
+            m.update(string.getBytes(), 0, string.length());
714
+            return new BigInteger(1, m.digest()).toString(16);
715
+        } catch (NoSuchAlgorithmException e) {
716
+            return "";
717
+        }
718
+    }
719
+
720
+    /**
721
+     * Get name to display for client.
722
+     *
723
+     * @param client The client to get the display name for
724
+     *
725
+     * @return name to display
726
+     */
727
+    protected String getDisplayName(final ClientInfo client) {
728
+        return getDisplayName(client, "");
729
+    }
730
+
731
+    /**
732
+     * Get name to display for client.
733
+     *
734
+     * @param client       The client to get the display name for
735
+     * @param overrideNick Nickname to display instead of real nickname
736
+     *
737
+     * @return name to display
738
+     */
739
+    protected String getDisplayName(final ClientInfo client, final String overrideNick) {
740
+        if (overrideNick.isEmpty()) {
741
+            return (client == null) ? "Unknown Client" : client.getNickname();
742
+        } else {
743
+            return overrideNick;
744
+        }
745
+    }
746
+
747
+    /**
748
+     * Get name to display for channelClient (Taking into account the channelmodeprefix setting).
749
+     *
750
+     * @param channelClient The client to get the display name for
751
+     *
752
+     * @return name to display
753
+     */
754
+    protected String getDisplayName(final ChannelClientInfo channelClient) {
755
+        return getDisplayName(channelClient, "");
756
+    }
757
+
758
+    /**
759
+     * Get name to display for channelClient (Taking into account the channelmodeprefix setting).
760
+     *
761
+     * @param channelClient The client to get the display name for
762
+     * @param overrideNick  Nickname to display instead of real nickname
763
+     *
764
+     * @return name to display
765
+     */
766
+    protected String getDisplayName(final ChannelClientInfo channelClient, final String overrideNick) {
767
+        if (channelClient == null) {
768
+            return (overrideNick.isEmpty()) ? "Unknown Client" : overrideNick;
769
+        } else if (overrideNick.isEmpty()) {
770
+            return channelmodeprefix ? channelClient.toString() : channelClient.getClient().
771
+                    getNickname();
772
+        } else {
773
+            return channelmodeprefix ? channelClient.getImportantModePrefix() + overrideNick
774
+                    : overrideNick;
775
+        }
776
+    }
777
+
778
+    /**
779
+     * Shows the history window for the specified target, if available.
780
+     *
781
+     * @param target The window whose history we're trying to open
782
+     *
783
+     * @return True if the history is available, false otherwise
784
+     */
785
+    protected boolean showHistory(final FrameContainer target) {
786
+        Object component;
787
+
788
+        if (target instanceof Channel) {
789
+            component = ((Channel) target).getChannelInfo();
790
+        } else if (target instanceof Query) {
791
+            final Parser parser = ((Query) target).getConnection().getParser();
792
+            component = parser.getClient(((Query) target).getHost());
793
+        } else if (target instanceof Connection) {
794
+            component = ((Connection) target).getParser();
795
+        } else {
796
+            // Unknown component
797
+            return false;
798
+        }
799
+
800
+        final String log = getLogFile(component);
801
+
802
+        if (!new File(log).exists()) {
803
+            // File doesn't exist
804
+            return false;
805
+        }
806
+
807
+        ReverseFileReader reader;
808
+
809
+        try {
810
+            reader = new ReverseFileReader(log);
811
+        } catch (IOException | SecurityException ex) {
812
+            return false;
813
+        }
814
+
815
+        final HistoryWindow window = new HistoryWindow("History", reader, target, urlBuilder,
816
+                historyLines);
817
+        windowManager.addWindow(target, window);
818
+
819
+        return true;
820
+    }
821
+
822
+    /** Updates cached settings. */
823
+    public void setCachedSettings() {
824
+        networkfolders = config.getOptionBool(domain, "general.networkfolders");
825
+        filenamehash = config.getOptionBool(domain, "advanced.filenamehash");
826
+        addtime = config.getOptionBool(domain, "general.addtime");
827
+        stripcodes = config.getOptionBool(domain, "general.stripcodes");
828
+        channelmodeprefix = config.getOptionBool(domain, "general.channelmodeprefix");
829
+        autobackbuffer = config.getOptionBool(domain, "backbuffer.autobackbuffer");
830
+        backbufferTimestamp = config.getOptionBool(domain, "backbuffer.timestamp");
831
+        usedate = config.getOptionBool(domain, "advanced.usedate");
832
+        timestamp = config.getOption(domain, "general.timestamp");
833
+        usedateformat = config.getOption(domain, "advanced.usedateformat");
834
+        historyLines = config.getOptionInt(domain, "history.lines");
835
+        colour = config.getOption(domain, "backbuffer.colour");
836
+        backbufferLines = config.getOptionInt(domain, "backbuffer.lines");
837
+    }
838
+
839
+    /** Open File. */
840
+    private static class OpenFile {
841
+
842
+        /** Last used time. */
843
+        public long lastUsedTime = System.currentTimeMillis();
844
+        /** Open file's writer. */
845
+        public final BufferedWriter writer;
846
+
847
+        /**
848
+         * Creates a new open file.
849
+         *
850
+         * @param writer Writer that has file open
851
+         */
852
+        protected OpenFile(final BufferedWriter writer) {
853
+            this.writer = writer;
854
+        }
855
+
856
+    }
857
+
858
+}

+ 79
- 0
src/com/dmdirc/addons/logging/LoggingModule.java View File

@@ -0,0 +1,79 @@
1
+/*
2
+ * Copyright (c) 2006-2014 DMDirc Developers
3
+ *
4
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
5
+ * of this software and associated documentation files (the "Software"), to deal
6
+ * in the Software without restriction, including without limitation the rights
7
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ * copies of the Software, and to permit persons to whom the Software is
9
+ * furnished to do so, subject to the following conditions:
10
+ *
11
+ * The above copyright notice and this permission notice shall be included in
12
+ * all copies or substantial portions of the Software.
13
+ *
14
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20
+ * SOFTWARE.
21
+ */
22
+
23
+package com.dmdirc.addons.logging;
24
+
25
+import com.dmdirc.ClientModule;
26
+import com.dmdirc.ClientModule.GlobalConfig;
27
+import com.dmdirc.ClientModule.UserConfig;
28
+import com.dmdirc.commandline.CommandLineOptionsModule.Directory;
29
+import com.dmdirc.commandline.CommandLineOptionsModule.DirectoryType;
30
+import com.dmdirc.interfaces.config.AggregateConfigProvider;
31
+import com.dmdirc.interfaces.config.ConfigProvider;
32
+
33
+import java.io.File;
34
+
35
+import javax.inject.Qualifier;
36
+
37
+import dagger.Module;
38
+import dagger.Provides;
39
+
40
+/**
41
+ * Dependency injection module for the logging plugin.
42
+ */
43
+@Module(addsTo = ClientModule.class, injects = {LoggingManager.class, LoggingCommand.class})
44
+public class LoggingModule {
45
+
46
+    @Qualifier
47
+    public @interface LoggingDomain {
48
+    }
49
+
50
+    public static final String LOGS_DIRECTORY = "logs";
51
+
52
+    private final String domain;
53
+
54
+    public LoggingModule(final String domain) {
55
+        this.domain = domain;
56
+    }
57
+
58
+    @Provides
59
+    @LoggingDomain
60
+    public String getDomain() {
61
+        return domain;
62
+    }
63
+
64
+    @Provides
65
+    @Directory(LOGS_DIRECTORY)
66
+    public String getLogsDirectory(
67
+            @UserConfig final ConfigProvider userConfig,
68
+            @GlobalConfig final AggregateConfigProvider globalConfig,
69
+            @Directory(DirectoryType.BASE) final String baseDirectory,
70
+            @LoggingDomain final String domain) {
71
+        if (!userConfig.hasOptionString(domain, "general.directory")) {
72
+            userConfig.setOption(domain, "general.directory",
73
+                    baseDirectory + "logs" + File.separator);
74
+        }
75
+
76
+        return globalConfig.getOptionString(domain, "general.directory");
77
+    }
78
+
79
+}

+ 16
- 836
src/com/dmdirc/addons/logging/LoggingPlugin.java View File

@@ -22,237 +22,58 @@
22 22
 
23 23
 package com.dmdirc.addons.logging;
24 24
 
25
-import com.dmdirc.Channel;
26
-import com.dmdirc.FrameContainer;
27
-import com.dmdirc.Query;
28
-import com.dmdirc.actions.CoreActionType;
29 25
 import com.dmdirc.config.prefs.PluginPreferencesCategory;
30 26
 import com.dmdirc.config.prefs.PreferencesCategory;
31 27
 import com.dmdirc.config.prefs.PreferencesDialogModel;
32 28
 import com.dmdirc.config.prefs.PreferencesSetting;
33 29
 import com.dmdirc.config.prefs.PreferencesType;
34
-import com.dmdirc.interfaces.ActionController;
35
-import com.dmdirc.interfaces.ActionListener;
36
-import com.dmdirc.interfaces.CommandController;
37
-import com.dmdirc.interfaces.Connection;
38
-import com.dmdirc.interfaces.actions.ActionType;
39
-import com.dmdirc.interfaces.config.AggregateConfigProvider;
40
-import com.dmdirc.interfaces.config.ConfigChangeListener;
41
-import com.dmdirc.interfaces.config.ConfigProvider;
42
-import com.dmdirc.interfaces.config.IdentityController;
43
-import com.dmdirc.logger.ErrorLevel;
44
-import com.dmdirc.logger.Logger;
45
-import com.dmdirc.parser.interfaces.ChannelClientInfo;
46
-import com.dmdirc.parser.interfaces.ChannelInfo;
47
-import com.dmdirc.parser.interfaces.ClientInfo;
48
-import com.dmdirc.parser.interfaces.Parser;
49 30
 import com.dmdirc.plugins.PluginInfo;
50 31
 import com.dmdirc.plugins.implementations.BaseCommandPlugin;
51
-import com.dmdirc.ui.WindowManager;
52
-import com.dmdirc.ui.messages.Styliser;
53
-import com.dmdirc.util.URLBuilder;
54
-import com.dmdirc.util.io.ReverseFileReader;
55
-import com.dmdirc.util.io.StreamUtils;
56 32
 
57
-import java.awt.Color;
58
-import java.io.BufferedWriter;
59
-import java.io.File;
60
-import java.io.FileWriter;
61
-import java.io.IOException;
62
-import java.math.BigInteger;
63
-import java.security.MessageDigest;
64
-import java.security.NoSuchAlgorithmException;
65
-import java.text.DateFormat;
66
-import java.text.SimpleDateFormat;
67
-import java.util.ArrayList;
68
-import java.util.Collection;
69
-import java.util.Collections;
70
-import java.util.Date;
71
-import java.util.HashMap;
72
-import java.util.Map;
73
-import java.util.Stack;
74
-import java.util.Timer;
75
-import java.util.TimerTask;
33
+import dagger.ObjectGraph;
76 34
 
77 35
 /**
78 36
  * Adds logging facility to client.
79 37
  */
80
-public class LoggingPlugin extends BaseCommandPlugin implements ActionListener,
81
-        ConfigChangeListener {
38
+public class LoggingPlugin extends BaseCommandPlugin {
82 39
 
83
-    /** Cached boolean settings. */
84
-    private boolean networkfolders;
85
-    private boolean filenamehash;
86
-    private boolean addtime;
87
-    private boolean stripcodes;
88
-    private boolean channelmodeprefix;
89
-    private boolean autobackbuffer;
90
-    private boolean backbufferTimestamp;
91
-    private boolean usedate;
92
-    /** Cached string settings. */
93
-    private String timestamp;
94
-    private String usedateformat;
95
-    private String logDirectory;
96
-    private String colour;
97
-    /** Cached int settings. */
98
-    private int historyLines;
99
-    private int backbufferLines;
100 40
     /** This plugin's plugin info. */
101 41
     private final PluginInfo pluginInfo;
102
-    /** The action controller to use. */
103
-    private final ActionController actionController;
104
-    /** Global config. */
105
-    private final AggregateConfigProvider config;
106
-    /** Addon identity. */
107
-    private final ConfigProvider identity;
108
-    /** Parent Identity Manager. */
109
-    private final IdentityController identityController;
110
-    /** The manager to add history windows to. */
111
-    private final WindowManager windowManager;
112
-    /** Timer used to close idle files. */
113
-    protected Timer idleFileTimer;
114
-    /** Map of open files. */
115
-    protected final Map<String, OpenFile> openFiles = Collections.synchronizedMap(
116
-            new HashMap<String, OpenFile>());
117
-    /** Date format used for "File Opened At" log. */
118
-    final DateFormat openedAtFormat = new SimpleDateFormat("EEEE MMMM dd, yyyy - HH:mm:ss");
119
-    private final URLBuilder urlBuilder;
42
+
43
+    /** The manager in use. */
44
+    private LoggingManager manager;
120 45
 
121 46
     /**
122 47
      * Creates a new instance of this plugin.
123 48
      *
124
-     * @param pluginInfo         This plugin's plugin info
125
-     * @param actionController   The action controller to register listeners with
126
-     * @param identityController The Identity Manager that controls the current config
127
-     * @param commandController  Command controller to register commands
128
-     * @param windowManager      The manager to add history windows to.
129
-     * @param urlBuilder         The URL builder to use when finding icons.
49
+     * @param pluginInfo This plugin's plugin info
130 50
      */
131
-    public LoggingPlugin(final PluginInfo pluginInfo,
132
-            final ActionController actionController,
133
-            final IdentityController identityController,
134
-            final CommandController commandController,
135
-            final WindowManager windowManager,
136
-            final URLBuilder urlBuilder) {
137
-        super(commandController);
138
-        this.identityController = identityController;
139
-        this.windowManager = windowManager;
140
-        this.urlBuilder = urlBuilder;
141
-
51
+    public LoggingPlugin(final PluginInfo pluginInfo) {
142 52
         this.pluginInfo = pluginInfo;
143
-        this.actionController = actionController;
144
-        config = identityController.getGlobalConfiguration();
145
-        identity = identityController.getAddonSettings();
146
-
147
-        registerCommand(new LoggingCommand(commandController, this), LoggingCommand.INFO);
148 53
     }
149 54
 
150
-    /** {@inheritDoc} */
151 55
     @Override
152
-    public void domainUpdated() {
153
-        identity.setOption(pluginInfo.getDomain(), "general.directory",
154
-                identityController.getConfigurationDirectory() + "logs" + System.getProperty(
155
-                "file.separator"));
56
+    public void load(final PluginInfo pluginInfo, final ObjectGraph graph) {
57
+        super.load(pluginInfo, graph);
58
+
59
+        setObjectGraph(graph.plus(new LoggingModule(pluginInfo.getDomain())));
60
+        manager = getObjectGraph().get(LoggingManager.class);
61
+
62
+        registerCommand(LoggingCommand.class, LoggingCommand.INFO);
156 63
     }
157 64
 
158
-    /**
159
-     * Called when the plugin is loaded.
160
-     */
161 65
     @Override
162 66
     public void onLoad() {
163
-        setCachedSettings();
164
-
165
-        final File dir = new File(logDirectory);
166
-        if (dir.exists()) {
167
-            if (!dir.isDirectory()) {
168
-                Logger.userError(ErrorLevel.LOW,
169
-                        "Unable to create logging dir (file exists instead)");
170
-            }
171
-        } else {
172
-            if (!dir.mkdirs()) {
173
-                Logger.userError(ErrorLevel.LOW, "Unable to create logging dir");
174
-            }
175
-        }
176
-
177
-        config.addChangeListener(pluginInfo.getDomain(), this);
178
-
179
-        actionController.registerListener(this,
180
-                CoreActionType.CHANNEL_OPENED,
181
-                CoreActionType.CHANNEL_CLOSED,
182
-                CoreActionType.CHANNEL_MESSAGE,
183
-                CoreActionType.CHANNEL_SELF_MESSAGE,
184
-                CoreActionType.CHANNEL_ACTION,
185
-                CoreActionType.CHANNEL_SELF_ACTION,
186
-                CoreActionType.CHANNEL_GOTTOPIC,
187
-                CoreActionType.CHANNEL_TOPICCHANGE,
188
-                CoreActionType.CHANNEL_JOIN,
189
-                CoreActionType.CHANNEL_PART,
190
-                CoreActionType.CHANNEL_QUIT,
191
-                CoreActionType.CHANNEL_KICK,
192
-                CoreActionType.CHANNEL_NICKCHANGE,
193
-                CoreActionType.CHANNEL_MODECHANGE,
194
-                CoreActionType.QUERY_OPENED,
195
-                CoreActionType.QUERY_CLOSED,
196
-                CoreActionType.QUERY_MESSAGE,
197
-                CoreActionType.QUERY_SELF_MESSAGE,
198
-                CoreActionType.QUERY_ACTION,
199
-                CoreActionType.QUERY_SELF_ACTION);
200
-
201
-        // Close idle files every hour.
202
-        idleFileTimer = new Timer("LoggingPlugin Timer");
203
-        idleFileTimer.schedule(new TimerTask() {
204
-            /** {@inheritDoc} */
205
-            @Override
206
-            public void run() {
207
-                timerTask();
208
-            }
209
-        }, 3600000);
210 67
         super.onLoad();
68
+        manager.load();
211 69
     }
212 70
 
213
-    /**
214
-     * What to do every hour when the timer fires.
215
-     */
216
-    protected void timerTask() {
217
-        // Oldest time to allow
218
-        final long oldestTime = System.currentTimeMillis() - 3480000;
219
-
220
-        synchronized (openFiles) {
221
-            final Collection<String> old = new ArrayList<>(openFiles.size());
222
-            for (Map.Entry<String, OpenFile> entry : openFiles.entrySet()) {
223
-                if (entry.getValue().lastUsedTime < oldestTime) {
224
-                    StreamUtils.close(entry.getValue().writer);
225
-                    old.add(entry.getKey());
226
-                }
227
-            }
228
-
229
-            openFiles.keySet().removeAll(old);
230
-        }
231
-    }
232
-
233
-    /**
234
-     * Called when this plugin is unloaded.
235
-     */
236 71
     @Override
237 72
     public void onUnload() {
238
-        if (idleFileTimer != null) {
239
-            idleFileTimer.cancel();
240
-            idleFileTimer.purge();
241
-        }
242
-
243
-        actionController.unregisterListener(this);
244
-
245
-        synchronized (openFiles) {
246
-            for (OpenFile file : openFiles.values()) {
247
-                StreamUtils.close(file.writer);
248
-            }
249
-            openFiles.clear();
250
-        }
251
-
252 73
         super.onUnload();
74
+        manager.unload();
253 75
     }
254 76
 
255
-    /** {@inheritDoc} */
256 77
     @Override
257 78
     public void showConfig(final PreferencesDialogModel manager) {
258 79
         final PreferencesCategory general = new PluginPreferencesCategory(
@@ -329,645 +150,4 @@ public class LoggingPlugin extends BaseCommandPlugin implements ActionListener,
329 150
         manager.getCategory("Plugins").addSubCategory(general.setInlineAfter());
330 151
     }
331 152
 
332
-    /**
333
-     * Log a query-related event.
334
-     *
335
-     * @param type      The type of the event to process
336
-     * @param format    Format of messages that are about to be sent. (May be null)
337
-     * @param arguments The arguments for the event
338
-     */
339
-    protected void handleQueryEvent(final CoreActionType type, final StringBuffer format,
340
-            final Object... arguments) {
341
-        final Query query = (Query) arguments[0];
342
-        if (query.getConnection() == null) {
343
-            Logger.appError(ErrorLevel.MEDIUM, "Query object has no server (" + type.toString()
344
-                    + ")", new Exception("Query object has no server (" + type.toString() + ")"));
345
-            return;
346
-        }
347
-
348
-        final Parser parser = query.getConnection().getParser();
349
-        ClientInfo client;
350
-
351
-        if (parser == null) {
352
-            // Without a parser object, we might not be able to find the file to log this to.
353
-            if (networkfolders) {
354
-                // We *wont* be able to, so rather than logging to an incorrect file we just won't log.
355
-                return;
356
-            }
357
-            client = null;
358
-        } else {
359
-            client = parser.getClient(query.getHost());
360
-        }
361
-
362
-        final String filename = getLogFile(client);
363
-
364
-        switch (type) {
365
-            case QUERY_OPENED:
366
-                if (autobackbuffer) {
367
-                    showBackBuffer(query, filename);
368
-                }
369
-
370
-                appendLine(filename, "*** Query opened at: %s", openedAtFormat.format(new Date()));
371
-                appendLine(filename, "*** Query with User: %s", query.getHost());
372
-                appendLine(filename, "");
373
-                break;
374
-            case QUERY_CLOSED:
375
-                appendLine(filename, "*** Query closed at: %s", openedAtFormat.format(new Date()));
376
-                if (openFiles.containsKey(filename)) {
377
-                    StreamUtils.close(openFiles.get(filename).writer);
378
-                    openFiles.remove(filename);
379
-                }
380
-                break;
381
-            case QUERY_MESSAGE:
382
-            case QUERY_SELF_MESSAGE:
383
-            case QUERY_ACTION:
384
-            case QUERY_SELF_ACTION:
385
-                final boolean isME = (type == CoreActionType.QUERY_SELF_MESSAGE || type
386
-                        == CoreActionType.QUERY_SELF_ACTION);
387
-                final String overrideNick = isME ? getDisplayName(parser.getLocalClient()) : "";
388
-
389
-                if (type == CoreActionType.QUERY_MESSAGE || type
390
-                        == CoreActionType.QUERY_SELF_MESSAGE) {
391
-                    appendLine(filename, "<%s> %s", getDisplayName(client, overrideNick),
392
-                            arguments[2]);
393
-                } else {
394
-                    appendLine(filename, "* %s %s", getDisplayName(client, overrideNick),
395
-                            arguments[2]);
396
-                }
397
-                break;
398
-        }
399
-    }
400
-
401
-    /**
402
-     * Log a channel-related event.
403
-     *
404
-     * @param type      The type of the event to process
405
-     * @param format    Format of messages that are about to be sent. (May be null)
406
-     * @param arguments The arguments for the event
407
-     */
408
-    protected void handleChannelEvent(final CoreActionType type, final StringBuffer format,
409
-            final Object... arguments) {
410
-        final Channel chan = ((Channel) arguments[0]);
411
-        final ChannelInfo channel = chan.getChannelInfo();
412
-        final String filename = getLogFile(channel);
413
-
414
-        final ChannelClientInfo channelClient = (arguments.length > 1
415
-                && arguments[1] instanceof ChannelClientInfo) ? (ChannelClientInfo) arguments[1]
416
-                : null;
417
-        final ClientInfo client = channelClient == null ? null : channelClient.getClient();
418
-
419
-        final String message = (arguments.length > 2 && arguments[2] instanceof String)
420
-                ? (String) arguments[2] : null;
421
-
422
-        switch (type) {
423
-            case CHANNEL_OPENED:
424
-                if (autobackbuffer) {
425
-                    showBackBuffer(chan, filename);
426
-                }
427
-
428
-                appendLine(filename, "*** Channel opened at: %s", openedAtFormat.format(new Date()));
429
-                appendLine(filename, "");
430
-                break;
431
-            case CHANNEL_CLOSED:
432
-                appendLine(filename, "*** Channel closed at: %s", openedAtFormat.format(new Date()));
433
-                if (openFiles.containsKey(filename)) {
434
-                    StreamUtils.close(openFiles.get(filename).writer);
435
-                    openFiles.remove(filename);
436
-                }
437
-                break;
438
-            case CHANNEL_MESSAGE:
439
-            case CHANNEL_SELF_MESSAGE:
440
-            case CHANNEL_ACTION:
441
-            case CHANNEL_SELF_ACTION:
442
-                if (type == CoreActionType.CHANNEL_MESSAGE || type
443
-                        == CoreActionType.CHANNEL_SELF_MESSAGE) {
444
-                    appendLine(filename, "<%s> %s", getDisplayName(client), message);
445
-                } else {
446
-                    appendLine(filename, "* %s %s", getDisplayName(client), message);
447
-                }
448
-                break;
449
-            case CHANNEL_GOTTOPIC:
450
-                // ActionManager.processEvent(CoreActionType.CHANNEL_GOTTOPIC, this);
451
-                final DateFormat timeFormat = new SimpleDateFormat("HH:mm:ss");
452
-                final DateFormat dateFormat = new SimpleDateFormat("dd/MM/yyyy");
453
-
454
-                appendLine(filename, "*** Topic is: %s", channel.getTopic());
455
-                appendLine(filename, "*** Set at: %s on %s by %s", timeFormat.format(1000 * channel.
456
-                        getTopicTime()), dateFormat.format(1000 * channel.getTopicTime()), channel.
457
-                        getTopicSetter());
458
-                break;
459
-            case CHANNEL_TOPICCHANGE:
460
-                appendLine(filename, "*** %s Changed the topic to: %s",
461
-                        getDisplayName(channelClient), message);
462
-                break;
463
-            case CHANNEL_JOIN:
464
-                appendLine(filename, "*** %s (%s) joined the channel", getDisplayName(channelClient),
465
-                        client.toString());
466
-                break;
467
-            case CHANNEL_PART:
468
-                if (message.isEmpty()) {
469
-                    appendLine(filename, "*** %s (%s) left the channel", getDisplayName(
470
-                            channelClient), client.toString());
471
-                } else {
472
-                    appendLine(filename, "*** %s (%s) left the channel (%s)", getDisplayName(
473
-                            channelClient), client.toString(), message);
474
-                }
475
-                break;
476
-            case CHANNEL_QUIT:
477
-                if (message.isEmpty()) {
478
-                    appendLine(filename, "*** %s (%s) Quit IRC", getDisplayName(channelClient),
479
-                            client.toString());
480
-                } else {
481
-                    appendLine(filename, "*** %s (%s) Quit IRC (%s)", getDisplayName(channelClient),
482
-                            client.toString(), message);
483
-                }
484
-                break;
485
-            case CHANNEL_KICK:
486
-                final String kickReason = (String) arguments[3];
487
-                final ChannelClientInfo kickedClient = (ChannelClientInfo) arguments[2];
488
-
489
-                if (kickReason.isEmpty()) {
490
-                    appendLine(filename, "*** %s was kicked by %s", getDisplayName(kickedClient),
491
-                            getDisplayName(channelClient));
492
-                } else {
493
-                    appendLine(filename, "*** %s was kicked by %s (%s)",
494
-                            getDisplayName(kickedClient), getDisplayName(channelClient), kickReason);
495
-                }
496
-                break;
497
-            case CHANNEL_NICKCHANGE:
498
-                appendLine(filename, "*** %s is now %s", getDisplayName(channelClient, message),
499
-                        getDisplayName(channelClient));
500
-                break;
501
-            case CHANNEL_MODECHANGE:
502
-                if (channelClient.getClient().getNickname().isEmpty()) {
503
-                    appendLine(filename, "*** Channel modes are: %s", message);
504
-                } else {
505
-                    appendLine(filename, "*** %s set modes: %s", getDisplayName(channelClient),
506
-                            message);
507
-                }
508
-                break;
509
-        }
510
-    }
511
-
512
-    /**
513
-     * Process an event of the specified type.
514
-     *
515
-     * @param type      The type of the event to process
516
-     * @param format    Format of messages that are about to be sent. (May be null)
517
-     * @param arguments The arguments for the event
518
-     */
519
-    @Override
520
-    public void processEvent(final ActionType type, final StringBuffer format,
521
-            final Object... arguments) {
522
-        if (type instanceof CoreActionType) {
523
-            final CoreActionType thisType = (CoreActionType) type;
524
-
525
-            switch (thisType) {
526
-                case CHANNEL_OPENED:
527
-                case CHANNEL_CLOSED:
528
-                case CHANNEL_MESSAGE:
529
-                case CHANNEL_SELF_MESSAGE:
530
-                case CHANNEL_ACTION:
531
-                case CHANNEL_SELF_ACTION:
532
-                case CHANNEL_GOTTOPIC:
533
-                case CHANNEL_TOPICCHANGE:
534
-                case CHANNEL_JOIN:
535
-                case CHANNEL_PART:
536
-                case CHANNEL_QUIT:
537
-                case CHANNEL_KICK:
538
-                case CHANNEL_NICKCHANGE:
539
-                case CHANNEL_MODECHANGE:
540
-                    handleChannelEvent(thisType, format, arguments);
541
-                    break;
542
-                case QUERY_OPENED:
543
-                case QUERY_CLOSED:
544
-                case QUERY_MESSAGE:
545
-                case QUERY_SELF_MESSAGE:
546
-                case QUERY_ACTION:
547
-                case QUERY_SELF_ACTION:
548
-                    handleQueryEvent(thisType, format, arguments);
549
-                    break;
550
-                default:
551
-                    break;
552
-            }
553
-        }
554
-    }
555
-
556
-    /** {@inheritDoc} */
557
-    @Override
558
-    public void configChanged(final String domain, final String key) {
559
-        setCachedSettings();
560
-    }
561
-
562
-    /**
563
-     * Add a backbuffer to a frame.
564
-     *
565
-     * @param frame    The frame to add the backbuffer lines to
566
-     * @param filename File to get backbuffer from
567
-     */
568
-    protected void showBackBuffer(final FrameContainer frame, final String filename) {
569
-        if (frame == null) {
570
-            Logger.userError(ErrorLevel.LOW, "Given a null frame");
571
-            return;
572
-        }
573
-
574
-        final File testFile = new File(filename);
575
-        if (testFile.exists()) {
576
-            try {
577
-                final ReverseFileReader file = new ReverseFileReader(testFile);
578
-                // Because the file includes a newline char at the end, an empty line
579
-                // is returned by getLines. To counter this, we call getLines(1) and do
580
-                // nothing with the output.
581
-                file.getLines(1);
582
-                final Stack<String> lines = file.getLines(backbufferLines);
583
-                while (!lines.empty()) {
584
-                    frame.addLine(getColouredString(colour, lines.pop()), backbufferTimestamp);
585
-                }
586
-                file.close();
587
-                frame.addLine(getColouredString(colour, "--- End of backbuffer\n"),
588
-                        backbufferTimestamp);
589
-            } catch (IOException | SecurityException e) {
590
-                Logger.userError(ErrorLevel.LOW, "Unable to show backbuffer (Filename: " + filename
591
-                        + "): " + e.getMessage());
592
-            }
593
-        }
594
-    }
595
-
596
-    /**
597
-     * Get a coloured String. If colour is invalid, IRC Colour 14 will be used.
598
-     *
599
-     * @param colour The colour the string should be (IRC Colour or 6-digit hex colour)
600
-     * @param line   the line to colour
601
-     *
602
-     * @return The given line with the appropriate irc codes appended/prepended to colour it.
603
-     */
604
-    protected static String getColouredString(final String colour, final String line) {
605
-        String res = null;
606
-        if (colour.length() < 3) {
607
-            int num;
608
-
609
-            try {
610
-                num = Integer.parseInt(colour);
611
-            } catch (NumberFormatException ex) {
612
-                num = -1;
613
-            }
614
-
615
-            if (num >= 0 && num <= 15) {
616
-                res = String.format("%c%02d%s%1$c", Styliser.CODE_COLOUR, num, line);
617
-            }
618
-        } else if (colour.length() == 6) {
619
-            try {
620
-                Color.decode("#" + colour);
621
-                res = String.format("%c%s%s%1$c", Styliser.CODE_HEXCOLOUR, colour, line);
622
-            } catch (NumberFormatException ex) { /* Do Nothing */ }
623
-        }
624
-
625
-        if (res == null) {
626
-            res = String.format("%c%02d%s%1$c", Styliser.CODE_COLOUR, 14, line);
627
-        }
628
-        return res;
629
-    }
630
-
631
-    /**
632
-     * Add a line to a file.
633
-     *
634
-     * @param filename Name of file to write to
635
-     * @param format   Format of line to add. (NewLine will be added Automatically)
636
-     * @param args     Arguments for format
637
-     *
638
-     * @return true on success, else false.
639
-     */
640
-    protected boolean appendLine(final String filename, final String format, final Object... args) {
641
-        return appendLine(filename, String.format(format, args));
642
-    }
643
-
644
-    /**
645
-     * Add a line to a file.
646
-     *
647
-     * @param filename Name of file to write to
648
-     * @param line     Line to add. (NewLine will be added Automatically)
649
-     *
650
-     * @return true on success, else false.
651
-     */
652
-    protected boolean appendLine(final String filename, final String line) {
653
-        final StringBuffer finalLine = new StringBuffer();
654
-
655
-        if (addtime) {
656
-            String dateString;
657
-            try {
658
-                final DateFormat dateFormat = new SimpleDateFormat(timestamp);
659
-                dateString = dateFormat.format(new Date()).trim();
660
-            } catch (IllegalArgumentException iae) {
661
-                // Default to known good format
662
-                final DateFormat dateFormat = new SimpleDateFormat("[dd/MM/yyyy HH:mm:ss]");
663
-                dateString = dateFormat.format(new Date()).trim();
664
-
665
-                Logger.userError(ErrorLevel.LOW, "Dateformat String '" + timestamp
666
-                        + "' is invalid. For more information: http://java.sun.com/javase/6/docs/api/java/text/SimpleDateFormat.html");
667
-            }
668
-            finalLine.append(dateString);
669
-            finalLine.append(' ');
670
-        }
671
-
672
-        if (stripcodes) {
673
-            finalLine.append(Styliser.stipControlCodes(line));
674
-        } else {
675
-            finalLine.append(line);
676
-        }
677
-
678
-        BufferedWriter out;
679
-        try {
680
-            if (openFiles.containsKey(filename)) {
681
-                final OpenFile of = openFiles.get(filename);
682
-                of.lastUsedTime = System.currentTimeMillis();
683
-                out = of.writer;
684
-            } else {
685
-                out = new BufferedWriter(new FileWriter(filename, true));
686
-                openFiles.put(filename, new OpenFile(out));
687
-            }
688
-            out.write(finalLine.toString());
689
-            out.newLine();
690
-            out.flush();
691
-            return true;
692
-        } catch (IOException e) {
693
-            /*
694
-             * Do Nothing
695
-             *
696
-             * Makes no sense to keep adding errors to the logger when we can't write to the file,
697
-             * as chances are it will happen on every incomming line.
698
-             */
699
-        }
700
-        return false;
701
-    }
702
-
703
-    /**
704
-     * Get the name of the log file for a specific object.
705
-     *
706
-     * @param obj Object to get name for
707
-     *
708
-     * @return the name of the log file to use for this object.
709
-     */
710
-    protected String getLogFile(final Object obj) {
711
-        final StringBuffer directory = new StringBuffer();
712
-        final StringBuffer file = new StringBuffer();
713
-        String md5String = "";
714
-
715
-        directory.append(logDirectory);
716
-        if (directory.charAt(directory.length() - 1) != File.separatorChar) {
717
-            directory.append(File.separatorChar);
718
-        }
719
-
720
-        if (obj == null) {
721
-            file.append("null.log");
722
-        } else if (obj instanceof ChannelInfo) {
723
-            final ChannelInfo channel = (ChannelInfo) obj;
724
-            if (channel.getParser() != null) {
725
-                addNetworkDir(directory, file, channel.getParser().getNetworkName());
726
-            }
727
-            file.append(sanitise(channel.getName().toLowerCase()));
728
-            md5String = channel.getName();
729
-        } else if (obj instanceof ClientInfo) {
730
-            final ClientInfo client = (ClientInfo) obj;
731
-            if (client.getParser() != null) {
732
-                addNetworkDir(directory, file, client.getParser().getNetworkName());
733
-            }
734
-            file.append(sanitise(client.getNickname().toLowerCase()));
735
-            md5String = client.getNickname();
736
-        } else {
737
-            file.append(sanitise(obj.toString().toLowerCase()));
738
-            md5String = obj.toString();
739
-        }
740
-
741
-        if (usedate) {
742
-            final String dateFormat = usedateformat;
743
-            final String dateDir = new SimpleDateFormat(dateFormat).format(new Date());
744
-            directory.append(dateDir);
745
-            if (directory.charAt(directory.length() - 1) != File.separatorChar) {
746
-                directory.append(File.separatorChar);
747
-            }
748
-
749
-            if (!new File(directory.toString()).exists() && !(new File(directory.toString())).
750
-                    mkdirs()) {
751
-                Logger.userError(ErrorLevel.LOW, "Unable to create date dirs");
752
-            }
753
-        }
754
-
755
-        if (filenamehash) {
756
-            file.append('.');
757
-            file.append(md5(md5String));
758
-        }
759
-        file.append(".log");
760
-
761
-        return directory.toString() + file.toString();
762
-    }
763
-
764
-    /**
765
-     * This function adds the networkName to the log file. It first tries to create a directory for
766
-     * each network, if that fails it will prepend the networkName to the filename instead.
767
-     *
768
-     * @param directory   Current directory name
769
-     * @param file        Current file name
770
-     * @param networkName Name of network
771
-     */
772
-    protected void addNetworkDir(final StringBuffer directory, final StringBuffer file,
773
-            final String networkName) {
774
-        if (!networkfolders) {
775
-            return;
776
-        }
777
-
778
-        final String network = sanitise(networkName.toLowerCase());
779
-
780
-        boolean prependNetwork = false;
781
-
782
-        // Check dir exists
783
-        final File dir = new File(directory.toString() + network + System.getProperty(
784
-                "file.separator"));
785
-        if (dir.exists() && !dir.isDirectory()) {
786
-            Logger.userError(ErrorLevel.LOW,
787
-                    "Unable to create networkfolders dir (file exists instead)");
788
-            // Prepend network name to file instead.
789
-            prependNetwork = true;
790
-        } else if (!dir.exists() && !dir.mkdirs()) {
791
-            Logger.userError(ErrorLevel.LOW, "Unable to create networkfolders dir");
792
-            prependNetwork = true;
793
-        }
794
-
795
-        if (prependNetwork) {
796
-            file.insert(0, " -- ");
797
-            file.insert(0, network);
798
-        } else {
799
-            directory.append(network);
800
-            directory.append(System.getProperty("file.separator"));
801
-        }
802
-    }
803
-
804
-    /**
805
-     * Sanitise a string to be used as a filename.
806
-     *
807
-     * @param name String to sanitise
808
-     *
809
-     * @return Sanitised version of name that can be used as a filename.
810
-     */
811
-    protected static String sanitise(final String name) {
812
-        // Replace illegal chars with
813
-        return name.replaceAll("[^\\w\\.\\s\\-\\#\\&\\_]", "_");
814
-    }
815
-
816
-    /**
817
-     * Get the md5 hash of a string.
818
-     *
819
-     * @param string String to hash
820
-     *
821
-     * @return md5 hash of given string
822
-     */
823
-    protected static String md5(final String string) {
824
-        try {
825
-            final MessageDigest m = MessageDigest.getInstance("MD5");
826
-            m.update(string.getBytes(), 0, string.length());
827
-            return new BigInteger(1, m.digest()).toString(16);
828
-        } catch (NoSuchAlgorithmException e) {
829
-            return "";
830
-        }
831
-    }
832
-
833
-    /**
834
-     * Get name to display for client.
835
-     *
836
-     * @param client The client to get the display name for
837
-     *
838
-     * @return name to display
839
-     */
840
-    protected String getDisplayName(final ClientInfo client) {
841
-        return getDisplayName(client, "");
842
-    }
843
-
844
-    /**
845
-     * Get name to display for client.
846
-     *
847
-     * @param client       The client to get the display name for
848
-     * @param overrideNick Nickname to display instead of real nickname
849
-     *
850
-     * @return name to display
851
-     */
852
-    protected String getDisplayName(final ClientInfo client, final String overrideNick) {
853
-        if (overrideNick.isEmpty()) {
854
-            return (client == null) ? "Unknown Client" : client.getNickname();
855
-        } else {
856
-            return overrideNick;
857
-        }
858
-    }
859
-
860
-    /**
861
-     * Get name to display for channelClient (Taking into account the channelmodeprefix setting).
862
-     *
863
-     * @param channelClient The client to get the display name for
864
-     *
865
-     * @return name to display
866
-     */
867
-    protected String getDisplayName(final ChannelClientInfo channelClient) {
868
-        return getDisplayName(channelClient, "");
869
-    }
870
-
871
-    /**
872
-     * Get name to display for channelClient (Taking into account the channelmodeprefix setting).
873
-     *
874
-     * @param channelClient The client to get the display name for
875
-     * @param overrideNick  Nickname to display instead of real nickname
876
-     *
877
-     * @return name to display
878
-     */
879
-    protected String getDisplayName(final ChannelClientInfo channelClient, final String overrideNick) {
880
-        if (channelClient == null) {
881
-            return (overrideNick.isEmpty()) ? "Unknown Client" : overrideNick;
882
-        } else if (overrideNick.isEmpty()) {
883
-            return channelmodeprefix ? channelClient.toString() : channelClient.getClient().
884
-                    getNickname();
885
-        } else {
886
-            return channelmodeprefix ? channelClient.getImportantModePrefix() + overrideNick
887
-                    : overrideNick;
888
-        }
889
-    }
890
-
891
-    /**
892
-     * Shows the history window for the specified target, if available.
893
-     *
894
-     * @param target The window whose history we're trying to open
895
-     *
896
-     * @return True if the history is available, false otherwise
897
-     */
898
-    protected boolean showHistory(final FrameContainer target) {
899
-        Object component;
900
-
901
-        if (target instanceof Channel) {
902
-            component = ((Channel) target).getChannelInfo();
903
-        } else if (target instanceof Query) {
904
-            final Parser parser = ((Query) target).getConnection().getParser();
905
-            component = parser.getClient(((Query) target).getHost());
906
-        } else if (target instanceof Connection) {
907
-            component = ((Connection) target).getParser();
908
-        } else {
909
-            // Unknown component
910
-            return false;
911
-        }
912
-
913
-        final String log = getLogFile(component);
914
-
915
-        if (!new File(log).exists()) {
916
-            // File doesn't exist
917
-            return false;
918
-        }
919
-
920
-        ReverseFileReader reader;
921
-
922
-        try {
923
-            reader = new ReverseFileReader(log);
924
-        } catch (IOException | SecurityException ex) {
925
-            return false;
926
-        }
927
-
928
-        final HistoryWindow window = new HistoryWindow("History", reader, target, urlBuilder,
929
-                historyLines);
930
-        windowManager.addWindow(target, window);
931
-
932
-        return true;
933
-    }
934
-
935
-    /** Updates cached settings. */
936
-    public void setCachedSettings() {
937
-        networkfolders = config.getOptionBool(pluginInfo.getDomain(), "general.networkfolders");
938
-        filenamehash = config.getOptionBool(pluginInfo.getDomain(), "advanced.filenamehash");
939
-        addtime = config.getOptionBool(pluginInfo.getDomain(), "general.addtime");
940
-        stripcodes = config.getOptionBool(pluginInfo.getDomain(), "general.stripcodes");
941
-        channelmodeprefix = config.getOptionBool(pluginInfo.getDomain(),
942
-                "general.channelmodeprefix");
943
-        autobackbuffer = config.getOptionBool(pluginInfo.getDomain(), "backbuffer.autobackbuffer");
944
-        backbufferTimestamp = config.getOptionBool(pluginInfo.getDomain(), "backbuffer.timestamp");
945
-        usedate = config.getOptionBool(pluginInfo.getDomain(), "advanced.usedate");
946
-        timestamp = config.getOption(pluginInfo.getDomain(), "general.timestamp");
947
-        usedateformat = config.getOption(pluginInfo.getDomain(), "advanced.usedateformat");
948
-        historyLines = config.getOptionInt(pluginInfo.getDomain(), "history.lines");
949
-        colour = config.getOption(pluginInfo.getDomain(), "backbuffer.colour");
950
-        backbufferLines = config.getOptionInt(pluginInfo.getDomain(), "backbuffer.lines");
951
-        logDirectory = config.getOption(pluginInfo.getDomain(), "general.directory");
952
-    }
953
-
954
-    /** Open File. */
955
-    protected static class OpenFile {
956
-
957
-        /** Last used time. */
958
-        public long lastUsedTime = System.currentTimeMillis();
959
-        /** Open file's writer. */
960
-        public BufferedWriter writer = null;
961
-
962
-        /**
963
-         * Creates a new open file.
964
-         *
965
-         * @param writer Writer that has file open
966
-         */
967
-        protected OpenFile(final BufferedWriter writer) {
968
-            this.writer = writer;
969
-        }
970
-
971
-    }
972
-
973 153
 }

Loading…
Cancel
Save