Friday, October 08, 2010

Grails and JCifs

JCIFS is: Open Source client library that implements the CIFS/SMB networking protocol in 100% Java. CIFS is the standard file sharing protocol on the Microsoft Windows platform.
As part of a project to provide schools and businesses with an open source solution to access their "My Documents" folder anytime/anywhere over the web, I recently had the pleasure of integrating JCIFS into my Grails application.

The obligatory screenshot:

I dropped the latest JCIFS jar file into my $GRAILS-APP/lib folder, and began implementing the "My Documents" feature against a samba server for starters. When I moved to a Windows 2008 server everything fell apart, with all operations started timing out. After some digging around in the rather extensive set of config options, I realized I need the following in my grails config file:
System.setProperty("jcifs.smb.client.dfs.disabled", "true");
Your environment may differ but make sure you take a good look at the JCIFS configuration options at least.

Ok, so here's a simple example of removing a file:
  void removeFile(WorkspacePath p)
def ntlm = new NtlmPasswordAuthentication("", p.username, p.password);
SmbFile file = new SmbFile(absoluteFilePath(p.url, p.path), ntlm);
Note: I pass "" as the first argument to NtlmPasswordAuthentication as the domain is part of p.username (e.g.

One thing you need to make sure of is always ending directory paths with a "/", otherwise you will get errors. Here's a more complicated example of a "eachFile" method that takes a closure as it's final argument:
  public void eachFile(WorkspacePath p, Closure c)
println "eachFile ${p.url} - ${p.path}";
def path = absoluteDirPath(p.url, p.path);
def ntlm = new NtlmPasswordAuthentication("", p.username, p.password);
SmbFile file = new SmbFile(path, ntlm);

// are we dealing with a directory path or just a single file?
if (!file.isDirectory()) {[name:, file: file, path: file.canonicalPath,
inputStream: { return new SmbFileInputStream(file); },
outputStream: { return new SmbFileOutputStream(file); }

file.listFiles().each {
f-> if (f.isDirectory()) return;
if (f.isHidden()) return;[name:, file: f, path: f.canonicalPath,
inputStream: { return new SmbFileInputStream(f); },
outputStream: { return new SmbFileOutputStream(f); }
We've been quite pleased with JCIFS and it well its been working in our grails application. We are currently using 1.3.14 with the patches noted here. I just noticed that 1.3.15 is out so I'm interested in trying that as soon as possible!


Bob Fleischman said...

How are you getting the users password? Are you asking for it in clear text?

jr said...

When a user logs in, they use their AD credentials to do so. The password is cached in the session data.