Monday, March 21, 2011

PDF Forms Editing in OS X

I needed a simple PDF forms editor so that I can fill in and send forms via email and did not want to use the stone age process of printing the PDF out, filling it in, scanning it back in and then sending off the digitised copy.


FormulatePro fits the bill perfectly

Thursday, February 3, 2011

Bundling jruby app with rawr:bundle:exe dies with 'private method `split' called for nil:NilClass' in

I have a little jruby SWT app that I'm trying to bundle up in its own little cocoon with rawr but I keep getting the following:

C:\nms-helper4.git>rake rawr:bundle:exe
(in C:/nms-helper4.git)
mkdir -p package/classes/java
javac -target 1.6 -cp lib/java/jruby-complete.jar;lib/java/swt_linux.jar;lib/jav a/swt_linux64.jar;lib/java/swt_osx.jar;lib/java/swt_osx64.jar;lib/java/swt_win32.jar;src -sourcepath src -d package/classes/java src/org/rubyforge/rawr/Main.java
mkdir -p package/classes/ruby
Compile src/main.rb into package/classes/ruby/main.class
compile_dirs has src_dirs = ["src"]
glob_ruby_files has directory 'src' glob ["src/main.rb", "src/swt_wrapper.rb"]
files for src: 2
ruby_globs.each has glob_data = #
Go compile ["src/main.rb", "src/swt_wrapper.rb"]
Compiling src/main.rb to class main
Compiling src/swt_wrapper.rb to class swt_wrapper
mkdir -p package/classes/META-INF
mkdir -p package/jar
=== Creating jar file: package/jar/nms-helper.jar
cp lib/java/jruby-complete.jar package/jar/lib/java/jruby-complete.jar
cp lib/java/swt_linux.jar package/jar/lib/java/swt_linux.jar
cp lib/java/swt_linux64.jar package/jar/lib/java/swt_linux64.jar
cp lib/java/swt_osx.jar package/jar/lib/java/swt_osx.jar
cp lib/java/swt_osx64.jar package/jar/lib/java/swt_osx64.jar
cp lib/java/swt_win32.jar package/jar/lib/java/swt_win32.jar
mkdir -p package/windows
Creating Windows application in package/jar/nms-helper.exe
rake aborted!
private method `split' called for nil:NilClass

(See full trace by running task with --trace)

Taking the advice presented at the end there I run it again with:

C:\nms-helper4.git>rake rawr:bundle:exe --trace
(in C:/nms-helper4.git)
** Invoke rawr:bundle:exe (first_time)
** Invoke rawr:jar (first_time)
** Invoke package/jar/nms-helper.jar (first_time, not_needed)
** Invoke package/classes/java/org/rubyforge/rawr/Main.class (first_time, not_needed)
** Invoke src/org/rubyforge/rawr/Main.java (first_time, not_needed)
** Invoke package/classes/java (first_time, not_needed)
** Invoke package/classes/ruby/main.class (first_time, not_needed)
** Invoke src/main.rb (first_time, not_needed)
** Invoke package/classes/ruby (first_time, not_needed)
** Invoke package/classes/ruby/swt_wrapper.class (first_time, not_needed)
** Invoke src/swt_wrapper.rb (first_time, not_needed)
** Invoke package/classes/ruby (not_needed)
** Invoke package/classes/META-INF (first_time, not_needed)
** Invoke package/jar (first_time, not_needed)
** Execute rawr:jar
cp lib/java/jruby-complete.jar package/jar/lib/java/jruby-complete.jar
cp lib/java/swt_linux.jar package/jar/lib/java/swt_linux.jar
cp lib/java/swt_linux64.jar package/jar/lib/java/swt_linux64.jar
cp lib/java/swt_osx.jar package/jar/lib/java/swt_osx.jar
cp lib/java/swt_osx64.jar package/jar/lib/java/swt_osx64.jar
cp lib/java/swt_win32.jar package/jar/lib/java/swt_win32.jar
** Invoke package/windows (first_time, not_needed)
** Execute rawr:bundle:exe
Creating Windows application in package/jar/nms-helper.exe
rake aborted!
private method `split' called for nil:NilClass
c:/jruby-1.6.0.RC1/lib/ruby/gems/1.8/gems/rawr-1.4.5/lib/exe_bundler.rb:92:in `deploy'
c:/jruby-1.6.0.RC1/lib/ruby/gems/1.8/gems/rawr-1.4.5/lib/rawr.rb:225:in `(root)'

