Wednesday, September 28, 2005

my Java blog is created

http://jroller.com/page/jeffrobertson

Now I just need to blogroll myself.

Use Stored Procedures for Java Persistence

Find out why you should use stored procedures to build your Java persistence layer instead of embedded SQL, entity beans, or tools such as Hibernate. Then learn how to do it.


Contrarian, to say the least.

Tuesday, September 27, 2005

the big three-oh, belated

I've been thirty for over a month, and it finally hit me: I'm not a 20-something anymore. What finally did it for me? Looking up the ages of various TV and movie stars on IMDB.

Throughout my 20s, I could count on the fact that actors my age were still being cast as teenagers. You, the old 90210 factor.. a 26 year old guy playing a 17 year old guy is, while not believable to anybody, apparently what audiences want to see.

But once you hit 30, you're finally an adult by hollywood standards.

For example: just last year, Freddie Prinze Jr. was able to play the apparently-teenaged Fred in "Scooby Doo II". Next year, young master Prinze will turn 30. He'd better land himself a nice adult sitcom quick. Whoops, he just did!

my baby pictures!

Several months ago, my wife got on to me for putting pictures of our kids in public view on Flickr. Rather than making them private and setting up the people that I wanted to show them to as friends, I did the lazy thing and just deleted them off of Flicr.

Unfortunately, it turns out that these were the only copies of these particular pictures! Including the first picturs of my younger daughter when she came home from the hospital.

If any of you, for any reason, saved off a copy of any of these pictures while they were online, please send me a copy.

Monday, September 26, 2005

This morning I overslept, and stumbled out to the car, forgetting to take the trash to the curb (now I remember, dammit!), and was very pleasantly surprised by the presence of rain.

I guess this is the after-effects of Hurricane Rita. I think it is also the first time this month that it has rained at my house. Every green growing thing in my yard is thankful.

Sunday, September 25, 2005

Slashdot | Why Vista Had To Be Rebuilt From Scratch

Yes, I'm blogging a Slashdot story. Still in the process of reading TFA, but this one line right here is what makes me think this article is a keeper:
In 2001 Microsoft made a documentary film celebrating the creation of Windows XP, which remains the latest full update of Windows. When Mr. Allchin previewed the film, it confirmed some of his misgivings about the Windows culture. He saw the eleventh-hour heroics needed to finish the product and get it to customers. Mr. Allchin ordered the film to be burned.


Interesting that according to this WSJ article, Microsoft's problem has been too much "cowboy coding" and not enough disciple, whereas the natural tendency of the open source culture is to accuse of closed-source companies as having too much process and not enough freedom.

Friday, September 23, 2005

java.net: Dynamic Interaction with Your Web Application

In this article I will show you the code of a simple servlet. This servlet accepts just one attribute via the POST method. An equally simple HTML page consisting of a text area and a submit button is written to interact with it. Yet despite the simplicity of these two components, what we will have is a powerful tool to interactively analyze the state of any web application.

music to steal

"Black Crow Heart of Gold" by Numbers. This song is very... canonical. The chunk-chunk-chunk of the guitar, that droning keyboard, the lyrics that I assumed had something to do with infinite improbability drives until I found out the song really was supposed to be about crows, the frankly and probably completely accidentally Rush-like arrangement (slow but jerky rythym like "Tom Sawyer", that part starting at 4:00 reminds me of parts of "Bytor and the Snow Dog").. oh hell, just listen to it.

Thursday, September 22, 2005

have the Rita-induced gas panics started yet?

Any price-gouging going on already?

most pointlessly narcissistic thing ever

See if you can recognize the 20 Flvxxvm Florvm songs excerpted here.

0x90.org // [Absinthe :: Automated Blind SQL Injection] // ver1.3.1

Absinthe is a gui-based tool that automates the process of downloading the schema & contents of a database that is vulnerable to Blind SQL Injection.

Absinthe does not aid in the discovery of SQL Injection holes. This tool will only speed up the process of data recovery.

How It's Difficult to Ruin a Good Name: An Analysis of Reputational Risk

