it.tidalwave.geo.geocoding.geonamesprovider.GeoNames Maven / Gradle / Ivy
/***********************************************************************************************************************
*
* forceTen - open source geography
* Copyright (C) 2007-2012 by Tidalwave s.a.s. (http://www.tidalwave.it)
*
***********************************************************************************************************************
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*
***********************************************************************************************************************
*
* WWW: http://forceten.tidalwave.it
* SCM: https://bitbucket.org/tidalwave/forceten-src
*
**********************************************************************************************************************/
package it.tidalwave.geo.geocoding.geonamesprovider;
import javax.annotation.CheckForNull;
import javax.annotation.Nonnull;
import java.util.Arrays;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.MalformedURLException;
import java.net.URL;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import org.apache.commons.io.IOUtils;
import org.w3c.dom.Document;
import it.tidalwave.util.logging.Logger;
import it.tidalwave.netbeans.util.Locator;
import it.tidalwave.netbeans.workspacemanager.WorkspaceManager;
import org.apache.commons.io.FileUtils;
/***********************************************************************************************************************
*
* @author Fabrizio Giudici
* @version $Id$
*
**********************************************************************************************************************/
final class GeoNames
{
private static final String CLASS = GeoNames.class.getName();
private static final Logger logger = Logger.getLogger(CLASS);
private static final File cacheFolder;
/*******************************************************************************************************************
*
*
******************************************************************************************************************/
static
{
try
{
File folder = null;
try
{
final WorkspaceManager workspaceManager = Locator.find(WorkspaceManager.class);
folder = workspaceManager.getCacheFolder("GeoData/GeoNames");
}
catch (RuntimeException e)
{
folder = new File(System.getProperty("java.io.tmpdir"));
folder = new File(folder, "GeoData/GeoNames");
logger.warning("Can't find WorkspaceManager: using %s as cache folder", folder.getAbsolutePath());
logger.throwing("static", CLASS, e);
}
cacheFolder = folder;
if (!cacheFolder.mkdirs() && (!cacheFolder.exists() || !cacheFolder.isDirectory()))
{
throw new IOException("Can't create cache folder: " + cacheFolder);
}
}
catch (Exception e)
{
throw new ExceptionInInitializerError(e);
}
}
/*******************************************************************************************************************
*
*
******************************************************************************************************************/
@Nonnull
public static Document retrieveDocument (final @Nonnull String command, final @Nonnull Object... args)
{
InputStream is = null;
URL url = null;
try
{
logger.finer("retrieveDocument(%s, %s)", command, Arrays.toString(args));
url = createURL(args, command);
logger.finest(">>>> url: %s", url);
is = openCachedStream(url);
final DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
final DocumentBuilder docBuilder = factory.newDocumentBuilder();
final Document document = docBuilder.parse(is);
// TODO: if contains a geonames/status, it's an error message -> throw new IOException
return document;
}
catch (RuntimeException e)
{
throw e;
}
catch (Exception e)
{
logger.throwing(CLASS, "retrieveDocument()", e);
logger.warning("Cannot retrieve document: %s", url);
throw new RuntimeException(e);
}
finally
{
IOUtils.closeQuietly(is);
}
}
/*******************************************************************************************************************
*
*
******************************************************************************************************************/
@CheckForNull
public static Icon retrieveIcon (final @Nonnull URL url)
{
InputStream is = null;
try
{
logger.finer("retrieveIcon(%s)", url);
is = openCachedStream(url);
return new ImageIcon(IOUtils.toByteArray(is));
}
catch (FileNotFoundException e)
{
return null;
}
catch (Exception e)
{
logger.throwing(CLASS, "retrieveDocument()", e);
logger.warning("Cannot retrieve document: %s", url);
throw new RuntimeException(e);
}
finally
{
IOUtils.closeQuietly(is);
}
}
/*******************************************************************************************************************
*
*
******************************************************************************************************************/
@Nonnull
public static String retrieveString (final @Nonnull String command, final @Nonnull Object... args)
{
BufferedReader br = null;
try
{
logger.finer("retrieveString(%s, %s)", command, Arrays.toString(args));
final URL url = createURL(args, command);
logger.finest(">>>> url: %s", url);
br = new BufferedReader(new InputStreamReader(openCachedStream(url)));
final String result = br.readLine();
assert result != null : "Read null for " + url;
return result;
}
catch (RuntimeException e)
{
throw e;
}
catch (Exception e)
{
logger.throwing(CLASS, "retrieveString()", e);
logger.warning("Cannot retrieve string");
throw new RuntimeException(e);
}
finally
{
IOUtils.closeQuietly(br);
}
}
/*******************************************************************************************************************
*
*
******************************************************************************************************************/
public static void clearCache()
throws IOException
{
FileUtils.cleanDirectory(cacheFolder);
// final File[] cachedFiles = cacheFolder.listFiles();
//
// if (cachedFiles != null)
// {
// for (final File file : cachedFiles)
// {
// file.delete();
// }
// }
}
/*******************************************************************************************************************
*
*
******************************************************************************************************************/
@Nonnull
private static URL createURL (final @Nonnull Object[] args, final @Nonnull String command)
throws MalformedURLException
{
final StringBuilder builder = new StringBuilder();
builder.append("http://ws.geonames.org/");
builder.append(command);
builder.append("?");
for (int i = 0; i < args.length; i += 2)
{
builder.append(args[i]);
builder.append("=");
builder.append(args[i + 1].toString());
builder.append("&");
}
final URL url = new URL(builder.toString());
return url;
}
/*******************************************************************************************************************
*
*
******************************************************************************************************************/
@Nonnull
private static String cleaned (final @Nonnull URL url)
{
final StringBuilder builder = new StringBuilder();
final String urlString = url.toExternalForm();
for (int i = 0; i < urlString.length(); i++)
{
char ch = urlString.charAt(i);
if (!Character.isLetterOrDigit(ch))
{
ch = '_';
}
builder.append(ch);
}
return builder.toString();
}
/*******************************************************************************************************************
*
*
******************************************************************************************************************/
@Nonnull
private static InputStream openCachedStream (final @Nonnull URL url)
throws IOException
{
logger.finer("openCachedStream(%s)", url);
final File cache = new File(cacheFolder, cleaned(url));
// TODO: the correct logic is: 1) try the file 2) use the file if not older than one day 3) otherwise try to get the
// network timestamp 4) if network is more recent, use it 5) if network fails use the file
if (cache.exists())
{
logger.finest(">>>> cached: %s", cache);
return new FileInputStream(cache);
}
else
{
logger.finest(">>>> not cached, retrieving: %s", cache);
final InputStream is = url.openStream();
final OutputStream os = new FileOutputStream(cache);
return new InputStream()
{
@Override
public int read()
throws IOException
{
int r = is.read();
if (r >= 0)
{
os.write(r);
}
return r;
}
//TODO: override also read(byte[], int, int)
@Override
public void close()
throws IOException
{
try
{
os.close();
}
catch (IOException e)
{
e.printStackTrace();
}
is.close();
}
};
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy