2008-11-25

Fun on the bleeding edge

My pet project jde-mvn depends on bleeding-edge snapshots of Maven 3.0. The reason is simple: MvnServer needs maven-embedder, which pre-3.0 is only available in a buggy and frankly unusable version 2.0.4.

Mostly this is not a problem; however, the recent work Shane Isbell has done on the POM model breaks some existing POMs. Among them, unfortunately, is the CXF parent POM; this means that jde-mvn will choke on any project that depends on CXF (or any other POM that triggers the underlying bug).

I've reported this issue as MNG-3838; no word yet on when it will be fixed (although "sometime before 3.0 goes final" is a safe bet).

Since some of the things I work on in my day job use CXF, I've made my own nastyhack version of Maven and created a "release" of jde-mvn that embeds it; read more about this "release" on the BitBucket site.

2008-11-24

More fun with JDEE

With jde-mvn having reached a more-or-less stable point, I've played with some other ideas to make JDEE an even better environment.

One of these ideas is jde-refactor, which has now gotten far enough to unleash upon the unsuspecting masses. Er. Maybe there is one other person in the world who might find this useful?

2008-11-10

Running a secondary X server

Sometimes it is useful to run a second (or third, or fourth...) X server for testing porpoises. I find this invaluable when hacking at window managers (such as my current favorite, awesome).

It is also occasionally useful to be able to kill an X server with impunity, e.g. to check how an application behaves when its X connection goes away.

Even better: You can use this to deal with less-than-well-behaved programs that require a given resolution or color depth; I use it to be able to play Might and Magic VI full-screen using Wine, without having to fiddle with XRandR to get my resolution back afterwards.

So how do I do this? Simple:
startx /path/to/program option1 option2 -- :1

It really is that simple. If you wish, you can add more options after the double dash to pass them to the invoked X server. For instance, to run MM6 I do this:
startx $HOME/bin/mm6-core -- :1 -depth 16

Where the -depth 16 tells X that I want 16-bit color. mm6-core is simply a script that takes care of invoking Wine with the right options.

2008-10-07

jde-mvn moves to the bit bucket

Tonight I moved jde-mvn to BitBucket, the Mercurial world's answer to GitHub. Hopefully this will make it easier for other people to contribute (yeah, right); it's also a cool experiment for me to do.

Check it out: http://bitbucket.org/espenhw/jde-mvn/wiki/. Also, please check out the issues list, and report any bugs/comments there.

2008-10-02

jde-mvn updates

I just fixed a bug in jde-mvn where nothing would work. But it worked for me last week, honest!

Many thanks to Tilman who made me aware of the problem; hopefully the problem I found is the problem you had...

2008-09-25

pom-parser is dead, long live jde-mvn!

As some of you know (I know you're out there, freaks), I'm happily hacking away at my JDEE-Maven integration project. Up to now I have had two separate projects:
  1. pom-parser, which dealt with getting information from the POM and into JDEE's variables
  2. jde-mvn, which dealt with using Maven as a build tool
This became cumbersome, and got in the way of some cool stuff I wanted to do. So I merged them. :)

pom-parser is now deprecated; if you use it, you should move to jde-mvn.

This shouldn't be onerous for the, like, two people besides me who use it (while I'm on the subject, if you use this please drop me a note!), even though most (all?) of the functions in pom-parser have changed names.

jde-mvn is packaged as a JDEE plugin (for more on this, read about plugins in the JDEE manual), which means that the installation process is both simpler and more complicated, but ultimately I think this is the way I want to go.

Anyway, jde-mvn now supports a server mode, thus amortizing the startup cost of the JVM across calls. Wee! The initial startup cost is quite heavy, though, but there is not much I can do about that.

So. If you want to play with jde-mvn, it is available from my Mercurial repository. I will try to keep even tip fairly stable (I do the major hacking on a local clone), but I will also tag what I consider to be stable revisions with 'stable-DATE'; if you don't fancy life on the severely-hemorrhaging edge, you may want to go with one of these.

Enjoy!

2008-09-19

New features in pom-parser

