IpLocator in JavaFX

By Srikalyan Chandrashekar, March 15, 2010

IpLocator

Not all domains are registered with the same registrars. Therefore, to find an exact registered address, you must first find the parent registrar. The best place to start is from the root internic.net, which might be the registrar. If not, it might know the whois server to which the domain or IP is registered and to which you can query again for final details.

This example uses Yahoo API Map Services to fetch geocoding information (latitude and longitude), given the address. The example uses that information in turn to fetch a hybrid map image tile from Google Maps. This application, called as IpLocator, basically is a simple GUI interface that performs a whois query of the registry servers processing rich JavaFX graphics. GeoTask.fx and WhoisTask.fx in FX correspond respectively to GeoHandler.java and Who.java in Java.

Source Code
public class GeoHandler implements RunnableFuture {

    public static String gMapsApiKey = "ABQIAAAAd7ym__Ls6_KKUGOg27LRCRQcFBkBp5CpZugniGV6Ken1nvBZ3RSnqYoZjBMipC46EE1pCySvfvLOTA";
    public static String yahooMapsAppId = "477Wp3fV34GHn4PFPzhhtuc83T24RGJu1oYm0TMwdLI3_GEkjp_Op5qeFpOQ_Kwoa7DjGzOalusoIwcXrL4-";
    public static String googleImageUrl = "http://maps.google.com/staticmap?size=340x200";
    public static String yahooLatLongUrl = "http://local.yahooapis.com/MapsService/V1/geocode?appid=";
    private String lat;
    private String lon;
    private String ip = "";
    public String isp = "";
    public String city = "";
    public String state = "";
    public String country = " ";

    public GeoHandler() {
    }
//This function can be called to perform all actions as intended by this class
    private String getGeoInformation() {
        findLatLonFromAddress(getYahooUrl());
        return getGoogleUrl();
    }


//Given an address get the latitude and longitide from yahoo maps

    private void findLatLonFromAddress(String yahooUrl) {
        try {
            HttpURLConnection con = (HttpURLConnection) new URL(yahooUrl).openConnection();
            con.setRequestMethod("GET");
            con.setReadTimeout(10000);
            con.setDoInput(true);
            con.connect();
            //read the result from the server
            InputStream is = con.getInputStream();
            Document doc = null;
            DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
            DocumentBuilder db = dbf.newDocumentBuilder();
            doc = db.parse(is);
            Element root = doc.getDocumentElement();
            System.out.println("The root element is " + root.getNodeName() + ".\n");

            Node result = root.getFirstChild();
            Element latitude = (Element) result.getFirstChild();
            Element longitude = (Element) latitude.getNextSibling();

            lat = latitude.getFirstChild().getNodeValue();
            lon = longitude.getFirstChild().getNodeValue();
            System.out.println(" latitude " + lat);
            System.out.println(" longitude " + lon);
            is.close();
            con.disconnect();

        } catch (SAXException ex) {
            Logger.getLogger(GeoHandler.class.getName()).log(Level.SEVERE, null, ex);
        } catch (ParserConfigurationException ex) {
            Logger.getLogger(GeoHandler.class.getName()).log(Level.SEVERE, null, ex);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (ProtocolException ex) {
            Logger.getLogger(GeoHandler.class.getName()).log(Level.SEVERE, null, ex);
        } catch (MalformedURLException ex) {
            Logger.getLogger(GeoHandler.class.getName()).log(Level.SEVERE, null, ex);
        } catch (IOException ex) {
            Logger.getLogger(GeoHandler.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    public void run() throws Exception {
        getGeoInformation();
    }
}

Figure 1: GeoHandler.java Class

Several significant points are notable in this application. The primary focus is making the application access the network and open sockets when launched in a browser profile.This capability requires signing the .jar file. To enable signing the .jar file, perform the following steps:
1. Include <security> tag with <all-permissions> enabled in the .jnlp file.
2. Export the certificate from the local keystore to a file.
3. Upload the certificate to the same folder where the application resides on the server.

The user will be prompted. When the certificate is accepted, the certificate cache option can also be enabled to store the certificate on the client Java Virtual Machine(JVM) keystore. The second notable point is the use of TaskBase in the javafx.async package and also connecting it to RunnableFuture, which is written in Java code. Writing in Java code enables running the I/O information in a separate thread. This makes the UI more responsive than the JavaFX Event Dispatcher Thread (EDT), which handles events sequentially. See Figure 1.

The third point is tweaking the default appearance of controls such as radio buttons. The default implementation classes located in the imported package, com.sun.javafx.scene.control.caspian.*, has been used for this purpose. Hover text, a custom close button, a search button, a save button, and a sticky note to display help text are a few other features. An exact search is the default, which can be changed in settings to a pattern search. When a pattern search is performed the showGeo button is disabled.

Click the geo button to view a location on a map. A small, round button at the upper left of the Maps pane can be used to zoom in/out a map. Five zoom levels are provided. A similar button is displayed at the lower right corner of the Map Pane. This button is used to show or hide the address information. The front of the frame's skin can also be changed in the configuration. The frame flips vertically when you click the Settings button, Save button, MapButton, or BackButton. Finally the exit button, which is supposed to exit the JVM software, does not work within the browser.