Loading...

I’ve been having trouble recently with a javascript worm (‘Gumblar’) which infected my blog & tried to make browsers download some malware. I’ve finally tracked down the last infected script file (a wordpress blog theme header file), upgraded Wordpress, changed passwords and updated my blog them. We’re there. Finally.

2009-9
11
In:blog by duncanj
Tags:

Changed the theme of my blog again as I decided it was looking a bit too techy. Not that most of the stuff I post is at all tech-related. No.

VirtualBox is really quite impressive, especially as you find out more about what it does behind the scenes. It just seems so easy to use compared with VMWare (though I’m sure VMWare does more).

I finally got my ancient Windows 2000 system cloned last night. I didn’t want to have to go through the pain of completely reinstalling it, but felt the need to move to a (slightly) more up to date OS (Windows XP). I was already dual-booting into XP on a separate partition and having played with VirtualBox before, turning the Windows 2000 system into a Virtual Machine (VM) that I could run on Windows XP seemed the right thing to do.

For the record, the steps (after much experimenting) were:

  1. I slimmed down my windows drive by moving all my data files onto another partition
  2. I installed DesktopOK and saved my desktop icon positions
  3. I followed the section on “Hard Disk Support” from the VirtualBox guide (this is vital)
  4. I downloaded VMWare Converter, a free tool that makes a virtual machine out of a hard disk partition.
  5. VMWare Converter made a VMWare virtual machine for VMWare Player 2.5* out of my 20GB C: drive (onto another drive)
  6. I started up VirtualBox, created a new Windows 2000 virtual machine image, and specified the VMWare-created disk image as the hard drive image (which VirtualBox handily understands).
  7. I fired up the new VM.
  8. In the vm, Windows complained loudly about different hardware. I made it install the VGA components but ignored all else.
  9. I rebooted the VM, installed the VirtualBox guest addons, changed the screen resolution, restored DesktopOK’s icon positions and bingo!

I now have all my old applications and services running in the virtual machine, but with all the advantages that a VM gives. Making a backup of my Windows 2000 machine is now just a matter of copying a single 20GB file. I can pause and resume it. I can save its state, switch off my computer entirely, then come back and continue from exactly where I left off.

I’ve installed the basics (browser, email, etc) on my XP installation, but because that’s a minimal usable system (for me) it boots up much more quickly than the Windows 2000 system did, and if I need the Windows 2000 VM, I can restore it in just a few seconds.

The only real issue is that none of the graphics intensive games I had installed will run particularly well from inside a VM, but then most of them are outdated and modern games mostly require XP these days anyway. Besides, Chuckie Egg runs just fine inside the VM and who needs more anyway? ;-)

2009-5
4
In:geek by duncanj
Tags: ,

I’ve recently started using Unison to keep all my photos in sync between my Windows desktop machine, a Windows laptop and my Mac mini server.

It works really well, however the other day I started seeing the following error:

Fatal error: Warning: inconsistent state.
The archive file is missing on some hosts.
For safety, the remaining copies should be deleted.
Archive ar604df3 on host HOLLY is MISSING
Archive ar4fcd50c1d8c24915dbcbc359c32578fe on host Hal.local should be DELETED
Please delete archive files as appropriate and try again.

I couldn’t locate the archive file on Hal (the Mac mini) to delete it, until eventually I found it in:

/Users/my-username/Library/Application Support/Unison

Once deleted, Unison continued happily on its way.

I’ve been enjoying X-Plane for several months now and figured that since I’m a programmer, it’s time to give something back. I’ve been messing around and have come up with an information display – useful if you have a second computer sitting around (maybe a laptop) that isn’t powerful enough to run X-Plane. It basically displays information useful for a fly-in:

* Time in GMT
* Altitude (relative to ground), speed, heading, etc.
* Moving map display (so you can get an idea of what you’re flying over)
* Basic radar (showing other aircraft)

It’s by no means perfect, but I’ve used it for the last few fly-ins and found it surprisingly helpful.

www.duncanjauncey.com/xplane/xpdisplay

2009-4
7

The beginning of this month saw the release of version 14 of JDarkRoom, the full-screen text editor that has developed a loyal following since its first release over two years ago.

