Package org.geotools.data.postgis

Source Code of org.geotools.data.postgis.PostgisNGDataStoreFactory

/*
*    GeoTools - The Open Source Java GIS Toolkit
*    http://geotools.org
*
*    (C) 2002-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.postgis;

import static org.geotools.data.postgis.PostgisNGDataStoreFactory.SIMPLIFY;

import java.io.IOException;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Map;

import javax.sql.DataSource;

import org.geotools.jdbc.JDBCDataStore;
import org.geotools.jdbc.JDBCDataStoreFactory;
import org.geotools.jdbc.SQLDialect;
import org.geotools.util.KVP;

/**
*
*
* @source $URL$
*/
public class PostgisNGDataStoreFactory extends JDBCDataStoreFactory {
   
    /** parameter for database type */
    public static final Param DBTYPE = new Param("dbtype", String.class, "Type", true, "postgis");
   
    /** enables using && in bbox queries */
    public static final Param LOOSEBBOX = new Param("Loose bbox", Boolean.class, "Perform only primary filter on bbox", false, Boolean.TRUE);
   
    /** parameter that enables estimated extends instead of exact ones */
    public static final Param ESTIMATED_EXTENTS = new Param("Estimated extends", Boolean.class, "Use the spatial index information to quickly get an estimate of the data bounds", false, Boolean.TRUE);
   
    /** parameter for database port */
    public static final Param PORT = new Param("port", Integer.class, "Port", true, 5432);
   
    /** parameter for database schema */
    public static final Param SCHEMA = new Param("schema", String.class, "Schema", false, "public");
   
    /** attempt to create the database if missing */
    public static final Param CREATE_DB_IF_MISSING = new Param("create database", Boolean.class,
            "Creates the database if it does not exist yet", false, false, Param.LEVEL, "advanced");
   
    /** attempt to create the database if missing */
    public static final Param CREATE_PARAMS = new Param("create database params", String.class,
            "Extra specifications appeneded to the CREATE DATABASE command", false, "", Param.LEVEL, "advanced");

    /**
     * Wheter a prepared statements based dialect should be used, or not
     */
    public static final Param PREPARED_STATEMENTS = new Param("preparedStatements", Boolean.class, "Use prepared statements", false, Boolean.FALSE);
   
    /**
     * Enables direct encoding of selected filter functions in sql
     */
    public static final Param ENCODE_FUNCTIONS = new Param( "encode functions", Boolean.class,
            "set to true to have a set of filter functions be translated directly in SQL. " +
            "Due to differences in the type systems the result might not be the same as evaluating " +
            "them in memory, including the SQL failing with errors while the in memory version works fine. " +
            "However this allows to push more of the filter into the database, increasing performance." +
            "the postgis table.", false, new Boolean(false),
            new KVP( Param.LEVEL, "advanced"));
   
    /**
     * Enables usage of ST_Simplify when the queries contain geometry simplification hints
     */
    public static final Param SIMPLIFY = new Param("Support on the fly geometry simplification", Boolean.class,
            "When enabled, operations such as map rendering will pass a hint that will enable the usage of ST_Simplify", false, Boolean.TRUE);
   
   
    @Override
    protected SQLDialect createSQLDialect(JDBCDataStore dataStore) {
        return new PostGISDialect(dataStore);
    }

    @Override
    protected String getDatabaseID() {
        return (String) DBTYPE.sample;
    }
   
    @Override
    public String getDisplayName() {
        return "PostGIS";
    }

    public String getDescription() {
        return "PostGIS Database";
    }
   
    @Override
    protected String getDriverClassName() {
        return "org.postgresql.Driver";
    }
   
    @Override
    protected boolean checkDBType(Map params) {
        if (super.checkDBType(params)) {
          //check for old factory
            try {
                Class.forName("org.geotools.data.postgis.PostgisDataStoreFactory");
               
                //old factory is around, let it handle the connection
                return false;
            }
            catch(ClassNotFoundException e) {
                //old factory is not around, handle this connection
                return true;
            }
        }
        else {
            //check for postgisng as well
            return checkDBType(params, "postgisng");
        }
    }
   
    protected JDBCDataStore createDataStoreInternal(JDBCDataStore dataStore, Map params)
        throws IOException {
       
        // setup loose bbox
        PostGISDialect dialect = (PostGISDialect) dataStore.getSQLDialect();
        Boolean loose = (Boolean) LOOSEBBOX.lookUp(params);
        dialect.setLooseBBOXEnabled(loose == null || Boolean.TRUE.equals(loose));
       
        // check the estimated extents
        Boolean estimated = (Boolean) ESTIMATED_EXTENTS.lookUp(params);
        dialect.setEstimatedExtentsEnabled(estimated == null || Boolean.TRUE.equals(estimated));
       
        // check if we can encode functions in sql
        Boolean encodeFunctions = (Boolean) ENCODE_FUNCTIONS.lookUp(params);
        dialect.setFunctionEncodingEnabled(encodeFunctions != null && encodeFunctions);
       
        // setup the ps dialect if need be
        Boolean usePs = (Boolean) PREPARED_STATEMENTS.lookUp(params);
        if(Boolean.TRUE.equals(usePs)) {
            dataStore.setSQLDialect(new PostGISPSDialect(dataStore, dialect));
        }
       
        // check geometry simplification (on by default)
        Boolean simplify = (Boolean) SIMPLIFY.lookUp(params);
        dialect.setSimplifyEnabled(simplify == null || simplify);

        return dataStore;
    }
   
    @Override
    protected void setupParameters(Map parameters) {
        // NOTE: when adding parameters here remember to add them to PostgisNGJNDIDataStoreFactory
       
        super.setupParameters(parameters);
        parameters.put(DBTYPE.key, DBTYPE);
        parameters.put(SCHEMA.key, SCHEMA);
        parameters.put(LOOSEBBOX.key, LOOSEBBOX);
        parameters.put(ESTIMATED_EXTENTS.key, ESTIMATED_EXTENTS);
        parameters.put(PORT.key, PORT);
        parameters.put(PREPARED_STATEMENTS.key, PREPARED_STATEMENTS);
        parameters.put(MAX_OPEN_PREPARED_STATEMENTS.key, MAX_OPEN_PREPARED_STATEMENTS);
        parameters.put(ENCODE_FUNCTIONS.key, ENCODE_FUNCTIONS);
        parameters.put(SIMPLIFY.key, SIMPLIFY);
        parameters.put(CREATE_DB_IF_MISSING.key, CREATE_DB_IF_MISSING);
        parameters.put(CREATE_PARAMS.key, CREATE_PARAMS);
    }
   
    @Override
    protected String getValidationQuery() {
        return "select now()";
    }
   
    @Override
    protected String getJDBCUrl(Map params) throws IOException {
        String host = (String) HOST.lookUp(params);
        String db = (String) DATABASE.lookUp(params);
        int port = (Integer) PORT.lookUp(params);
        return "jdbc:postgresql" + "://" + host + ":" + port + "/" + db;
    }
   
    protected DataSource createDataSource(Map params, SQLDialect dialect) throws IOException {
        DataSource ds = super.createDataSource(params, dialect);
        JDBCDataStore closer = new JDBCDataStore();

        if (Boolean.TRUE.equals(CREATE_DB_IF_MISSING.lookUp(params))) {
            // verify we can connect
            Connection cx = null;
            boolean canConnect = true;
            try {
                cx = ds.getConnection();
            } catch (SQLException e) {
                canConnect = false;
            } finally {
                closer.closeSafe(cx);
            }

            if (!canConnect) {
                // get the connection params
                String host = (String) HOST.lookUp(params);
                int port = (Integer) PORT.lookUp(params);
                String db = (String) DATABASE.lookUp(params);
                String user = (String) USER.lookUp(params);
                String password = (String) PASSWD.lookUp(params);

                Statement st = null;
                try {
                    // connect to template1 instead
                    String url = "jdbc:postgresql" + "://" + host + ":" + port + "/template1";
                    cx = getConnection(user, password, url);

                    // create the database

                    String createParams = (String) CREATE_PARAMS.lookUp(params);
                    String sql = "CREATE DATABASE \"" + db + "\" " + (createParams == null ? "" : createParams);
                    st = cx.createStatement();
                    st.execute(sql);
                } catch (SQLException e) {
                    throw new IOException("Failed to create the target database", e);
                } finally {
                    closer.closeSafe(st);
                    closer.closeSafe(cx);
                }

                // if we got here the database has been created, now verify it has the postgis
                // extensions
                // and eventually try to create them
                ResultSet rs = null;
                try {
                    String url = "jdbc:postgresql" + "://" + host + ":" + port + "/" + db;
                    cx = DriverManager.getConnection(url, user, password);

                    // check we have postgis
                    st = cx.createStatement();
                    try {
                        rs = st.executeQuery("select PostGIS_version()");
                        rs.close();
                    } catch (SQLException e) {
                        // not available eh? create it
                        st.execute("create extension postgis");
                    }
                } catch (SQLException e) {
                    throw new IOException("Failed to create the target database", e);
                } finally {
                    closer.closeSafe(st);
                    closer.closeSafe(cx);
                }

                // and finally re-create the connection pool
                ds = super.createDataSource(params, dialect);
            }
        }

        return ds;
    }

    private Connection getConnection(String user, String password, String url) throws SQLException {
        Connection cx;
        if(user != null) {
            cx = DriverManager.getConnection(url, user, password);
        } else {
            cx = DriverManager.getConnection(url);
        }
        return cx;
    }

    /**
     * Drops the database specified in the connection params. The database must not be in use, and
     * the user must have the necessary privileges
     * @param params
     * @throws IOException
     */
    public void dropDatabase(Map<String, Object> params) throws IOException {
        JDBCDataStore closer = new JDBCDataStore();
        // get the connection params
        String host = (String) HOST.lookUp(params);
        int port = (Integer) PORT.lookUp(params);
        String db = (String) DATABASE.lookUp(params);
        String user = (String) USER.lookUp(params);
        String password = (String) PASSWD.lookUp(params);

        Connection cx = null;
        Statement st = null;
        try {
            // connect to template1 instead
            String url = "jdbc:postgresql" + "://" + host + ":" + port + "/template1";
            cx = getConnection(user, password, url);

            // drop the database
            String sql = "DROP DATABASE \"" + db + "\"";
            st = cx.createStatement();
            st.execute(sql);
        } catch (SQLException e) {
            throw new IOException("Failed to drop the target database", e);
        } finally {
            closer.closeSafe(st);
            closer.closeSafe(cx);
        }

    }


}
TOP

Related Classes of org.geotools.data.postgis.PostgisNGDataStoreFactory

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.