To what extent is (or isn't) investor confidence shaken? In other words, why is it the case that information security incidents do not appear to have a greater impact on both investor confidence as well as the public at large? To phrase the question in financial terms: why isn't the top line effected more than it is? To poignantly highlight this phenomena we ask: If 40 million customer credit card numbers are exposed in a security breach at the credit card processor CardSystems , why do a significant number people not cancel their Visa and/or Mastercard?

Wednesday, September 21, 2005

N453 EAT


4th floor hallway of founders hall

This is the top floor from which the aforementioned stairs are (one of) the escape routes. Obviously built out in recent times in space that used to just be attic. Very out of place; almost like being on a spaceship . Check out all those metal doors on the right wall.


stairwell in founders hall, royal holloway, egham, england

These narrow spiral metal stairs are an officially designated fire escape route for the upper floors.


Erinna


Erinna, originally uploaded by jeff_robertson.

Victorian half-naked-lady statue located at formerly all-female college. There's a dirty movie in there somewhere.

Yes, the pictures I took in England finally got developed. This is the statue which, the first time I saw it (across a shadowy courtyard at 2:00 am), struck me as unnervingly.. ghostlike? I think the word is "numinous". The photo really doesn't capture that part.


11Alive.com: Atlanta - Red Cross Kicked Out of DeKalb

Officials with the American Red Cross decided to vacate a mega relief center in DeKalb County at 5 p.m. Monday after the county CEO complained publicly about the agency's services or lack thereof.

Buggin' My Life Away : Anatomy of a Software Bug

I thought I’d discuss the anatomy of one of the more famous bugs we’ve had in Word: the “Disk is full” on save error.

Why software sucks - scottberkun.com

In order for people to say “this sucks” they have to care enough about the thing you’ve made to spend time with it and recognize how bad it is. For things that are equally bad, but are unimportant to someone, you won’t hear the same complaint.

yeah, that's what I need: another blog!

I'm thinking of setting up a separate blog purely for discussion of programming topics. The posts that consist entirely of Java code will go there in the future. Advantages:

  1. Keep that sort of thing off this blog.
  2. Have a blog that consists entirely of completely safe-for-work material so I can put it on business cards and such.
  3. With those eyes diverted to the other blog, I'll have greater freedom of speech here.
  4. A blog on jroller.com or somewhere like that seems likely to attract an audience of people who like to read posts consisting mostly of Java code.
  5. Anybody who wants to read both, can just subscribe to both.
Stretching myself too thin? Considering how few people read this blog anyway, is this just asking for trouble?

Tuesday, September 20, 2005

Woman pass men in IT pay scale - ZDNet UK News

Across all sectors the average female team leader, at 37 years old, is four years younger than her male counterpart, while female IT managers earn on average £45,869 per year — £779 more than the men do.

Georgia's New


Friday, September 16, 2005

see all that stuff in there? that's why your robot never worked

Ever have one of the days where you wake up in the morning and say to yourself: "Self, the world doesn't have enough J2EE web frameworks. Let's make one" ?

My framework, which I will probably not even name much less actually build, will have the following features:

  1. A "web page", with it's forms, buttons, etc., is represented by a POJO, or something very POJO-ish.
  2. Form fields on the web page will have their values copied into like-named bean properties on the POJO. Nothing new there, this is basic Struts stuff.
  3. Buttons, links, etc., being clicked by the user will result in the like-named method of the POJO being executed. Again, nothing new here.
  4. There will be no XML config file. Everything the framework needs to know, it gets from the POJO by doing reflection or annotations or something.
  5. All HTML will be generated by the framework by looking at the metadata on the POJO. That's right, there is NO template language.
  6. Note that does not mean that there will be HTML in the code or the annotations; it means that there will be annotations like "@Textarea" that flag that a certain bean property is represented by a text area.
  7. Annotations are optional, you can use this framework with older versions of Java by conforming to a naming convention for your bean properties and methods.
  8. In other words, all you write is a bunch of plain old classes, that follow some set of naming conventions and annotations, and you produce a working web app.
  9. Maybe the objects don't even have to be written in Java; maybe they are written in a language that does not need to be compiled, to facilitate on the fly hacking.
  10. The HTML produced by the framework will be very basic and is intended to be styled completely with CSS. If you don't think CSS is powerful enough to avoid the need to customize the HTML itself, then you haven't kept up with CSS.
  11. This is a pure web framework; it will not muddy itself by trying to deal with persistence, transactions, etc. Since the page objects are just POJO's, there should be no reason why you can't use them with EJB or Hibernate or something.
How's that for a manifesto?

Tim Boudreau's Blog: Patterns, Schmatterns

it's the same type of hype that says that one day, in the land of milk and honey, all software will be made by "component assemblers" (who presumably get paid minimum wage). I'd like to coin a term for these thingies - YAWMTI - Yet Another Way to Make Talent Irrelevant.

Monday, September 12, 2005

Slashdot | The Six Dumbest Ideas in Computer Security

Actual work-related content on Slashdot! How long has it been? I'm still in the process of RTFA but I do plan to skim the comments.

Friday, September 09, 2005

100 dishes to eat in Alabama before you die

This is old, and I think it's been discussed on certain email lists I'm on a few months back. However, somebody mentioned it to me yesterday so here it is again.

I've had 5 of the 100 dishes (not telling you which ones), although I've eaten at more of the restaurants than that.

Thursday, September 08, 2005

yahoo! vs. google: synerge

Pretty much what it says: yahoo vs. google

something remotely like an actual use for DynamicDelegator

Closer than our barking vehicle example, but still a toy. But hopefully you should be able to see the power of this thing. Without DynamicDecorator, the class below would have to provide an implementation of the entire COnnection interface, with all of it's methods except for close() just tunnelling straight through to the real connection. Something like this (but not exactly this) is why I wrote this kind of code for a real project at work.


/*
* StoopidDatabaseConnectionPool.java
*
* Created on September 8, 2005, 4:24 PM
*/
import java.util.*;
import java.sql.*;
/**
* Really simple example of how you might use DynamicDelegator.
*
* @author jRobertson
*/
public class StoopidDatabaseConnectionPool {

Collection pool = new HashSet();

public synchronized Connection getConnection() {
Connection con;
if( pool.isEmpty() ) {

// no connections already exist, so make one
con = reallyConnectToDatabase();

} else {
// get one from the pool
con = (Connection) pool.iterator().next();

// remove it so no one else can have it
pool.remove(con);
}

// wrap the connection with a proxy that will
// put the (real) connection back into the pool
// when the proxy is closed.
return (Connection) new PooledConnection(con).getProxy();

}


// named class, not anonymous, because of issues using
// reflection on local classes
public class PooledConnection extends DynamicDelegator {

public PooledConnection(Connection c) {
super(c);
}
public void close() {
pool.add(wrapped);
}

}

private Connection reallyConnectToDatabase() {
// not implemented for this silly example!
// if you want to try it, implement it yourself

// create a mock "Connection" that implements the
// Connection interface in the sense of being able
// to be assignable, but which does not actually
// implement any of the methods (they will throw exceptions).
// Another crazy use for InvocationChain.
InvocationChain chain = new InvocationChain();
chain.add(new Object() );
chain.addInterface(Connection.class);
return (Connection) chain.newProxyInstance();
}

public String toString() {
return "StoopidDatabaseConnectionPool: "+pool.size();
}

public int size() {
return pool.size();
}


}

Dynamic delegation, act 2

Last time, I showed an example of an InvocationHandler that used reflection on its own methods to decide when and how to delegate. Today I am going to take this a step further and present a base class that can be extended for any number uses. All of the code in this post has been tested, and I may also make it available in a zip file.

Firstly, the main class, DynamicDelegator. This is an abstract class that needs to be extended to add the methods that you want to override. For a simple example, a wrapper around java.util.Map might look like this:

public class MapWrapper extends DynamicDelegator {

public MapWrapper(Object o) {
super(o);
}

public Object put(Object key, Object value) {
System.out.println("Put called!");
return ((Map)wrapped).put(key,value);
}
}

Another class might use MapWrapper like this:

Map m = (Map) new MapWrapper(new HashMap()).getProxy();
m.put("foo","bar");
System.out.println( m.get("foo"));

When put is called, the method declared in MapWrapper will be executed. When get is called, the method executed will be the one from HashMap. It so happens that in this case, MapWrapper's put method also calls the method on the underlying Map after doing some logging output.

Here is an example that illustrates the introduction of an extra interface (in this case, Runnable) that is not implemented by the wrapped class:

public class MapWrapper extends DynamicDelegator implements Runnable {

public MapWrapper(Object o) {
super(o);
}

public Object put(Object key, Object value) {
System.out.println("Put called!");
return ((Map)wrapped).put(key,value);
}

public void run() {
System.out.println("Whoohoo!");
}
}

Obviiously the above is highly contrived. The code to use it might look like this:

Map m = (Map) new MapWrapper(new HashMap()).getProxy();
m.put("foo","bar");
System.out.println( m.get("foo"));
((Runnable)m).run();


What follows is the actual code for DynamicDelegator and the supporting classes that make it work. (HashKey and MethodSig from last time are used as well, but are not repeated).


/*
* DynamicDelegator.java
*
* Created on January 13, 2005, 9:31 AM
*/

import java.lang.reflect.*;

/**
* A class to make it easy to write dynamic proxies that
* wrap existing classes. Simply write methods that have
* the same names and signatures as the methods that you
* want to override. All other methods will be tunnelled
* straight through to the wrapped object. Uses reflection
* heavily, obviously.
* <p>
* It is not neccessary for the wrapper class to implement the same
* interface(s) as the wrapped object at compile time. Method name matching
* takes place dynamically at run time.
* <p>
* For a simple example, a wrapper around java.util.Map might look like this:
* <pre>
* public class MapWrapper extends DynamicDele {
*
* public MapWrapper(Object o) {
* super(o);
* }
*
* public Object put(Object key, Object value) {
* System.out.println("Put called!");
* return ((Map)wrapped).put(key,value);
* }
* }
* </pre>
* Another class might use MapWrapper like this:
* <pre>
* Map m = (Map) new MapWrapper(new HashMap()).getProxy();
* m.put("foo","bar");
* System.out.println( m.get("foo"));
* </pre>
* When <code>put</code> is called, the method declared in MapWrapper
* will be executed. When <code>get</code> is called, the method executed
* will be the one from HashMap. It so happens that in this case, MapWrapper's
* <code>put</code> method also calls the method on the underlying Map after
* doing some logging output.
* <p>
* Here is an example that illustrates the introduction of an extra interface
* (in this case, Runnable) that is not implemented by the wrapped class:
*<pre>
* public class MapWrapper extends DynamicDelegator implements Runnable {
*
* public MapWrapper(Object o) {
* super(o);
* }
*
* public Object put(Object key, Object value) {
* System.out.println("Put called!");
* return ((Map)wrapped).put(key,value);
* }
*
* public void run() {
* System.out.println("Whoohoo!");
* }
* }
* </pre>
* Obviiously the above is highly contrived.
* The code to use it might look like this:
* <pre>
* Map m = (Map) new MapWrapper(new HashMap()).getProxy();
* m.put("foo","bar");
* System.out.println( m.get("foo"));
* ((Runnable)m).run();
* </pre>
* @see java.lang.reflect.Proxy
* @see java.lang.reflect.InvocationHandler
* @see WrapperFactory
* @author jRobertson
*/
public abstract class DynamicDelegator {

/**
* The inner object that is being wrapped by us.
*/
protected Object wrapped;

/**
* If the getProxy method has been called, thisProxy
* is a reference to the proxy object that was returned
* by getProxy. This reference may be passed to any callbacks
* or other methods where you would normally pass "this".
*/
protected Object thisProxy;

/** Creates a new instance of DynamicDelegator */
public DynamicDelegator(Object wrapped) {
this.wrapped = wrapped;
}


/**
* Uses InvocationChain to tie this wrapper and the wrapped object
* together as a single proxy instance. The proxy implements all
* interfaces that are implemented by either this wrapper or by
* the wrapped Object, as well as any interfaces returned by the
* getAdditionalInterfaces method. Any method called on this proxy
* will be invoked on the wrapper if such a method if found there,
* or on the wrapped object otherwise.
* @see InvocationChain
*/
public Object getProxy() {
InvocationChain chain = new InvocationChain();
chain.add(this);
chain.add(wrapped);
chain.addInterfaces(getAdditionalInterfaces());
thisProxy = chain.newProxyInstance();
return thisProxy;
}




/**
* Normally this returns a zero-length array. Override to specify
* that the proxies created by this class should implement the
* returned interface(s) in addition to any that are implemented
* by the wrapper or the wrapped object.
*/
protected Class[] getAdditionalInterfaces() {
return new Class[0];
}


}


Now, to prove that I tested this thing, here is a JUnit test case which creates a couple of concrete implementations:


/*
* WrapperTest.java
* JUnit based test
*
* Created on January 13, 2005, 9:43 AM
*/

import junit.framework.*;

/**
*
* @author jRobertson
*/
public class WrapperTest extends TestCase {

public WrapperTest(String testName) {
super(testName);
}



protected void setUp() throws java.lang.Exception {
}

protected void tearDown() throws java.lang.Exception {
}

// TODO add test methods here. The name must begin with 'test'. For example:
// public void testHello() {}

public void testMap() throws Exception {

java.util.Map m = new java.util.HashMap();

MapWrapper mw = new MapWrapper(m);

java.util.Map proxyMap = (java.util.Map) mw.getProxy();

proxyMap.put("a","b");

assertEquals("b", proxyMap.get("a"));

assertTrue(mw.putCalled);

}

public void testRunnableMap() throws Exception {

java.util.Map m = new java.util.HashMap();

RunnableMapWrapper mw = new RunnableMapWrapper(m);

java.util.Map proxyMap = (java.util.Map) mw.getProxy();

proxyMap.put("a","b");

assertEquals("b", proxyMap.get("a"));

assertTrue(mw.putCalled);

((Runnable)proxyMap).run();

assertTrue(mw.runRan);

}

public void testRunnableMap2() throws Exception {

java.util.Map m = new java.util.HashMap();

RunnableMapWrapper2 mw = new RunnableMapWrapper2(m);

java.util.Map proxyMap = (java.util.Map) mw.getProxy();

proxyMap.put("a","b");

assertEquals("b", proxyMap.get("a"));

assertTrue(mw.putCalled);

((Runnable)proxyMap).run();

assertTrue(mw.runRan);

}

public class MapWrapper extends DynamicDelegator {

public boolean putCalled = false;

public MapWrapper(Object o) {
super(o);
}


public Object put(Object key, Object value) {
putCalled = true;
return ((java.util.Map)wrapped).put(key,value);
}

}


public class RunnableMapWrapper extends DynamicDelegator {

public boolean putCalled = false;
public boolean runRan = false;

public RunnableMapWrapper(Object o) {
super(o);
}

protected Class[] getAdditionalInterfaces() {
return new Class[] {
Runnable.class
};
}

public Object put(Object key, Object value) {
putCalled = true;
System.out.println("Put called!");
return ((java.util.Map)wrapped).put(key,value);
}

public void run() {
runRan = true;
}

}



public class RunnableMapWrapper2 extends DynamicDelegator implements Runnable {

public boolean putCalled = false;
public boolean runRan = false;

public RunnableMapWrapper2(Object o) {
super(o);
}

public Object put(Object key, Object value) {
putCalled = true;
System.out.println("Put called!");
return ((java.util.Map)wrapped).put(key,value);
}

public void run() {
runRan = true;
}

}


}


You will no doubt have noticed that DyanamicDelegator uses another class called InvocationChain to do the heavy lifting. InvocationChain is what I ended up with after re-factoring as much of logic related to conditional delegation out into it's own class, and generalizing it as much as possible.


/*
* InvocationChain.java
*
* Created on January 18, 2005, 10:46 PM
*/

import java.lang.reflect.*;
import java.util.*;

/**
* Uses reflection to create a chain of responsibility out of a
* collection of otherwise unrelated classes.
*
* @see java.lang.Proxy
* @see java.lang.InvocationHandler
* @see DynamicDelegator
*
* @author jRobertson
*/
public class InvocationChain implements InvocationHandler {

private Set interfaces = new HashSet();
private LinkedList links = new LinkedList();

/** Creates a new instance of InvocationChain */
public InvocationChain() {
}

/** Creates a new instance of InvocationChain
* with one object.
*/
public InvocationChain(Object a) {
this();
add(a);
}

/** Creates a new instance of InvocationChain
* with one object.
*/
public InvocationChain(Object a, Object b) {
this();
add(a);
add(b);
}

/**
* Adds the specified object to the end of the chain.
*/
public void add(Object o) {
ChainLink link = new ChainLink(o);
links.add(link);
ReflectionUtils.getAllInterfaces(o.getClass(), interfaces);
}

/**
* Manually add this interface to this list of interfaces
* that will be implemented by this chain.
*/
public void addInterface(Class c) {
interfaces.add(c);
}

/**
* Manually add these interfaces to this list of interfaces
* that will be implemented by this chain.
*/
public void addInterfaces(Class[] c) {
interfaces.addAll(Arrays.asList(c));
}

/**
* This method implements the InvocationHandler interface. The chain
* of responsibility will be searched until a method of the required
* name and argument types is found, and that method will then be
* invoked. The search stops after finding the first occurrence of
* a method in the chain, so the order in which the objects were
* added is important.
*/
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

// search the objects in the chain, one by one
for(Iterator i=links.iterator(); i.hasNext();) {
ChainLink link = (ChainLink) i.next();

// if the class implements the interface that
// declared this method, run it. we do this because
// I've seen cases where methods declared by a class's
// distant ancestors don't show up when you enumerate
// it's methods. specifically, the Connection objects
// returned from Oracle's database driver are like this.
if( method.getDeclaringClass().isAssignableFrom( link.getObject().getClass() ) ) {
return method.invoke(link.getObject(), args);
}

// if the class has a method that has the same
// name and type as this method, find that
// method and run it instead
Method match = link.matchMethod(method);
if( match != null) {
return match.invoke(link.getObject(), args);
}

}

// ok, the fast way of just looking stuff up in a hashmap
// failed... now try the slow way that involves catching
// exceptions. not sure if it is really possible to get
// here, but you never can tell with reflection
for(Iterator i=links.iterator(); i.hasNext();) {
ChainLink link = (ChainLink) i.next();

try {
return method.invoke(link.getObject(), args);
} catch (IllegalAccessException e) {
// nothing
} catch (IllegalArgumentException e) {
// nothing
}
}

throw new NoSuchMethodException("couldn't find metho in my chain of respsonsibility: "+method);
}

/**
* Returns the set of all interfaces implemented by
* any objects in the chain.
*/
public Class[] getInterfaces() {
Class[] intArray = new Class[interfaces.size()];
return (Class[]) interfaces.toArray(intArray);
}

/**
* Creates a proxy that implements all interfaces that are
* implemented by any object in the chain, and with this
* InvocationChain as the invocation handler.
*/
public Object newProxyInstance() {
return Proxy.newProxyInstance(getClass().getClassLoader(), getInterfaces(), this);
}

/**
* Inner class for each delegate in the chain.
*/
private static class ChainLink {
private Map methodMap = new java.util.HashMap();
private Object object;

ChainLink(Object o) {
object = o;
Method[] methods = o.getClass().getMethods();
for(int i=0; i<methods.length;i++) {
Method method = methods[i];

// do not count methods that we can't access
if( Modifier.isPublic(method.getModifiers())
&&
Modifier.isPublic(method.getDeclaringClass().getModifiers())
) {
methodMap.put( new MethodSig(method), method);
}
}
}

Method matchMethod(Method m) {
return (Method)methodMap.get( new MethodSig(m));
}

Object getObject(){ return object; }


}



}