pom-parser just got a bit simpler; I now delegate the work of resolving artifacts to files in the file system to Maven (using the dependency:list goal with outputAbsoluteArtifactFilename=true). Less work for me, more robust system; it should now work out of the box if you have a non-standard local repository location (or if you're on Windows).

There are also three notable bug fixes:
  • with-pom will no longer fall over if there is no POM; this allows you to have a single prj.el in the parent directory of all your source dirs without nastiness happening if you need to work on an Ant-based project
  • Newer versions of maven-help-plugin have changed the output format; pom-parser should now be able to find the effective POM regardless of the plugin version
  • The classpath order (as presented by Maven) is now preserved. This is only relevant if you're using Maven 2.0.9 or later; before 2.0.9, the classpath order as generated by Maven was non-deterministic anyway (!).
Next up: Integrating with Nexus for completion of artifacts (in pom-add-dependency).

pom-parser is, as usual, available from my Subversion repository.

2008-09-05

I just can't let this go unpublished...

public class $_ {
public static <$_> $_ $_($_ a) {
return a;
}
public static <$_> void $_($_ ... $__) {
for ($_ $_ : $__) {
// \u000a\u0053\u0079\u0073tem\u002eo\u0075t\u002epr\u0069n\u0074\uu006c\u006e($_($_));
}
}

public static void \u006d\u0061\u0069\u006e(\u0053t\u0072i\u006e\u0067 ... $_) {
$_($_);
}
}


Or, even better:

public class $_ {
public static <$_> $_ $_($_ a) {
return \u0061\u003b\u002f\u002f$!"#$&/($##§!"a;
}
public static <$_> void $_($_ ... $__) {
for ($_ $_ : $__) {
// \u000a\u0053\u0079\u0073tem\u002eo\u0075t\u002epr\u0069n\u0074($_($_));
}
}

public static void \u006d\u0061\u0069\u006e(\u0053t\u0072i\u006e\u0067 ... $_) {
/*
* \u002a\u002fif($_\u002ele\u006egth\u003d=0)$_=\u006ee\u0077 \u0053t\u0072i\u006e\u0067[]{\u002f\u002a\u002a\u002f"Obfuscated!"};\u002f\u002a
*/

for (\u0053t\u0072i\u006e\u0067 _$ : $_) {
$_(_$\u002es\u0070\u006ci\u0074(\u0022"));
$_(\u0022\n"\u002c "")\u003b;
}
}
}

More obfuscation fun

From this blog entry comes this gem:

import java.util.Collection;
public class TestType {
public static <Collection> Collection myMethod(Collection a) {
return a;
}
public static void main(String ... args) {
System.out.println(myMethod("Hello World"));
}
}


Beautiful, just beautiful...

2008-09-02

The joy of programming

Today I had occasion to rediscover the joy of programming. Not that it's been dull lately, far from it, but today I did something real fun. Today's word is 'obfuscation'.

It started when I directed a colleague to The International Obfuscated C Code Contest. Obfuscation is just so easy in C; but can the same kind of thing be done in Java? Well...

Inspired particularly by the Mullender entry from the very first IOCCC, in 1984, I sat down and thought.

Here is what I came up with:
public class Obfuscated {
static String n, m;
static java.util.Map bm = new java.util.HashMap();
static {
try {
n = new String(new byte[] {79,66,70,85,67,76,65,83,83}, "UTF-8");
bm.put(n, new byte[] {
120,-100,109,80,93,75,2,65,20,61,-41,
-81,117,-73,45,77,-45,62,5,95,34,-19,33,-95,87,-93,
-88,64,8,36,-125,45,95,122,-102,-43,81,70,118,103,
67,103,-125,126,86,61,20,-12,-48,15,-24,71,69,
119,77,-112,-64,121,-72,-9,-50,-103,115,-18,61,119,
-66,127,62,-65,0,-100,-94,70,-80,123,87,-99,-121,
-21,-18,-91,-25,89,32,66,113,34,-98,69,43,16,122,
-36,-22,-7,19,57,48,22,-46,-124,66,-49,31,-59,-77,
-127,48,114,120,-110,16,8,-71,51,-91,-107,57,39,
-92,27,-51,-66,-117,28,44,7,25,-28,9,-103,80,40,
77,-88,54,30,-69,-53,86,-98,-103,42,61,110,55,-5,
-1,6,120,47,51,35,67,11,46,119,-119,98,67,-88,-4,
73,84,-44,-70,99,-66,97,-107,20,97,-37,-59,6,10,
54,-42,81,-28,-74,55,51,125,100,-22,-47,-62,-114,
-118,116,125,20,-21,-117,60,74,-124,-14,10,-79,-123,
45,-126,-11,-108,0,1,-69,-86,52,86,-103,114,81,
-59,-74,-125,10,118,-40,-2,117,52,-108,-68,112,87,
105,121,27,-121,-66,-100,-34,11,63,96,-60,-15,-94,
120,58,-112,29,21,72,16,82,-68,108,114,82,92,-13,
-18,28,-9,-8,86,-29,76,-100,-77,-57,31,-80,95,
-71,32,-20,115,-52,-51,65,-2,106,56,88,91,80,15,-25,
82,-64,126,-61,102,-87,-4,-114,-35,37,-35,-31,
39,36,-97,-119,44,35,7,-13,41,-39,95,48,-4,89,-18
});

m = new String(new byte[] {109,97,105,110}, "UTF-8");
} catch (java.io.UnsupportedEncodingException e) {
}
}

public static void main(String[] a) throws Exception {
ClassLoader cl = new ClassLoader() {
protected Class findClass(String cn) throws ClassNotFoundException {
if (bm.containsKey(cn)) {
try {
java.io.ByteArrayOutputStream baos = new java.io.ByteArrayOutputStream();
java.util.zip.InflaterOutputStream ios = new java.util.zip.InflaterOutputStream(baos);
ios.write(bm.get(cn));
ios.close();
byte[] bytes = baos.toByteArray();
return defineClass(cn, bytes, 0, bytes.length);
} catch (java.io.IOException e) {
throw new ClassNotFoundException(cn, e);
}
} else {
return super.findClass(cn);
}
}
};

Class c = Class.forName(n, true, cl);

for (java.lang.reflect.Method me : c.getDeclaredMethods()) {
if (m.equals(me.getName()))
me.invoke(null, (Object)a);
}
}
}
You can download this code.
Not as pithy as Mullender's, but it still has a certain something.

Now, of course, I didn't write that monstrous byte array by hand; in fact, the entire program above was written by another program, which is listed below:

public class Obfuscator {
static String n, m;
static java.util.Map bm = new java.util.HashMap();
static {
try {
n = new String(new byte[] {79,66,70,85,67,76,65,83,83}, "UTF-8");
bm.put(new String(new byte[] {77,101,116,104,111,100,82,101,110,97,109,101,114}, "UTF-8"),
new byte[] {
120,-100,-107,84,-51,78,19,81,24,61,-73,
45,20,-38,-31,-81,-108,42,34,32,32,-38,118,40,
69,65,65,1,21,17,-76,74,107,34,-124,-123,-69,-95,
-67,-64,-32,48,37,-19,-16,-93,111,-30,-54,37,91,77,
68,-125,11,-29,-54,-123,-113,-32,11,-8,14,-58,-120,
-25,78,-85,-87,-76,42,-90,-55,-52,-67,-33,-49,
57,-25,-98,-5,77,63,125,127,-9,30,-64,101,-36,23,
104,74,75,103,61,-97,123,36,109,99,83,22,-4,16,2,
-67,-7,-62,90,50,-65,-78,33,-77,-50,-82,92,73,26,
-59,-51,100,-87,104,38,103,108,57,-86,-56,43,16,
-6,-83,111,120,-61,-40,49,4,26,-14,86,46,-61,125,
81,-96,101,65,-123,-110,-37,-114,105,37,23,-91,51,
41,-32,-73,-27,-82,74,-78,-73,-108,-77,12,123,45,
-71,-24,20,76,123,-115,105,-49,-26,-114,64,-33,-62,
-97,-72,-105,-51,-94,-23,-28,11,44,-84,-97,50,
109,-45,-71,33,48,23,-3,103,-11,49,17,-43,-68,-79,
101,-127,-13,-1,-58,-119,45,107,-48,-48,28,-128,
15,45,26,2,8,54,-62,-125,54,13,-11,-16,-85,85,-69,
-122,6,52,-86,85,7,29,-35,81,77,75,79,-73,100,-54,
46,-38,2,-111,104,-86,54,111,-45,111,-30,-4,-24,
-92,-127,-39,-68,-19,24,-90,77,3,59,-94,21,93,15,
93,109,-109,-79,-57,26,-70,112,54,-120,51,-24,-2,
-53,61,-107,85,-5,-47,-85,-31,20,78,7,113,14,125,
2,-51,-82,-82,121,83,90,-71,-110,-80,-21,-75,-124,
-99,36,-94,-60,123,87,-51,61,-127,11,-47,26,-39,
-22,-112,-122,65,92,8,-48,-98,-117,26,6,112,94,9,
-118,113,68,92,65,37,-55,74,-111,6,-67,-108,27,-94,
17,38,7,-51,-32,33,-108,127,-79,-118,107,76,-107,
-29,-60,28,70,82,57,49,-62,-127,-86,-50,-5,113,
-103,35,-73,110,20,51,114,-49,-95,-36,-88,-14,110,
12,87,-126,24,-59,85,1,-97,-19,-122,-61,-47,88,
-75,-53,26,38,112,77,-43,93,23,104,61,126,22,63,-90,
-120,107,-38,57,-71,-9,112,-11,-40,45,-3,52,32,
-91,-31,6,110,6,48,-115,91,2,-127,-126,-36,-78,-116,
-84,-100,-79,44,-127,-119,26,-27,39,116,-16,54,
102,21,-30,29,106,-97,-51,-25,-92,-6,-62,76,91,
102,-74,55,87,100,97,-55,88,-79,24,105,90,116,-116,
-20,-109,-76,-79,85,-34,7,22,-13,-37,-123,-84,-100,
55,45,-119,62,-70,-17,-29,71,-17,-27,-101,83,
-53,-107,71,-51,-84,-5,-26,60,-13,93,7,-63,25,111,
-30,115,-98,-69,-23,114,125,71,92,127,-117,-42,-72,
126,-128,80,124,-24,0,-31,120,-30,0,-111,87,76,
8,-36,-27,51,-62,54,-80,-83,-114,-115,1,52,-93,-123,
-65,48,90,-103,-27,-32,-107,-95,30,-112,-44,-53,
119,79,-4,53,-62,67,-121,-24,-15,-32,57,26,-72,
-119,-92,-7,8,117,49,-44,-17,-59,43,87,-118,-62,
12,-71,-60,-19,68,12,115,29,65,55,-79,-18,-71,-46,
69,-120,-112,28,-96,50,-16,42,79,-94,-24,39,42,-127,
-69,92,76,-123,-98,-120,119,-6,-34,34,122,-120,
120,29,-10,121,16,-105,-85,50,120,-100,-14,12,41,
-69,56,-86,-35,24,71,-81,75,-23,-125,103,-80,-115,
108,-6,127,115,38,106,113,38,-86,57,-5,-55,57,
64,-50,65,114,94,-84,-32,-12,-88,79,-90,-52,-7,-116,
71,87,-75,-41,-12,-113,-72,-86,120,15,113,73,32,
77,-10,113,65,-10,1,46,-8,-65,-8,1,-45,25,61,-15,
6,51,-98,23,71,95,-12,-124,82,-13,6,115,11,-5,71,
-97,-11,-105,-65,72,123,-36,-85,-113,19,78,-25,
109,37,-24,-20,48,71,35,-55,-56,8,5,-116,-71,2,-126,
-16,124,67,-77,31,-93,95,17,-91,-126,-108,-37,
92,-9,3,-68,-120,101,94
});
bm.put(new String(new byte[] {67,108,97,115,115,82,101,110,97,109,101,114}, "UTF-8"),
new byte[] {
120,-100,-83,84,91,79,19,65,20,-2,-90,
-76,93,104,-73,92,-54,117,1,11,5,-124,-19,-115,42,
34,-105,114,81,44,-96,-43,82,-116,24,-116,-6,-76,
-76,11,44,46,109,-45,46,-105,-8,-32,-1,-48,23,31,
125,-43,68,32,-43,-60,-8,-60,-125,63,-63,63,-32,
127,48,68,60,-77,20,-71,-76,4,30,-52,38,-77,51,-25,
-100,-7,-50,-9,-51,-100,51,63,-2,124,-7,6,96,0,
-113,25,-60,-88,-82,-28,-13,79,-44,-76,-78,-82,-26,
4,48,6,79,38,-73,18,-50,44,-83,-87,73,99,75,93,
10,43,-7,-11,-80,25,51,-107,82,-78,6,-113,-87,96,
-112,74,99,-26,-77,-55,76,74,-51,11,-80,49,-44,-99,
6,-19,95,83,54,21,-122,-54,-116,-98,74,-48,58,
-49,80,19,-25,-90,-16,-122,-95,-23,-31,5,-43,24,99,
16,-46,-22,22,119,50,-72,-113,124,-70,-110,94,9,
47,24,57,45,-67,66,110,-5,-72,-106,-42,-116,73,-122,
105,57,126,1,-69,69,45,-81,25,-103,-36,-40,57,
-24,82,52,-33,34,67,-9,-91,48,-66,69,17,34,-86,29,
-80,-94,70,68,37,-86,-86,96,65,-99,8,7,-100,124,
86,-49,96,-37,-28,-95,12,9,57,22,43,-51,114,21,-53,
-53,-14,-28,92,103,20,8,104,102,-88,80,82,41,-122,
70,-7,-44,-122,121,-109,-5,-104,-17,-123,8,9,
-83,78,-76,-96,-115,-63,-110,-36,100,-24,-68,76,-101,
-120,107,-16,112,21,29,23,95,118,49,86,-128,87,
68,35,-102,-100,-24,66,55,-125,-45,-44,60,-89,26,
-85,25,-30,-77,46,-1,71,-31,101,72,31,-27,57,102,
77,-89,-80,-84,109,51,-12,-54,-27,118,-105,-104,
68,-12,65,118,-112,72,-97,-120,-21,-24,-27,2,2,116,
-74,71,-104,-1,-54,61,-60,48,83,-82,22,-50,-90,
-66,66,77,-15,106,9,59,-48,-113,27,12,29,-105,-32,
9,24,-96,118,-48,-88,-105,20,90,49,52,-55,-66,83,
25,98,69,59,41,24,-60,109,126,-79,67,-44,21,-91,
126,1,35,-44,55,-85,74,62,-95,110,83,25,86,-56,-68,
20,34,24,115,98,20,-29,12,-42,-76,105,110,-112,
125,-91,69,35,98,18,119,120,-36,93,-122,-38,-13,
98,4,-36,35,92,45,-99,82,-73,-25,-105,-49,21,-35,
-79,-36,-104,-120,105,-52,56,16,-59,44,-125,35,-89,
102,117,37,-87,78,-23,58,-61,72,-103,-16,43,-34,
-41,3,-60,56,-30,67,-30,30,-91,-105,-124,63,19,90,
90,77,108,-84,47,-87,-71,-89,-54,-110,78,22,-41,
-126,-95,36,95,-51,41,-39,-30,-38,-79,-112,-39,-56,
37,-43,89,77,87,-31,-91,-69,-74,-126,-34,10,-6,
91,120,-57,-46,11,-25,-26,-3,74,127,110,23,-31,-94,
49,78,-85,65,51,18,-88,-11,7,-10,104,8,-18,-64,
-19,15,-19,-96,-31,19,-39,24,-26,-52,125,-36,-17,
-126,13,-43,-124,80,67,95,45,121,-88,15,-118,8,83,
16,-24,3,-68,-2,-49,112,-121,10,104,-73,-32,25,
77,59,-37,-84,52,54,72,86,-55,38,-39,11,-24,17,112,
2,89,-115,10,26,-21,-119,78,3,58,9,-118,-15,-86,
44,-62,101,-120,52,-121,-101,48,49,-126,-2,-48,30,
-4,126,-55,74,-93,100,43,32,104,71,-60,46,-39,-9,
-31,105,-85,-77,-30,-51,59,52,125,69,-1,115,-55,
-50,115,-13,116,123,-72,-55,-3,31,9,-64,114,-118,
125,11,90,-23,101,-24,-93,49,-126,118,36,-56,82,
9,118,-128,-120,-128,91,20,71,-51,81,76,-2,-102,-120,
-15,-8,-47,-64,62,-122,56,102,1,-61,68,57,88,
-64,4,-61,91,116,-45,100,-118,-31,59,-94,-119,64,
104,23,-9,45,-17,15,127,5,66,60,-17,46,30,-59,63,
28,-2,12,-100,36,-10,28,29,10,-63,117,-111,-34,30,
52,-109,70,47,-87,-12,83,-70,97,4,76,18,78,88,14,
80,45,96,-12,-73,-55,96,-34,-36,44,-4,5,18,3,-92,
-11
});
bm.put(n, new byte[] {
120,-100,-107,87,121,120,27,-59,21,-1,
-115,108,107,-27,-107,18,-37,74,-28,-80,4,-110,37,
64,34,57,-118,12,118,49,65,54,9,62,48,56,-8,0,-100,
-60,56,110,74,-41,-46,-38,86,34,-19,-118,-43,
42,-119,49,38,16,82,-96,-123,-74,20,122,81,-24,-107,
-46,-70,119,33,-76,50,-58,77,74,75,47,40,-67,40,
-67,75,79,-38,-46,-5,-8,-89,31,-3,10,-18,-101,93,
-55,-110,34,-39,-112,-3,108,-51,-18,-101,119,-49,
-69,-26,-23,87,30,63,9,-96,9,-1,98,-88,30,-24,-24,
-34,-43,-39,-37,62,56,40,-128,49,-44,-18,83,14,
40,-115,113,69,27,111,28,24,-35,-89,70,76,1,21,12,
-110,110,-116,55,-22,-42,-9,65,117,-76,81,73,37,
26,7,-110,17,61,-86,-90,4,84,49,-44,12,-116,-114,
-91,83,17,-59,-44,-115,16,-89,103,112,-74,-59,-76,
-104,-71,-115,-95,-62,31,-40,-19,-127,11,-43,34,
42,33,50,84,38,-108,-104,-58,80,-17,31,-23,-51,75,
26,52,-115,-104,54,-34,26,-40,-51,-80,42,15,-67,
-4,80,68,77,-102,49,93,19,-80,-78,72,-79,-63,-55,
-108,-87,38,4,-44,18,123,-43,48,24,124,54,-81,-104,
-34,120,53,49,50,-119,-99,-86,36,90,61,-16,98,
85,53,-22,-80,-102,97,79,58,-91,-116,-85,97,57,-81,
-88,-36,22,-119,43,-87,-108,-90,36,-44,109,114,
91,66,53,39,-12,-88,-87,-57,-76,3,-6,126,14,-32,112,
125,44,66,-116,76,53,106,97,110,-109,71,-38,-108,
104,52,-58,53,82,-30,54,40,20,10,-19,117,-95,62,
-89,118,-79,2,2,-50,96,16,-110,28,16,39,-109,125,
-2,114,22,123,112,38,-42,-118,-112,112,22,-7,70,
61,20,51,105,-15,-9,112,-8,58,-84,23,73,121,89,-124,
-125,59,-82,-62,72,19,-109,-34,50,76,94,11,-92,
-84,-73,61,56,23,-25,113,-10,-25,-77,-86,71,-109,
-23,-47,120,44,34,91,118,-55,83,23,76,-53,-101,
-90,54,-119,50,61,41,83,49,105,-61,-90,-110,-75,-96,
-100,104,45,-124,115,-66,-95,-76,25,-117,-121,
-6,-108,100,-101,-115,21,28,-99,52,-43,-111,-67,-37,
-28,-47,-124,124,-87,-84,-87,7,11,-80,-82,84,82,
19,-91,-104,-2,64,17,-45,-100,108,-2,-104,-58,100,
-47,55,127,52,98,59,117,-31,116,-85,56,-43,52,
93,-76,-63,-27,77,53,79,-73,46,2,-89,101,58,-19,-56,
-124,-20,-73,52,-120,-23,-95,93,90,42,-99,76,-22,
6,29,-21,-27,26,-123,48,41,-79,24,104,-78,26,40,
18,101,-13,-98,22,-83,37,-21,-96,-84,-122,7,-12,
88,84,-26,-79,-20,-73,13,25,-39,43,43,1,-39,-100,
48,-12,-125,41,57,-49,-80,-112,91,39,119,109,-81,
-82,68,85,-125,-36,-100,117,76,1,-48,31,40,-79,51,
105,-24,38,-27,-100,26,-75,-15,-38,-74,111,-109,
-57,98,90,-44,-6,-56,10,-106,35,-38,-94,92,11,-34,
-81,-101,-35,122,90,-117,-106,87,34,-9,-60,-58,
100,-1,104,34,20,-47,53,-109,-116,72,93,-91,78,-6,
-119,81,-87,6,-53,-99,66,-31,-109,115,111,7,-99,
103,-69,97,40,-109,3,105,51,-103,-50,102,-126,60,
-86,-24,-87,-62,72,88,10,49,23,6,75,74,-80,66,-24,
-58,88,50,-44,-93,-115,-59,41,53,-115,34,49,-79,
98,41,-53,34,-5,-71,78,-53,-120,35,94,-95,-125,70,
-52,84,-71,-101,-58,85,-45,114,-49,-14,-24,-111,
-72,-98,82,-105,51,-63,14,118,107,-31,-118,114,13,
66,-90,-66,-24,-119,-27,72,13,-43,76,27,-102,28,
85,-23,-4,85,-5,-4,35,-108,-117,22,-85,-96,124,65,
-10,45,20,87,-75,113,115,98,9,62,37,-71,-48,51,-80,
100,-24,-97,-6,88,17,-106,-113,-40,-110,32,-77,
-76,81,-105,18,92,2,-99,-106,-43,120,74,93,82,98,
-42,90,-54,84,-43,8,-27,35,-98,-114,-96,84,64,49,
-13,-4,23,21,-127,-30,-44,-29,-39,19,33,-73,91,31,
-95,49,-35,-24,-89,26,-17,39,-75,77,35,-83,6,41,
37,3,5,20,-76,-99,-11,19,-81,-103,33,67,29,-117,
83,34,-122,-6,-84,62,33,39,84,57,44,71,120,88,116,
-87,84,49,13,53,106,111,-92,-4,101,82,-120,-89,90,
34,-92,-34,-112,86,-30,41,127,66,-27,84,-106,-28,
64,32,80,98,12,109,-37,45,-56,-81,-91,-29,-15,-96,
-20,-73,-101,112,64,41,48,60,87,-107,-90,93,-40,
-60,-80,-58,42,-20,60,-44,27,123,99,-38,126,53,
-54,11,-20,-96,74,125,59,32,-94,-127,119,-114,21,
121,12,11,30,-92,102,66,-115,-20,-108,-114,100,11,
106,13,-20,-15,32,-124,70,55,-74,-32,2,-122,-70,
60,105,-74,110,11,104,18,-47,-52,-39,-70,40,55,12,
-34,73,121,55,15,-12,-26,49,123,-78,112,106,-64,
23,-95,-123,115,-70,-104,-63,91,-70,47,-32,18,-22,
-113,19,74,-86,95,61,100,90,-109,2,-55,110,69,-101,
27,97,92,74,109,80,-77,-64,-85,115,-68,11,-75,
-12,96,59,46,-29,120,-19,-59,-125,-127,85,17,5,116,
-110,118,-28,101,-21,-96,-87,55,23,113,-80,-128,
-60,-32,114,116,-13,-111,-28,-118,-100,7,11,24,116,
-92,99,113,-86,-57,2,122,68,-20,-32,-90,10,-122,
-102,-116,43,17,-107,91,-38,-39,25,40,-19,-91,30,
-12,-94,79,68,23,-6,105,-12,81,-110,73,85,35,-9,
110,41,-41,-16,75,64,89,97,-60,-30,106,92,-61,-27,
93,75,44,66,86,27,118,97,39,25,98,-22,54,-30,-87,
-82,88,20,-67,27,67,-100,-18,58,-102,-61,78,49,
83,-64,30,50,-97,60,113,-83,-102,-46,-45,70,68,109,
79,-39,-59,-113,33,-80,-76,114,52,-59,-12,104,-117,
117,-110,4,-68,30,123,69,-116,-32,13,12,103,-105,
-50,-127,-106,-96,107,85,-59,114,-40,27,25,-50,
-16,-105,-27,98,79,-127,-93,34,20,68,-106,-26,51,
-60,11,46,-15,81,57,50,-115,63,99,32,-77,-41,45,
-127,-36,30,85,-110,22,118,-116,-31,92,127,-17,18,
88,-69,99,-87,24,15,70,91,-127,-3,34,-10,33,78,
30,-74,-45,-47,3,13,-115,-4,-36,-12,-110,88,-73,82,
-27,6,17,6,68,23,31,-116,61,89,67,-7,96,72,50,-45,
12,93,-81,42,-77,-73,40,-13,-54,-116,101,-74,82,
7,69,28,-64,33,30,57,17,94,77,25,-50,123,85,-50,
-42,-124,120,35,-90,-72,63,111,34,127,-26,92,94,
-74,-85,10,-72,89,-60,97,30,-56,27,-14,10,81,95,108,
-20,82,75,-5,-94,-128,91,105,-34,-49,31,98,-31,
94,86,-33,-37,68,28,-63,81,6,119,65,-17,-30,99,107,
96,-92,-61,-125,-37,113,7,63,-73,59,25,-86,-84,
-10,73,-85,127,-92,-125,19,-66,5,119,113,-62,-69,
9,98,117,74,15,-34,-58,-81,5,71,-16,118,-122,115,
120,103,-55,-74,-57,-87,-78,45,-63,-123,119,112,
-39,107,121,-88,-33,-57,-51,33,9,78,-69,-35,89,-75,
-93,-57,-125,119,-29,61,124,-9,-67,12,103,-47,8,
-67,108,-90,-67,-113,35,62,-64,17,-53,-92,115,33,
-30,-5,57,-30,7,-88,86,46,-95,-44,-121,-56,112,34,
74,120,112,-116,-89,97,23,62,66,21,-87,20,-19,-93,
-92,44,-115,89,-86,65,-89,27,-14,-9,-100,94,97,
-104,-63,-57,-71,22,-97,-96,-53,90,74,53,123,45,
-101,61,-8,20,79,-112,29,-8,52,-43,-42,-46,-98,-24,
-62,103,11,46,37,5,-119,40,-32,97,17,-113,112,-105,
23,-76,5,-85,-82,63,74,110,36,52,-122,-83,101,
-38,66,-103,70,81,-82,42,127,1,25,55,62,-113,89,
-78,118,-65,58,73,49,79,105,85,-44,27,120,26,120,
48,-121,-57,57,-38,60,-87,88,-88,53,13,90,-92,-128,
-33,-123,19,12,76,115,-31,75,100,-80,-98,-67,-80,
81,28,109,124,77,-11,-108,-40,127,25,95,-31,-73,
-102,39,25,28,65,-14,-3,-41,-8,74,73,-4,13,50,112,
-100,-85,-76,-79,92,-33,43,103,-50,83,120,-102,
-21,-7,45,-18,-8,-12,104,42,91,-122,125,-27,-126,
-117,-80,-65,-115,-17,-16,0,-8,46,-119,-95,110,-19,
-62,-9,-23,69,79,-101,30,-4,-64,-66,-122,62,-105,
107,53,38,53,-74,-58,62,53,-59,-81,-92,-35,-70,
-111,80,-88,-46,-4,-120,92,54,102,-67,51,92,82,-58,
-48,-111,-27,85,94,84,-30,39,-8,-87,-120,31,-29,
103,-28,-38,50,119,62,1,-65,32,103,-116,116,8,-8,
37,85,-103,92,120,44,119,37,18,-16,107,82,-101,103,
-89,-51,-62,95,-104,-88,46,-4,-106,-110,121,-41,
-50,-18,45,91,93,120,-63,110,-70,-68,34,-92,120,
-93,44,115,88,-68,62,-4,1,127,-28,94,122,-111,-54,
-57,116,80,-34,96,17,111,8,-72,-16,103,74,-92,78,
61,74,-25,92,67,115,-116,-38,-97,78,-116,-86,-58,
78,101,52,78,-112,21,-125,-90,18,-39,79,81,-102,
-3,22,23,-43,35,73,-30,-96,-43,-38,-70,99,113,21,
100,28,-11,116,114,37,96,-83,46,84,-45,-17,95,-23,
-21,108,90,25,-83,85,13,-77,112,63,66,47,12,127,
-93,95,-89,5,-84,39,52,15,86,16,49,71,-67,14,85,
22,116,83,-61,73,-25,49,-44,28,-121,-49,-69,38,-125,
-77,43,31,-61,57,-13,112,12,-49,98,67,67,69,83,
67,101,83,67,85,83,67,6,27,57,51,-121,-59,-84,-98,
8,65,-9,121,39,-42,98,37,-50,-126,23,-21,-79,17,
50,-2,78,-48,10,48,47,-2,-111,85,-85,-122,-2,-23,
-22,109,-53,-85,124,-103,8,-42,16,-113,125,94,127,
-40,57,-113,6,-110,-80,57,44,72,-62,-26,57,92,-24,
-64,-112,84,121,-46,-7,16,-50,113,-74,-72,124,
46,122,63,-122,122,73,-112,42,125,-82,38,123,-5,-88,
-117,-51,44,-68,56,-113,102,34,123,93,-40,37,9,
115,-40,-54,16,-82,-106,-86,-25,-80,-115,-31,126,
-74,-99,-65,117,48,60,-127,-82,-80,72,10,95,57,-113,
29,-124,123,-107,36,-42,-122,106,27,51,24,-56,
96,-48,-69,-117,126,50,24,-50,-32,-6,-80,123,30,
-54,-80,-28,-98,69,52,-20,-103,-57,-40,-80,115,22,
19,-31,21,-13,-40,55,44,-83,-104,69,34,-68,82,18,
55,103,-112,-68,31,-21,-25,97,16,-93,84,-72,-58,
107,-122,107,-25,113,-128,16,-92,26,-87,118,22,-109,
-124,-28,-111,86,86,100,48,61,-113,-61,-124,115,
75,-72,102,30,71,-122,-91,-102,89,-68,41,92,43,
-43,74,43,50,120,115,6,111,-107,106,51,-72,-121,-21,
-29,-67,119,22,-17,12,-41,73,53,25,-68,43,-20,
-107,-68,39,91,86,85,-76,-84,-10,-83,-10,-83,58,-122,
54,-55,-21,91,-35,-36,-30,-109,-22,50,-72,-65,
-91,94,-86,-13,-7,50,120,-80,54,-104,-63,7,-121,
124,-11,-75,-35,73,107,-125,-42,-121,-32,-106,-22,
-68,31,38,83,-122,-114,-82,38,-81,60,-55,57,-13,
77,-78,-21,33,-30,95,-31,-3,88,6,-97,36,41,117,22,
69,101,52,-125,-49,16,-63,-25,56,-127,-28,-50,-32,
-72,-28,-110,68,11,127,14,-113,85,96,104,-26,-107,
19,89,95,-111,59,93,115,-8,34,-125,-19,92,81,18,
109,-25,-30,14,-2,-106,117,-82,91,114,-37,-114,
113,121,-51,25,84,73,-18,-80,71,-86,-10,-98,36,-18,
-7,-115,39,102,80,-35,32,121,102,-15,-43,34,-16,
-41,9,-33,-5,-51,2,-48,26,82,-59,61,-121,103,28,
-100,115,45,121,-23,123,51,-88,41,-124,-15,67,123,
-106,43,62,-77,-112,110,-16,-102,-60,-112,14,55,
-56,23,-9,113,-4,80,114,10,39,80,57,92,-79,101,112,
-72,82,18,7,-121,-85,-92,-22,-63,97,-89,-28,30,
124,12,63,-89,80,-50,-121,-20,113,4,-23,119,35,69,
101,47,-59,127,31,-123,112,63,-91,-54,0,-4,-44,-6,
46,-94,-75,21,59,41,89,119,33,66,83,-26,29,24,-62,
-67,-108,29,15,98,-104,90,-46,30,60,76,51,-31,
28,13,-121,39,-80,23,-49,-32,122,60,71,-77,-56,-13,
24,-59,-117,-124,-3,111,68,-15,31,-116,49,7,13,
112,-21,49,-63,54,-46,-112,-42,-116,125,-84,19,-5,
-39,85,4,-69,6,9,54,1,-115,-103,52,121,-35,-124,
36,-69,21,6,-69,7,41,118,31,13,86,15,-30,0,123,2,
7,-39,-77,56,-28,-72,8,-45,-114,-83,56,-20,-72,12,
-73,56,-82,-64,17,71,12,-73,-15,116,98,79,-63,-69,
64,-103,85,45,-64,33,-96,43,-9,-9,60,-84,-91,-127,
-78,-9,-65,56,-13,101,-44,9,104,22,16,94,-64,-51,
-88,41,-113,105,35,88,-17,-113,8,80,4,-116,9,52,
32,98,-127,-116,-10,-99,6,-123,-128,-61,2,-114,
8,-40,33,-32,87,52,43,-30,101,-70,-38,-80,-105,80,
-75,-128,118,-120,-53,-15,-31,-94,-22,-31,94,6,101,
-121,-123,-11,63,-100,75,-80,118,-6,-25,-8,43,
94,5,-33,-34,0,-93,-81,5,-86,73,-81,17,-35,97,125,
117,93,109,81,-79,-45,-92,-70,-34,-94,114,-97,38,
-43,75,68,-111,47,-118,14,-34,-71,-77,69,-8,1,-86,
-104,2,-83,125,86,117,-8,29,101,111,-33,102,-17,
-17,51,-8,83,-1,-106,-109,45,-107,21,45,85,-66,42,
95,-27,49,-84,-35,-30,-85,106,110,113,6,125,-50,
-59,-110,112,-76,-118,82,-1,-123,96,48,-105,-31,
65,-17,95,120,-98,-48,-9,-16,-61,-117,113,-65,-50,
98,126,59,68,-118,-22,-13,113,39,46,-92,-11,98,-102,
80,-37,113,23,-82,-60,-35,86,-55,62,3,-114,5,
-6,113,-26,44,-54,29,-18,-70,69,-107,127,67,-1,-1,
-76,120,10,-1,7,0,126,-15,92
});

m = new String(new byte[] {109,97,105,110}, "UTF-8");
} catch (java.io.UnsupportedEncodingException e) {
}
}

public static void main(String[] a) throws Exception {
ClassLoader cl = new ClassLoader() {
protected Class findClass(String cn) throws ClassNotFoundException {
if (bm.containsKey(cn)) {
try {
java.io.ByteArrayOutputStream baos = new java.io.ByteArrayOutputStream();
java.util.zip.InflaterOutputStream ios = new java.util.zip.InflaterOutputStream(baos);
ios.write(bm.get(cn));
ios.close();
byte[] bytes = baos.toByteArray();
return defineClass(cn, bytes, 0, bytes.length);
} catch (java.io.IOException e) {
throw new ClassNotFoundException(cn, e);
}
} else {
return super.findClass(cn);
}
}
};

Class c = Class.forName(n, true, cl);

for (java.lang.reflect.Method me : c.getDeclaredMethods()) {
if (m.equals(me.getName()))
me.invoke(null, (Object)a);
}
}
}
You can download this code, too.
You'll need to have ASM 3.0 or later on your classpath to run this.

Happy hacking, and remember, kids:

If it ain't fun, you ain't doin' it right!

Final (hopefully) edit: Updated the example and the obfuscator to actually work. Wee.

Really final and last edit (2008-09-03): Tweaked the obfuscator to produce smaller class files, allows obfuscation of more complicated classes without bumping into JVM limits.

2008-06-03

Next step, world domination

My JDEE/Maven integration work is proceeding apace; pom-parser is now learning to modify the POM. The first evidence of this is the command pom-add-dependency, which allows you to add a dependency element to your POM. It even does completing-reads of groupId, artifactId and version!

It doesn't reparse the POM when it changes, though. I know how to do it, I just haven't gotten around to it yet; besides, I'm not sure if I want it to. Maybe it should be a customizable option?

I've also fixed one genuine bug (I only changed the first dot in the groupId to a slash... oops) and one unexpected behavior:

Imagine a file structure where you have a src directory with two Maven projects inside, foo and bar. You have a generic prj.el file in the src directory.

If you visit a Java file from project foo, the foo POM is read and JDEE variables are set correctly; then visit a file from project bar, and the bar POM is read and JDEE variables set.

But if you then switch back to the file from the foo project, you will get bar's variable settings (e.g. classpath). Bummer.

Once I twigged to what was going on, though ("Dude, why is this file not compiling? Hang on, that classpath looks strange...") it was fairly easy to fix.




In other news, I have more-or-less ready code to use Maven as a build tool for JDEE (ala the Ant integration); I just want to hammer it a bit more before I make it public.

And I may have a solution for the "making JDEE wait for Maven" issue mentioned a couple of weeks ago. Once again, stay tuned!

Bidirectional Mercurial + SVN

I've been playing with Mercurial lately, and I'm really impressed. However, I still need to interact with Subversion repositories (not least my own), so I thought I'd try hgsvn, which lets you use Mercurial locally on a Subversion checkout. Sweetness!

That is, as long as you remember to tell Emacs that you prefer Mercurial to Subversion by moving the 'Hg' entry before 'SVN' in vc-handled-backends...

One wrinkle, though: hgsvn does not handle pushing changes back to the remote repo...

But that's nothing a little shell scripting can't fix!

hgpushsvn.sh lets you do just that.

Run it like this: hgpushsvn.sh mono[lithic]|single


monolithic (or mono)

Checks in all changes since the last revision in Subversion as one commit. The commit message is the output of hg log --style changelog for the changesets back to the last pulled from Subversion.

single

Checks in each changeset since the last pull as a separate commit. The commit message is still the output of hg log --style changelog. This is a much slower operation!

2008-05-19

Picking Java's brains

Ever wondered what Java does with all that memory? Not so long ago you'd have to trigger a heap dump and then grovel over it with arcane tools.

But since the release of Java 1.5 (old news, I know, but still new to me) two wonderful utilities are included in the JDK:
  • jstat, which outputs statistics in a vmstat-like format (if you're familiar with Unix administration)
  • jmap, whose output is a bit friendlier.
jstat is very useful when you want to take several samples over a period of time to watch trends, but most people will want jmap, especially with the -heap option; this tells you the current (and maximum) sizes of various parts of the Java memory, along with how much of that memory is actually used.

jmap also supports other run modes; the most useful (at least to me) are:

-histo gives you a listing of the objects in the Java heap, listed by class. For each class, it tells you how many objects of that class are in the heap and how much memory they use. The listing is (at least on my system) in decreasing memory size order.

-permstat gives you a listing of the objects in the permanent generation; interesting (although unfortunately not really detailed enough) when something[tm] is eating your permgen space...

jmap can also be used to generate a heap dump, if you're so inclined. This can then be further inspected with jhat or similar tools.

And the best part? Well, there are two:
  1. These tools use the built-in instrumentation of the JVM, so you don't need to pass any funky commandline options (if you're running them on a local JVM, that is)
  2. They work on running processes!

2008-05-16

More pom-parser fun

Almost forgot: pom-parser now parses the output of mvn dependency:tree instead of dependency:build-classpath. This means that we can (and do) construct separate compile and runtime classpaths!

2008-05-15

Exciting developments in pom-parser

pom-parser.el (http://svn.grumblesmurf.org/svn/pom-el/trunk/) has undergone a major change: It now does all Maven operations asynchronously.

This has its advantages; most important is that Emacs will no longer hang for several seconds the first time you open a Java file in a project. The work to make this happen also makes it easier for me to add more Maven operations.

The first additional Maven operation is already in place: M-x pom-resolve-source-artifacts will ask Maven to download any source attachments it can find in your remote repositories; pom-set-jde-variables will then add those source artifacts to jde-sourcepath (if you pass it :include-dependency-sources t). It sure is nice to do C-c C-v C-y on a class name or variable and have the source for that class pop up...

There is a downside to this asynchronous goodness, though: You must wait for the message "POM parsing done." to appear in your minibuffer before doing anything that relies on the project variables being set. This particularly applies to compiling (as well as anything else that uses bsh).

I have tried various ways to make JDEE wait for Maven, but haven't figured out a working solution yet. Stay tuned, though!

Bug in JDEE with CVS emacs

If you're running CVS emacs and JDEE 2.3.5.1, you'll want to patch beanshell.el with the following:

--- jde/beanshell.el~ 2008-05-15 01:28:59.000000000 +0200
+++ jde/beanshell.el 2008-05-15 01:29:57.000000000 +0200
@@ -341,7 +341,7 @@

(insert output)
(compilation-handle-exit
- 'exit status
+ 'exit (string-to-number status)
(if (string= "0" status)
"finished\n"
(format "exited abnormally with code %s\n"


This avoids jde-compile falling over when the compilation is done (when running with debug-on-error).

Update: Turns out that parse-integer is not core Emacs; string-to-number, however, is.

2008-05-14

Fixing emacs startup on Ubuntu Hardy (and Debian?)

Real quick: During emacs startup you may get messages in your *Messages* buffer saying "Error while loading file /etc/emacs/site-start.d/xxx.el". Most likely this is because that file includes a form (symbol-name flavor). Fix it to say (symbol-name debian-emacs-flavor) instead, and emacs will be much happier.

Noticed on Ubuntu Hardy with the emacs-snapshot package; I don't know if it affects any other distributions/versions.

Revisiting Maven + JDEE

I admit it, I've been an apostate. I have been seduced by the flashy pointclickiness of Eclipse, and have thus neglected my beloved Emacs (for Java coding, that is; I would never abandon the glory that is Emacs for reading news and mail, and for editing anything but Java).

However, recently I've come to feel dissatisfied with my heathen idols, and sought to return to the blessed, ever-welcoming arms of Emacs.

At this juncture I must apologize to the people who have commented on (and helped with) pom-parser.el. You have been most foully neglected, but now updates have happened.

http://svn.grumblesmurf.org/svn/pom-el/trunk/ holds the latest, greatest version of the pom-parser; it now correctly deals with all extant versions of maven-dependency-plugin, and adds the correct bits to jde-sourcepath.

Still to come: Separate runtime/compiletime classpaths; we need the runtime classpath to have completion work correctly, but should compile with the compiletime classpath in order to avoid relying on runtime dependencies in our code.

2008-04-21

Hands off my content(-type), Apache!

Just a quick note for anyone using Apache as a proxy (commonly with Tomcat, Jetty or some other Java application server behind): If your application does not set the Content-Type header, Apache will apply one for you. Which one, you ask? Well, that depends on the extension of the URL your content is served from. If that URL is http://localhost:8080/app/spring_security_login, you get...

text/plain

Bah.

Workaround: Include 'DefaultType None' in your Apache config (works well in a VirtualHost.

The fix, of course, is to set the content type. I've submitted this to the Spring Security team; hopefully it'll make it into 2.0.1.

2008-03-11

A NamedQuery a day keeps the RuntimeExceptions away

Getting your queries right takes some work; and if you get them wrong, you'll get exceptions at runtime, right?

Wrong. Using named queries means that (at least with sensible persistence engines) that your queries are parsed at startup time (technically when the persistence engine is instantiated). Your application fails early, and that is a good thing.

There is a further idea lurking below, so read on!

Consider the following code (Spring-/Hibernate-y, but the principle is general):

public User findUserByName(String username) {
return (User)getHibernateTemplate().find("select from User u where u.username = '" + username + "'");
}

Leaving aside the obvious stupidity of using string concatenation to construct queries (can you say "SQL injection"?), there is a further problem here.

Look at the User class:

@Entity
public class User {
@Id @GeneratedValue public Long id;
public String userName;
}

Spot the problem.

The above query will fail at runtime, with an error message along the lines of "failed to find property username of User"; the capitalization is wrong.

Of course, you will catch this during testing. You will, right? Right?

But why not let the engine catch it for you?

@Entity
@NamedQuery(name="User.byName", query="select from User u where u.userName = :username")
public class User {
@Id @GeneratedValue public Long id;
public String userName;
}

Any errors in the query will be reported at startup time. However, we introduce another failure point: What if you mistype the query name when using it? Or, for that matter, when defining it - I've done both?

public User findUserByName(String username) {
return (User)getHibernateTemplate().findByNamedQueryAndNamedParam("User.byname", "username", username);
}

But we have a compiler; introduce a constant and let it do the work for us!

@Entity
@NamedQuery(name=User.BY_NAME, query="select from User u where u.userName = :username")
public class User {
public static final String BY_NAME = "User.byName";
@Id @GeneratedValue public Long id;
public String userName;
}

public User findUserByName(String username) {
return (User)getHibernateTemplate().findByNamedQueryAndNamedParam(User.BY_NAME, "username", username);
}

End of problem.

Of course, you still have to remember how many parameters a query takes and what their names are. If I come up with a solution, you'll be the first to know.

2008-03-10

Tomcat and Log4jConfigListener don't mix

At least not if you want to load your log4j.properties with classpath:log4j.properties. What happens is that Tomcat internally uses commons-logging, which finds log4j on your classpath and thinks "Hey, I'll use log4j". Log4j then finds your log4j.properties and reads it before Log4jConfigListener ever gets instantiated.

The result?
log4j:ERROR setFile(null,true) call failed.
java.io.FileNotFoundException: /logs/spring.log (No such file or directory)
at java.io.FileOutputStream.openAppend(Native Method)
at java.io.FileOutputStream.(FileOutputStream.java:177)
at java.io.FileOutputStream.(FileOutputStream.java:102)
at org.apache.log4j.FileAppender.setFile(FileAppender.java:289)
at org.apache.log4j.FileAppender.activateOptions(FileAppender.java:163)
at org.apache.log4j.config.PropertySetter.activate(PropertySetter.java:256)
at org.apache.log4j.config.PropertySetter.setProperties(PropertySetter.java:132)
[...]
No worries, though; the application comes up just fine, and logs where you expect... If you're lucky and don't have a security manager.

With a security manager, you get a nice, fatal AccessControlException.

Bah.

The fix is simple: move log4j.properties away from the classpath root, e.g. into /WEB-INF.

2008-03-06

Marking target as derived

From this post on the maven-users mailing list comes the following script, lightly edited to work with the current version of Monkey:

--- Came wiffling through the eclipsey wood ---
/*
* Menu: Maven > Make Maven Targets Derived
* Kudos: Donnchadh Ó Donnabháin
* License: EPL 1.0
* DOM: http://download.eclipse.org/technology/dash/update/org.eclipse.eclipsemonkey.lang.javascript
*/

function main() {
var files = resources.filesMatching(".*/pom\\.xml");
var targetFolder;

for each( file in files ) {
if (targetFolder = file.eclipseObject.parent.findMember("target")) {
targetFolder.setDerived(true);
}
}
}
--- And burbled as it ran! ---
You will of course need Monkey installed, point Eclipse at http://download.eclipse.org/technology/dash/update/. Then copy the above script (including the funky separator lines) and select the Scripts->Paste New Script menu item.

Why would you want to do this? Well, if you (like me) are tired of Eclipse suggesting stuff in the target directory when you do "Open Resource", this is for you.

2008-01-14

Spring Security 2.0 + Spring 2.5 + Maven

If you're a Mavenite Spring 2.5 user, you'll need to jump through some extra hoops to use Spring Security 2, just as you had to when using Acegi with Spring 2.0.

First off you'll want to exclude org.springframework:spring-remoting and org.springframework:spring-support, as these two artifacts no longer exist in Spring 2.5.

In addition, you will most likely need to include org.springframework:spring-aop and org.springframework:spring-orm as dependencies, unless you're already using them.

That said, Spring Security's new config is nice. One particular security config file went from 118 lines to 24!