February 15, 2012

Create Your Own Java URL Handlers

Introduction
Custom URL handlers are becoming more popular as desktop applications are interacting with Internet or Cloud sources.  For example, to subscribe to a iTunes podcast, a website will have a link which looks something like this:

itpc://www.company.com/public/get/podcast.rss

Where "itpc" is a custom protocol handler created by iTunes to handle URLs of this type.  The purpose of this article is to demonstrate how to create your own URL handler in Java.

Problem
Suppose there is need to create the "JTLC" protocol? If I were to create a URL object with this protocol...

public static void main(String[] args) throws Exception
{
  String urlStr 
    = "jtlc://www.mycompany.com/some/path/to/resource";
  URL url = new URL(urlStr);
}

I will get a nasty stack trace from Java...

Exception in thread "main" java.net.MalformedURLException: 
unknown protocol: jtlc
    at java.net.URL.<init>(URL.java:574)
    at java.net.URL.<init>(URL.java:464)
    at java.net.URL.<init>(URL.java:413)
    at jtlc.main.Main.main(Main.java:14)

This is because Java comes with a set of built in handlers to handle well known protocols like HTTP, but your JTLC protocol is unknown to Java so you get a stack trace.  However, before Java throws the stack trace, it attempts to locate a handler for the JTLC protocol.  If you provide the handler, Java will use it to handle JTLC.

Solution

Package

First (and easiest) thing to do is to create the following package in you application to hold the code for your JTLC protocol handler:

sun.net.www.protocol.jtlc

Java will automatically look in the root sun.net.www.protocol package for protocol handlers.  Furthermore, by adding the additional sub-package jtlc (making the full package name you should use sun.net.www.protocol.jtlc), you are telling Java the code in this package handles the JTLC protocol.  When you try to create a new URL object with the "jtlc" protocol, Java will look in the root sun.net.www.protocol package for a sub-package named jtlc to find the code to handle this protocol.

If you do not use this package, then you will have to set special system properties to tell Java what package holds the handlers for you JTLC protocol. 

URLConnection

Second, you need to create a class which extends java.net.URLConnection.

The name of this class can be whatever you want, but it is good convention to name it after the letters in the protocol.  The class for the JTLC protocol may look something like this:

package sun.net.www.protocol.jtlc;

import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection;

public class JtlcConnection extends URLConnection
{
    public JtlcConnection(URL u) {
        super(u);
    }

    @Override
    public void connect() 
    throws IOException {
      throw new UnsupportedOperationException(
        "The connect() method is not supported"
      );
    }
   
    @Override
    public Object getContent() 
    throws IOException {
      throw new UnsupportedOperationException(
        "The getContent() method is not supported"
      );
    }

    @Override
    public InputStream getInputStream() 
    throws IOException {
      throw new UnsupportedOperationException(
        "The getInputStream() method is not supported"
      );
    }
}

Of course you will want to provide a real implementations for these methods to handle connecting to your resource and getting a stream to the content.

URLStreamHandler

Finally, you will need to create a class with extends java.net.URLStreamHandler.

THE NAME OF THIS CLASS MUST BE "Handler".  Java will automatically look for a class named Handler inside the sun.net.www.protocol.jtlc package.  If you name this class something other than Handler, Java will not find it.

The purpose of Handler is to create an instance of URLConnection subclass.  An example may look like this:

package sun.net.www.protocol.jtlc;

import java.io.IOException;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLStreamHandler;

public class Handler extends URLStreamHandler
{
    @Override
    protected URLConnection openConnection(URL u)
    throws IOException
    {
        return new JtlcConnection(u);
    }
}


Summary
Although there are more than one way to create your own Java protocol handlers, this is the quickest and easiest way I've found.

That's it.  Enjoy!

NetBeans and Public-Private SSH Key Access to CVS

Introduction
The purpose of this article is to document how to configure NetBeans to access a CVS repository over SSH using public-private keypairs.

Install "Putty" Applications
Putty is located at http://www.chiark.greenend.org.uk/~sgtatham/putty/.  The primary applications need are pageant.exe and plink.exe.

Run Pageant
Startup pageant.exe. It will be accessible via the system tray.