org/jruby/RubyProc.java:276:in `call'
org/jruby/RubyProc.java:236:in `call'
c:/jruby-1.6.0.RC1/lib/ruby/gems/1.8/gems/rake-0.8.7/lib/rake.rb:636:in `execute'
org/jruby/RubyArray.java:1671:in `each'
c:/jruby-1.6.0.RC1/lib/ruby/gems/1.8/gems/rake-0.8.7/lib/rake.rb:631:in `execute'
c:/jruby-1.6.0.RC1/lib/ruby/gems/1.8/gems/rake-0.8.7/lib/rake.rb:597:in `invoke_with_call_chain'
c:/jruby-1.6.0.RC1/lib/ruby/1.8/monitor.rb:191:in `mon_synchronize'
c:/jruby-1.6.0.RC1/lib/ruby/gems/1.8/gems/rake-0.8.7/lib/rake.rb:590:in `invoke_with_call_chain'
c:/jruby-1.6.0.RC1/lib/ruby/gems/1.8/gems/rake-0.8.7/lib/rake.rb:583:in `invoke'

c:/jruby-1.6.0.RC1/lib/ruby/gems/1.8/gems/rake-0.8.7/lib/rake.rb:2051:in `invoke_task'
c:/jruby-1.6.0.RC1/lib/ruby/gems/1.8/gems/rake-0.8.7/lib/rake.rb:2029:in `top_level'
org/jruby/RubyArray.java:1671:in `each'
c:/jruby-1.6.0.RC1/lib/ruby/gems/1.8/gems/rake-0.8.7/lib/rake.rb:2029:in `top_level'
c:/jruby-1.6.0.RC1/lib/ruby/gems/1.8/gems/rake-0.8.7/lib/rake.rb:2068:in `standard_exception_handling'
c:/jruby-1.6.0.RC1/lib/ruby/gems/1.8/gems/rake-0.8.7/lib/rake.rb:2023:in `top_level'
c:/jruby-1.6.0.RC1/lib/ruby/gems/1.8/gems/rake-0.8.7/lib/rake.rb:2001:in `run'
c:/jruby-1.6.0.RC1/lib/ruby/gems/1.8/gems/rake-0.8.7/lib/rake.rb:2068:in `standard_exception_handling'
c:/jruby-1.6.0.RC1/lib/ruby/gems/1.8/gems/rake-0.8.7/lib/rake.rb:1998:in `run'
c:/jruby-1.6.0.RC1/lib/ruby/gems/1.8/gems/rake-0.8.7/bin/rake:31:in `(root)'
org/jruby/RubyKernel.java:1066:in `load'

Aah, so things are coming undone in exe_bundler.rb:92:

80 if Platform.instance.using_windows?
81 # Check for FAT32 vs NTFS, the cacls command doesn't work on FAT32 nor is it required
82 output = `fsutil fsinfo volumeinfo #{file_dir_name.split(':')[0]}:\\`
83 # fsutil can only work with admin priviledges
84 raise output if output =~ /requires that you have administrative privileges/
85 # ===== Sample output of 'fsutil fsinfo volumeinfo c:\'
86 # Volume Name :
87 # Volume Serial Number : 0x80a5650a
88 # Max Component Length : 255
89 # File System Name : FAT32
90 # Preserves Case of filenames
91 # Supports Unicode in filenames
92 if 'NTFS' == output.split("\n")[3].split(':')[1].strip
93 sh "echo y | cacls \"#{file_dir_name}/launch4j/bin-win/windres.exe\" /G \"#{ENV['USERNAME']}\":F"
94 sh "echo y | cacls \"#{file_dir_name}/launch4j/bin-win/ld.exe\" /G \"#{ENV['USERNAME']}\":F"
95 end
96 link_launch4j_bin('win', file_dir_name)

Line 92 seems to rely on what happens in line 82 where we try and get some filesystem info based on the drive name. The bit that tries to determine the drive letter uses '\\' at the end which is the issue. If you change that to '\\\\' you get things to work as they should again:

