24 February 2009

equals and hashCode Generation

Recently we discussed equals() and hashCode() implementations. A proper implementation is not trivial, as "father" Bloch showed us years ago. Back in 2004 I wrote a plugin for Eclipse 2 to generate these methods. (Unfortunately I never managed to publish it. I know I am weak ;-) My home grown solution would produce something like
public int hashCode() {
  long bits;
  int result = 17;
  result = 37 * result + (aBoolean ? 1231 : 1237);
  result = 37 * result + (int)
    ((bits = Double.doubleToLongBits(aDouble)) ^ (bits >> 32));
  result = 37 * result + (int) (aLong ^ (aLong >> 32));
  result = 37 * result + anInt;
  if (anObject != null) {
    result = 37 * result + anObject.hashCode();
  }
  if (anArray != null) {
    result = 37 * result + anArray.hashCode();
  }
  return result;
}
public boolean equals(Object obj) {
  if (this == obj) {
    return true;
  }
  else if (obj == null || getClass() != obj.getClass()) {
    return false;
  }
  final Homegrown o = (Homegrown) obj;
  return (aBoolean == o.aBoolean &&
         aDouble == o.aDouble &&
         aLong == o.aLong &&
         anInt == o.anInt &&
         (anObject == o.anObject ||
           (anObject != null && anObject.equals(o.anObject))) &&
         (anArray == o.anArray ||
           (anArray != null && anArray.equals(o.anArray))));
}
I know, I know the implementation for arrays is most likely not what you want. (Did I say that I am weak? :-) Since Java 5 one could use the java.util.Arrays class to fix it. Nevertheless, it served me well for some years. There are several other plugins for Eclipse, and Scott McMaster wrote about in 2006. Since version 3.3 (Europa) Eclipse can finally do it on its own:
public int hashCode() {
  final int prime = 31;
  int result = 1;
  result = prime * result + (aBoolean ? 1231 : 1237);
  long temp;
  temp = Double.doubleToLongBits(aDouble);
  result = prime * result + (int) (temp ^ (temp >>> 32));
  result = prime * result + (int) (aLong ^ (aLong >>> 32));
  result = prime * result + anInt;
  result = prime * result +
                   ((anObject == null) ? 0 : anObject.hashCode());
  result = prime * result + Arrays.hashCode(anArray);
  return result;
}
public boolean equals(Object obj) {
  if (this == obj) {
    return true;
  }
  if (obj == null) {
    return false;
  }
  if (getClass() != obj.getClass()) {
    return false;
  }
  final Eclipse33Java5 other = (Eclipse33Java5) obj;
  if (aBoolean != other.aBoolean) {
    return false;
  }
  if (Double.doubleToLongBits(aDouble) !=
      Double.doubleToLongBits(other.aDouble)) {
    return false;
  }
  if (aLong != other.aLong) {
    return false;
  }
  if (anInt != other.anInt) {
    return false;
  }
  if (anObject == null) {
    if (other.anObject != null) {
      return false;
    }
  }
  else if (!anObject.equals(other.anObject)) {
    return false;
  }
  if (!Arrays.equals(anArray, other.anArray)) {
    return false;
  }
  return true;
}
Using the ternary operator the hashCode method gets quite compact, but equals is a bit too verbose for my liking. IntelliJ IDEA could always generate these methods. IDEA 7.0 creates something like
public int hashCode() {
  int result;
  long temp;
  result = (aBoolean ? 1 : 0);
  temp = aDouble != +0.0d ? Double.doubleToLongBits(aDouble) : 0L;
  result = 31 * result + (int) (temp ^ (temp >>> 32));
  result = 31 * result + (int) (aLong ^ (aLong >>> 32));
  result = 31 * result + anInt;
  result = 31 * result +
                (anObject != null ? anObject.hashCode() : 0);
  result = 31 * result +
                (anArray != null ? Arrays.hashCode(anArray) : 0);
  return result;
}
public boolean equals(Object o) {
  if (this == o) {
    return true;
  }
  if (o == null || getClass() != o.getClass()) {
    return false;
  }
  Idea70Java5 original = (Idea70Java5) o;
  if (aBoolean != original.aBoolean) {
    return false;
  }
  if (Double.compare(original.aDouble, aDouble) != 0) {
    return false;
  }
  if (aLong != original.aLong) {
    return false;
  }
  if (anInt != original.anInt) {
    return false;
  }
  if (anObject != null ? !anObject.equals(original.anObject) :
                         original.anObject != null) {
    return false;
  }
  // Probably incorrect - comparing Object[] with Arrays.equals
  if (!Arrays.equals(anArray, original.anArray)) {
    return false;
  }
  return true;
}
Typical IDEA, with a little fix for +0.0/-0.0 and some warning concerning Arrays.equals, but else totally the same. In fact, all these implementations suck (including my own, which sucks most). All these result = prime * result ... and if ... return false; are definitely not DRY. I always favour Apache Commons Lang builders. A hand-coded solution using them would look like
public int hashCode() {
  return new HashCodeBuilder().
         append(aBoolean).
         append(aDouble).
         append(aLong).
         append(anInt).
         append(anObject).toHashCode();
}
public boolean equals(Object other) {
  if (this == other) {
    return true;
  }
  if (other == null || getClass() != other.getClass()) {
    return false;
  }
  ApacheCommons o = (ApacheCommons) other;
  return new EqualsBuilder().
         append(aBoolean, o.aBoolean).
         append(aDouble, o.aDouble).
         append(aLong, o.aLong).
         append(anInt, o.anInt).
         append(anObject, o.anObject).
         append(anArray, o.anArray).isEquals();
}
Well, that's much shorter, isn't it.