Right click on the pageant icon in the system tray to add the private key you use to access the CVS server.  Keep in mind that putty and all the putty related applications do not work with keys generated by the linux `ssh-keygen` command.  The private key generated by `ssh-keygen` needs to be opened with the puttygen.exe application and converted into a putty specific private key which can then be used in pageant.exe.

Configure NetBeans
Startup NetBeans.  Go to Team > Checkout.  For the CVS repository configuration, select the radio button to "Use External Shell".  In the "Shell Command" textbox, enter the fully qualified path to plink.exe. Click the "Next >" button and the CVS repository will be access via SSH using your public-private keypair.





























That's it.  Enjoy!

December 01, 2011

IE7 Preserve Whitespace Problem and Solution

Overview
Internet Explorer 7 has a well documented problem when it comes to using innerHTML and dynamically generating content which needs to preserve whitespace.  There is a lot information on the Internet about using the CSS properties white-space, word-wrap, and a multitude of other properties, hacks, and tricks to solve this problem.  However I found none of them worked.  After a few days of research I have a simple solution which I will explain here.

The Problem
Here is the problem.  You are building a dynamic website and in your database you have data which is formatted using newlines and spaces and looks like this:

Hello        Doctor             Name
    Continue
Yest..
 ..erday

Tomorrow


Your website is to pull this data from the database and display it on the page.  The implementation to do this will vary greatly, but essentially you will have an empty <div> to hold the data and you'll use jQuery to look up the <div> by ID then you will set the <div>'s HTML content.  Here is a very basic version of this:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
    <head>               
    </head>
    <body>       
        <div id="theData"></div>       
        <script src="jquery-1.6.2.min.js"></script>
        <script>
            var theData = "Hello        Doctor             Name\n    Continue\nYest..\n ..erday\n\nTomorrow";
            $(document).ready(
                function() {
                    $("#theData").html(theData);
                }
            );
        </script>
    </body>
</html>


Of course when you run this in any browser, the white space and newlines in the text will be removed and you will see this on the screen:
Hello Doctor Name Continue Yest.. ..erday Tomorrow

So CSS to the rescue!  Use the font-family and white-space attributes to tell the browser how to format the text in the <div>.

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
    <head>
        <style>
            #theData {
                font-family:monospace;
                white-space:pre-wrap;               
            }
        </style>

    </head>
    <body>       
        <div id="theData"></div>

        <script src="jquery-1.6.2.min.js"></script>
        <script>
            var theData = "Hello        Doctor             Name\n    Continue\nYest..\n ..erday\n\nTomorrow";
            $(document).ready(
                function() {
                    $("#theData").html(theData);
                }
            );
        </script>
    </body>
</html>


Of course you quickly realize this works in Firefox and Chrome but not IE (which is why you are reading this).  This resource http://web.student.tuwien.ac.at/~e0226430/innerHtmlQuirk.html gives a good explanation about what is happening in IE.  Although researching this problem will give you a headache, I found a solution which seems to work with all browsers and is quite easy.

The easiest thing to do is to wrap the data with <pre> tags before setting the inner HTML of the <div>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
    <head>
        <style>
            #theData {
                font-family:monospace;
                white-space: pre-wrap;               
            }
        </style>
    </head>
    <body>       
        <div id="theData"></div> 

        <script src="jquery-1.6.2.min.js"></script>
        <script>
            var theData = "Hello        Doctor             Name\n    Continue\nYest..\n ..erday\n\nTomorrow";
            $(document).ready(
                function() {                   
                    $("#theData").html( 

                       "<pre>" + theData + "</pre>" 
                     );
                }
            );
        </script>
    </body>
</html>


That's it!  Of course, remember your CSS has to change now since you need to format #theData pre{} now...

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
    <head>
        <style>
            #theData pre {
                margin:0;
                color:purple;               
            }
        </style>

    </head>
    <body>       
        <div id="theData"></div>       
        <script src="jquery-1.6.2.min.js"></script>
        <script>
            var theData = "Hello        Doctor             Name\n    Continue\nYest..\n ..erday\n\nTomorrow";
            $(document).ready(
                function() {

                    $("#theData").html( 
                       "<pre>" + theData + "</pre>" 
                     );
                }
            );
        </script>
    </body>
</html>

Enjoy!