/* * 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.mysql; import java.io.IOException; import java.util.Collections; import java.util.Map; import java.util.logging.Logger; import javax.sql.DataSource; import org.geotools.data.AbstractDataStoreFactory; import org.geotools.data.DataSourceException; import org.geotools.data.DataStore; import org.geotools.data.jdbc.datasource.DataSourceUtil; import org.geotools.data.jdbc.datasource.ManageableDataSource; /** * Creates a MySQLDataStoreFactory based on the correct params. * * <p> * This factory should be registered in the META-INF/ folder, under services/ * in the DataStoreFactorySpi file. * </p> * * @author Andrea Aime, University of Modena and Reggio Emilia * * @source $URL$ */ public class MySQLDataStoreFactory extends AbstractDataStoreFactory { private static final Logger LOGGER = org.geotools.util.logging.Logging.getLogger(MySQLDataStoreFactory.class.getName()); /** Creates MySQL JDBC driver class. */ private static final String DRIVER_CLASS = "com.mysql.jdbc.Driver"; /** Param, package visibiity for JUnit tests */ public static final Param DBTYPE = new Param("dbtype", String.class, "must be 'mysql'", true, "mysql"); /** Param, package visibiity for JUnit tests */ public static final Param HOST = new Param("host", String.class, "mysql host machine", true, "localhost"); /** Param, package visibiity for JUnit tests */ public static final Param PORT = new Param("port", Integer.class, "mysql connection port", false, "3306"); /** Param, package visibiity for JUnit tests */ public static final Param DATABASE = new Param("database", String.class, "msyql database"); /** Param, package visibiity for JUnit tests */ public static final Param USER = new Param("user", String.class, "user name to login as", false); /** Param, package visibiity for JUnit tests */ public static final Param PASSWD = new Param("passwd", String.class, "password used to login", false); public static final Param MAXCONN = new Param("max connections", Integer.class, "maximum number of open connections", false, new Integer(10)); public static final Param MINCONN = new Param("min connections", Integer.class, "minimum number of pooled connection", false, new Integer(4)); public static final Param VALIDATECONN = new Param("validate connections", Boolean.class, "check connection is alive before using it", false, Boolean.FALSE); /** Param, package visibiity for JUnit tests */ public static final Param NAMESPACE = new Param("namespace", String.class, "namespace prefix used", false); public static final Param WKBENABLED = new Param("wkb enabled", Boolean.class, "set to true if Well Known Binary should be used to read MySQL" + "data (experimental)", false, new Boolean(true)); /** Array with all of the params */ static final Param[] arrayParameters = { DBTYPE, HOST, PORT, DATABASE, USER, PASSWD, NAMESPACE, WKBENABLED }; /** * Creates a new instance of MysqlDataStoreFactory */ public MySQLDataStoreFactory() { } /** * Checks to see if all the mysql params are there. * * <p> * Should have: * </p> * * <ul> * <li> * dbtype: equal to mysql * </li> * <li> * host * </li> * <li> * user * </li> * <li> * passwd * </li> * <li> * database * </li> * </ul> * * * @param params Set of parameters needed for a mysql data store. * * @return <code>true</code> if dbtype equals mysql, and contains keys * for host, user, passwd, and database. */ public boolean canProcess(Map params) { if (!super.canProcess(params)) { return false; } return ((String) params.get("dbtype")).equalsIgnoreCase("mysql"); } /** * Construct a mysql data store using the params. * * @param params The full set of information needed to construct a live * data source. Should have dbtype equal to mysql, as well as * host, user, passwd, database, and table. * * @return The created DataSource, this may be null if the required * resource was not found or if insufficent parameters were given. * Note that canProcess() should have returned false if the * problem is to do with insuficent parameters. * * @throws IOException See DataSourceException * @throws DataSourceException Thrown if there were any problems creating * or connecting the datasource. */ public DataStore createDataStore(Map params) throws IOException { // lookup will throw nice exceptions back to the client code String host = (String) HOST.lookUp(params); String user = (String) USER.lookUp(params); String passwd = (String) PASSWD.lookUp(params); Integer maxConn = (Integer) MAXCONN.lookUp(params); Integer minConn = (Integer) MINCONN.lookUp(params); Boolean validateConn = (Boolean) VALIDATECONN.lookUp(params); int port = ((Integer) PORT.lookUp(params)).intValue(); String database = (String) DATABASE.lookUp(params); String namespace = (String) NAMESPACE.lookUp(params); Boolean wkbEnabled = (Boolean) WKBENABLED.lookUp(params); if (!canProcess(params)) { // Do this as a last sanity check. LOGGER.warning("Can not process : " + params); throw new IOException("The parameteres map isn't correct!!"); } boolean validate = (validateConn != null) && validateConn.booleanValue(); int maxActive = (maxConn != null) ? maxConn.intValue() : 10; int maxIdle = (minConn != null) ? minConn.intValue() : 4; DataSource ds = getDefaultDataSource(host, user, passwd, port, database, maxActive, maxIdle, validate); MySQLDataStore store; if (namespace != null) { store = new MySQLDataStore(ds, null, namespace); } else { store =new MySQLDataStore(ds); } if(wkbEnabled != null) store.setWKBEnabled(wkbEnabled.booleanValue()); return store; } public static ManageableDataSource getDefaultDataSource(String host, String user, String passwd, int port, String database, int maxActive, int minIdle, boolean validate) throws DataSourceException { // this one will have to wait for another iteration over the code // String url = "jdbc:mysql://" + host + ":" + port + "/" + database + "?useCursorFetch=true&defaultFetchSize=100"; String url = "jdbc:mysql://" + host + ":" + port + "/" + database; String driver = "com.mysql.jdbc.Driver"; return DataSourceUtil.buildDefaultDataSource(url, driver, user, passwd, maxActive, minIdle, validate ? "select version()" : null, false, 0); } /** * Mysql cannot create a new database. * * @param params * * * @throws IOException See UnsupportedOperationException * @throws UnsupportedOperationException Cannot create new database */ public DataStore createNewDataStore(Map params) throws IOException { throw new UnsupportedOperationException("MySQL cannot create a new Database"); } /** * @return "MySQL" */ public String getDisplayName() { return "MySQL"; } /** * Describe the nature of the datasource constructed by this factory. * * @return A human readable description that is suitable for inclusion in a * list of available datasources. Currently uses the string "MySQL Database" */ public String getDescription() { return "MySQL Database"; } // /** // * // */ // public DataSourceMetadataEnity createMetadata( Map params ) throws IOException { // String host = (String) HOST.lookUp(params); // String user = (String) USER.lookUp(params); // String port = (String) PORT.lookUp(params); // String database = (String) DATABASE.lookUp(params); // return new DataSourceMetadataEnity( host+"port", database, "MySQL connection to "+host+" as "+user ); // } /** * 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. This method is used for gui apps, so as to not * advertise data store capabilities they don't actually have. * * @return <tt>true</tt> if and only if this factory is available to create * DataStores. */ public boolean isAvailable() { try { Class.forName(DRIVER_CLASS); } catch (ClassNotFoundException cnfe) { LOGGER.warning("MySQL data sources are not available: " + cnfe.getMessage()); return false; } return true; } /** * Describe parameters. * * * @see org.geotools.data.DataStoreFactorySpi#getParametersInfo() */ public Param[] getParametersInfo() { return new Param[] { DBTYPE, HOST, PORT, DATABASE, USER, PASSWD, MAXCONN, MINCONN, VALIDATECONN, NAMESPACE }; } /** * Returns the implementation hints. The default implementation returns en empty map. */ public Map getImplementationHints() { return Collections.EMPTY_MAP; } }