InvocationChain is a pretty wild and wooly utility by itself. You could use it to combine unrelated classes and interfaces in a complete arbitrary way, as this test code illustrates:


import junit.framework.*;
/*
* InvocationChainTest.java
* JUnit based test
*
* Created on September 1, 2005, 12:02 PM
*/

/**
*
* @author jRobertson
*/
public class InvocationChainTest extends TestCase {

public InvocationChainTest(String testName) {
super(testName);
}


public static interface Animal {
String speak();
}

public static interface Vehicle {
int topSpeed();
}

public static class Dog implements Animal {
public String speak() {
return "woof!";
}
}

public static class Sled implements Vehicle {
public int topSpeed() {
return 5;
}
}

public void testChain() {

InvocationChain chain = new InvocationChain(new Dog(), new Sled());

Object dogSled = chain.newProxyInstance();

assertEquals( "woof!", ((Animal) dogSled).speak() );

assertEquals( 5, ((Vehicle) dogSled).topSpeed() );

}

}


Finally, InvocationHandler itself needs a method to enumerate all the interfaces implemented by a class and any of it's superclasses, and the super-interfaces of all of those, and so on. Because this is a general utility I put it into a separate class.


/*
* ReflectionUtils.java
*
* Created on January 18, 2005, 8:07 PM
*/

