/* * Copyright (c) 2015 Data Harmonisation Panel * * All rights reserved. This program and the accompanying materials are made * available under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation, either version 3 of the License, * or (at your option) any later version. * * You should have received a copy of the GNU Lesser General Public License * along with this distribution. If not, see <http://www.gnu.org/licenses/>. * * Contributors: * Data Harmonisation Panel <http://www.dhpanel.eu> */ package eu.esdihumboldt.hale.io.jdbc.spatialite.internal; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import org.sqlite.SQLiteConnection; import com.google.common.cache.Cache; import com.google.common.cache.CacheBuilder; import de.fhg.igd.slf4jplus.ALogger; import de.fhg.igd.slf4jplus.ALoggerFactory; /** * Helper for SpatiaLite. * * @author Simon Templer */ public class SpatiaLiteHelper { private static final ALogger log = ALoggerFactory.getLogger(SpatiaLiteHelper.class); /** * Determine if the SpatiaLite module is loaded. * * @param connection the database connection * @return <code>true</code> if the SpatiaLite module is loaded, * <code>false</code> if it is not or the status cannot be * determined */ private static boolean isSpatiaLiteLoaded(SQLiteConnection connection) { PreparedStatement statement = null; try { statement = connection.prepareStatement("SELECT spatialite_version();"); } catch (SQLException e1) { // function not available return false; } try { ResultSet result = statement.executeQuery(); if (result.next()) { @SuppressWarnings("unused") String spatiaLiteVersion = result.getString(1); return true; } else { return false; } } catch (SQLException e) { return false; } finally { try { statement.close(); } catch (SQLException e) { // ignore } } } private static final Cache<SQLiteConnection, Boolean> loadedCache = CacheBuilder.newBuilder() .weakKeys().build(); /** * Determine if SpatiaLite is loaded for the given connection. If not, * reports to the user about the misconfiguration. A report is done only * once per unique connection. * * @param connection the database connection * @param error if the report should be an error, otherwise it is a warning * @return <code>true</code> if the SpatiaLite module is loaded, * <code>false</code> if it is not or the status cannot be * determined */ public static boolean isSpatialLiteLoadedReport(final SQLiteConnection connection, boolean error) { try { Boolean result = loadedCache.getIfPresent(connection); if (result != null) { return result; } result = loadedCache.get(connection, new Callable<Boolean>() { @Override public Boolean call() throws Exception { return isSpatiaLiteLoaded(connection); } }); if (!result) { String msg = "The SpatiaLite extension for SQLite (mod_spatialite) could not be loaded. " + "This means that it is not possible to properly load or store geometries from/to SQLite.\n\n" + "Please check the HALE help on how to make it available:\n" + "HALE User Guide > Reference > Supported formats > Import > SQLite and SpatiaLite"; if (error) { log.userError(msg); } else { log.userWarn(msg); } } return result; } catch (ExecutionException e) { log.error("Error determining if SpatiaLite is loaded", e); // state that it is not loaded return false; } } }