The new version is the first for almost a year and brings some much-needed bug fixes, new features and a complete rewrite of the settings screen. The main new feature is the ability to export your file via a converter – for example the supplied ‘Markdown‘ converter will generate a snippet of HTML suitable for posting into a web page, using the Markdown syntax rules for formatting. Suggestions for other converters are welcome.

Future development plans include a plugin system, so that other friendly Java developers can get in on the act to add features they’d like to see in JDarkRoom.

Finally, a big thank you to everyone who requested features, submitted bug reports and gave feedback on JDarkRoom – your input is always very much appreciated.

While working with Java Swing UIs, I’ve occasionally found it difficult to locate a complete list of all the tweakable colours, borders, fonts etc that form part of a Swing Look and Feel. Here’s my solution to that problem: www.duncanjauncey.com/java/ui

The last few months have been especially busy with the arrival of my beautiful daughter, but I have still managed to find some time to write a couple of new applications for CodeAlchemists.

BabyPatterns is a simple program that displays stimulating high-contrast patterns of the type which occasionally entertain young babies.

Contact Sheets generates a ‘Contact Sheet’ for each folder, showing all the photos in that folder. It’s vaguely intelligent about it, regenerating sheets for folders if they’ve changed, skipping folders that haven’t, that sort of thing. Useful when you’ve built up a large archive of photos, as I have. :-)

Next on the development list is a new version of JDarkRoom.

2008-11
26
Tags:

I’ve been looking for a decent flight simulator for years & finally have found one that fits the bill: X-plane. I’ve taken some screenshots of a few Sunday online fly-ins for your viewing pleasure.

I’ve finally upgraded the version of WordPress which runs this blog. In doing so, sadly I managed to trash all the comments that people had contributed. One of the reasons for the upgrade was that I’d had to disable comments due to the sheer deluge of comment-spam (1000+ messages a day). Comments are now enabled again.

I’ve chosen this retro theme because I like it and it’s clear and easy to read – but it still needs a few tweaks.

2008-7
2
Tags:

Nearly three years after I first started the project, the first public beta of NextDesk is now online.

Put simply, NextDesk lets you easily drag and drop files from your computer to another computer. If you paste text to it from the clipboard, the pasted text will appear on the clipboard of the other computer.

Have fun!

2008-6
20

National Express On-Train WiFi

I was on an intercity train this evening, journeying up the East Coast main line from London to Edinburgh; it was my first trip on the new National Express service since they took over from GNER some months ago. They offer free wifi to all passengers, which I was keen to try out with my new Eee 900 PC.

Upon firing up the ‘Wireless Networks’ window, I was heartened to see five hotspots with names like BN06DE, BN06EF and BN06FH. Selecting the one with the strongest signal yielded a WEP key prompt, which I eventually discovered could be bypassed simply by pressing OK. The window then displayed more hotspots named ‘nxecwifi’ and one called ‘Jet Blue hot spot’.

After several futile attempts at connecting to the more-enticing ‘Jet Blue hot spot’, I tried ‘nxecwifi’ … and Bingo! It took 15 seconds or so to acquire an IP address via DHCP, but after that I could ping www.google.com. Upon opening firefox I was immediately redirected to www.nationalexpresswifi.train – hosted on the train’s LAN. The page presents a login box asking for your email address (the password is supplied). After logging in you’re finally online at this point and can type any website address into your browser’s address bar.

Being a geek I now felt compelled to poke around and measure a few things. The network latency was pretty variable – between 500 and 6000 milliseconds, but this still seems remarkable considering you’re hurtling along backwards – in my case – at 150mph through the countryside. Tunnels tend to cause temporary blackouts, however TCP keepalive handles this nicely. www.speedtest.net recorded my ping time as 1 second, my download rate as 714kbps and my upload rate as 34kbps. There didn’t appear to be any direct correlation between latency and train speed.

Actual browsing seemed fairly slow, but definitely usable. My surfing was at one point redirected back to the train login page, whereupon I had to log back in using my email address, but this only happened once.

So all in all, an impressive service, especially so given that it’s free. One last gem to finish with – the onboard train website has a map showing where you are. And I’ve just passed Berwick-upon-Tweed.

2008-5
7
In:life by duncanj
Tags:

