/* * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * You may not modify, use, reproduce, or distribute this * software except in compliance with the terms of the License at: * * http://developer.sun.com/berkeley_license.html * * $Id: GeoCoder.java,v 1.4 2007/04/16 23:43:14 sean_brydon Exp $ */ package com.sun.javaee.blueprints.petstore.proxy; import com.sun.javaee.blueprints.petstore.util.PetstoreUtil; import java.io.IOException; import java.io.InputStream; import java.io.UnsupportedEncodingException; import java.net.MalformedURLException; import java.net.URL; import java.net.URLEncoder; import java.util.ArrayList; import java.util.List; import java.util.logging.Level; import java.util.logging.Logger; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import org.xml.sax.SAXException; /** *
Service object that interacts with the Yahoo GeoCoding service. For * information on the relevant APIs, see * http://developer.yahoo.net/maps/rest/V1/geocode.html.
*/ public class GeoCoder { private String applicationId = APPLICATION_ID; private Logger logger = Logger.getLogger("com.sun.javaee.blueprints.components.ui.GeoCoder", "com.sun.javaee.blueprints.components.ui.MessageStrings"); private String proxyHost = null; private int proxyPort = 0; private boolean proxySet = false; // ------------------------------------------------------ Manifest Constants /** *The default application identifier required by the geocoding
* service. This may be overridden by setting the applicationId
* property.
The URL of the geocoding service we will be using.
*/ private static final String SERVICE_URL = "http://api.local.yahoo.com/MapsService/V1/geocode"; // -------------------------------------------------------------- Properties /** *Return the application identifier to be passed to the geocoding * service.
*/ public String getApplicationId() { return this.applicationId; } /** *Set the application identifier to be passed to the geocoding * service.
* * @param applicationId The new application identifier */ public void setApplicationId(String applicationId) { if (applicationId == null) { throw new NullPointerException(); } this.applicationId = applicationId; } /** *Return the proxy host to use for network connections, or null
* if the default proxy host for the application server's JVM should be
* used instead.
null
* to use the default proxy host for the application server's JVM.
*
* @param proxyHost The new proxy host
*/
public void setProxyHost(String proxyHost) {
this.proxyHost = proxyHost;
this.proxySet = false;
}
/**
* Return the proxy port to use for network connections, or 0
* if the default proxy port for the application server's JVM should be
* used instead.
0
* to use the default proxy port for the application server's JVM.
*
* @param proxyPort The new proxy port
*/
public void setProxyPort(int proxyPort) {
this.proxyPort = proxyPort;
this.proxySet = false;
}
// ---------------------------------------------------------- Public Methods
/**
* Return an array of zero or more {@link GeoPoint} instances for results * that match a search for the specified location string. This string can * be formatted in any of the following ways:
*location does not
* conform to one of the specified patterns
* @exception NullPointerException if location is null
*/
public GeoPoint[] geoCode(String location) {
// Bail out immediately if no location was specified
if (location == null) {
return null;
}
// Set the proxy configuration (if necessary)
if (!proxySet) {
setProxyConfiguration();
proxySet = false;
}
// URL encode the specified location
String applicationId = getApplicationId();
try {
applicationId = URLEncoder.encode(applicationId, "ISO-8859-1");
} catch (UnsupportedEncodingException e) {
if (logger.isLoggable(Level.WARNING)) {
logger.log(Level.WARNING, "geoCoder.encodeApplicationId", e);
}
throw new IllegalArgumentException(e.getMessage());
}
// URL encode the specified location
try {
location = URLEncoder.encode(location, "ISO-8859-1");
} catch (UnsupportedEncodingException e) {
if (logger.isLoggable(Level.WARNING)) {
logger.log(Level.WARNING, "geoCoder.encodeLocation", e);
}
throw new IllegalArgumentException(e.getMessage());
}
// Perform the actual service call and parse the response XML document,
// then format and return the results
Document document = null;
StringBuilder sb = new StringBuilder(SERVICE_URL);
sb.append("?appid=");
sb.append(applicationId);
sb.append("&location=");
sb.append(location);
try {
document = parseResponse(sb.toString());
return convertResults(document);
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (ParserConfigurationException e) {
e.printStackTrace();
} catch (SAXException e) {
e.printStackTrace();
}
return null; // FIXME
}
/**
* Convert the parsed XML results into the appropriate output from
* our geoCode() method. If there were no results (and no
* exception was thrown), a zero-length array will be returned.
Parse the XML content at the specified URL into an XML
* Document, which can be further processed to extract
* the necessary content.
FIXME - only uses implied JVM-wide proxy, * so needs to be modified for Java SE 5.
* * @param url URL of the resource to be parsed * * @exception IOException if an input/output error occurs * @exception MalformedURLException if the specified URL is invalid * @exception ParserConfigurationException if thrown by the XML parser * configuration mechanism * @exception SAXException if a parsing error occurs */ private Document parseResponse(String url) throws IOException, MalformedURLException, ParserConfigurationException, SAXException { DocumentBuilder db = DocumentBuilderFactory.newInstance().newDocumentBuilder(); InputStream stream = null; try { stream = new URL(url).openStream(); return db.parse(stream); } finally { PetstoreUtil.closeIgnoringException(stream); } } /** *Attempt to set the system properties related to the HTTP proxy host
* and port to be used, but swallow security exceptions if the security
* policy that our container is running under forbids this. In a JDK 1.5
* environment, we'll be able to use the java.net.Proxy class
* and deal with this on a per-connection basis. Until then, oh well.