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.

Thursday, October 21, 2010

TACACS+, packet loss and 'Authorization failed' errors

I've been hunting a TACACS+ issue that a customer reported whereby they would be able to log into a network device but somewhere in the duration of the session they would try and run a command and get the dreaded '% Authorization failed' error.

After a couple of seconds they would be able to continue as if nothing was amiss.

The tac_plus (I am using the Event-Driven version) logs were not showing anything out of the ordinary so this was a rather perplexing issue. The error seemed to be popping up rather randomly (and always when I did not have a tcpdump running).

While observing several devices over a larger time period I noticed that they were experiencing intermittent packet loss and this got me to wonder of the packet loss events I was noticing were not coinciding with the authorization failures.

Lucky for me tac_plus is running on a Linux host and so I thought I'd simulate packet loss between one of my own devices and the tac_plus service to see what that would result in. To implement the simulated packet loss I simply put the following rule in place:

iptables -A INPUT -m static -mode random -probability 0.5 -s /32 -j DROP

With a probability of 0.5 (this can be between 0 and 1) I was dropping around 40-50% of the packets.

Lo and behold, '% Authorization failure', scientifically reproducible.

Wednesday, September 1, 2010

Sharing is caring: Ruby, Perl, Memcached and MsgPack

Do you need to share data structures between ruby and perl ... FAST?

I recently saw MsgPack bubble through my RSS feeds and tagged it to go have another look. It provides very fast multi-language bindings for serialisation/de-serialisation.

A few quick experiments with the data I share (via memcached) between ruby and perl showed a write (serialisation + write to memcached) speed increase from 20s to 1.8s. Read (read from memcached + de-serialisation) performance showed similar performance increases.

All initial testing was done ruby -> memcached -> ruby but as soon as I switched to reading from memcached via perl I started getting 'extra bytes' errors from the perl side. I then tried perl -> memcached -> perl and everything was fine.

Weird.

A closer look at the data written to memcached and then read from perl showed that the data serialised with MsgPack on the ruby end was not the same as the data read by perl from memcached (validating the 'extra bytes' error).

Testing the write -> read process from perl to ruby yielded the following error:

/opt/local/lib/ruby/gems/1.8/gems/memcached-0.19.5/lib/memcached/memcached.rb:514:in `load': incompatible marshal file format (can't be read) (TypeError)
format version 4.8 required; 147.1 given
from /opt/local/lib/ruby/gems/1.8/gems/memcached-0.19.5/lib/memcached/memcached.rb:514:in `get'
from ./t_msgpack.rb:35:in `read_test'
from ./t_msgpack.rb:49

Now why on earth would I be getting a 'incompatible marshal file format' error as I am not using the ruby marshalling lib at all?

Turns out the memcached lib I use turns marshalling of ruby data on by default when you write to/read from memcached. This is most likely the best option for most cases where you don't want to use some other form of serialisation/de-serialisation but was really biting me here.

The solution is to simply stop the default behaviour of the memcached lib by using the following forms of get and set that turns on the 'raw' data handling switch for the memcached lib:

get KEY, false
set KEY, VALUE, TTL, false

The 'false' parameter at the end of those overrides the default behaviour turning default serialisation/de-serialisation via Marshall off.

Reality restored.

Thursday, July 1, 2010

How do you make your Clojure REPL suck less?

Simple, rely on the venerable rlwrap that provides you with a readline wrapper around your existing REPL.

My sucky REPL looked like this:

#!/bin/sh
java -cp PATH_TO/clojure.jar clojure.main $1

Simply install the rlwrap package using your favorite package manager and change your REPL script (clj) to the following:

#!/bin/sh
rlwrap java -cp PATH_TO/clojure.jar clojure.main $1

Major suckiness averted. The added boon of this approach is that you now get all the readline goodness (history traversal, inline editing, etc.) you've come to depend on in other REPLs.

Monday, October 12, 2009

B0rked ports on Snow Leopard

If you are using MacPort to manage OSS on your box and you recently upgraded to Snow Leopard you will find error messages like this when trying to use the ports system:
$ port selfupdate
dlopen(/Library/Tcl/macports1.0/MacPorts.dylib, 10): no suitable image
found. Did find:
/Library/Tcl/macports1.0/MacPorts.dylib: mach-o, but wrong architecture
while executing
"load /Library/Tcl/macports1.0/MacPorts.dylib"
("package ifneeded macports 1.0" script)
invoked from within
"package require macports"
(file "/opt/local/bin/port" line 39)
The issue is simply that you have all your libs and binaries managed via MacPorts compiled for the i386 architecture and not x86-64 (as required for Snow Leopard).

The solution is simple, but, arduous. You need to install the new version of MacPorts for Snow Leopard, make a backup list of the installed ports, delete them and reinstall the ones you still want.

You may want to pay close attention to the variants of the ports that you had previously installed when reinstalling them.

Also, you need the latest version of Xcode (a version greater than v3.0 will do) installed.

Fun.

See the following two URLs for more info:
Happy recompiling!


Tuesday, September 22, 2009

OS X Snow Leopard and broken scrolling in MacVim

My upgrade to Snow Leopard has been pretty smooth sailing bar one annoying hitch. After the upgrade MacVim stopped scrolling properly.

When you scroll down only the last few lines on the screen update and scrolling up only the first few lines. This requires you CTRL-L to redraw the window every time you've finished scrolling.

Yuck!

Looks like this is caused by MacVim's support for ATSUI which has been deprecated in favour of Core Text in Snow Leopard.

If you are experiencing this you can simply turn the ATSUI renderer off by unchecking MacVim -> Preferences -> Advanced -> Use ATSUI renderer.

This is switched off by default so most people won't be affected by this. At the time of this post there was no real indication from the MacVim project if they'd be switching to Core Text in the future in addition to using the ATSUI renderer.


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).