My BT Broadband failed at 16.30 last Thursday. As it turned out, all I needed to do was change the part of my broadband username which read ‘hg4.btinternet.com’ to ‘btinternet.com’. A quick reboot of the router, and I’m connected again. I’m writing this up in the hope it might help someone else – because I’d been through the fault reporting process, line check etc, but nobody from BT Broadband was able to either diagnose the fault or suggest that the username might have changed.

Comments off
2008-2
25

XFire Custom Types – 25th February 2008 – XFire 1.2.6

  • Custom Types are types registered with XFire that perform their own mapping to/from XML.
  • "complex types" are your own beans/objects which don’t have a custom type mapping, therefore XFire will attempt to map to/from XML on its own.
  • They *do* work, but you have to be careful that you set everything up right, otherwise you’ll see a StackOverflowError and many other exceptions.
  • XFire sometimes gets terribly confused if one of your own (complex) types is put inside a map (e.g. of <String,Object>) – unless you create a custom type mapping as described below. (see bug XFIRE-831)
  • I couldn’t find a proper example of this on the web & spent several days discovering the correct way to do this.

Example: java.util.Date
Date objects are automatically converted to XMLGregorianCalendar by XFire. This behaviour may not be appropriate since converting back from an XMLGregorianCalendar to a Date is very slow. This example overrides the normal mapping for java.util.Date so that only a long value is passed across the wire, then reparsed back into a java.util.Date again.

  1. Define your type mapping class. The below defines a mapping for java.util.Date, so that it will be read and written as a String containing a long value (the number of milliseconds from the Date object). Note that this class must be available on the classpath for both client and server.
    import java.util.Date;
     
    import javax.xml.namespace.QName;
     
    import org.codehaus.xfire.MessageContext;
    import org.codehaus.xfire.aegis.MessageReader;
    import org.codehaus.xfire.aegis.MessageWriter;
    import org.codehaus.xfire.aegis.type.basic.ObjectType;
    import org.codehaus.xfire.aegis.type.java5.Java5TypeCreator;
    import org.codehaus.xfire.fault.XFireFault;
     
    public class DateType extends ObjectType {
    	private static final Class&lt;java.util.Date&gt; componentClass = java.util.Date.class;
    	protected QName qname = new Java5TypeCreator().createQName(componentClass);
     
    	public DateType()
    	{
    		setNillable(true);
    		setTypeClass(java.util.Date.class);
    		setSchemaType(qname);
    		System.out.println(&quot;Created DateType&quot;);
    	}
     
    	public Object readObject(MessageReader reader, MessageContext context) throws XFireFault
    	{	
    		String value = reader.getValue();
    		System.out.println(&quot;Reading DateType from '&quot;+value+&quot;'&quot;);
     
    		if (value == null)
    			return null;
     
    		try {
        		Long l = Long.parseLong(value);
        		return new Date(l.longValue());
    		} catch( NumberFormatException e ) {
    			throw new XFireFault(&quot;Could not parse Date: &quot; + e.getMessage(), e, XFireFault.SENDER);
    		}
    	}
     
    	public void writeObject(Object object, MessageWriter writer, MessageContext context)
    	{
    		System.out.println(&quot;Writing DateType..&quot;);
     
    		assert( object instanceof Date );
     
    		Date d = (Date) object;
    		writer.writeValue(&quot;&quot;+d.getTime());
    	}
    }
  2. Register the type mapping with both the client and the server

    Registering with the client is easy. I dare say you already have a convenience method that allows you to get hold of a Service. The important parts from mine look something like this:

    	String serviceURL = ... // replace with your service URL
    	Class serviceClass = ... // replace with the class object for your service (e.g. MyService.class)
    	Service service = new ObjectServiceFactory().create(serviceClass);
     
    	// register our new type mapping class
    	TypeMapping tm = ((AegisBindingProvider)service.getBindingProvider()).getTypeMapping(serviceModel);
    	tm.register(new DateType());	
     
    	serviceObject = new XFireProxyFactory().create(service, serviceURL);
    	System.out.println(&quot;Created service object.&quot;);
     
    	// then cast your serviceObject to the correct type (e.g. MyService) and use it.

    Registering with the server is somewhat more confusing. I tried several things and ended up extending XFireConfigurableServlet so that the type mappings were registered inside the init() method:

    public class MyXFireServlet extends XFireConfigurableServlet {
    	public MyXFireServlet() {
    		super();
    		System.out.println(&quot;Creating MyXFireServlet.&quot;);
    	}
     
    	public void init() throws ServletException {
    		super.init();
     
    		System.out.println(&quot;Initializing My XFire Servlet..&quot;);
     
    		ServiceRegistry serviceRegistry = getXFire().getServiceRegistry();
    		for( Service service : (Collection&lt;Service&gt;) serviceRegistry.getServices() ) {
    			TypeMapping tm = ((AegisBindingProvider) service.getBindingProvider()).getTypeMapping(service);
    			tm.register(new DateType());
    			System.out.println(&quot;Registering DateType for service &quot;+service.getName());
    		}
     
    		System.out.println(&quot;Initialization complete.&quot;);
    	}
    }

    If you do this, you should also update your web.xml file so that your servlet definition for XFire uses your customized servlet, like this:

    	&lt;!-- XFire --&gt;
    	&lt;servlet&gt;
    		&lt;servlet-name&gt;XFireServlet&lt;/servlet-name&gt;
    		&lt;display-name&gt;XFire Servlet&lt;/display-name&gt;
    		&lt;servlet-class&gt;my.package.name.MyXFireServlet&lt;/servlet-class&gt;
    	&lt;/servlet&gt;

    Now your type mapping will be used whenever XFire encounters an object of the type registered by setTypeClass().