/**
* Utility methods for reflection, classes, interfaces, etc.
* @author jRobertson
*/
public class ReflectionUtils {

/**
* Recursively walks the graph of all superclasses and interfaces
* that are related to the passed-in class, and adds all the Class
* objects representing all the interfaces that are found to the
* passed-in Set.
*/
public static java.util.Set getAllInterfaces(Class c) {
java.util.Set s = new java.util.HashSet();
getAllInterfaces(c, s);
return s;
}

/**
* Recursively walks the graph of all superclasses and interfaces
* that are related to the passed-in class, and adds all the Class
* objects representing all the interfaces that are found to the
* passed-in Set.
*/
public static void getAllInterfaces(Class c, java.util.Set col) {

if(c == null) {
return;
}

Class[] ifaces = c.getInterfaces();

for(int i=0; i< ifaces.length; i++) {
col.add(ifaces[i]);
getAllInterfaces(ifaces[i], col);
}

getAllInterfaces(c.getSuperclass(), col);

}


}


Next time: more examples of what you can do with this stuff.

NPR : Alabama Town

Bayou La Batre was an impoverished coastal town in Alabama before Katrina swept through its mobile homes and one-story houses. Jim Zarroli went on patrol with a FEMA official and reports and how residents are coping with what's left and what's lost.

