1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.log4j.chainsaw.vfs;
18
19 import org.apache.commons.vfs.*;
20 import org.apache.commons.vfs.provider.URLFileName;
21 import org.apache.commons.vfs.provider.sftp.SftpFileSystemConfigBuilder;
22 import org.apache.commons.vfs.util.RandomAccessMode;
23 import org.apache.log4j.chainsaw.receivers.VisualReceiver;
24 import org.apache.log4j.varia.LogFilePatternReceiver;
25
26 import javax.swing.*;
27 import java.awt.*;
28 import java.io.*;
29 import java.util.zip.GZIPInputStream;
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145 public class VFSLogFilePatternReceiver extends LogFilePatternReceiver implements VisualReceiver {
146
147 private boolean promptForUserInfo = false;
148 private Container container;
149 private final Object waitForContainerLock = new Object();
150 private boolean autoReconnect;
151 private VFSReader vfsReader;
152
153 public VFSLogFilePatternReceiver() {
154 super();
155 }
156
157 public void shutdown() {
158 getLogger().info("shutdown VFSLogFilePatternReceiver");
159 active = false;
160 container = null;
161 if (vfsReader != null) {
162 vfsReader.terminate();
163 vfsReader = null;
164 }
165 }
166
167
168
169
170
171
172
173 public void setPromptForUserInfo(boolean promptForUserInfo) {
174 this.promptForUserInfo = promptForUserInfo;
175 }
176
177 public boolean isPromptForUserInfo() {
178 return promptForUserInfo;
179 }
180
181
182
183
184
185
186 public boolean isAutoReconnect() {
187 return autoReconnect;
188 }
189
190
191
192
193
194
195 public void setAutoReconnect(boolean autoReconnect) {
196 this.autoReconnect = autoReconnect;
197 }
198
199
200
201
202
203 public void setContainer(Container container) {
204 if (promptForUserInfo) {
205 synchronized (waitForContainerLock) {
206 this.container = container;
207 waitForContainerLock.notify();
208 }
209 }
210 }
211
212
213
214
215 public void activateOptions() {
216
217 active = true;
218
219 if (promptForUserInfo && !getFileURL().contains("@")) {
220
221
222
223
224
225
226
227
228
229 new Thread(() -> {
230 synchronized (waitForContainerLock) {
231 while (container == null) {
232 try {
233 waitForContainerLock.wait(1000);
234 getLogger().debug("waiting for setContainer call");
235 } catch (InterruptedException ie) {
236 }
237 }
238 }
239
240 Frame containerFrame1;
241 if (container instanceof Frame) {
242 containerFrame1 = (Frame) container;
243 } else {
244 synchronized (waitForContainerLock) {
245
246 while ((containerFrame1 = (Frame) SwingUtilities.getAncestorOfClass(Frame.class, container)) == null) {
247 try {
248 waitForContainerLock.wait(1000);
249 getLogger().debug("waiting for container's frame to be available");
250 } catch (InterruptedException ie) {
251 }
252 }
253 }
254 }
255 final Frame containerFrame = containerFrame1;
256
257 SwingUtilities.invokeLater(() -> {
258 Frame owner = null;
259 if (container != null) {
260 owner = (Frame) SwingUtilities.getAncestorOfClass(Frame.class, containerFrame);
261 }
262 final UserNamePasswordDialog f = new UserNamePasswordDialog(owner);
263 f.pack();
264 Dimension d = Toolkit.getDefaultToolkit().getScreenSize();
265 f.setLocation(d.width / 2, d.height / 2);
266 f.setVisible(true);
267 if (null == f.getUserName() || null == f.getPassword()) {
268 getLogger().info("Username and password not both provided, not using credentials");
269 } else {
270 String oldURL = getFileURL();
271 int index = oldURL.indexOf("://");
272 String firstPart = oldURL.substring(0, index);
273 String lastPart = oldURL.substring(index + "://".length());
274 setFileURL(firstPart + "://" + f.getUserName() + ":" + new String(f.getPassword()) + "@" + lastPart);
275
276 setHost(oldURL.substring(0, index + "://".length()));
277 setPath(oldURL.substring(index + "://".length()));
278 }
279 vfsReader = new VFSReader();
280 new Thread(vfsReader).start();
281 });
282 }).start();
283 } else {
284
285 String oldURL = getFileURL();
286 if (oldURL != null && oldURL.contains(":/") && !oldURL.contains("://")) {
287 int index = oldURL.indexOf(":/");
288 String lastPart = oldURL.substring(index + ":/".length());
289 int passEndIndex = lastPart.indexOf("@");
290 if (passEndIndex > -1) {
291 setHost(oldURL.substring(0, index + ":/".length()));
292 setPath(lastPart.substring(passEndIndex + 1));
293 }
294 vfsReader = new VFSReader();
295 new Thread(vfsReader).start();
296 } else if (oldURL != null && oldURL.contains("://")) {
297
298 int index = oldURL.indexOf("://");
299 String lastPart = oldURL.substring(index + "://".length());
300 int passEndIndex = lastPart.indexOf("@");
301 if (passEndIndex > -1) {
302 setHost(oldURL.substring(0, index + "://".length()));
303 setPath(lastPart.substring(passEndIndex + 1));
304 }
305 vfsReader = new VFSReader();
306 new Thread(vfsReader).start();
307 } else {
308 getLogger().info("null URL - unable to parse file");
309 }
310 }
311 }
312
313 private class VFSReader implements Runnable {
314 private boolean terminated = false;
315 private Reader reader;
316 private FileObject fileObject;
317
318 private boolean isGZip(String fileName) {
319 return fileName.endsWith( ".gz" );
320 }
321
322 public void run() {
323
324 while (reader == null && !terminated) {
325 int atIndex = getFileURL().indexOf("@");
326 int protocolIndex = getFileURL().indexOf("://");
327
328 String loggableFileURL = atIndex > -1 ? getFileURL().substring(0, protocolIndex + "://".length()) + "username:password" + getFileURL().substring(atIndex) : getFileURL();
329 getLogger().info("attempting to load file: " + loggableFileURL);
330 try {
331 FileSystemManager fileSystemManager = VFS.getManager();
332 FileSystemOptions opts = new FileSystemOptions();
333
334 try {
335 SftpFileSystemConfigBuilder.getInstance().setStrictHostKeyChecking(opts, "no");
336 } catch (NoClassDefFoundError ncdfe) {
337 getLogger().warn("JSch not on classpath!", ncdfe);
338 }
339
340 synchronized (fileSystemManager) {
341 fileObject = fileSystemManager.resolveFile(getFileURL(), opts);
342 if (fileObject.exists()) {
343 reader = new InputStreamReader(fileObject.getContent().getInputStream(), "UTF-8");
344
345
346 if (fileObject.getName() instanceof URLFileName) {
347 URLFileName urlFileName = (URLFileName) fileObject.getName();
348 setHost(urlFileName.getHostName());
349 setPath(urlFileName.getPath());
350 }
351 } else {
352 getLogger().info(loggableFileURL + " not available - will re-attempt to load after waiting " + MISSING_FILE_RETRY_MILLIS + " millis");
353 }
354 }
355 } catch (FileSystemException fse) {
356 getLogger().info(loggableFileURL + " not available - may be due to incorrect credentials, but will re-attempt to load after waiting " + MISSING_FILE_RETRY_MILLIS + " millis", fse);
357 } catch (UnsupportedEncodingException e) {
358 getLogger().info("UTF-8 not available", e);
359 }
360 if (reader == null) {
361 synchronized (this) {
362 try {
363 wait(MISSING_FILE_RETRY_MILLIS);
364 } catch (InterruptedException ie) {
365 }
366 }
367 }
368 }
369 if (terminated) {
370
371 return;
372 }
373 initialize();
374 getLogger().debug(getPath() + " exists");
375 boolean readingFinished = false;
376
377 do {
378 long lastFilePointer = 0;
379 long lastFileSize = 0;
380 createPattern();
381 try {
382 do {
383 FileSystemManager fileSystemManager = VFS.getManager();
384 FileSystemOptions opts = new FileSystemOptions();
385
386 try {
387 SftpFileSystemConfigBuilder.getInstance().setStrictHostKeyChecking(opts, "no");
388 } catch (NoClassDefFoundError ncdfe) {
389 getLogger().warn("JSch not on classpath!", ncdfe);
390 }
391
392
393 synchronized (fileSystemManager) {
394 if (fileObject != null) {
395 fileObject.getFileSystem().getFileSystemManager().closeFileSystem(fileObject.getFileSystem());
396 fileObject.close();
397 fileObject = null;
398 }
399
400 fileObject = fileSystemManager.resolveFile(getFileURL(), opts);
401 }
402
403
404 boolean fileLarger = false;
405 if (fileObject != null && fileObject.exists()) {
406 try {
407
408 fileObject.refresh();
409 } catch (Error err) {
410 getLogger().info(getPath() + " - unable to refresh fileobject", err);
411 }
412
413 if (isGZip(getFileURL())) {
414 InputStream gzipStream = new GZIPInputStream(fileObject.getContent().getInputStream());
415 Reader decoder = new InputStreamReader(gzipStream, "UTF-8");
416 BufferedReader bufferedReader = new BufferedReader(decoder);
417 process(bufferedReader);
418 readingFinished = true;
419 }
420
421 if (fileObject.getContent().getSize() < lastFileSize) {
422 reader = new InputStreamReader(fileObject.getContent().getInputStream(), "UTF-8");
423 getLogger().debug(getPath() + " was truncated");
424 lastFileSize = 0;
425 lastFilePointer = 0;
426 } else if (fileObject.getContent().getSize() > lastFileSize) {
427 fileLarger = true;
428 RandomAccessContent rac = fileObject.getContent().getRandomAccessContent(RandomAccessMode.READ);
429 rac.seek(lastFilePointer);
430 reader = new InputStreamReader(rac.getInputStream(), "UTF-8");
431 BufferedReader bufferedReader = new BufferedReader(reader);
432 process(bufferedReader);
433 lastFilePointer = rac.getFilePointer();
434 lastFileSize = fileObject.getContent().getSize();
435 rac.close();
436 }
437 try {
438 if (reader != null) {
439 reader.close();
440 reader = null;
441 }
442 } catch (IOException ioe) {
443 getLogger().debug(getPath() + " - unable to close reader", ioe);
444 }
445 } else {
446 getLogger().info(getPath() + " - not available - will re-attempt to load after waiting " + getWaitMillis() + " millis");
447 }
448
449 try {
450 synchronized (this) {
451 wait(getWaitMillis());
452 }
453 } catch (InterruptedException ie) {
454 }
455 if (isTailing() && fileLarger && !terminated) {
456 getLogger().debug(getPath() + " - tailing file - file size: " + lastFileSize);
457 }
458 } while (isTailing() && !terminated && !readingFinished);
459 } catch (IOException ioe) {
460 getLogger().info(getPath() + " - exception processing file", ioe);
461 try {
462 if (fileObject != null) {
463 fileObject.close();
464 }
465 } catch (FileSystemException e) {
466 getLogger().info(getPath() + " - exception processing file", e);
467 }
468 try {
469 synchronized (this) {
470 wait(getWaitMillis());
471 }
472 } catch (InterruptedException ie) {
473 }
474 }
475 } while (isAutoReconnect() && !terminated && !readingFinished);
476 getLogger().debug(getPath() + " - processing complete");
477 }
478
479 public void terminate() {
480 terminated = true;
481 }
482 }
483
484 public class UserNamePasswordDialog extends JDialog {
485 private String userName;
486 private char[] password;
487
488 private UserNamePasswordDialog(Frame containerFrame) {
489 super(containerFrame, "Login", true);
490 JPanel panel = new JPanel(new GridBagLayout());
491 GridBagConstraints gc = new GridBagConstraints();
492 gc.fill = GridBagConstraints.NONE;
493
494 gc.anchor = GridBagConstraints.NORTH;
495 gc.gridx = 0;
496 gc.gridy = 0;
497 gc.gridwidth = 3;
498 gc.insets = new Insets(7, 7, 7, 7);
499 panel.add(new JLabel("URI: " + getFileURL()), gc);
500
501 gc.gridx = 0;
502 gc.gridy = 1;
503 gc.gridwidth = 1;
504 gc.insets = new Insets(2, 2, 2, 2);
505 panel.add(new JLabel("Username"), gc);
506
507 gc.gridx = 1;
508 gc.gridy = 1;
509 gc.gridwidth = 2;
510 gc.weightx = 1.0;
511 gc.fill = GridBagConstraints.HORIZONTAL;
512
513 final JTextField userNameTextField = new JTextField(15);
514 panel.add(userNameTextField, gc);
515
516 gc.gridx = 0;
517 gc.gridy = 2;
518 gc.gridwidth = 1;
519 gc.fill = GridBagConstraints.NONE;
520
521 panel.add(new JLabel("Password"), gc);
522
523 gc.gridx = 1;
524 gc.gridy = 2;
525 gc.gridwidth = 2;
526 gc.fill = GridBagConstraints.HORIZONTAL;
527
528 final JPasswordField passwordTextField = new JPasswordField(15);
529 panel.add(passwordTextField, gc);
530
531 gc.gridy = 3;
532 gc.anchor = GridBagConstraints.SOUTH;
533 gc.fill = GridBagConstraints.NONE;
534
535 JButton submitButton = new JButton(" Submit ");
536 panel.add(submitButton, gc);
537
538 getContentPane().add(panel);
539 submitButton.addActionListener(evt -> {
540 userName = userNameTextField.getText();
541 password = passwordTextField.getPassword();
542 getContentPane().setVisible(false);
543 UserNamePasswordDialog.this.dispose();
544 });
545 }
546
547 public String getUserName() {
548 return userName;
549 }
550
551 public char[] getPassword() {
552 return password;
553 }
554 }
555 }