Monthly Archives: October

Stop Using GMT!

GMT, the famous Greenwich Mean Time, is used everywhere. However, we should all consider not using it. Universal Time (UT) — or even better, Coordinated Universal Time (UTC) — should be used instead. Why? In a given location, the real solar time is the time indicated by the Sun on a sundial. It is defined as the angle, expressed in hours, minutes and seconds of time — 1 hour corresponding to 15° — between the sun and the local meridian. According to the definition, it is then 0h when the sun crosses the local meridian, which is noon local time, and not 12h! The mean solar time is the real solar time corrected by the equation of time. The Greenwich Mean Time is the mean solar time at the Royal Observatory in Greenwich, London.

As you can see, GMT refers to an astronomical day starting at noon, and is thus not designed for civil timekeeping. Universal Time is the Greenwich Mean Time adjusted to have a civil day starting at midnight.

Universal Time (UT) is not a perfectly uniform timescale (the Earth’s rotation is not perfectly uniform) To compensate for this lack of accuracy, we now use Coordinated Universal Time (UTC), which is an atomic timescale (thus perfectly uniform) that approximates Universal Time (UT) by less than a second (remember hearing in the news that we need to add or remove a second to our clocks at the end of the year? Those are leap seconds to keep UTC in sync with the Earth’s rotation!)

Do yourself a favor and stop using GMT. Look smart and start using UTC instead. Cheers!

forbrukslån med betalingsanmerkning

YUI Compressor and Java Class Loader

The YUI Compressor uses a slightly modified version of the parser used in the Rhino JavaScript engine. The reason for modifying the parser came from the need to support JScript conditional comments, unescaped forward slashes in regular expressions — which all browsers support and many people use — and a few micro optimizations. The problem is that many users had the original Rhino Jar file somewhere on their system, either in their classpath, or in their JRE extension directory (<JRE_HOME>/lib/ext) This caused many headaches because the wrong classes were being loaded, leading to many weird bugs.

Today, I finally decided to do something about it. This meant writing a custom class loader to load the modified classes directly from the YUI Compressor Jar file. You can download the source and binary package here:

Download version 2.4 of the YUI Compressor

The skeleton of the custom class loader is pretty straightforward:

package com.yahoo.platform.yui.compressor;
public class JarClassLoader extends ClassLoader
{
    public Class loadClass(String name) throws ClassNotFoundException
    {
        // First check if the class is already loaded
        Class c = findLoadedClass(name);
        if (c == null) {
            // Try to load the class ourselves
            c = findClass(name);
        }
        if (c == null) {
            // Fall back to the system class loader
            c = ClassLoader.getSystemClassLoader().loadClass(name);
        }
        return c;
    }
    protected Class findClass(String name)
    {
        // Most of the heavy lifting takes place here
    }
}

The role of the findClass method is to first locate the YUI Compressor Jar file. To do that, we look in the classpath for a Jar file that contains the com.yahoo.platform.yui.compressor.JarClassLoader class:

private static String jarPath;
private static String getJarPath()
{
    if (jarPath != null) {
        return jarPath;
    }
    String classname = JarClassLoader.class.getName().replace('.', '/') + ".class";
    String classpath = System.getProperty("java.class.path");
    String classpaths[] = classpath.split(System.getProperty("path.separator"));
    for (int i = 0; i < classpaths.length; i++) {
        String path = classpaths[i];
        JarFile jarFile = new JarFile(path);
        JarEntry jarEntry = findJarEntry(jarFile, classname);
        if (jarEntry != null) {
            jarPath = path;
            break;
        }
    }
    return jarPath;
}
private static JarEntry findJarEntry(JarFile jarFile, String entryName)
{
    Enumeration entries = jarFile.entries();
    while (entries.hasMoreElements()) {
        JarEntry entry = (JarEntry) entries.nextElement();
        if (entry.getName().equals(entryName)) {
            return entry;
        }
    }
    return null;
}

Once we know where the YUI Compressor Jar file is, we can load the appropriate class from that file. Note the need to define the package the class belongs to before calling defineClass!

protected Class findClass(String name)
{
    Class c = null;
    String jarPath = getJarPath();
    if (jarPath != null) {
        JarFile jarFile = new JarFile(jarPath);
        c = loadClassData(jarFile, name);
    }
    return c;
}
private Class loadClassData(JarFile jarFile, String className)
{
    String entryName = className.replace('.', '/') + ".class";
    JarEntry jarEntry = findJarEntry(jarFile, entryName);
    if (jarEntry == null) {
        return null;
    }
    // Create the necessary package if needed...
    int index = className.lastIndexOf('.');
    if (index >= 0) {
        String packageName = className.substring(0, index);
        if (getPackage(packageName) == null) {
            definePackage(packageName, "", "", "", "", "", "", null);
        }
    }
    // Read the Jar File entry and define the class...
    InputStream is = jarFile.getInputStream(jarEntry);
    ByteArrayOutputStream os = new ByteArrayOutputStream();
    copy(is, os);
    byte[] bytes = os.toByteArray();
    return defineClass(className, bytes, 0, bytes.length);
}
private void copy(InputStream in, OutputStream out)
{
    byte[] buf = new byte[1024];
    while (true) {
        int len = in.read(buf);
        if (len < 0) break;
        out.write(buf, 0, len);
    }
}

The last thing we need to do is bootstrap the application. In order to do that, we simply load the main class (YUICompressor) using our new custom class loader. All the classes that will be needed at runtime will use the same class loader:

package com.yahoo.platform.yui.compressor;
public class Bootstrap
{
    public static void main(String args[]) throws Exception
    {
        ClassLoader loader = new JarClassLoader();
        Thread.currentThread().setContextClassLoader(loader);
        Class c = loader.loadClass(YUICompressor.class.getName());
        Method main = c.getMethod("main", new Class[]{String[].class});
        main.invoke(null, new Object[]{args});
    }
}

As you can see, it's not terribly complicated to write a custom class loader. Note: I left out all the exception handling code and the import statements for clarity. The final code can be found in the downloadable archive. Cheers!

The Modern Moon: A Personal View

The Modern Moon: A Personal View (book cover)

I just finished reading The Modern Moon: A Personal View by planetary geologist Charles A. Wood, and felt compelled to write a few lines about this genuinely brilliant book. I have been practicing amateur astronomy for the past 17 years, and have occasionally looked at the moon through various telescopes. But for some reason, our natural satellite has always failed to captivate my attention. I suppose you don’t take interest in what you fail to understand. Moreover, telescopic views of the moon are overwhelming with details, making it hard to decipher what you are looking at. Wood’s book brings order to chaos and does a great job at explaining the science behind some of the surface features of the moon. For this reason, I warmly recommend anybody even remotely interested in lunar geology to read this book. Observers will want to complement it with a good lunar atlas, such as Antonin Rukl’s Atlas of the Moon.