Wednesday, September 07, 2005

some real code..

All of the code in the previous post was typed on the fly, and I would not expect it to compile. Before I get any further into refactoring it, here are complete working versions:

MyInvocationHandler.java

/*
* MyInvocationHandler.java
*
* Created on September 7, 2005, 1:35 PM
*/
import java.lang.reflect.*;
import java.util.*;
/**
* Test code for my blog postings about InvocationHandlers.
*
* @author jRobertson
*/

public class MyInvocationHandler implements InvocationHandler {

/**
* The interface for the class that we are proxying/decorating/delegating-to.
*/
public static interface SomeInterface {
int foo(int x);
void bar(String s);
boolean baz();
void quux();
}


/**
* An implementation of this interface.
*/
public static class SomeImpl implements SomeInterface {
public int foo(int x) {
System.out.println("SomeImpl.foo");
return x+1;
}
public void bar(String s) {
System.out.println("SomeImpl.bar");
}
public boolean baz() {
System.out.println("SomeImpl.baz");
return true;
}
public void quux() {
System.out.println("SomeImpl.quux");
}
}



private Object realObject;

private Map methodsMap = new HashMap();

private void addMethod(Method m) {
methodsMap.put( new MethodSig(m), m);
}

public MyInvocationHandler(Object realObject) {
this.realObject = realObject;

Method[] methods = getClass().getMethods();
for(int i =0; i<methods.length; i++) {
addMethod( methods[i]);
}
}

public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Method myMethod = (Method) methodsMap.get( new MethodSig(method));

if( myMethod != null ) {
// if it's in the map, run the one from the map
return myMethod.invoke(this,args);
} else {
// otherwise just run the method on the original object
return method.invoke(realObject,args);
}
}

