The Source for Java Technology Collaboration
User: Password:



Evan Summers's Blog

March 2007 Archives


Screen Capture

Posted by evanx on March 28, 2007 at 06:52 AM | Permalink | Comments (6)

For documentation purposes (and perhaps remote support), we need snapshot images of our application. So let's build such support directly into our application itself.


Code Snippets

We can capture whole desktop, and save it to a PNG file, as follows.

    public void captureScreen(String fileName) throws Exception {
        Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
        BufferedImage image = new Robot().createScreenCapture(new Rectangle(screenSize));
        ImageIO.write(image, "png", new File(fileName));
    }

Alternatively, we might capture our JFrame, including its window decoration, as follows.

    public void captureFrame(JFrame frame, String fileName) throws Exception {
        BufferedImage image = new Robot().createScreenCapture(frame.getBounds());
        ImageIO.write(image, "png", new File(fileName));
    }




Interview with Mono's Miguel de Icaza

Posted by evanx on March 26, 2007 at 04:47 AM | Permalink | Comments (9)

i was just reading an interview with Miguel de Icaza, creator of Mono.

He mentions their "Mono Migration Analyzer" tool for users to see the coverage for their (Windows) .NET apps. They collect automated reports generated by this tool to see what features of Mono are missing for most real world applications in the wild, and this is used to prioritise Mono development. He mentions they expect to support 50% of current applications with some minor incremental updates, and Novell is staffing up the Mono team for a big push.

Mono 2.0 will support ASP.NET 2.0, but Windows.Forms 2.0 will come later. (When is Mono 2.0 scheduled?)

On the opensourcing of Java, he says Mono is targeting the .NET crowd who are typically not using Java, for migration of .NET apps to Linux, so it doesn't impact them. But naturally it will make Java more ubiquitous in the opensource space.

He suggests that for desktop applications, Java still has to address its memory usage limitations. (Don't other high-level runtimes like .NET and Mono also have relatively high memory usage compared to native C/C++ apps? I thought this was the trade-off for easing development.)

He doesn't seem to like WPF. Although it has some great elements to it, it has some "ugly" ones too, he says. For now they are focussing on Windows.Forms, because people have adopted that in droves, whereas WPF is too new, so not used much yet. (How do these GUI toolkits compare to Swing?)

PS. If Netbeans supported Mono, and automatically converted the uppercase method names to lowercase ones, then i'd give it a try ;) That is, if Windows.Forms compares favourably with Swing?

Google vs the OpenSource Desktop

Posted by evanx on March 24, 2007 at 03:47 AM | Permalink | Comments (0)

i was just reading a blog "Google Hasn’t Improved Search" (to kill some time before the South Africa vs Australia cricket match starts shortly). The author says,

Whenever they release a new product, it does nothing to improve the existing search offering. Whenever they do something to change the existing search offering, it's a minor layout move. Whenever there's a new product in labs, it's no longer outlandish, it doesn't make me think and again; is no improvement or change to their core offering: SEARCH.

I agreed and added the following ranting comment about Google, which i repeat below.

But enough about you, let's talk about me, what i think

Google don't seem to have a cohesive plan except to hire anyone who's anyone, away from other companies who need them eg. Sun et al, for what purpose? To take over the information world, to displace and replace everyone else? It doesn't feel right.

Rather than leverage and contribute to opensource projects such as Thunderbird and OpenOffice, to web-enable those as stateless RIAs or something, they develop web-based apps for mail, calendaring and docs which are relatively poor in terms of usability and features compared to the opensource desktop equivalents. But at least the web apps have ads! ;)

Why don't they use Thunderbird/XUL for gmail? Why not add "G-drive" integration to OpenOffice? And throw in ads somewhere to pay for it.

So i think they are taking the industry backwards with their "web-browser-hobbled desktop knock-offs" when they could be driving the whole rich opensource desktop forward to leverage their internet infrastructure, and not just the browser.

But enough about my thoughts, let's talk about my plans

It looks like i'm back on the road again. Every six months to a year, i decide to switch locations from Johannesburg and Cape Town or visa versa, and it seems that time has come again.