82 output = `fsutil fsinfo volumeinfo #{file_dir_name.split(':')[0]}:\\\\`

Somehow the double backslash is not making it to the shell correctly from the backticks being called. Adding the extra set of backslashes saves the day:

C:\nms-helper4.git>rake rawr:bundle:exe
(in C:/nms-helper4.git)
cp lib/java/jruby-complete.jar package/jar/lib/java/jruby-complete.jar
cp lib/java/swt_linux.jar package/jar/lib/java/swt_linux.jar
cp lib/java/swt_linux64.jar package/jar/lib/java/swt_linux64.jar
cp lib/java/swt_osx.jar package/jar/lib/java/swt_osx.jar
cp lib/java/swt_osx64.jar package/jar/lib/java/swt_osx64.jar
cp lib/java/swt_win32.jar package/jar/lib/java/swt_win32.jar
Creating Windows application in package/jar/nms-helper.exe
echo y | cacls "c:/jruby-1.6.0.RC1/lib/ruby/gems/1.8/gems/rawr-1.4.5/lib/launch4j/bin-win/windres.exe" /G "cmatthee":F
Are you sure (Y/N)?echo y | cacls "c:/jruby-1.6.0.RC1/lib/ruby/gems/1.8/gems/rawr-1.4.5/lib/launch4j/bin-win/ld.exe" /G "cmatthee":F
Are you sure (Y/N)?call: java -jar "c:/jruby-1.6.0.RC1/lib/ruby/gems/1.8/gems/rawr-1.4.5/lib/launch4j/launch4j.jar" "package/windows/configuration.xml"
java -jar "c:/jruby-1.6.0.RC1/lib/ruby/gems/1.8/gems/rawr-1.4.5/lib/launch4j/launch4j.jar" "package/windows/configuration.xml"
launch4j: Compiling resources
launch4j: Linking
launch4j: Successfully created C:\nms-helper4.git\package\windows\nms-helper.exe

Reality restored.

From what I can see I am running the latest rawr gem:

C:\nms-helper4.git>jruby -S gem search -r rawr

*** REMOTE GEMS ***

drawr (1.0.1)
rawr (1.4.5)

C:\nms-helper4.git>jruby -S gem list rawr

*** LOCAL GEMS ***

rawr (1.4.5)

Checking the master branch on github though shows this file is no longer the same and the issue has been fixed:

81 if Platform.instance.using_windows?
82 # Check for FAT32 vs NTFS, the cacls command doesn't work on FAT32 nor is it required
83 volume = file_dir_name.split(":").first.upcase + ':'
84 output = `fsutil fsinfo ntfsinfo #{volume}`
85 # fsutil can only work with admin priviledges
86 raise output if output =~ /requires that you have administrative privileges/
87 raise output if output =~ /Error:/
88 if 'NTFS' == output.split("\n")[0][0..3]
89 sh "echo y | cacls \"#{file_dir_name}/launch4j/bin-win/windres.exe\" /G \"#{ENV['USERNAME']}\":F"
90 sh "echo y | cacls \"#{file_dir_name}/launch4j/bin-win/ld.exe\" /G \"#{ENV['USERNAME']}\":F"
91 end
92 link_launch4j_bin('win', file_dir_name)

The Rakefile refers us to 'rawr/rawr_version' that is:

1 module Rawr
2 VERSION = "1.5.0"
3 end


Looks like the latest version of the project on github has not made it into the wild as yet.

Resizing your OS X VMWare Fusion Virtual Disk

Assumptions:
  • New disk size is 40GB.
  • Current virtual disk is foo.vdmk
  • Current VM image is at /Users/foo/Documents/Foo.vmwarevm

Quick recipe:
  • Open up a teminal window
  • Run: cd /Users/foo/Documents/Foo.vmwarevm && /Library/Application\ Support/VMware\ Fusion/vmware-vdiskmanager -x 40GB foo.vmdk
  • Resize the host OS with a third party tool. In my case I was resizing a NTFS partition with XP installed on it. Easeus Partition Manager home Edition did the trick for me.

About Me

My photo
I love solving real-world problems with code and systems (web apps, distributed systems and all the bits and pieces in-between).