With tonight's episode "Hiro's", Heroes has become a must-watch show for me. A more interesting implementation of the "six degrees" theme than Six Degrees, that's for sure.
If I was a taxpayer that had helped fund a stadium for my local NFL team, I'd be pissed to learn that the league decided they were going to take regular-season home games away from my community. It'll be interesting to see how the league or team owners will compensate fans and local businesses negatively affected by this decision.
Since their announcement about five months ago, I've eagerly awaited Dell's first AMD-Opteron-based servers. The PowerEdge 6950 was released today. I'm quite familiar with HP's ProLiant DL585 boxes; I think they've been the best VMware ESX hosts on the market for the last few years. With the PE6950 release I compared its specs to HP's latest DL585, the G2. Beyond the badges and management software/interfaces, here are the major differences I see:
The PE6850 utilizes Broadcom chipsets; the DL585 G2 uses nVidia plus AMD. Until I saw the Dell specs, I wasn't even aware Broadcom made system chipsets. Their ServerWorks division does; perhaps it's the first time system chipsets have been marketed as Broadcom since the acquisition. I know nVidia's been making AMD system chipsets for some time. Advantage: HP.
The DL585 G2 offers one more PCIe x8 slot than the PE6950 and two PCI-X slots that aren't present in the Dell. Advantage: HP.
A sweet config with four 2.6GHz processors, 32GB of RAM (16 x 2GB DIMMs), a RAID controller with four 72GB drives, and a DVD-ROM drive lists for $22,560 from Dell, and $23,624 from HP. Advantage: Dell.
This is Dell's first enterprise product with Opteron processors; HP's been doing Opteron for a few years now. Advantage: HP.
Besides the BDFL podcasts, I haven't had much in the way of Net output, so here goes. I've been busy at home getting furniture moved around as previously blogged; we have some stuff coming tomorrow. As a part of the moves, I got a new Dell 1907FP LCD monitor and it definitely beats the 17" CRT that it's demoted. After having a similar one at work for over a year now, I definitely knew what I was missing at home.
More of my audio stuff (Mackie 1202VLZ, Alesis QSR, Yamaha MIDI controller) has made it back into the basement as a result. I haven't played the synth much since getting the bass thing going full-time again, but we'll see.
I've been extremely busy at work, probably one of my busiest times there. I've been waist-deep in blade servers and VMware for the last few weeks and it's all finally coming online. This is probably going to end up being the most significant infrastructure I've helped design and build to date, and I think it's going to showcase how we can best manage our Windows Server infrastructure in the future. It's also fun to have extra hardware to test out Ubuntu on. :)
Melissa is doing great. We can't wait for her next ultrasound so that we can find out the baby's gender. We're both looking forward to having another little one around here.
I mentioned on last Tuesday's BDFL podcast that I finally moved this site to another hosting provider. I now have cygweb and the MHS site co-hosted on the same MT 3.33 instance. One thing I wasn't prepared for is a rise in comment spam. Apparently this MT instance was in some spammers' site, but since MHS doesn't have comments, it was bulletproof. Not so much now. I highly encourage you to use TypeKey if you want to comment, but I may incorporate a simple Turing test (perhaps the one implemented in the TinyTuring plugin) for those that don't want to authenticate just to comment.
Just as the winter weather starts kicking in here in Harrisburg, the wheels of change have started turning as it pertains to our furniture. We're expecting our second child in early May, so to get his/her new room ready we have to move some stuff around.
To make our office an even better guest room, we've decided to move the computer desk and quite a bit of the multimedia hardware to the basement. In its place will be a very functional armoire-style desk that will be narrower and easy to close up when guests are using the room. I have to move quite a few things around to make that happen, but we will be modernizing some of our equipment to soften the blow. My venerable Samsung Syncmaster 17GLsi monitor will go downstairs and it its place will most likely be a new Dell 20" LCD.
Ryan's room will say bye-bye to the dresser that can host a baby-changing mat, in favor of a larger chest of drawers and a computer desk. He plays games on my old "Maestro" computer, which will get its own keyboard, mouse, and small LCD monitor.
We will most likely hold on to Melissa's childhood furniture which is now in the new baby's room for later use, but some of it will have to go in the already crowded basement. I think we're going to have to finally junk some of the stuff we have in storage to make room. And of course, the crib will be rebuilt in the baby's room in the spring, after we've had a chance to paint it and decorate.
We've had the benefit of a lot of storage space for years now. The new little one is making us re-evaluate some of this stuff we hold on to for no other reason than to not get rid of it.
package com.sixlegs.definalizer;import java.lang.instrument.*;import java.security.ProtectionDomain;import org.objectweb.asm.*;import static org.objectweb.asm.Opcodes.ACC_FINAL;public class Main implements ClassFileTransformer{ public static void premain(String args, Instrumentation inst) { inst.addTransformer(new Main()); } public byte[] transform(ClassLoader loader, String className, Class> clazz, ProtectionDomain protectionDomain, byte[] b) { ClassReader reader = new ClassReader(b); ClassWriter writer = new ClassWriter(true); ClassAdapter adapter = new Definalizer(writer, className); reader.accept(adapter, true); return writer.toByteArray(); } static class Definalizer extends ClassAdapter { public Definalizer(ClassVisitor cv, String className) { super(cv); } @Override public void visit(int version, int access, /* ... */) { access &= ~ACC_FINAL; cv.visit(version, access, name, signature, superName, interfaces); } @Override public MethodVisitor visitMethod(int access, String name, /* ... */) { access &= ~ACC_FINAL; return cv.visitMethod(access, name, desc, signature, exceptions); } }}
Compile this code into a jar and specify a "Premain-Class" manifest entry:
Premain-Class: com.sixlegs.definalizer.Main
Now the jar can be specified as an argument to -javaagent.Here is an example which demonstrates using CGLIB to create a subclass at runtime:
import net.sf.cglib.proxy.*;import java.lang.reflect.Method;public class Test{ public static class FinalExample { @Override final public String toString() { return "final method"; } } public static void main(String[] args) throws Exception { Enhancer e = new Enhancer(); e.setSuperclass(FinalExample.class); e.setCallback(new MethodInterceptor(){ public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable { System.err.println("calling " + method); return proxy.invokeSuper(obj, args); } }); System.err.println("RESULT: " + (FinalExample)e.create()); }}
The command line I used to run it was:
CLASSPATH=.:cglib.jar java -javaagent:definalizer.jar Test
Normally this would fail because the class and method are final, butbecause definalizer has stripped all of the final modifiers, the methodis successfully intercepted:
calling public java.lang.String Test$FinalExample.toString()
The entire source distribution can be downloaded here,or just the binary jar (use at your own risk). If someone is interested inintegrating this into their own project, let me know.
Today we are releasing a free Java-based desktop application whichcan view Microsoft PowerPoint 97-2003 presentations.Download it here,or look atthe screenshots. It uses the same underlying code as our enterpriseJava libraries and should run on any platform where the 1.5 JRE isavailable.
OS X and Linux users should find it especially useful as Microsoft doesnot provide a free viewer for those platforms (the last viewer for theMac was for Office 98 and requires OS 9). It should also start up fasterand have better overall fidelity than free office suites likeOpenOffice. There is no true "slide show" mode yet (we hope to add thateventually), but the slide navigator view and incremental search featuremake browsing nicer.
Although fidelity is one of our top goals, there are likely a few things thatare "not quite right" because our knowledge of the file format is necessarilyreverse-engineered. If you find a presentation which demonstrates a bug,please visit our forums.Of course feature suggestions are welcome too!
On the technical side, there are a bunch of libraries and tools which we usedin creating the viewer, besides the standard ones like Ant and Emacs :).Here are most of them:
The code is structured so that the viewer could be launched viaJava Web Start,although the experience isn't quite as nice as a desktop app. If anyonereally wants to run this via Web Start, let me know.
Classpath wildcards are a long-awaited feature which are finally makingtheir appearance in Mustang. You can read more about themhereand here.
Now that the syntax is nailed down I've added the same capabilities tothe latest release of the Jar Jar Links library.In particular the dependencyfinding feature is much easier to use now:
$ java -jar jarjar.jar --find --level=jar 'lib/*'
This will parse all of the jar files in the lib directory and print outall of the inter-jar dependencies. Note that the asterisk normally must bequoted in order to prevent expansion by the shell.
One good use I've found for the dependency code is in building WARfiles. We have a number of web applications built from the same sourcetree, and each one depends on a slightly different set of libraries. Thesimple approach is to just dump every library into every WAR, but it isnot too much harder to use Jar Jar to determine exactly which librariesshould be included.
Because the format of the --find command to Jar Jar is not exactlywhat we need, we can use the programmatic API instead:
import com.tonicsystems.jarjar.*;public class DepDump{ public static void main(String[] args) throws Exception { DepHandler handler = new AbstractDepHandler(DepHandler.LEVEL_JAR){ public void handle(String from, String to) { System.out.println(new File(to).getName()); } }; new DepFind().run(args[0], args[1], handler); }}
This will only print out the dependencies in the second classpathargument. For example:
$ java DepDump build/main 'lib/*' > includes.txt
Assuming all of your class files are in build/main and your libraries inlib, this will only print out the names of the libraries that your code actuallyuses. Redirecting the output to includes.txt is useful because in ourAnt task we can use the includesfile option to only add thoseparticular libraries to our WAR:
If you are using the JarJarTask to embed other libraries, using theDepFind API can also be useful to verify that the resulting library haszero dependencies.
I've been working on an application which can be deployed via JavaWeb Start. One nice think about Web Start is that it willuse contentnegotiation with the server to download highly compressed jar fileswhen they are available.
The documentation includes sample Servlet code to handle thenegotiation, which is nice, but I didn't want to run a Servlet containerjust for this. Thankfully I ran across Keith Lea's blog entryGuide:How to use Pack200 for your Java Web Start applications on Apache WebServer which shows how to use Apache's own content negotiationmodules and eliminates the need for any Servlets. However, it seemedlike it could still be made a little simpler. In particular, I didn'tlike having to create a "type map" for each compressed jar. What follows iswhat I think is the simplest possible configuration for gettingthis to work on Apache 2.
In each folder where you will serve jar files from, addan .htaccess file with these lines:
Options +MultiViewsMultiviewsMatch Any
That's it for configuration! Now you just have to drop the right jarsinto the folder with the .htaccess file. If your originaljar is named foo.jar, you should put the following into thefolder:
foo.jar.unpacked
original jar, just renamed
foo.jar.gz
gzipped
foo.jar.pack.gz
compressed with Pack200
For my application these three jars were 823, 698, and 234 kilobytes,respectively. Because Web Start auto-updates those bytes can reallyadd up in saved bandwidth costs over time.
Here is a simple shell script which will take a single unpacked jarfile and create the three necessary files:
Note that renaming foo.jarto foo.jar.unpacked is a critical step. The ApacheMultiViews feature will disregard the compressed jars and alwaysserve foo.jar if it actually exists. You don't have to usethe .unpacked suffix, just make sure to tack onsomething.