/* * GeoTools - The Open Source Java GIS Toolkit * http://geotools.org * * (C) 2007-2008, Open Source Geospatial Foundation (OSGeo) * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License. * * This library 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 * Lesser General Public License for more details. */ package org.geotools.data.ogr; import static org.bridj.Pointer.*; import static org.geotools.data.ogr.bridj.OgrLibrary.*; import static org.geotools.data.ogr.OGRUtils.*; import java.io.IOException; import java.net.MalformedURLException; import java.net.URI; import java.net.URL; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; import org.bridj.Pointer; import org.geotools.data.DataSourceException; import org.geotools.data.DataStore; import org.geotools.data.DataStoreFactorySpi; /** * Implementation of the DataStore service provider interface for OGR. * * @author Andrea Aime, GeoSolution * * * * @source $URL$ * @version $Id$ */ @SuppressWarnings("rawtypes") public class OGRDataStoreFactory implements DataStoreFactorySpi { public static final Param OGR_NAME = new Param("DatasourceName", String.class, "Name of the file, or data source to try and open", true); public static final Param OGR_DRIVER_NAME = new Param( "DriverName", String.class, "Name of the OGR driver to be used. Required to create a new data source, optional when opening an existing one", false); public static final Param NAMESPACEP = new Param("namespace", URI.class, "uri to a the namespace", false); // not required static { GdalInit.init(); // perform OGR format registration once if (OGRGetDriverCount() == 0) { OGRRegisterAll(); } } /** * Caches opened data stores. TODO: is this beneficial or problematic? It's a static cache, so * opening a lot of datastore (thousands, hundreds of thousands...) may become a memory problem. * Plus OGR is not designed to be thread safe. */ private Map liveStores = new HashMap(); public boolean canProcess(Map params) { boolean accept = false; String ogrName = null; String ogrDriver = null; try { ogrName = (String) OGR_NAME.lookUp(params); } catch (IOException ioe) { // yes, I am eating this } try { ogrDriver = (String) OGR_DRIVER_NAME.lookUp(params); } catch (IOException ioe) { // yes, I am eating this } accept = canProcess(ogrName, ogrDriver); return accept; } public DataStore createDataStore(Map params) throws IOException { DataStore ds = null; if (!liveStores.containsKey(params)) { URL url = null; try { ds = createNewDataStore(params); liveStores.put(params, ds); } catch (MalformedURLException mue) { throw new DataSourceException("Unable to attatch datastore to " + url, mue); } } else ds = (DataStore) liveStores.get(params); return ds; } /** * Not implemented yet. * * @param params * * @throws IOException * * @throws IOException DOCUMENT ME! * @throws UnsupportedOperationException */ public DataStore createNewDataStore(Map params) throws IOException { DataStore ds = null; String ogrName = (String) OGR_NAME.lookUp(params); String ogrDriver = (String) OGR_DRIVER_NAME.lookUp(params); URI namespace = (URI) NAMESPACEP.lookUp(params); ds = new OGRDataStore(ogrName, ogrDriver, namespace); return ds; } public String getDisplayName() { return "OGR"; } /** * Describes the type of data the datastore returned by this factory works with. * * @return String a human readable description of the type of restore supported by this * datastore. */ public String getDescription() { return "Uses OGR as a data source"; } /** * Test to see if this datastore is available, if it has all the appropriate libraries to * construct a datastore. This datastore just returns true for now. * * @return <tt>true</tt> if and only if this factory is available to create DataStores. * * @task REVISIT: I'm just adding this method to compile, maintainer should revisit to check for * any libraries that may be necessary for datastore creations. */ public boolean isAvailable() { try { return OGRGetDriverCount() > 0; } catch (Throwable t) { return false; } } /** * Describe parameters. * * * @see org.geotools.data.DataStoreFactorySpi#getParametersInfo() */ public Param[] getParametersInfo() { return new Param[] { OGR_NAME, OGR_DRIVER_NAME, NAMESPACEP }; } /** * Assume we can process an ogrName if the ogrName exists and can be opened, or if the specified * driver does exist. * * @param ogrName * @param driverName * @return */ public boolean canProcess(String ogrName, String driverName) { Pointer dataset = OGROpenShared(pointerToCString(ogrName), 0, null); if (dataset != null) { OGRReleaseDataSource(dataset); return true; } Pointer driver = OGRGetDriverByName(pointerToCString(driverName)); if (driver != null) { return true; } return false; } public static Set<String> getAvailableDrivers() { int count = OGRGetDriverCount(); Set<String> result = new HashSet<String>(); for (int i = 0; i < count; i++) { Pointer driver = OGRGetDriver(i); String name = getCString(OGR_Dr_GetName(driver)); result.add(name); } return result; } public Map getImplementationHints() { return Collections.EMPTY_MAP; } }