Jeremy Rayner on java and other stuff.

All | AudioDrama | Chatter | Fun | Groovy | Java | Life

Lightning Groovy
Posted on 25 May 2007

My 6 minute elevator pitch for the Groovy language.

Recorded at Google offices in London on 24 May 2007,
as part of the Open Source Code Jam 3

 Presented and Edited by me ( Jeremy Rayner )

25 May 2007 |

Groovy at JavaOne 2007
Posted on 14 May 2007
Here is a round up of bloggers feedback about Groovy from JavaOne2007
Bernard Ng
Ben Teese [1], [2]
Charles Ditzel [1], [2]
Michael Kovacs
Andres Almiray [1], [2]
Peter Pilgrim
Chirag Mehta
Matt Stine [1], [2], [3]
Jason [1], [2]
Maryland Pok Guy
Lucas Jellema [1], [2]
Michael Yuan
Antoni Batchelli
Keyur Shah
Cameron Purdy
Frank Coyle
Igor Minar
Brendon Humphreys

Ola Bini [1], [2]
Cay Horstmann [1], [2], [3]
Hani Suleiman
Geertjan Wielenga (Netbeans plugin)
Graeme Rocher [1], [2], [3], [4] (Grails Lead)
Jason Rudolph [1] [2] [3]
Ian Roughley (InfoQ)
Cedric Beust + comments
Danno Ferrin
Ron Hitchens
Steve Giovannetti
It looks like we managed to enthuse some people about Groovy and we even made it to the best seller list (#5)

Special thanks to Guillaume Laforge, Dierk König, Rod Cope, Vladimir Vivien Graeme Rocher and anyone else who talked about Groovy at JavaOne, either on stage, or in the corridors. Nice one.

14 May 2007 |

Third Groovy Developers Conference
Posted on 01 Feb 2007
01 Feb 2007 |

Groovy 1.0 released!
Posted on 03 Jan 2007
Groovy 1.0 has finally been released.

It has been a long road, lasting over three years, but at last I can recommend Groovy as a stable, production proven and well documented programming language for the Java platform. (not to mention a very helpful and large user community)

This release coincides with the launch of the Manning book Groovy in Action, which gives an in depth reference to Groovy 1.0

[Full Disclosure: I'm a core committer for Groovy and I was a technical reviewer for this book]

Groovy 1.0 Highlights:

  • A formal syntax based closely on Java 1.5, with added Groovy bits.
  • Groovy can easily run source from the command line, ant, embedded in code
        (simply place groovy-all-1.0.jar in your classpath)
  • Close ties with Spring, Lucene and other real world Java products.
  • Fantastic for reducing the verbosity of common tasks in Java

quick start: example installation to /usr/local

$ cd /usr/local
$ wget
$ tar xvfz groovy-1.0.tar.gz
$ export GROOVY_HOME=/usr/local/groovy-1.0
$ export PATH=${GROOVY_HOME}/bin:$PATH
$ groovy -e "println 'hello world'"

To coincide with this release, I have also released version 0.0.2 of the JVM command line interpreter Grash.

I'll be giving a Talk about the Groovy Compiler on 25 Jan 2007 in London, please come along to that, and the pub afterwards, to discuss all things Groovy.

I will be at the Groovy Developers Conference in Paris (starts 29 Jan 2007) to discuss the future direction of Groovy, in particular enhanced IDE support.

In May 2007 there will be a three day Groovy and Grails conference at the Barbican, which will be perfect for anyone interested in this language to meet the core developers, and discover the cutting edge progress in Groovy.

But most of all, Groovy 1.0 would not be where it is today without the work of the open source community. I'd like to thank each person for their work in making Groovy a fantastic language:
Guillaume Laforge (glaforge), Jochen Theodorou (blackdrag), Jeremy Rayner (jez), John Wilson (tug), Russel Winder (russel), James Strachan (jstrachan), Dierk Koenig (dierk), Christian Stein (cstein), Paul King (paulk), Joe Walnes (joe), Chris Stevenson (skizz), Jamie McCrindle (jamiemc), Matt Foemmel (mattf), Sam Pullara (spullara), Kasper Nielsen (kasper), Travis Kay (travis), Zohar Melamed (zohar), Bob McWhirter (bob), Chris Poirier (cpoirier), Christiaan ten Klooster (ckl), Steve Goetze (goetze), Bing Ran (bran), John Stump (jstump), Pilho Kim (phk), Mark Chu-Carroll (markcc), Alan Green (alang), Edward Povazan (emp), Franck Rasolo (fraz), John Rose (jrose), Graeme Rocher (graeme), Guillaume Alleon (galleon), Antti Karanta (akaranta), Dave Kerber (davekerber), Hein Meling (hmeling), Joachim Baumann (jbaumann), James E. Ervin (jervin), Scott Hickey (jshickey), Martin C. Martin (mcspanky), Marc Guillemot (mguillem), Aslak Hellesoy (rinkrank), Steven Devijver (sdevijver), Scott Stirling (sstirling), Yuri Schimke (yuri)
Joern Eyrich, Robert Kuzelj, Rod Cope, James Birchfield, Robert Fuller, Sergey Udovenko Hallvard Traetteberg, Peter Reilly, Brian McCallister Richard Monson-Haefel, Brian Larson, Artur Biesiadowski Ivan Z. Ganza, Arjun Nayyar, Mark Turansky, Jean-Louis Berliet, Graham Miller, Marc Palmer, Tugdual Grall, and many many many other contributors and organisations.

Thankyou All (and apologies if I missed anyone, so many people...) :-)

P.S. an improved java2groovy is now in the core distribution of groovy 1.0 :-)