Note: if sending Date objects created by Hibernate, they may be of type java.sql.Date – in which case XFire will still convert them to XMLGregorianCalendar unless you add a type mapping (as above) for java.sql.Date. Depending on your database vendor, you may also have to register mappings for vendor-specific types (e.g. com.sybase.jdbc2.tds.SybTimestamp).

You can define type mappings for any of your own objects – just substitute your fully-qualified class name where java.util.Date is used in the example above, and customize the readObject() and writeObject() methods to read and write a representation of your object.

For this example, I used the 3.2.4 version of the woodstox library. If you don’t specify woodstox as a dependency, you may get a cryptic com.bea.xml.stream.MXParserFactory not found error.

Hints:

If you see the following then your client is almost certainly not aware of a custom type mapping that it needs in order to parse a type that it has encountered (possibly in a Map or List). Check that you’ve registered it with the appropriate code that creates your service object.

java.lang.StackOverflowError
	at com.ctc.wstx.util.StringVector.findLastNonInterned(StringVector.java:194)
	at com.ctc.wstx.sr.NsInputElementStack.getNamespaceURI(NsInputElementStack.java:503)
	at com.ctc.wstx.sr.BasicStreamReader.getNamespaceURI(BasicStreamReader.java:775)
	at org.codehaus.xfire.util.stax.DepthXMLStreamReader.getNamespaceURI(DepthXMLStreamReader.java:142)
	at org.codehaus.xfire.util.stax.DepthXMLStreamReader.getNamespaceURI(DepthXMLStreamReader.java:142)
	at org.codehaus.xfire.aegis.stax.ElementReader.getNamespaceForPrefix(ElementReader.java:271)
	at org.codehaus.xfire.aegis.type.basic.ObjectType.extractQName(ObjectType.java:146)
	at org.codehaus.xfire.aegis.type.basic.ObjectType.readObject(ObjectType.java:97)
	at org.codehaus.xfire.aegis.type.basic.ObjectType.readObject(ObjectType.java:133)
	at org.codehaus.xfire.aegis.type.basic.ObjectType.readObject(ObjectType.java:133)
	at org.codehaus.xfire.aegis.type.basic.ObjectType.readObject(ObjectType.java:133)
	at org.codehaus.xfire.aegis.type.basic.ObjectType.readObject(ObjectType.java:133)
	at org.codehaus.xfire.aegis.type.basic.ObjectType.readObject(ObjectType.java:133)
	at org.codehaus.xfire.aegis.type.basic.ObjectType.readObject(ObjectType.java:133)
Comments off
2008-1
12

JDarkRoom version 12 is now available including the following new features:

  • Auto-save backups
  • Adjustable screen margins for smaller displays
  • Text search

As I write this, JDarkRoom has now been downloaded over 20,000 times.