/**
* Replacement method that overrides the matching foo() method
*/
public int foo(int x) {
System.out.println("MyInvocationHandler.foo");
return ((SomeInterface) realObject).foo(x);
}

/**
* Replacement method that overrides the matching bar() method
*/
public void bar(String s) {
// do nothing! hahaha
}

/**
* Replacement method that overrides the matching baz() method
*/
public boolean baz() {
throw new RuntimeException("you can't call baz()!");
}


// notice that we have no replacement method for quux()


/**
* Main method to serve as a basic test.
*/
public static void main(String args[]) throws Throwable {

SomeInterface si = (SomeInterface)
Proxy.newProxyInstance(MyInvocationHandler.class.getClassLoader(), new Class[]{SomeInterface.class}, new MyInvocationHandler(new SomeImpl()));

// should print:
// MyInvocationHandler.foo
// SomeImpl.foo
si.foo(1);

// should print NOTHING, since the proxy should suppress the call to the object
si.bar("test");

// should print "SomeImpl.quux" because we don't declare a replacement method
si.quux();

// should throw!
try {
si.baz();
} catch (Throwable t) {
System.out.println(t);
}

}

}


MethodSig.java

/*
* MethodSig.java
*
* Created on September 7, 2005, 1:36 PM
*/

import java.lang.reflect.Method;

/**
* Hash key for a map of methods based on method name and parameters.
*/
public class MethodSig extends HashKey {
public MethodSig(Method m) {
super( m.getName(),
java.util.Arrays.asList( m.getParameterTypes()) );

}
}


HashKey.java

/*
* HashKey.java
*
* Created on February 8, 2005, 9:54 AM
*/

import java.util.*;

