/******************************************************************************* * Copyright 2013 Geoscience Australia * * 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. ******************************************************************************/ package org.gdal; import java.io.BufferedOutputStream; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import java.util.zip.ZipEntry; import java.util.zip.ZipInputStream; import org.gdal.gdal.gdal; import org.gdal.ogr.ogr; /** * Setup the GDAL data configuration based on a data file source strategy * * @author James Navin (james.navin@ga.gov.au) * */ public class GDALDataSetup { private static final String GDALDATA_ZIP = "gdaldata.zip"; private static final String GDALDATA_CONFIG = "GDAL_DATA"; private static Map<String, File> extractedDataMap = new ConcurrentHashMap<String, File>(); /** * A strategy interface for obtaining a target file for unpacking data */ public static interface DataFileSource { /** * Return a file to unpack the named data file into. */ File getDataFile(String dataFileName); /** * Return a reference to the data folder to use */ File getDataFolder(); } /** * Run the GDAL data setup using the provided data file source strategy */ public static void run(DataFileSource fileSource) { unpackData(fileSource); setupGdalDataConfig(fileSource); registerGdalDrivers(); } /** * Return the File object of the extracted data file with the given name, or <code>null</code> * if no such file exists. * * @param name The name of the file to retrieve * * @return The named GDAL data file */ public static File getDataFile(String name) { return extractedDataMap.get(name); } /** * Unpack the GDAL_DATA folder into the plugin data area */ private static void unpackData(DataFileSource fileSource) { try { InputStream is = null; try { is = GDALDataSetup.class.getResourceAsStream(GDALDATA_ZIP); ZipInputStream zis = new ZipInputStream(is); ZipEntry entry = zis.getNextEntry(); while (entry != null) { if (!entry.isDirectory()) { String name = entry.getName(); File output = fileSource.getDataFile(name); extractedDataMap.put(name, output); if (output.length() > 0) { // File already exists - move on to the next one entry = zis.getNextEntry(); continue; } writeStreamToFile(zis, output); } zis.closeEntry(); entry = zis.getNextEntry(); } } finally { if (is != null) { is.close(); } } } catch (IOException e) { // Catch exceptions occurring while closing the stream etc. } } /** * Setup the GDAL_DATA configuration setting to point to the data area for * the plugin */ private static void setupGdalDataConfig(DataFileSource fileSource) { gdal.SetConfigOption(GDALDATA_CONFIG, fileSource.getDataFolder().getAbsolutePath()); } /** * Register required GDAL drivers and OGR transforms etc. */ private static void registerGdalDrivers() { gdal.AllRegister(); ogr.RegisterAll(); } /** * Write the contents of the input stream to the given file, overwriting any * contents that already exist. * * @param is * The input stream to read from * @param file * The file to write to */ private static void writeStreamToFile(InputStream is, File file) { byte[] buffer = new byte[512]; BufferedOutputStream out = null; try { try { out = new BufferedOutputStream(new FileOutputStream(file)); while (true) { int read = is.read(buffer); if (read < 0) { break; } out.write(buffer, 0, read); } } finally { if (out != null) { out.close(); } } } catch (IOException e) { } } }