String filtering in Java

Today I’ve needed to match strings in Java against a pattern similar to the ones used in filename matching. Java already has a String.matches() method to test against a regular expression, but hasn’t one to match against more limited filename-like patterns (* and ? wildcards).

At first, I tought about implementing the matching by hand, comparing character to character, but soon found a quickier and simpler approach: transform the pattern into a regular expression. Maybe this source code could be useful for you:

    private boolean matchFilter(String sample, String filter) {
        if (sample==null || filter==null) return true;

        StringBuffer f=new StringBuffer(".*");
        
        for (StringTokenizer st=new StringTokenizer(
                filter,"%*",true);
                st.hasMoreTokens();) {
            String t=st.nextToken();
            if (t.equals("?")) f.append(".");
            else if (t.equals("*")) f.append(".*");
            else f.append(Pattern.quote(t));
        }
        f.append(".*");
        
        return sample.matches(f.toString());
    }

Tapestry redirections

It’ll soon be a year for me working in a project that uses Tapestry as one of its core technologies. I’ve learnt many interesting things and also faced some challenges to do certain specific stuff. Internet has always been a good help tool, and now it’s time to give back my little bit.

Tapestry features the class RedirectException to break the execution at any time and bring the user to the URL you want. But that exception expects an URL, and if you want to reach an existing Tapestry page, you need the corresponging URL for it.

Fortunately, this post in the Tapestry wiki at apache.org showed me how to get that URL for Tapestry3. But I also needed that exception to work for Tapestry4, so I had to investigate how to do the same think using the HiveMind registry. Finally, I got the class working and I’ve contributed it to the wiki where I found the Tapestry3 one.

I hope this to be useful!

Second life goes open source, second life goes Linux

As said in their web, Linden Labs has dual licensed their Second Life client both proprietary and GPL. But that isn’t everything: a new Linux client has been developed, so we all can enjoy the experience, and there are even people talking about using Mono as a scripting engine.