/**
* A convenience class for easily making hashmap
* keys that involve multiple objects. Essentially
* just a read-only collection of Objects, except for
* the 9 overloaded constructors that allow you to
* write code like this:
* <pre>
*
* map.put( new HashKey("foo","bar"), someValue);
*
* Object v = map.get( new HashKey("foo","bar"));
*
* </pre>
*
* Can be useful as a base class for local hash key classes:
*
* <pre>
*
* public class MyHashKey extends HashKey {
* public MyHashKey(SomeClass thing) {
* super( thing.getFoo(), thing.getBar());
* }
* }
*
* </pre>
*
* @author jRobertson
*/
public class HashKey extends AbstractCollection implements Collection, java.io.Serializable {

private Collection keys;

/** Creates a new instance of HashKey */
public HashKey(Object key1) {
this( new Object[]{ key1 });
}

/** Creates a new instance of HashKey */
public HashKey(Object key1, Object key2) {
this( new Object[]{ key1, key2});
}

/** Creates a new instance of HashKey */
public HashKey(Object key1, Object key2, Object key3) {
this( new Object[]{ key1,key2,key3});
}

/** Creates a new instance of HashKey */
public HashKey(Object key1, Object key2, Object key3, Object key4) {
this( new Object[]{ key1,key2,key3,key4});
}

/** Creates a new instance of HashKey */
public HashKey(Object key1, Object key2, Object key3, Object key4, Object key5) {
this( new Object[]{ key1,key2,key3,key4,key5});
}

/** Creates a new instance of HashKey */
public HashKey(Object key1, Object key2, Object key3, Object key4, Object key5, Object key6) {
this( new Object[]{ key1,key2,key3,key4,key5,key6});
}

/** Creates a new instance of HashKey */
public HashKey(Object key1, Object key2, Object key3, Object key4, Object key5, Object key6, Object key7) {
this( new Object[]{ key1,key2,key3,key4,key5,key6,key7});
}

/** Creates a new instance of HashKey */
public HashKey(Object key1, Object key2, Object key3, Object key4, Object key5, Object key6, Object key7, Object key8) {
this( new Object[]{ key1,key2,key3,key4,key5,key6,key7,key8});
}

/** Creates a new instance of HashKey */
public HashKey(Object key1, Object key2, Object key3, Object key4, Object key5, Object key6, Object key7, Object key8, Object key9) {
this( new Object[]{ key1,key2,key3,key4,key5,key6,key7,key8,key9});
}


/** Creates a new instance of HashKey */
public HashKey(Object[] keys) {
this( Arrays.asList(keys));
}


/** Creates a new instance of HashKey */
public HashKey(Collection keysToAdd) {
keys = keysToAdd;
}

public boolean equals(Object obj) {

if( !(obj instanceof HashKey) )
return false;

HashKey that = (HashKey) obj;

return keys.equals( that.keys);

}

public String toString() {
return keys.toString();
}

public int hashCode() {
return keys.hashCode();
}

public int size() {
return keys.size();
}

public Iterator iterator() {
return keys.iterator();
}


}

Tuesday, September 06, 2005

Dynamic delegation in Java without ugly InvocationHandlers

I have also seen dynamic proxies (the Proxy and InvocationHandler classes in J2SE) be used for a lot of situations where what the programmer really wants is something more like dynamic delegation.

The design of the InvocationHandler.invoke() works great for when you want to do the same thing no matter what method is being invoked. For instance, logging:


class MyInvocationHandler implements InvocationHandler {

public MyInvocationHandler(Object realObject) {
this.realObject = realObject;
}

private Object realObject;

public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// log it
log.debug(m);

// now run it
m.invoke( realObject, args);
}
}


But one often sees these invocation handlers start to grow hair like this:


private Object realObject;

public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if( m.getName().equals( "foo" )) {
// .. insert any special logic for foo method here ..

// followed by actually running the method
m.invoke( realObject, args);
} else if (m.getName().equals( "bar" )) {
// swallow the call to bar() and don't pass it on!
} else if (m.getName().equals( "baz" )) {
throw new SomeException("you can't call baz()!");
} else {
// any other method, just call it straight through
m.invoke( realObject, args);
}

}


While the above will get the job done, it is about as anti-OOP, anti-Design Patterns, and just plain anti-Java-esque a method as you could possibly invent. It violates one of the first rules we learned as Java programmers, which is that switch/case statements (of which the above is really an instance, if only Java supported switching on an object) are a relic from procedural languages and should be replaced by more modern constructs. You'll get this advice from Effective Java, you'll get it from Fowler's Refactoring. How can we remove this ugliness?

What is the code actually trying to do? It wants to match the Method object to any custom invocation code that needs to run when that Method is called. This is a mapping operation, hence this block of if/else statements is really trying to be a Map.

Now, a first approximation of our goal might look something like this:


private Map handlersMap = new HashMap();

public MyInvocationHandler(Object realObject) {
this.realObject = realObject;

handlersMap.put("foo", new InvocationHandler() {
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// special code for foo()
}
);

// add mappings for bar(), baz(), etc..

}

public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
InvocationHandler h = (InvocationHandler) handlersMap.get(method.getName());

if( h != null ) {
h.invoke(proxy,method,args);
} else {
method.invoke(realObject,args);
}
}


Big friggin deal, right? So far all we've done is shifted most of the code into the constructor that builds up the map, and made ourselves look smarter by using some anonymous classes. But considering how much reflection we are using already, maybe we could ue just a bit more to get rid of some of those classes without having to re-introduce the old switch block. Maybe the map shouldn't contain a bunch of baby InvocationHandlers, maybe it should contain Methods. Our Methods! Since we are now dealing with methods more directly, we now need to know the signatures of the methods that we want to intercept, as well as their names. For this purpose, let's say Foo takes and int, bar takes a String, and baz is void.


private Map methodsMap = new HashMap();

