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