Author: sdeboy
Date: Wed Aug 8 23:40:16 2007
New Revision: 564112
URL: http://svn.apache.org/viewvc?view=rev&rev=564112
Log:
Updating VFSLogFilePatternReceiver to suport remote tailing
(thanks to Isuru Suriarachchi for the initial work!)
To tail via VFS, a version of commons-vfs is required which
provides the fileobject.refresh method (added Mar 30 19:16:24 2006)
(not sure if a version of VFS containing this method is available from maven)
Modified:
logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/vfs/VFSLogFilePatternReceiver.java
Modified:
logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/vfs/VFSLogFilePatternReceiver.java
URL:
http://svn.apache.org/viewvc/logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/vfs/VFSLogFilePatternReceiver.java?view=diff&rev=564112&r1=564111&r2=564112
==============================================================================
---
logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/vfs/VFSLogFilePatternReceiver.java
(original)
+++
logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/vfs/VFSLogFilePatternReceiver.java
Wed Aug 8 23:40:16 2007
@@ -25,6 +25,7 @@
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
+import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Reader;
@@ -41,12 +42,17 @@
import org.apache.commons.vfs.FileSystemException;
import org.apache.commons.vfs.FileSystemManager;
import org.apache.commons.vfs.FileSystemOptions;
+import org.apache.commons.vfs.RandomAccessContent;
import org.apache.commons.vfs.VFS;
import org.apache.commons.vfs.provider.URLFileName;
import org.apache.commons.vfs.provider.sftp.SftpFileSystemConfigBuilder;
+import org.apache.commons.vfs.util.RandomAccessMode;
import org.apache.log4j.chainsaw.receivers.VisualReceiver;
import org.apache.log4j.varia.LogFilePatternReceiver;
+import com.jcraft.jsch.UIKeyboardInteractive;
+import com.jcraft.jsch.UserInfo;
+
/**
* A VFS-enabled version of org.apache.log4j.varia.LogFilePatternReceiver.
*
@@ -167,6 +173,7 @@
private boolean promptForUserInfo = false;
private Container container;
private Object waitForContainerLock = new Object();
+ private String password;
public VFSLogFilePatternReceiver() {
super();
@@ -231,11 +238,11 @@
synchronized(waitForContainerLock) {
while (container == null) {
try {
- waitForContainerLock.wait();
+ waitForContainerLock.wait(1000);
} catch (InterruptedException ie){}
}
}
-
+
Frame containerFrame1;
synchronized(waitForContainerLock) {
//loop until the container has a frame
@@ -245,71 +252,136 @@
} catch (InterruptedException ie) {}
}
}
- final Frame containerFrame = containerFrame1;
-
- //create the dialog
- SwingUtilities.invokeLater(new Runnable() {
- public void run() {
- final UserNamePasswordDialog f = new
UserNamePasswordDialog(containerFrame);
- f.pack();
- Dimension d =
Toolkit.getDefaultToolkit().getScreenSize();
- f.setLocation(d.width /2, d.height/2);
- f.setVisible(true);
- if (null == f.getUserName() || null ==
f.getPassword()) {
- getLogger().warn("No username
or password provided - not loading file " + getFileURL());
- } else {
- int index =
getFileURL().indexOf("://");
- String firstPart =
getFileURL().substring(0, index);
- String lastPart =
getFileURL().substring(index + "://".length());
- setFileURL(firstPart + "://" +
f.getUserName()+ ":" + new String(f.getPassword()) + "@" + lastPart);
- new Thread(new
VFSReader()).start();
- }
- }
- });
+ final Frame containerFrame = containerFrame1;
+ //create the dialog
+ SwingUtilities.invokeLater(new Runnable() {
+ public void run() {
+ Frame owner = null;
+ if (container != null) {
+ owner =
(Frame)SwingUtilities.getAncestorOfClass(Frame.class, containerFrame);
+ }
+ final UserNamePasswordDialog f = new
UserNamePasswordDialog(owner);
+ f.pack();
+ Dimension d =
Toolkit.getDefaultToolkit().getScreenSize();
+ f.setLocation(d.width /2, d.height/2);
+ f.setVisible(true);
+ if (null == f.getUserName() || null ==
f.getPassword()) {
+ getLogger().warn("No username
or password provided - not loading file " + getFileURL());
+ } else {
+ password = new
String(f.getPassword());
+ int index =
getFileURL().indexOf("://");
+ String firstPart =
getFileURL().substring(0, index);
+ String lastPart =
getFileURL().substring(index + "://".length());
+ setFileURL(firstPart + "://" +
f.getUserName()+ ":" + new String(password) + "@" + lastPart);
+ new Thread(new
VFSReader()).start();
+ }
+ }
+ });
}}).start();
} else {
- new Thread(new VFSReader()).start();
+ int index = getFileURL().indexOf("://");
+ String lastPart = getFileURL().substring(index +
"://".length());
+ password = lastPart.substring(lastPart.indexOf(":") + 1,
lastPart.indexOf("@"));
+ new Thread(new VFSReader()).start();
}
}
-
+
private class VFSReader implements Runnable {
- public void run() {
- while (reader == null) {
- getLogger().info("attempting to load file: " + getFileURL());
- try {
- FileSystemManager fileSystemManager = VFS.getManager();
- FileSystemOptions opts = new FileSystemOptions();
-
SftpFileSystemConfigBuilder.getInstance().setStrictHostKeyChecking(opts, "no");
-
- FileObject fileObject =
fileSystemManager.resolveFile(getFileURL(), opts);
- reader = new
InputStreamReader(fileObject.getContent().getInputStream());
- //now that we have a reader, remove additional portions of the
file url (sftp passwords, etc.)
- //check to see if the name is a URLFileName..if so, set file name
to not include username/pass
- if (fileObject.getName() instanceof URLFileName) {
- URLFileName urlFileName = (URLFileName)fileObject.getName();
- setHost(urlFileName.getHostName());
- setPath(urlFileName.getPath());
+ public void run() {
+ FileObject fileObject = null;
+ while (reader == null) {
+ int atIndex = getFileURL().indexOf("@");
+ int protocolIndex = getFileURL().indexOf("://");
+
+ String loggableFileURL = atIndex > -1?
getFileURL().substring(0, protocolIndex + "://".length()) + "username:password"
+ getFileURL().substring(atIndex) : getFileURL();
+ getLogger().info("attempting to load file: " +
loggableFileURL);
+ try {
+ FileSystemManager fileSystemManager = VFS.getManager();
+ FileSystemOptions opts = new FileSystemOptions();
+ //if jsch not in classpath, can get NoClassDefFoundError
here
+ try {
+
SftpFileSystemConfigBuilder.getInstance().setStrictHostKeyChecking(opts, "no");
+
SftpFileSystemConfigBuilder.getInstance().setUserInfo(opts, new MyUserInfo());
+ } catch (NoClassDefFoundError ncdfe) {
+ getLogger().warn("JSch not on classpath!", ncdfe);
+ }
+
+ fileObject = fileSystemManager.resolveFile(getFileURL(),
opts);
+ reader = new
InputStreamReader(fileObject.getContent().getInputStream());
+ //now that we have a reader, remove additional portions of
the file url (sftp passwords, etc.)
+ //check to see if the name is a URLFileName..if so, set
file name to not include username/pass
+ if (fileObject.getName() instanceof URLFileName) {
+ URLFileName urlFileName = (URLFileName)
fileObject.getName();
+ setHost(urlFileName.getHostName());
+ setPath(urlFileName.getPath());
+ }
+ } catch (FileSystemException fse) {
+ getLogger().info("file not available - may be due to
incorrect credentials, but will re-attempt to load in 10 seconds", fse);
+ synchronized (this) {
+ try {
+ wait(10000);
+ } catch (InterruptedException ie) {}
+ }
+ }
}
- } catch (FileSystemException fse) {
- getLogger().info("file not available - will try again in 10
seconds");
- synchronized(this) {
- try {
- wait(10000);
- } catch (InterruptedException ie){}
+ initialize();
+
+ try {
+ long lastFilePointer = 0;
+ long lastFileSize = 0;
+ BufferedReader bufferedReader;
+ createPattern();
+ getLogger().debug("tailing file: " + isTailing());
+
+ do {
+ FileSystemManager fileSystemManager = VFS.getManager();
+ FileSystemOptions opts = new FileSystemOptions();
+ //if jsch not in classpath, can get NoClassDefFoundError
here
+ try {
+
SftpFileSystemConfigBuilder.getInstance().setStrictHostKeyChecking(opts, "no");
+
SftpFileSystemConfigBuilder.getInstance().setUserInfo(opts, new MyUserInfo());
+ } catch (NoClassDefFoundError ncdfe) {
+ getLogger().warn("JSch not on classpath!", ncdfe);
+ }
+
+ fileObject = fileSystemManager.resolveFile(getFileURL(),
opts);
+ reader = new
InputStreamReader(fileObject.getContent().getInputStream());
+
+ if (fileObject.getContent().getSize() > lastFileSize) {
+ RandomAccessContent rac =
fileObject.getContent().getRandomAccessContent(RandomAccessMode.READ);
+ rac.seek(lastFilePointer);
+ reader = new InputStreamReader(rac.getInputStream());
+ bufferedReader = new BufferedReader(reader);
+ process(bufferedReader);
+ lastFilePointer = rac.getFilePointer();
+ lastFileSize = fileObject.getContent().getSize();
+ rac.close();
+ }
+
+ try {
+ synchronized (this) {
+ wait(5000);
+ }
+ } catch (InterruptedException ie) {
+ }
+ try {
+ //available in vfs as of 30 Mar 2006 - will load but
not tail if not available
+ fileObject.refresh();
+ } catch (Error err) {
+ getLogger().info("Unable to refresh fileobject", err);
+ }
+
+ } while (isTailing());
+
+ } catch (IOException ioe) {
+ getLogger().info("stream closed");
}
- }
- }
- initialize();
-
- try {
- process(reader);
- } catch (IOException ioe) {
- getLogger().info("stream closed");
+ getLogger().debug("processing " + getFileURL() + " complete");
+ shutdown();
}
- }
- }
+ }
- public class UserNamePasswordDialog extends JDialog{
+ public class UserNamePasswordDialog extends JDialog {
private String userName;
private char[] password;
private UserNamePasswordDialog(Frame containerFrame) {
@@ -381,4 +453,39 @@
return password;
}
}
-}
\ No newline at end of file
+
+ /**
+ * UserInfo class used to automatically log in if needed - also implemements
+ * UIKeyboardInteractive (UserInfo methods not used, just
UIKeyboardInteractive)
+ *
+ * @author sdeboy
+ */
+ public class MyUserInfo implements UserInfo, UIKeyboardInteractive {
+ public String[] promptKeyboardInteractive(String destination, String
loginName, String instruction, String[] prompt, boolean[] echo) {
+ return new String[]{password};
+ }
+
+ public String getPassphrase() {
+ return null;
+ }
+
+ public String getPassword() {
+ return null;
+ }
+
+ public boolean promptPassphrase(String arg0) {
+ return false;
+ }
+
+ public boolean promptPassword(String arg0) {
+ return false;
+ }
+
+ public boolean promptYesNo(String arg0) {
+ return false;
+ }
+
+ public void showMessage(String arg0) {
+ }
+ }
+}