Categories
Uncategorized

Advertisments

I’ve seen advertising targeted at developers for a long time. DDJ & Linux Journal are full of them. But TV ads are somewhat of a new territory. But I’ve realised that more and more, open source projects are doing video adverts. What really struck it home for me was seeing the anouncement for the new Google Update Engine:

It’s an advert if ever I saw one. Yes, it’s a tech presentation, but it’s an advert.

Video for developers is something that’s been growing for a while. One of the reasons for Rails taking off was the screencast showing how simple it was to get started. And I learned tonnes about Textmate from the screencasts that Allan Odgaard posted to the textmate blog.

But it’s not just the flashy GUI things that have videos. If an XML writing library can have a video introduction, what can’t?

It’s great that we have these resources, as developers. I certainly didn’t think I’d see such focused media that I’m actually interested in. But as a developer, it does raise the bar for getting your project noticed.

Categories
Uncategorized

Managing 3rd Party Code

I’m in a pickle. There’s a project at $WORK that I should have been paying closer attention to (but haven’t). We’ve taken some 3rd party software (guanxi as it happens), and made some modifications in order to form our own custom distribution. But:

  • We started modifying what was then the trunk.
  • The trunk has moved forwards.
  • Our modifications are not isolated chunks of work (though they should be).

In other words, it’s a classic merge scenario. Except that both our changes and the trunk are contained within a CVS repository. This means that the original ancestor (the point at which divergence started) can be somewhat difficult to ascertain.

Thankfully, I’ve had moderate success using git cvsimport to pull everything into a git repository. Well, actually five git repositories, thanks to git cvsimport not quite understanding CVS’ modules file format. So, git merge should assist me. But of course, I’m unfamiliar enough with the guanxi code to know how to successfully resolve conflicts. Best of all, it looks like new development which is similar to ours is happening on a branch destined to go into the trunk.

Where does this leave me? For now, a long session of merging with the developer who did the changes. But longer term, we also need to:

  • Split out our code changes into their own packages (or for preference, project).
  • Regularly merge in changes from trunk.
  • Talk to the original developer about whether or not he can make life easier for us.
  • Switch to using git proper rather than developing in the original CVS tree.

It doesn’t help that the project in question is a Java webapp — we want to reuse the classes in that webapp as a jar file in our own webapp. This is yet another complicating factor…

My head hurts.

Categories
Uncategorized

Django’s Pony

I love _why.

Documents Reveal Django Pony, Caught In Tail Of Lies

Don’t forget to read the comments.

Update: As _why removed himself from the internet, I’ve made a local copy of the image. We miss you, _why.

Categories
Uncategorized

AntUnit inside Maven

I’m in the middle of converting jslint4java to use maven as its build system (yes, really). Part of this is ensuring that the antunit tests I wrote continue to work. Maven has the antrun plugin, but it’s not 100% obvious how to use an antlib inside it.

Normally, to run an antlib extension as part of your build, you first dump the jar in ~/.ant/lib (or on the command line using a -lib flag) and then reference it in a namespace. e.g.

This relies on ant being able to pick out org/apache/ant/antunit/antlib.xml from the classpath.

When doing this in maven through the antrun plugin, you can’t just dump stuff into ~/.ant/lib however. You need to tell ant where everything is. Originally, I was following the example of the rat ant task. This attempts to invoke a second copy of ant with the correct -lib argument. It’s ugly though. Why should we fork a second copy of the JVM? And ant may not even be installed (in maven, it’s just jar files in the local repository).

Eventually, I looked closer at the antlib documentation and found Load antlib from inside of the buildfile. This shows how a typedef is the key: You can associate a given antlib URI with a particular classpath entry. Thankfully, maven-antrun-plugin provides ${maven.test.classpath} (amongst others) which contains every entry that we need. So the solution now looks something like this.

Firstly, pom.xml.

  
    
      
        org.apache.ant
        ant-antunit
        1.0
        test
      
    
    
      
        maven-antrun-plugin
        
          
            test
            
              run
            
            
              
                
                  
                
              
            
          
        
        
          
          
            org.apache.ant
            ant
            1.7.0
          
        
      
    
  

So, when we get to the test phase, we automatically run antunit/tests.xml, passing in the correct classpath. This is what the ant file looks like:

This appears to work quite well, and runs my tests a sight quicker than before. If anybody from the apache rat project is listening, you might want to update your POMs. 🙂

Categories
Uncategorized

REST Web Services in Java

I’ve been taking a look at jersey today. It’s an implementation of JSR 311, which is a proposed spec for implementing REST-like web services in Java. I started with the tutorial, which is quite frankly pretty bloody simple.

  @Path("/helloworld")
  public class HelloWorldResource {
    @GET
    @Produces("text/plain")
    public String getClichedMessage() {
      return "Hello World";
    }
  }

The javadoc for the annotations explains what they do in some more detail (Path, GET, Produces).

The tutorial also includes a method of running that standalone using the grizzly HTTP connector. But I’m a stick-in-the-mud. I want it to run under tomcat. So how do I do that? Again, it turns out to be fairly simple. Just add the jersey-supplied integration servlet to your web.xml.

  
    Dispatcher
    com.sun.jersey.spi.container.servlet.ServletContainer
    
      com.sun.jersey.config.property.packages
      net.happygiraffe.jerseytest
    
    1
  

  
    Dispatcher
    /*
  

I specified an extra parameter to say which package I want scanned for resources. Otherwise Jersey will scan everything in /WEB-INF/classes and /WEB-INF/lib by default. Anyway, this works a treat:

% curl -i http://localhost:8080/jerseytest/hello
HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
Content-Type: text/plain
Transfer-Encoding: chunked
Date: Sat, 13 Sep 2008 20:44:41 GMT

hello world

I’m going to play with this some more. The API feels quite nice. Particularly when compared to Restlets, which I found a little bit too uniform. Mind you, the latest restlet code has its own version of JSR 311 support, so it may still be useful. It’s also actually worth checking out the JSR-311 spec, as it’s quite readable.

Categories
Uncategorized

Sitemap components in Cocoon 2.2

For the cocoon 2.1 project I did last year, I wrote a few components in Java (mostly Generators and one InputModule). It’s a bit of a pain because it’s built on the out-of-date and intrusive avalon framework. Anyway the end result is that you can write things in your cocoon sitemap like:

  
    
    
    
  

Now with the newer cocoon 2.2 project, we needed to reuse the InputModule. In order to get an Avalon component working in cocoon 2.2, you need:

  • src/main/java/com/myco/MyInputModule.java
  • src/main/resources/META-INF/cocoon/avalon/my-input-module.xconf

The latter is the old style avalon configuration file and looks like this:

  
    
      
    
  

But cocoon 2.2 is meant to be Spring based. So we should be able to write a Spring bean that does the same thing. Unfortunately, this doesn’t appear to be documented anywhere. But there’s always the source code for cocoon itself.

As an aside, I’m hugely grateful to Jukka Zitting for making available git mirrors of apache projects. This let me download all of cocoon’s source, including full history in a very short time. It’s a helluva useful resource, and I hope it gets proper support from the ASF.

So, I started looking through the Cocoon source code for Spring config files that might reference InputModules.

⇒ find . -name '*.xml' | grep META-INF/cocoon/spring | xargs egrep InputModule
./core/cocoon-servlet-service/cocoon-servlet-service-components/src/main/resources/META-INF/cocoon/spring/cocoon-servlet-linkRewritingReader.xml:        <property name="inputModule" ref="org.apache.cocoon.components.modules.input.InputModule/servlet"/>
./core/cocoon-servlet-service/cocoon-servlet-service-components/src/main/resources/META-INF/cocoon/spring/cocoon-servlet-service-complete-path-module.xml:    <bean name="org.apache.cocoon.components.modules.input.InputModule/servlet"
./core/cocoon-servlet-service/cocoon-servlet-service-components/src/main/resources/META-INF/cocoon/spring/cocoon-servlet-service-complete-path-module.xml:        <property name="blockPathModule" ref="org.apache.cocoon.components.modules.input.InputModule/block-path"/>
./core/cocoon-servlet-service/cocoon-servlet-service-components/src/main/resources/META-INF/cocoon/spring/cocoon-servlet-service-path-module.xml:    <bean name="org.apache.cocoon.components.modules.input.InputModule/block-path"
./core/cocoon-servlet-service/cocoon-servlet-service-components/src/main/resources/META-INF/cocoon/spring/cocoon-servlet-service-property-module.xml:	<bean name="org.apache.cocoon.components.modules.input.InputModule/block-property"

That seems to suggest that by creating a Spring bean whose name is the interface followed by a slash and then a name, you should be able to get at it in the sitemap. And it does indeed work like that. This is the bean name I ended up with.

  
    
  

In order for it to not be an Avalon component, I also removed the base class I was using and just implemented the InputModule interface directly. And to my surprise, I could use the bean directly in the sitemap.

But we have the source, so we can see why it’s working. Did you notice the ROLE constant in InputModule? We can grep for that in the source. That quickly led me to PreparedVariableResolver.java, which contains:

  InputModule module;
  try {
    module = (InputModule) this.manager.lookup(InputModule.ROLE + '/' + moduleName);
  } catch (ServiceException e) {
    throw new PatternException("Cannot get module named '" + moduleName +
    "' in expression '" + this.originalExpr + "'", e);
  }

The manager field is an instance of ServiceManager, which just happens to be AvalonServiceManager. And lookup() is a standard Spring construct:

  try {
    return this.beanFactory.getBean(role);
  } catch (BeansException be) {
    throw new ServiceException("AvalonServiceManager",
      "Exception during lookup of component with '" + role + "'.", be);
  }

Further nosing around reveals that Generators are looked up in Spring in a similar manner inside AbstractProcessingPipeline:

  try {
    this.generator = (Generator) this.newManager.lookup(Generator.ROLE + '/' + role);
  } catch (ServiceException ce) {
    throw ProcessingException.throwLocated("Lookup of generator '" + role + "' failed", ce, getLocation(param));
  }

I’m guessing that transformers, serializers and readers follow a similar pattern.

So, that’s how to do Cocoon components in Spring. It’s a bit simpler than before, which can’t be a bad thing. I just wish it was documente, but that’s a big problem for Cocoon anyway…

Categories
Uncategorized

Out Of Space?

My mother recently complained to me about a memory stick. She was trying to copy some photos on to it, but after a while, it just stopped saying “out of space”. So she took a look at it and found about 1.5Gb of free space. Weird.

Eventually, when I ended up looking at it, the first thing I noticed was how many files were on it. 512 exactly. A suspiciously round number. And when I fired up Disk Utility, it confirmed my suspicions: the memory stick was formatted with FAT16, which only allows 512 entries in the root directory. Thank you very much, you fool of a manufacturer.

Anyway, reformatting it with Disk Utility managed to turn it into a FAT32 filesystem with suitably larger limitations.

Actually, before I spread too much blame, it may be down to some weird licensing arrangement.

Categories
Uncategorized

jslint4java 1.2

I’ve finally gotten around to finishing off the code that I’ve had sitting around in google code for over a year, and released jslint4java 1.2. The changes are actually pretty small:

  • Update to jslint 2008-09-04. This adds several new options.
  • Several updates to the ant task:
    • Move the antlib definition to “antlib:net.happygiraffe.jslint” (incompatible change).
    • Default to failing the build if validation fails (incompatible change).
    • Allow use of the fileset element to be more flexible about specifying where your javascript files are. This replaces several attributes on the jslint task (incompatible change).
    • Add a formatter sub-element, which can output either XML or plain text, either to the console or to a file.
    • See the documentation for some examples of the new usage.
  • Allow access to the HTML report produced by JSLint through an API.

I’ve also uploaded the javadoc directly into subversion on google code, so it’s permanently online. The google-collections guys seem to do this, so it can’t be a bad idea, right?

Typical. Five minutes after I release, I notice that it’s been compiled with 1.6 instead of 1.5. So, I’ve just released v1.2.1…

Categories
Uncategorized

What’s in an IP address?

What is an IP address? To many people, it’s just a sequence of four digits separated by dots1. But really it’s just a 32 bit integer. So, my IP address right now is 192.168.1.52. As a 32 bit integer, that’s:

  • 0xC0A80134 (hexadecimal)
  • 11000000 10101000 00000001 00110100 (binary)

An IP address on it’s own isn’t terribly useful. It’s normally part of a network. That means that a certain part of the IP address designates the network and a certain part designates the “host” (your computer). Conventionally, this is represented through a network “mask” — a series of bits stating which bits identify the network and which bits don’t. My netmask is presently displayed as 255.255.255.0. Again, as an integer that is:

  • 0xffffff00 (hexadecimal)
  • 11111111 11111111 11111111 00000000 (binary)

Combining an IP address and a netmask, you can find out just the network. You have to use a “binary AND” to work it out.

  11000000 10101000 00000001 00110100 (192.168.1.52)
& 11111111 11111111 11111111 00000000 (255.255.255.0)
= 11000000 10101000 00000001 00000000 (192.168.1.0)

Effectively, that’s the lowest address in the network. Likewise, it’s fairly simple to work out the highest address in the network. You use a “binary OR” with the inverse of the netmask. i.e.

  11111111 11111111 11111111 00000000 (255.255.255.0)
~ 00000000 00000000 00000000 11111111 (0.0.0.255)
| 11000000 10101000 00000001 00110100 (192.168.1.52)
= 11000000 10101000 00000001 11111111 (192.168.1.255)

Thankfully, these are both far more expressible in high level programming languages.

  lowest  = address &  mask;
  highest = address | ~mask;

Now you may have noticed that the netmask is a contiguous range of bits. It’s common to express the netmask as just the number of bits in the netmask. So my IP address and netmask are expressible together as 192.168.1.52/24. This is known as CIDR format (and the number of bits is known as a prefix length).

Here’s some sample Java code for representing an IP address2. Doing this in Java is particularly entertaining because Java only has signed integers, unlike C. So there are some shenanigans involved in making the netmask.

  public class IP implements Comparable {

    private static final int MAX_MASK = 32;
    private static final int MIN_MASK = 0;

    private final int addr;
    private final int prefixLength;

    public IP(int addr) {
      this(addr, MAX_MASK);
    }

    public IP(int addr, int prefixLength) {
      this.addr = addr;
      if (prefixLength  MAX_MASK)
        throw new IllegalArgumentException("mask must be >= 0 && <= 32");
      this.prefixLength = prefixLength;
    }

    public int compareTo(IP o) {
      if (o == null)
        throw new NullPointerException("can't compare to null");
      if (addr  o.addr)
        return 1;
      return prefixLength - o.prefixLength;
    }

    public boolean equals(Object obj) {
      if (!(obj instanceof IP)) {
        return false;
      }
      IP other = (IP) obj;
      return prefixLength == other.prefixLength
          && (addr & getMask()) == (other.addr & other.getMask());
    }

    public IP getLowerBound() {
      return new IP(addr & getMask());
    }

    public int getMask() {
      // note: the >>> operator on 32-bit ints only considers the
      // five lowest bits of the shift count, so 32 shifts would
      // actually perform 0 shift!
      return prefixLength == 32 ? -1 : ~(-1 >>> prefixLength);
    }

    public IP getUpperBound() {
      return new IP(addr | ~getMask());
    }

    public int hashCode() {
      return addr ^ getMask();
    }

    private String intToString(int i) {
      return (i >> 24 & 0xFF) + "."
           + (i >> 16 & 0xFF) + "."
           + (i >> 8  & 0xFF) + "."
           + (i & 0xFF);
    }

    public String toString() {
      StringBuilder sb = new StringBuilder();
      sb.append(intToString(addr));
      if (prefixLength != MAX_MASK) {
        sb.append('/');
        sb.append(prefixLength);
      }
      return sb.toString();
    }
  }

This is fairly basic (it could use a contains() method, for example). But it’s been quite useful for me over the last couple of weeks for representing CIDR addresses. By treating an IP address as a CIDR range of /32, it’s handy for the general case.

I hope that this is of use to somebody who is tempted to use a String to store an IP address in future.

Of course, whilst it’s useful, you also need a parser of sorts to go from the String form to an instance of the IP class. This is what I’ve been using, which I “borrowed” from limewire’s IP.java.

  public class IpParser {
    private int parseMask(String maskStr) {
      return Integer.parseInt(maskStr);
    }

    public IP parseCidr(String addr) {
      int slash = addr.indexOf('/');
      if (slash == -1) {
        return parseSingleAddr(addr);
      } else if (addr.lastIndexOf('/') == slash) {
        return parseCidrOnly(addr);
      } else {
        throw new IllegalArgumentException("Can't parse " + addr);
      }
    }

    private IP parseCidrOnly(String addr) {
      int slash = addr.indexOf('/');
      String maskStr = addr.substring(slash + 1);
      String addrStr = addr.substring(0, slash);
      return new IP(stringToInt(addrStr), parseMask(maskStr));
    }

    private IP parseSingleAddr(String addr) {
      return new IP(stringToInt(addr));
    }

    private int stringToInt(final String ipStr) {
      int ip = 0;
      int numOctets = 0;
      int length = ipStr.length();
      // loop over each octet
      for (int i = 0; i < length; i++, numOctets++) {
        int octet = 0;
        // loop over each character making the octet
        for (int j = 0; i < length; i++, j++) {
          char c = ipStr.charAt(i);
          if (c == '.') { // finished octet?
            // can't be first in octet, and not ending 4th octet.
            if (j != 0 && numOctets = '0' && c <= '9' && j <= 2) {
            octet = octet * 10 + c - '0';
            // check it's not a faulty addr.
            if (octet <= 255) {
              continue;
            }
          }
          throw new IllegalArgumentException("Could not parse " + ipStr);
        }
        ip = ip << 8 | octet;
      }
      // if the address had less than 4 octets, push the ip over suitably.
      if (numOctets < 4) {
        ip <<= (4 - numOctets) * 8;
      }
      return ip;
    }
  }

1 Ignoring IPv6 for now, as I don’t have any need for it.

2 Don’t get me started on how non-useful Java’s InetAddress class is.

Categories
Uncategorized

Why I’m leaving Nildram

% traceroute news.bbc.co.uk
traceroute to newswww.bbc.net.uk (212.58.226.79), 64 hops max, 40 byte packets
 1  router.happygiraffe.net (192.168.1.1)  2.795 ms  1.574 ms  1.736 ms
 2  192.168.0.1 (192.168.0.1)  7.862 ms  2.403 ms  4.756 ms
 3  l1.ar21.nildram.gs1.dsl.pipex.net (62.241.167.243)  4453.422 ms  4861.269 ms *
 …

Plus, no response to a ticket opened over a week ago, despite repeated callbacks. I’m off to be. Now I just get to wait for the insane delays that BT put into the UK ADSL market (they’re worse than banks with cheques). Joy.