20 January 2009

Generic Build Server Notification Tray

I like to be notified immediately when our build fails (or at least before someone notices and tells me that it's my fault :-). I really have to know. In fact I am kind of paranoid about it. Ideal would be some kind of system tray notifier, like Team City has one.

Scituate Lighthouse Some years ago at Herold we were using Anthill OS, which is nice but minimalistic and did not offer any notifications. So I made a tray notifier myself using the System Tray Functionality of Java SE 6. The notifier polled the configured build server status page and used regular expressions from a property file to parse it. If a build changed to red then a little popup was shown. Later I was using Cruise Control and the only thing I was able to find was the CruiseControl-Eclipse-Plugin on Google Code. That's quite cool stuff, but I needed something that popped up in my face when the build was red.

So here is my Generic Build Server System Tray Notifier. After unpacking the zip you have to create a startup script or link executing the jar that looks like <path to java 6>\bin\javaw.exe -jar BuildServerSystemTray.jar <path to config> (Source is included in the zip.)

Configuration
The notifier is generic and needs a properties file. The zip contains sample configurations for Anthill OS 1.7, Cruise Control 2.3 and Hudson 1.2. You will have to customise the configuration. At least the build server URL (server.url) has to be set accordingly. It should be easy to create configurations for other build servers, just set the proper value for the status.pattern property. This property defines a regular expression matching the whole information about a build containing the project name, success or failure and build time. The regex grouping values status.name.group, status.value.group and status.date.group must be set accordingly.

FAQ
Q: I was checking out the source, why is the package at.kugel used as top level namespace instead of org.codecop? A: Kugel was my coder pseudonym in the 80ties when I started coding for Commodore 64. I'm using it from time to time when I'm feeling retro. Kugel is German for ball or sphere. The name was coined by my first coding buddy because I was quite overweight.

11 December 2008

New in Java 6

Java 6 New Features coverIt has been two years since Java 6 was released, so it's really high time to get to know it better.

Book about new features
Earlier this year I read Java 6 New Features by Budi Kurniawan to get an idea of the new features. I liked the book a lot because it is really unique. All the other books you find for Java 6 are general Java books that more or less cover the new features of Mustang. I do not want to read about the methods of java.lang.Object or the Collections Framework again. Budi Kurniawan does an excellent job focusing only on the new stuff. If you want to know what is new in release 6, go for this book!

List of all new classes in Mustang
Then I updated my list of all classes included in the runtime of Java, similar to what I did two years ago. I used Sun's Java 1.6.0_11 and created the updated list of all runtime environment classes in Java 1.6. Let's see what I found: Java 6 added only 74 new types in the java. name-space,
java.awt.Desktop
java.awt.font.LayoutPath
java.awt.geom.Path2D
java.awt.GridBagLayoutInfo
java.awt.LinearGradientPaint
java.awt.MultipleGradientPaint
java.awt.RadialGradientPaint
java.awt.SplashScreen
java.awt.SystemTray
java.awt.TrayIcon
java.beans.ConstructorProperties
java.io.Console
java.io.IOError
java.lang.management.LockInfo
java.lang.management.MonitorInfo
java.net.CookieManager
java.net.CookiePolicy
java.net.CookieStore
java.net.HttpCookie
java.net.IDN
java.net.InterfaceAddress
java.security.PolicySpi
java.security.URIParameter
java.sql.ClientInfoStatus
java.sql.NClob
java.sql.RowId
java.sql.RowIdLifetime
java.sql.SQLClientInfoException
java.sql.SQLDataException
java.sql.SQLFeatureNotSupportedException
java.sql.SQLIntegrityConstraintViolationException
java.sql.SQLInvalidAuthorizationSpecException
java.sql.SQLNonTransientConnectionException
java.sql.SQLNonTransientException
java.sql.SQLRecoverableException
java.sql.SQLSyntaxErrorException
java.sql.SQLTimeoutException
java.sql.SQLTransactionRollbackException
java.sql.SQLTransientConnectionException
java.sql.SQLTransientException
java.sql.SQLXML
java.sql.Wrapper
java.text.Normalizer
java.text.spi.BreakIteratorProvider
java.text.spi.CollatorProvider
java.text.spi.DateFormatProvider
java.text.spi.DateFormatSymbolsProvider
java.text.spi.DecimalFormatSymbolsProvider
java.text.spi.NumberFormatProvider
java.util.ArrayDeque
java.util.concurrent.BlockingDeque
java.util.concurrent.ConcurrentNavigableMap
java.util.concurrent.ConcurrentSkipListMap
java.util.concurrent.ConcurrentSkipListSet
java.util.concurrent.LinkedBlockingDeque
java.util.concurrent.locks.AbstractOwnableSynchronizer
java.util.concurrent.locks.AbstractQueuedLongSynchronizer
java.util.concurrent.RunnableFuture
java.util.concurrent.RunnableScheduledFuture
java.util.Deque
java.util.NavigableMap
java.util.NavigableSet
java.util.ServiceConfigurationError
java.util.ServiceLoader
java.util.spi.CurrencyNameProvider
java.util.spi.LocaleNameProvider
java.util.spi.LocaleServiceProvider
java.util.spi.TimeZoneNameProvider
java.util.zip.DeflaterInputStream
java.util.zip.InflaterOutputStream
java.util.zip.ZipError
and around 400 in javax. packages,
javax.activation
javax.annotation
javax.jws
javax.lang.model
javax.script
javax.smartcardio
javax.tools
javax.xml.bind
javax.xml.crypto
javax.xml.soap
javax.xml.stream
javax.xml.transform.stax
javax.xml.ws
mainly the Java Activation Framework, some extended annotations and the model of the Java language. Further there are the new Scripting (JSR 223) and Compiler (JSR 199) APIs. More than half of the new classes are XML related, including XML Binding/JAXB 2.0 (JSR 222), XML signatures (JSR 105), Streaming API 4 XML/StaX (JSR 175) and XML based Web Services/JAX-WS 2.0 (JSR 224).

The need for a better tool
Till now I used some ugly shell scripts to extract the needed information about the classes in rt.jar. With the growth of the JRE the repeated call of javap -public %class% for each class took more and more time. I needed something else to determine the accessibility of each class. I remembered that there was a field that determined various attributes of a class. I wanted to load the class file's bytes, jump to the offset of this field and read the package/public flag. The Java class file format is simple, but unfortunately not that simple. In order to read the access_flags, one needs to understand the whole constant pool because the access flag is stored afterwards and the constant pool is of variable length. So I started disassembling the class files. I do not know why, but I happened to write the new script in Ruby:
# Unpack HI-LO byte orders contained in the String.
class String
  # Return the _index_ 'th and the next element as unsigned word.
  def u2(index)
    self[index..index+1].unpack('n')[0]
  end
end

class JavaClassHeader

  # Parse the binary _data_ from the class file.
  def initialize(data)

    # u4 magic;
    # u2 minor_version;
    # u2 major_version;

    # u2 constant_pool_count;
    # cp_info constant_pool[constant_pool_count-1];

    constant_pool_count = data.u2(8)
    pos = 10
    cnt = 1
    while cnt <= constant_pool_count - 1
      case data.u1(pos) # cp_info_tag
        when 7
          pos += 3
        when 9
          pos += 5
        when 10
          pos += 5
        when 11
          pos += 5
        when 8
          pos += 3
        when 3
          pos += 5
        when 4
          pos += 5
        when 5
          pos += 9
          cnt += 1
        when 6
          pos += 9
          cnt += 1
        when 12
          pos += 5
        when 1
          length = data.u2(pos+1)
          pos += 3 + length
        else
          raise "const ##{cnt} unknown tag #{data[pos]}"
      end
      cnt += 1
    end

    # u2 access_flags;
    @access_flags = data.u2(pos)
  end
After (sort of) parsing the class file, the check if a class is public or only package accessible was straight forward to implement.
  ACC_PUBLIC = 0x0001

  # Return +true+ if the class is public.
  def accessible?
   (@access_flags & ACC_PUBLIC) != 0
  end
This improved performance a lot and I am looking forward to the release of Java 7 to use my new ClassList script again.

(Download the list of all classes in Mustang.)

Update 14 Mar 2009

javaclass-rb Project Initiated

The ClassList script was fun and made me want to play more with class files. Based on the source code above, I created javaclass-rb, a parser and disassembler for Java class files, similar to the javap command. The initial version reads the class file version and the package/public flag of a class as well as the constant pool. Expect updates soon!