I'm gonna be spending the next few months flitting around the country between Johannesburg, Durban and Cape Town, visiting various family and friends, with my two notebooks and my backpack. One "notebook" is a computer with GSM 3G connection, so i'm good to go. My other very important notebook is paper-based. Cos I find the best way to design software i want to write, is in a coffee shop with pen and paper and a double cappucino or three.

After i've overstayed my welcome and exhausted the hospitality of my family and friends once again, i'm thinking of heading over to Europe and getting a job like my mom says i should. I'm justing waiting for Netbeans6 with its minty goodies like JSR295, JSR296, JPA... Ooo, what a good time to reenter to job market! :)



Hyper Text Processor

Posted by evanx on March 22, 2007 at 09:19 AM | Permalink | Comments (0)

In the HTML Builder prequel, we generated a HTML artifacts for QHyperTextProcessorProperties.

So let's meet this QHyperTextProcessor itself, even if it's messy and not generally useful, but just a hack to serve the random purposes of this author, for this so-called trilogy.


Code Snippet

QHyperTextProcessor processes a document in toto, given it's text.

public class QHyperTextProcessor {
    protected QHyperTextProcessorProperties properties = 
            dependencyManager.getInstance(QHyperTextProcessorProperties.class);
    
    protected String text;
    protected QStringBuilder stringBuilder = new QStringBuilder();
    protected QTextState state = noState;
    
    public QHyperTextProcessor(String text) {
        this.text = text;
    }
    ...
    public String processText() {
        for (String string : stringHelper.splitString(text, "\n")) {
            try {
                processTextLine(string);
            } catch (Throwable e) {
                throw new QWrappedRuntimeException(e, null, string);
            }
        }
        return stringBuilder.toString();
    }
}

where we split the text up into lines, and invoke processTextLine() with each line of text in the file.




Tipsy Snipsy: Forward Focus Traversal

Posted by evanx on March 15, 2007 at 04:59 AM | Permalink | Comments (5)

As you've noticed, when you press Enter on fields like JTextField et al, an ActionEvent is generated, and focus is not transferred to the next field in the focus cycle.

But what if you are not interested in ActionEvent's on fields, and would rather Enter have the same effect as Tab, maybe because your users are used to having to enter data with the Enter key?

    protected void setDefaultFocusTraversalKeys() {
        Set set = new HashSet(
                KeyboardFocusManager.getCurrentKeyboardFocusManager().
                getDefaultFocusTraversalKeys(
                KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS));
        set.add(KeyStroke.getKeyStroke("ENTER"));
        KeyboardFocusManager.getCurrentKeyboardFocusManager().
                setDefaultFocusTraversalKeys(
                KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS, set);
    }   

But then we aint gonna get those ActionEvent's no more, which may or may not be a problem.


References

Setting Focus Traversal Keys for the Entire Application on JavaAlmanac.com.

Using the Swing Focus Subsystem on the Java Tutorial.




All your base-64 do not belong to prying eyes

Posted by evanx on March 12, 2007 at 11:06 AM | Permalink | Comments (10)

I was just reading a nice tip by Peter Bromberg, in his blog entry Simple XOR Encryption.

In Password Hash we used the following delegating class for base-64 encoding.

public class Base64 {    

    public static String encode(byte[] bytes) {
        return new sun.misc.BASE64Encoder().encode(bytes);
    }
    
    public static byte[] decode(String string) {       
        try {
            return new sun.misc.BASE64Decoder().decodeBuffer(string);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}    

As an alternative to the XOR'ing approach, we could use this encoding as "encryption" against prying eyes if nothing else, as follows.

    public static void main(String[] args) {
        String parameters = "username=evanx;password=mypassword";
        String encryptedParameters = Base64.encode(parameters);
        System.out.println(encryptedParameters);
        parameters = new String(Base64.decode(encryptedParameters));
        System.out.println(parameters);
    }

which outputs the following

dXNlcm5hbWU9ZXZhbng7cGFzc3dvcmQ9bXlwYXNzd29yZA==
username=evanx;password=mypassword

Developers 1, Managers 0 ;)




Cryptonomicon

Posted by evanx on March 08, 2007 at 02:55 AM | Permalink | Comments (0)

Let's check out some Java Cryptography, considering both symmetric and asymmetric algorithms.

We implement a client and server that mimic how SSL works, where the client uses the server's public key to asymmetrically encrypt and transfer a secret key, which is then used by both sides to encrypt messages using a symmetric cipher.


Code Snippet

The client connects to the server port, negotiates a key exchange, and then communicates securely.

public class CryptonomicalClient extends Thread {
    CryptonomicalSocket cryptoSocket;
    ...
    public void run() {
        try {
            String publicKey = cryptoSocket.sendRequest(cryptoRequest);
            cryptoSocket.setEncodedPublicKey(publicKey);
            cryptoSocket.generateSecretKey();
            String encryptedSecretKey = cryptoSocket.encryptSecretKey();
            String response = cryptoSocket.sendRequest(encryptedSecretKey);
            if (!response.equals(cryptoAcknowledge)) throw new RuntimeException();
            cryptoSocket.setEncrypt(true);
            process();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            cryptoSocket.close();            
        }
    }
    
