cpcc.ros.sim.osm.TileCache.java Source code

Java tutorial

Introduction

Here is the source code for cpcc.ros.sim.osm.TileCache.java

Source

// This code is part of the CPCC-NG project.
//
// Copyright (c) 2013 Clemens Krainer <clemens.krainer@gmail.com>
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software Foundation,
// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.

package cpcc.ros.sim.osm;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Locale;

import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.HttpClientBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;

/**
 * OpenStreetMap tile cache
 */
public class TileCache {
    private static final Logger LOG = LoggerFactory.getLogger(TileCache.class);

    private static final String FORMAT_TILE_CACHE_DIR = "%1$s/%2$d/%3$d";
    private static final String FORMAT_TILE_CACHE_FILE = "%1$s/%2$d/%3$d/%4$d.png";

    private String tileCacheBaseDir;

    private String tileServerUrl;

    /**
     * @param config the configuration.
     */
    public TileCache(Configuration config) {
        tileCacheBaseDir = config.getTileCacheBaseDir();
        tileServerUrl = config.getTileServerUrl();
    }

    /**
     * @param zoom the zoom level
     * @param x the X-coordinate of the tile.
     * @param y the Y-coordinate of the tile.
     * @return the tile as a <code>File</code> object.
     * @throws IOException thrown in case of errors.
     */
    @SuppressFBWarnings("PATH_TRAVERSAL_IN")
    public File getTile(int zoom, int x, int y) throws IOException {
        String tileCacheFileName = String.format(Locale.US, FORMAT_TILE_CACHE_FILE, tileCacheBaseDir, zoom, x, y);

        File tileCacheFile = new File(tileCacheFileName);

        if (tileCacheFile.exists()) {
            LOG.debug(String.format("Cached tile found for zoom=%d, x=%d, y=%d", zoom, x, y));
            return tileCacheFile;
        }

        String tileCacheDirName = String.format(Locale.US, FORMAT_TILE_CACHE_DIR, tileCacheBaseDir, zoom, x);
        File tileCacheDir = new File(tileCacheDirName);
        if (!tileCacheDir.exists()) {
            FileUtils.forceMkdir(tileCacheDir);
        }

        String tileDownloadUrl = String.format(Locale.US, tileServerUrl, zoom, x, y);

        LOG.debug(String.format("Downloading tile for zoom=%d, x=%d, y=%d, url=%s", zoom, x, y, tileDownloadUrl));

        downloadFile(tileDownloadUrl, tileCacheFile);

        return tileCacheFile;
    }

    /**
     * @param url the URL of the desired file.
     * @param file the path where to store the retrieved data.
     * @throws IOException thrown in case of errors.
     */
    public static void downloadFile(String url, File file) throws IOException {
        // TODO extract in a service.
        HttpResponse response = null;
        try {
            response = HttpClientBuilder.create().setUserAgent("TileCache/1.0").build().execute(new HttpGet(url));
        } catch (IOException e) {
            LOG.error("Can not load URL '" + url.toString() + "'", e);
            throw e;
        }

        if (response.getStatusLine().getStatusCode() != HttpStatus.SC_OK) {
            String msg = String.format("Can not load URL '%s' code=%d (%s)", url.toString(),
                    response.getStatusLine().getStatusCode(), response.getStatusLine().getReasonPhrase());
            LOG.error(msg);
            throw new IOException(msg);
        }

        HttpEntity entity = response.getEntity();
        if (entity != null) {
            try (FileOutputStream outStream = new FileOutputStream(file)) {
                IOUtils.copy(entity.getContent(), outStream);
            }
        }
    }

}