03 Jan 2007 |

Posted on 29 Dec 2006
Having just finished the first full run through of a groovy pretty printer, I thought I'd flex it's muscles by creating a useful command line program...
 java2groovy [file ...]

    The java2groovy tool reads class and interface definitions, written in the
    Java programming language, and converts them into groovy source files.
to do this...
  • I took the original java.g grammar which groovy.g is based upon
  • amended it to remove Java features not implemented in groovy.g ("do" keyword, Array Initialisers etc)
  • Created a Java2GroovyMain which takes Java files and parses into a Java like source AST
  • Converted the Java like source AST into a one for one Groovy equivalant
  • Applied a Groovifier, which applies common simplification tasks to the AST (e.g. don't need public keyword if you have other modifiers)
  • Then the resultant groovy AST is output using the "pretty printer"
(not in subversion yet RC3? post 1.0?)

So... job done, what's next :-)

Seriously though...

  • java.g needs to be amended some more to use create() instead of #[], otherwise line/col nums are lost
  • is an interesting step, lots of tiny refactorings, at the source AST level, very powerful...
    // (e.g. don't need public keyword if you have other modifiers)
    if (t.getType() == MODIFIERS) {
       GroovySourceAST publicNode = t.childOfType(LITERAL_public);
           if (t.getNumberOfChildren() > 1 && publicNode != null) {
           // has more than one modifier, and one of them is public
               // delete 'public' node
  • some minor changes to things like string literals (get a double double-quote each time at mo...)
  • all pretty printer issues apply (no comments on AST etc)
java2groovy is now included in Groovy 1.0 (download here)
(very very beta) NO DOCS, NO WARRANTIES etc etc

Oh yes... a sample...

$ java2groovy src/test/groovy/lang/

 Automatically Converted from Java Source

 by java2groovy v0.0.1   Copyright Jeremy Rayner 2007

 'java2groovy' cannot be used to convert one working program into another

package groovy.lang
class MockWriter


   private String output

   String getOutput() {
       String answer = output
       output = null
       return answer

   void setOutput(String
        output) {

   void println() {

   void println(Object
        object) {
       setOutput(""println("" + object + "")"")

   void print(Object
        object) {
       setOutput(""print("" + object + "")"")
29 Dec 2006 |

Second Groovy Conference
Posted on 28 Nov 2005

Starting out on a chilly November morning, with just a Burger King breakfast for company, I found myself checking in for the Eurostar to Paris. I boarded the train, and found I had two hours of my own time (a rare thing these days) and therefore decided to bring some of my projects up to speed with the latest Groovy release (JSR-04)

First off was my pet wiki server called biscuit, which was a simple affair needing changes only to variables not initialized with a type or the 'def' keyword. As I finish this task before arriving at the channel tunnel I decided to sink my teeth into a meatier topic, and look into providing tab completion for my Groovy shell called grash. The excellent jline library hooks for completion, so I quickly hook this up to the 'ls' function in grash and feel great as I navigate my object tree using the same nifty functionality I know in my favourite unix shells.
I then started bringing grash up to the latest Groovy release, but after the initial 'def' updates, I quickly realise that something else is afoot. It appears that providing user defined commands and attaching them to objects has broken. A quick debugging session shows that for some reason the GroovyClassLoader is being told to load two versions of the reflector for the same script.
At this point I get a phone call from James Strachan, it appears that he caught the train by the skin of his teeth, and after fighting his way down the carriages we meetup, just as we pull into Paris.

As we stand in the queue for the taxis, James and myself discuss the xbean project and how to best integrate Groovy closures into Springs template callback mechanisms. In order to prevent writing wrapper classes over the top of every spring template, James suggests adding functionality to groovy to allow single method interfaces to be automatically implemented by Closures, in much the same way as Listeners are implementable by Closures today. As James pulls out his laptop and starts showing me where these hooks would reside, I can tell that this is going to be a good JSR meeting, and one which would justify using two days of my own holiday and the excessive eurostar fares which I paid for.

We arrive, after a hairy taxi ride around the 'Arc de Triumphe' at the Sun offices in Paris. Guillaume excitedly takes us up to the 'Jupiter' room on the third floor, where I finally get to meet blackdrag, our debugger extraordinaire, and Dierk who has been writing Groovy in Action. We are delighted to find that Sun have provided an internet connection, and Guillaume has already uploaded photos to flickr for the watching world to see.

Having missed the morning session due to our travel, we are quickly brought up to speed. Finally we will get to talk about name resolution and scoping. The topic for the first day appears to be name resolution, with most of the discussion centring around how best to cope with vanilla names.

After a lunch paid for, very kindly, by Dierk, the discussion soon turns into a heated debate over the treatment of vanilla names.

class MyScript {
  String toString(){
    return "foo"

  void run() {
      // does this call MyScript.toString() or myList.toString() ?
I believe that... Tug argues the enclosing object instance should listen for and consume names prior to the lexical scope. (i.e. above example would call myList.toString())
James argues that the default should be lexically bound to the current context (i.e. above example would call myScript.toString()), and if the object instance was needed to be referred to that some form of syntax could be constructed to allow this, e.g. $toString() would be a dynamic name that could be interpreted differently.
At least, with my laptop pointing at the wiki, and up on the projector, I ensure that the examples and minutes are being captured in the wiki and not on the whiteboard.

We appear not to reach a resolution as Vincent Massol arrives to bring us to the Chinese restaurant for the evening. We all potter down to the Metro, Guillaume and tug have kindly arranged metro tickets for us delegates too laden with bags, and soon we arrive across town. There we meet Xwiki's Ludovic Dubost and Erwan Arzur and Benjamin Mestrallet from eXoPlatform.

A very entertaining evening ensues, with chatter ranging from XWiki through to 'flaming drunk prawns', and we all end up at Ludovics apartment nearby, where Erwan introduces us to a bottle of Calvados that he had stowed away for such occasions. At about 12:30 we stumble back on the last metro and finally check in to our sleepy hotel. I feel glad to find a towel in the room, and settle down to a restless Parisian slumber. (thanks so much to Bob at Codehaus for funding the room)

I awake 5 hours later to the sound of my Blackberry playing 'The Entertainer', and discover the delights of hot chocolate for breakfast (no sign of tea, I think coffee is more popular here). We stumble back to the Sun offices, again Guillaume and tug have the metro sorted.

Day Two starts out more productive, with discussion about opening up the DefaultGroovyMethods for the layman and we get some agreement about the 'use' keyword and my 'enhances' proposal. However the discussion soon gets round to the topic of Builders (a.k.a. Markup) and again the name resolution and scoping bear comes up to bite us again.

We have Tug and Guillaume firmly on the side of Builders being in charge of everything defined within the markup delimiters. James argues that markup is fundamentally broken and some kind of syntactic clue that we are suddenly entering a different 'markup world' where normal resolution and scoping doesn't apply. For some reason, that I cannot fathom, Tug and Guillaume both seem vehemently opposed to any indication in the code that we are in a Builder section. This includes both the suggestion of a 'with' keyword or .{ notation to indicate to the reader of the code that something different is about to occur.

String toString() {
  return "foo"
swingBuilder.frame() {
  panel() {
We were all fairly happy that the Builder could be responsible for name resolution inside it's own block (e.g. the swingBuilder instance would be responsible for how it treats toString() inside), but what seemed to really be a sticking point was the important fact that due to the dynamic nature of the name resolution/scoping within this block, some visual clue to the reader of the program was necessary.
James argued for, and I agree that, the use of some kind of syntactic indication was vital to ensure that the Groovy language was sane, predictable and maintainable. The above example would look something like this... (note the .{ syntax indicating a different lexical construct)
  panel() {
or the even clearer...
with (swingBuilder.frame()) {
  panel() {
Thus implying to any compiler, IDE, or human reader that the block of code was not a true lexical closure, but some other construct which was dynamic in it's very nature, and thus warnings, code completion and everything else specification related did not apply, as the responsibility would lie with the implementation of the builder.
I'm sad to report that no agreement was reached on this matter. Not so much which syntax would be useful, but actually whether we should have any syntax denoting the difference between a true lexical Closure and one of these Builder blocks. The historical reasons go back to Builder blocks looking just like Closures, and I'm afraid this long standing mistake must be removed from the language before any true progress can be made, as no sensible specification rules can be applied while the dichotomy exists.
I headed back to London with a very disappointed James Strachan, the language which has some of the finest minds, and most exciting ideas now faces a pivotal point in its life, and I'll do everything I can to ensure that clarity over dynamism wins the day.

My many thanks go to Guillaume for the meeting arrangements, to Sun for the facilities, to XWiki,eXoPlatform and Vincent Massol for the Chinese, Dierk for the Lunch, and Bob/GoogleAds for the hotel room.

28 Nov 2005 |

Lucene and Groovy example
Posted on 22 Apr 2005
Lucene in ActionI've just got hold of a copy of the Lucene in Action book by Erik Hatcher and Otis Gospodnetic and thought it would be fun to see what the examples of basic Lucene usage would look like in Groovy.

The Groovy code is used in the following manner, with my example using some free classic books from Project Gutenberg to search inside.

$ mkdir bookIndex
$ groovy -cp lucene-1.4.3.jar Indexer bookIndex ~/gutenberg
Indexing~/gutenberg/Bram Stoker/Dracula.txt
Indexing ~/gutenberg/H. G. Wells/The War of the Worlds.txt
Indexing ~/gutenberg/Mark Twain/Adventures of Tom Sawyer.txt
Indexing ~/gutenberg/Oscar Wilde/The Picture of Dorian Gray.txt
Indexing 4 files took 2320 milliseconds
$ groovy -cp lucene-1.4.3.jar Searcher bookIndex indefatigable
Found 1 document(s) (in 30 milliseconds) that matched query 'indefatigable':
/Users/j6wbs/gutenberg/H. G. Wells/The War of the Worlds.txt

The first example is a script that will build an inverted index from text files on your hard disc.

Usage: groovy -cp lucene-1.4.3.jar Indexer <index.dir> <text.files.dir>

Indexer.groovy (download)

import org.apache.lucene.analysis.standard.StandardAnalyzer
import org.apache.lucene.document.Document
import org.apache.lucene.document.Field
import org.apache.lucene.index.IndexWriter

/** * Indexer: traverses a file system and indexes .txt files * * @author Jeremy Rayner <> * based on examples in the wonderful 'Lucene in Action' book * by Erik Hatcher and Otis Gospodnetic ( ) * * requires a lucene-1.x.x.jar from */

if (args.size() != 2 ) { throw new Exception( "Usage: groovy -cp lucene-1.4.3.jar Indexer <index dir> <data dir>") } def indexDir = new File(args[0]) // Create Lucene index in this directory def dataDir = new File(args[1]) // Index files in this directory

def start = new Date().time def numIndexed = index(indexDir, dataDir) def end = new Date().time

println "Indexing $numIndexed files took ${end - start} milliseconds"

def index(indexDir, dataDir) { if (!dataDir.exists() || ! { throw new IOException("$dataDir does not exist or is not a directory") } def writer = new IndexWriter( indexDir, new StandardAnalyzer(), true) // Create Lucene index writer.useCompoundFile = false

dataDir.eachFileRecurse { if ( =~ /.txt$/) { // Index .txt files only indexFile(writer,it) } } def numIndexed = writer.docCount() writer.optimize() writer.close() // Close index return numIndexed }

void indexFile(writer, f) { if (f.hidden || !f.exists() || !f.canRead() || { return }

println "Indexing $f.canonicalPath" def doc = new Document()

// Construct a Field that is tokenized and indexed, // but is not stored in the index verbatim. doc.add(Field.Text("contents", new FileReader(f)))

// Construct a Field that is not tokenized, but is indexed and stored. doc.add(Field.Keyword("filename",f.canonicalPath))

writer.addDocument(doc) // Add document to Lucene index }

The second example builds upon the first by providing a command line tool to search the index of text files.

Usage: groovy -cp lucene-1.4.3.jar Searcher <index.dir> <your.query>

Searcher.groovy (download)

import org.apache.lucene.analysis.standard.StandardAnalyzer
import org.apache.lucene.queryParser.QueryParser

/** * Searcher: searches a Lucene index for a query passed as an argument * * @author Jeremy Rayner <> * based on examples in the wonderful 'Lucene in Action' book * by Erik Hatcher and Otis Gospodnetic ( ) * * requires a lucene-1.x.x.jar from */

if (args.size() != 2) { throw new Exception( "Usage: groovy -cp lucene-1.4.3.jar Searcher <index dir> <query>") } def indexDir = new File(args[0]) // Index directory create by Indexer def q = args[1] // Query string

if (!indexDir.exists() || ! { throw new Exception("$indexDir does not exist or is not a directory") }

def fsDir = FSDirectory.getDirectory(indexDir, false) def is = new IndexSearcher(fsDir) // Open index

def query = QueryParser.parse(q, "contents", new StandardAnalyzer()) // Parse query def start = new Date().time def hits = // Search index def end = new Date().time

println "Found ${hits.length()} document(s) " println "(in ${end - start} milliseconds) that matched query '$q':"

for ( i in 0 ..< hits.length() ) { println(hits.doc(i)["filename"]) // Retrieve matching document and display filename }

Further improvements to these scripts could be made in the future by providing groovy wrappers around common Lucene activities. This would allow you to supply the domain specific work inside a closure to convenience methods, e.g. lucene.write(dir) {...} Here is an idea of what it could look like (the following will not work... yet)

def index(indexDir, dataDir) {
    if (!dataDir.exists() || ! {
        throw new IOException(
          "$dataDir does not exist or is not a directory")
    def lucene = Lucene.newInstance()
    def numIndexed = lucene.write(indexDir) {writer->
        dataDir.eachFileRecurse {file->
            if ( =~ /.txt$/) { // Index .txt files only
    return numIndexed

My thanks to Erik and Otis for allowing me to make their examples more Groovy.

22 Apr 2005 |

Turn your build.xml into a pretty picture using Groovy
Posted on 02 Dec 2004
Inspired by Sam Newman (magpiebrain), I decided to see if it was possible to do a quick XSLT style transform using groovy on an ant build.xml file, so that it could be loaded up in FreeMind.

The example diagram below is the result of running groovy antmap.g > over the build.xml for my groovy shell called grash

mindmap of grash build file

A code snippet is below, which I've added to the groovy examples bundle (which is full of cool stuff b.t.w.)

#!/bin/env groovy
# convert an ant build file into a format 
#     suitable for
# by Jeremy Rayner - 2 Dec 2004
# inspired by Sam Newman 
#    ( )
# usage:   groovy antmap.g >

import groovy.util.XmlParser

buildFileName = "build.xml"  // default

// handle command line params
if (args.length > 0) {
buildFileName = args[0]

// header
println "<map version='0.7.1'>"
project = new XmlParser().parse(buildFileName)
name = project['@name']
println "<node TEXT='${name}'>"
level = 0


def void printChildren(node,level) {
node.each {
name = huntForName(it)
if (name != null) {
if (level > 1) {
println "<node TEXT='${name}' POSITION='right'>"
} else if ( == 'property' || == 'path' ) {
if (it.children().size() > 0) {
println "<node TEXT='${name}' POSITION='left' FOLDED='true'>"
} else {
println "<node TEXT='${name}' POSITION='left'>"
} else if (it.children().size() > 0) {
println "<node TEXT='${name}' POSITION='right' FOLDED='true'>"
} else {
println "<node TEXT='${name}' POSITION='right'>"
if (it.children().size() > 0) printChildren(it,level)
if (name!=null)println "</node>"

// footer
println "</node></map>"

def String huntForName(node) {
preferNodeNames = ["junitreport"]
if (node == null) return null
if (preferNodeNames.contains( return
if (node['@name'] != null) return node['@name']
if (node['@todir'] != null) return node['@todir']
if (node['@dir'] != null) return node['@dir']
if (node['@refid'] != null) return node['@refid']

02 Dec 2004 |

Some more Groovy notes
Posted on 17 Nov 2004
Here are some more notes from GC1 (Groovy Conference no.1), some of them might be inaccurate, subsequently changed or just plain wrong, but I might as well share what notes I did take...

Ideas for the specification

whitespace is significant, but it is significant as it applies to 'no dumb expression statement (NDES)' rule

macros are going to be implemented under the covers, but may not be exposed to user in first syntax spec, indeed 'while' might even be implemented as a macro under the covers...

builders have turned into lovely things :-) builders are now intended to be included within the EBNF this seems to have been achieved by changing the words around :-)

with (MyBuilder) { myPanel { myThing }}
or something

parens are optional, but again before you leave the planet... only on simple statements, not on expressions

escaping nested closures?
escaping nested closures involved break / return keywords break without label would break out of tightest closure break with label would treat closure just like while statement break (+ same with continue) return would always return from the method (that the closure was called from?) not sure I remember discussions about breaking with a value..?

I have published jstrachan's scribblings here

here are a few of my favourite things...

'with' keyword

with { wibble = 12; wobble = 13}
equiv to... = 12;;
and reused for builder syntax
with myFoo { bar { mooky {new Weeble()}}}
(syntax probably not quite like that)

'?.' operator

equiv to
(foo != null) ? : null
the question mark indicates that foo is questionable, i.e. it could be null, it could be any type etc... (i.e. no compile time errors if property bar doesn't exist on foo)

Anyway, just gives you an idea of some of the topics under discussion, none of it is set in stone. Look forward to comments :-)

17 Nov 2004 |

First Groovy Conference
Posted on 16 Nov 2004
I've just got back from a very interesting two day conference held to discuss both the Groovy language and JSR 241 which is aiming to standardize the language.

jez, pmuellr, jstrachan, jrose, rob, guillaume

James spent the first morning outlining his original vision for Groovy and the direction in which he'd like to take it forward. ( mp3, powerpoint)

James Strachan Groovy is trying to provide a high level language (like Ruby, Python or Dylan) that maps cleanly to Java bytecode. It needs to works with Java objects, and the root of all the object trees is java.lang.Object. The syntax will be Java friendly, but doesn't have to be backwards compatible. Groovy will sit on top of J2SE

After lunch I walked everyone through the story so far, from the conception of Groovy back in Aug 2003, up till the present day. (powerpoint)

Guillaume then took us through the user feedback we collected, including the main issues of the moment (powerpoint) which appear to be optionals, documentation, visibility, scoping, debugging, class loading, speed and security.

We then dicussed the roadmap for the Groovy JSR, particularly which key deliverables are necessary to reach a community release of Groovy.

Key Deliverables for Groovy JSR Community Release

  • Specification
    • A formal grammar (using similar to EBNF)
    • GLS - semantic rules expressed as a diff of the Java Language Specification
    • Limited references to groovy.* interfaces
  • Reference Implementation
  • Test Compatiblity Kit
    • Test cases following the GLS chapter by chapter
    • A subset of the JCK:Java 'language' tests or similar (e.g. Jacks)

one of the discussions

We have so much material from the two days (I recorded 15 hours of audio), it's going to take a while for all the details to surface.

16 Nov 2004 |


October 2007
  1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30 31
Prev | Today | Next

rss:subscribe (Groovy)

What I'm reading
my feed aggregator ->box

My websites
London Java Meetups
Programming Projects
Elite in Java
Jez's Photos
Fantasy Stock Market
Cool Saxophonist
Doctor Who Audios
Pisces Audios

Other Blogs
Mike Cannon-Brookes
James Strachan
Joe Walnes
Sam Dalton
Simon Brown
Cameron Purdy
Mike Roberts
Erik C. Thauvin
John Martin
Manfred Riem

B5 d++ t++ k s+ u- f
i+ o+ x-- e+ l- c--

powered by blogmento