    protected void process() throws Exception {
        String response = cryptoSocket.sendRequest("ALL YOUR BASE ARE BELONG TO US.");
        logger.info(response);
    }        
}

Once key change has been accomplished, we can securely send the server a test message in process().

PS. The title of this article is of course a tribute to Neal Stephenson's book Cryptonomicon, which is on my bedside table right now.




Airbus A380 vs Boeing 787 Dreamliner

Posted by evanx on March 05, 2007 at 11:27 AM | Permalink | Comments (11)

The Airbus vs Boeing competition has been interesting to watch in recent years. With the increasing number of world travellers, and limited airport capacity, there is a need for a very large carrier eg. 500+ seats. But the market can only support one such product. So Airbus stepped up with the A380 superjumbo, which in a typical three-class configuration supports 555 seats (and 853 in single cattle-class configuration). It's a double-decker 4-engined 10 billion dollar baby.

A380-2-250.jpg Boeing went for a more modest successor to the illustrious 747-400, namely the 787 Dreamliner, to debut in 2010. It's a 2-engined composite-framed liner seating 223, ie. half that of the A380. So it's gonna use more advanced materials, and wing design, but otherwise not be a radical departure from current models.

At the time, i thought Boeing had the right idea. I thought, I'd rather be a shareholder betting on Boeing, than Airbus. The young mechanical engineer in me thought it would be tremendously exciting to be involved in this ambitious A380 project, but the more experienced software engineer thought, oooo, dunno, a bit risky...

Anyways, now it seems that Airbus is having a hard time, with a two year delay, caused by wiring and weight issues because of its relatively oversized frame. FedEx and now UPS have cancelled their orders for cargo versions of the A380 superjumbo, and Airbus has announced 10,000 job cuts. Ouch.

I wonder what, if any, are the lessons to be learnt from this, for software development projects?

System Properties

Posted by evanx on March 01, 2007 at 07:25 AM | Permalink | Comments (0)

Let's use reflection to set a bunch of configurable values via the command-line using "system properties."


Code Snippet

We put our configurable properties into a separate object, specifying the default values, as follows.

public class CommandoDemoProperties {    
    public String host = "aptframework.net";
    public int port = 80;
    public int sslPort = 443;
    public boolean useSSL = true;    
    public String clientKeyStoreFileName = "keystores/client.private";    
    public String serverKeyStoreFileName = "keystores/server.public";    
    ...
}    

We create the following helper to inject any command-line parameters via reflection, according to the field names, eg. -Dport=8080.

public class QSystemPropertyHelper {
    ...
    protected void injectSystemProperties(Object properties) 
    throws IllegalAccessException {
        for (Field field : properties.getClass().getFields()) {
            Class type = field.getType();
            String key = field.getName();
            Object defaultValue = field.get(properties);
            Object value = defaultValue;
            String string = System.getProperty(key);
            if (string == null) continue;
            if (type == String.class) {
                value = string;
            } else if (type == Integer.class || type == int.class) {
                value = Integer.getInteger(key);
            } else if (type == Boolean.class || type == boolean.class) {
                value = Boolean.getBoolean(key);
            } else {
                logger.warning(key, type);
            }
            if (value != defaultValue) {
                field.set(properties, value);
            }
        }
    }    
}

where we support properties which are strings, integers or boolean values.






Powered by
Movable Type 3.01D
 Feed java.net RSS Feeds