I have tried Second Life, and the least I can tell you is that it’s simply amazing. You can create objects and animate them writing scripts, perform all kind of actions (riding bikes, driving cars, talking, listening music, watching videos (ok, only through QuickTime in Windows), buying and selling objects, meeting people… in summary living a life. You should give it a try.
As a sample, I show you this picture, where my avatar is editing her motorcycle and seeing the source code of the script that drives it (click to enlarge):

Second Life script editing

Curious facts about Hibernate

Hibernate is a very useful framework to do Object-Relational mapping in Java. It saves a lot of time, gives the programmer a lot of flexibility and allows you to do amazing things like mapping object inheritance.

Nevertheless, it has some “strange” behaviours that, in my opinion, seem a bit courterintuitive. I’m going to tell you about the way Hibernate translates object relations into joins.

Let’s imagine we have the class Person, with attributes id and name, and the class Car, with attributes id and brand. Class Person has a one-to-one relationship with Car named car, and there’ll be persons who have a car, and persons who haven’t.
If we want to query about the cars each people have, the “intuitive” query would be this:

select p.name, p.car from Person p

And the “intuitive” result would be: (John, Car instance #1); (Peter, null); (Mary, Car instance #2), isn’t it?

It isn’t. The real thing is that Hibernate translates the HQL sencence to a SQL one that selects from Person and does an (inner) join with Car, in order to instantiate a Car with all its attribute values set up. As a consequence of that inner join, all the people having a null car are missing from the result.

Intuitive solution: force the outer join by hand

select p.name, c.id, c.brand from Person p left join p.car c

Non intuitive (but valid) solution: use the required attributes directly

select p.name, p.car.id, p.car.brand from Person p

In this last query, I would expect a NullPointerException when the person has no car, since if there is no car, there is no attribute to evaluate, but the exception doesn’t get thrown, the problem doesn’t arise and you get the work done.

Quite strange, isn’t it?

My own flavour of network config automatic choosing

Until a couple of days ago, I used to use Gnome network-admin’s ability of having multiple network profiles to configure my wifi card at work and at home. But yesterday, the program went crazy and started to crash without any logical reason and I decided to shift to another solution: logical network interface mapping.

Interface mapping is a feature of ifupdown (/etc/network/interfaces). You can define some logical interfaces and call a script in order to choose which one will be mapped to a physical interface. The /etc/network/interfaces could be like this one (being HomeNET and WorkNET two existing ESSID network identifiers):

auto eth1
mapping eth1
script /root/WIFI/wldetect.sh
map HomeNET HomeNET
map WorkNET WorkNET

iface HomeNET inet static
address 192.168.1.2
netmask 255.255.255.0
gateway 192.168.1.1
wireless-essid HomeNET
wireless-key s:mysecretpass1 open
dns-nameservers 127.0.0.1 192.168.1.1

iface WorkNET inet dhcp
wireless-essid WorkNET
wireless-key s:mysecretpass2 open
dns-nameservers 127.0.0.1 192.168.100.1

I’m using resolvconf to activate the dns-nameservers directive in the interfaces file, and dnsmasq to take care of some dns issues with a couple of VPNs I use. That explains the first 127.0.0.1 entry.

The script /root/WIFI/wldetect.sh lists the available networks and chooses one of them being in a whitelist (HomeNET|WorkNET):

#!/bin/sh

# Config
WL_IFACE=`iwconfig 2>/dev/null | { read A _; echo $A; };`

# Reset the interface
ifconfig $WL_IFACE down
ifconfig $WL_IFACE 0.0.0.0
ifconfig $WL_IFACE up

# Search networks
NETWORKS=`iwlist $WL_IFACE scanning | grep ESSID | sed -e ‘s/.*”(.*)”/1/’`

# Bring down the interface
ifconfig $WL_IFACE down

# Select preferred networks
for NET in $NETWORKS
do
case $NET in
HomeNEt|WorkNET)
echo $NET;
exit 0;
;;
esac
done
exit 1;

And that’s all! I hope that this configuration could be helpful for someone.

Logitech QuickCam Express (USB ID 046d:092f) on Ubuntu Edgy

I’ve just bought the webcam in the title of this post at Alcampo and had a hard time trying to set it working.

In the pkg-spca5xx-devel Debian mailing list, Dmitry Semyonov says that this camera model is supported by the spca5xx driver, but its ID isn’t added to the driver source code yet. He’s published a patch, and I tried to apply it, but the patch utility complained. That was because the tabs would have been replaced with spaces or something. Then I discovered the “-l” option, which solved my problem and I could finally apply the patch.

At help.ubuntu.com I found detailed instructions about how to build the spca5xx source code, so, finally I had the work done.

I’ve written a recipe to perform all the steps. At first, copy the patch into the file /tmp/qcexpress.patch. Next, execute these instructions:

apt-get install spca5xx-source
cd /usr/src
tar jxvf spca5xx-source.tar.bz2
cd modules
patch -lp1 < /tmp/qcexpress.patch
cd spca5xx
make
make install

That’s all!
And, at the end, a living proof: MSN video chat using Kopete 🙂
MSN video chat with Kopete

Cryptographic Filesystem

Yesterday’ve been playing around with CFS in my Ubuntu. I’ve never tried a cryptographic filesystem before, altough I knew there were many flavours laying out there.

CFS has two main advantages, as far as I know:

  • It doesn’t require any special kernel patch (at least, not for Ubuntu), because it uses NFS to do loopback mounting of crypted directories.
  • It uses directly the underlying filesystem, avoiding the need of creating fs images to mount by loopback. Crypted directories and files are mapped to normal directories and files with its name and contents crypted.

The package provides some utilities:

  • cmkdir: Creates and initializes a crypted directory on the host filesystem.
  • cattach: Attaches a crypted directory, making it available (as cleartext) under /crypt/*.
  • cdetach: Dettaches a previously mounted crypted directory.

I’ve tried CFS successfully, and added it to my list of useful tools. It’s clean, easy and powerful. 🙂

Limited lifetime scripts

While helping Xavi with a small task (batch converting ODT documents to PDF via a web form), I’ve remembered a little recipe I’ve written some time ago.

It’s a way to force some script to die after a defined timeout. So, you can perform a command by ssh inside a script or perform any blocking task you want, and it will always return.

The only thing you have to do is to put these single 3 lines of code at the start of your bash script:

SECURITY_TIMEOUT=60
CMD_PID="$$";
{ sleep $SECURITY_TIMEOUT; kill -9 $CMD_PID; } 2>/dev/null &
Enjoy it!

SMTP and Cisco PIX firewall

Some months ago, I configured a complete mail gateway and other services for a client. As for almost every deployment, there were things that had to be investigated and one always learn something new.

One of the most surprising “curiosities” I found was about SMTP. When I telneted the SMTP gateway at port 25 from inside the intranet or localhost, the usual welcome message was displayed. But when I did the same from the internet, I received this weird welcome string:

220 **************************************

And when I tried to issue an ESMTP command (like EHLO), the server said that it wasn’t supported. What the hell??!! It can’t be! Someone or something is changing my packets!

After doing some searching at Google, I discovered who was the little guilty: a Cisco PIX firewall configured with the “fixup protocol smtp 25” option turned on. That was preventing internet users from authenticating and using TLS.

Thank you debian-administration.org guys!