methodsMap.put( "foo", getClass().getMethod("foo", new Class[]{ int.class });
methodsMap.put( "bar", getClass().getMethod("bar", new Class[]{ String.class });
methodsMap.put( "bar", getClass().getMethod("baz", new Class[]{ });

public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Method myMethod = (Method) handlersMap.get(method.getName());

if( myMethod != null ) {
// if it's in the map, run the one from the map
myMethod.invoke(this,args);
} else {
// otherwise just run the method on the original object
method.invoke(realObject,args);
}
}

public int foo(int x) {
// .. any custom stuff goes here ...
return (SomeInterface) realObject.foo(x);
}

public void bar(String s) {
// do nothing! hahaha
}

public boolean baz() {
throw new SomeException("you can't call baz()!");
}


Nice, huh? The above looks nifty, but it isn't quite correct.. the problem is that the SomeInterace/realObject might have multiple methods of the same name which again requires the argument types for disambiguation. So really method's whole signature should be the key to the HashMap. Now, you could just use an ArrayList or something to hold the name and the argument classes, but let's be nice to ourselves and make a helper class for this:


class MethodSig extends HashKey {
public MethodSig(Method m) {
super( m.getName(),
java.util.Arrays.asList( m.getParameterTypes()) );

}
}


MethodSig extends HashKey, which is one of the stupidest classes you could possibly imagine, but which I have actually written for use in real code. Someone please tell me that some new language feature in Tiger or later makes this class unneccessary!


public class HashKey extends AbstractCollection implements Collection, java.io.Serializable {

private Collection keys;

/** Creates a new instance of HashKey */
public HashKey(Object key1) {
this( new Object[]{ key1 });
}

/** Creates a new instance of HashKey */
public HashKey(Object key1, Object key2) {
this( new Object[]{ key1, key2});
}

/** Creates a new instance of HashKey */
public HashKey(Object key1, Object key2, Object key3) {
this( new Object[]{ key1,key2,key3});
}

// repeat constructors for as many different objects as you might want..

/** Creates a new instance of HashKey */
public HashKey(Object[] keys) {
this( Arrays.asList(keys));
}


/** Creates a new instance of HashKey */
public HashKey(Collection keysToAdd) {
keys = keysToAdd;
}

public boolean equals(Object obj) {

if( !(obj instanceof HashKey) )
return false;

HashKey that = (HashKey) obj;

return keys.equals( that.keys);

}

public String toString() {
return keys.toString();
}

public int hashCode() {
return keys.hashCode();
}

public int size() {
return keys.size();
}

public Iterator iterator() {
return keys.iterator();
}

}


Now, using MethodSig, we get this:


public class MyInvocationHandler implements InvocationHandler {
private Map methodsMap = new HashMap();

private void addMethod(Method m) {
methodsMap.put( new MethodSig(m), m);
}

public MyInvocationHandler(Object realObject) {
this.realObject = realObject;

addMethod( getClass().getMethod("foo", new Class[]{ int.class });
addMethod( getClass().getMethod("bar", new Class[]{ String.class });
addMethod( getClass().getMethod("baz", new Class[]{ });
}

public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Method myMethod = (Method) handlersMap.get( new MethodSig(method) );

if( myMethod != null ) {
// if it's in the map, run the one from the map
myMethod.invoke(this,args);
} else {
// otherwise just run the method on the original object
method.invoke(realObject,args);
}
}

public int foo(int x) {
// .. any custom stuff goes here ...
return (SomeInterface) realObject.foo(x);
}

public void bar(String s) {
// do nothing! hahaha
}

public boolean baz() {
throw new SomeException("you can't call baz()!");
}
}


That code that repeated lycalls addMethod() is the last vestige or the original if/else block. How can we get rid of it? That's when the bolt of lightning hits you. Duh, these methods are declared right on our own class, we can use reflectioin to find them, and loop over them! Our code now becomes:



public class MyInvocationHandler implements InvocationHandler {
private Map methodsMap = new HashMap();

private void addMethod(Method m) {
methodsMap.put( new MethodSig(m), m);
}

public MyInvocationHandler(Object realObject) {
this.realObject = realObject;

Method[] methods = getClass().getMethods();
for(i =0; i<methods.length; i++) {
addMethod( methods[i]);
}
}

public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Method myMethod = (Method) handlersMap.get( new MethodSig(method));

if( myMethod != null ) {
// if it's in the map, run the one from the map
myMethod.invoke(this,args);
} else {
// otherwise just run the method on the original object
method.invoke(realObject,args);
}
}

public int foo(int x) {
// .. any custom stuff goes here ...
return (SomeInterface) realObject.foo(x);
}

public void bar(String s) {
// do nothing! hahaha
}

public boolean baz() {
throw new SomeException("you can't call baz()!");
}
}


Tada! We have essentially achieved the dynamic delegate pattern (which is accomplished in C++ using templates, and in dynamic scripting languages, etc.) using nothing but plain old reflection. No code generation, no bytecode maniplation, no generics required.

Next time, I will show you what the above ended up looking like after I spent several more iterations refactoring it.

something is right with America

On labor day I went to the Red Cross blood donor station temporarily set up at a local mall, and there was such a long line of people there that 4 hours ended up elapsing between when I put my name on the wait list and when I finally got stuck.

At least it was in the mall, so I could go to the food court and Waldenbooks, etc., while waiting. And like I said, waiting to give blood is a hell of a lot better than waiting to get blood.

People in other cities have told me that they experienced the same thing. More than one person has said that when they went to volunteer last week, they were put on a waiting list and told "don't call us, we'll call you".

I really hope that this represents a surplus of folks wanting to help, rather than a lack of proper organization to do something with them all.

Friday, September 02, 2005

mork.pl


# In Netscape Navigator 1.0 through 4.0, the history.db file was just a
# Berkeley DBM file. You could trivially bind to it from Perl, and
# pull out the URLs and last-access time. In Mozilla, this has been
# replaced with a "Mork" database for which no tools exist.
#
# Let me make it clear that McCusker is a complete barking lunatic.
# This is just about the stupidest file format I've ever seen.