001: /*
002: * GeoTools - OpenSource mapping toolkit
003: * http://geotools.org
004: * (C) 2002-2006, GeoTools Project Managment Committee (PMC)
005: *
006: * This library is free software; you can redistribute it and/or
007: * modify it under the terms of the GNU Lesser General Public
008: * License as published by the Free Software Foundation;
009: * version 2.1 of the License.
010: *
011: * This library is distributed in the hope that it will be useful,
012: * but WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: * Lesser General Public License for more details.
015: */
016: package org.geotools.data.mysql;
017:
018: import java.io.IOException;
019: import java.util.Collections;
020: import java.util.Map;
021: import java.util.logging.Logger;
022:
023: import javax.sql.DataSource;
024:
025: import org.geotools.data.AbstractDataStoreFactory;
026: import org.geotools.data.DataSourceException;
027: import org.geotools.data.DataStore;
028: import org.geotools.data.jdbc.datasource.DataSourceUtil;
029: import org.geotools.data.jdbc.datasource.ManageableDataSource;
030:
031: /**
032: * Creates a MySQLDataStoreFactory based on the correct params.
033: *
034: * <p>
035: * This factory should be registered in the META-INF/ folder, under services/
036: * in the DataStoreFactorySpi file.
037: * </p>
038: *
039: * @author Andrea Aime, University of Modena and Reggio Emilia
040: * @source $URL: http://svn.geotools.org/geotools/tags/2.4.1/modules/unsupported/mysql/src/main/java/org/geotools/data/mysql/MySQLDataStoreFactory.java $
041: */
042: public class MySQLDataStoreFactory extends AbstractDataStoreFactory {
043:
044: private static final Logger LOGGER = org.geotools.util.logging.Logging
045: .getLogger(MySQLDataStoreFactory.class.getName());
046:
047: /** Creates MySQL JDBC driver class. */
048: private static final String DRIVER_CLASS = "com.mysql.jdbc.Driver";
049:
050: /** Param, package visibiity for JUnit tests */
051: static final Param DBTYPE = new Param("dbtype", String.class,
052: "must be 'mysql'", true, "mysql");
053:
054: /** Param, package visibiity for JUnit tests */
055: static final Param HOST = new Param("host", String.class,
056: "mysql host machine", true, "localhost");
057:
058: /** Param, package visibiity for JUnit tests */
059: static final Param PORT = new Param("port", Integer.class,
060: "mysql connection port", false, "3306");
061:
062: /** Param, package visibiity for JUnit tests */
063: static final Param DATABASE = new Param("database", String.class,
064: "msyql database");
065:
066: /** Param, package visibiity for JUnit tests */
067: static final Param USER = new Param("user", String.class,
068: "user name to login as", false);
069:
070: /** Param, package visibiity for JUnit tests */
071: static final Param PASSWD = new Param("passwd", String.class,
072: "password used to login", false);
073:
074: static final Param MAXCONN = new Param("max connections",
075: Integer.class, "maximum number of open connections", false,
076: new Integer(10));
077:
078: static final Param MINCONN = new Param("min connections",
079: Integer.class, "minimum number of pooled connection",
080: false, new Integer(4));
081:
082: static final Param VALIDATECONN = new Param("validate connections",
083: Boolean.class, "check connection is alive before using it",
084: false, Boolean.FALSE);
085:
086: /** Param, package visibiity for JUnit tests */
087: static final Param NAMESPACE = new Param("namespace", String.class,
088: "namespace prefix used", false);
089:
090: public static final Param WKBENABLED = new Param("wkb enabled",
091: Boolean.class,
092: "set to true if Well Known Binary should be used to read PostGIS "
093: + "data (experimental)", false, new Boolean(true));
094:
095: /** Array with all of the params */
096: static final Param[] arrayParameters = { DBTYPE, HOST, PORT,
097: DATABASE, USER, PASSWD, NAMESPACE, WKBENABLED };
098:
099: /**
100: * Creates a new instance of PostgisDataStoreFactory
101: */
102: public MySQLDataStoreFactory() {
103: }
104:
105: /**
106: * Checks to see if all the postgis params are there.
107: *
108: * <p>
109: * Should have:
110: * </p>
111: *
112: * <ul>
113: * <li>
114: * dbtype: equal to postgis
115: * </li>
116: * <li>
117: * host
118: * </li>
119: * <li>
120: * user
121: * </li>
122: * <li>
123: * passwd
124: * </li>
125: * <li>
126: * database
127: * </li>
128: * </ul>
129: *
130: *
131: * @param params Set of parameters needed for a postgis data store.
132: *
133: * @return <code>true</code> if dbtype equals postgis, and contains keys
134: * for host, user, passwd, and database.
135: */
136: public boolean canProcess(Map params) {
137: if (!super .canProcess(params))
138: return false;
139:
140: return ((String) params.get("dbtype"))
141: .equalsIgnoreCase("mysql");
142: }
143:
144: /**
145: * Construct a postgis data store using the params.
146: *
147: * @param params The full set of information needed to construct a live
148: * data source. Should have dbtype equal to postgis, as well as
149: * host, user, passwd, database, and table.
150: *
151: * @return The created DataSource, this may be null if the required
152: * resource was not found or if insufficent parameters were given.
153: * Note that canProcess() should have returned false if the
154: * problem is to do with insuficent parameters.
155: *
156: * @throws IOException See DataSourceException
157: * @throws DataSourceException Thrown if there were any problems creating
158: * or connecting the datasource.
159: */
160: public DataStore createDataStore(Map params) throws IOException {
161: // lookup will throw nice exceptions back to the client code
162: String host = (String) HOST.lookUp(params);
163: String user = (String) USER.lookUp(params);
164: String passwd = (String) PASSWD.lookUp(params);
165: Integer maxConn = (Integer) MAXCONN.lookUp(params);
166: Integer minConn = (Integer) MINCONN.lookUp(params);
167: Boolean validateConn = (Boolean) VALIDATECONN.lookUp(params);
168: int port = ((Integer) PORT.lookUp(params)).intValue();
169: String database = (String) DATABASE.lookUp(params);
170: String namespace = (String) NAMESPACE.lookUp(params);
171: Boolean wkbEnabled = (Boolean) WKBENABLED.lookUp(params);
172:
173: if (!canProcess(params)) {
174: // Do this as a last sanity check.
175: LOGGER.warning("Can not process : " + params);
176: throw new IOException("The parameteres map isn't correct!!");
177: }
178:
179: boolean validate = validateConn != null
180: && validateConn.booleanValue();
181: int maxActive = maxConn != null ? maxConn.intValue() : 10;
182: int maxIdle = minConn != null ? minConn.intValue() : 4;
183: DataSource ds = getDefaultDataSource(host, user, passwd, port,
184: database, maxActive, maxIdle, validate);
185:
186: MySQLDataStore store;
187: if (namespace != null) {
188: store = new MySQLDataStore(ds, null, namespace);
189: } else {
190: store = new MySQLDataStore(ds);
191: }
192: if (wkbEnabled != null)
193: store.setWKBEnabled(wkbEnabled.booleanValue());
194: return store;
195: }
196:
197: public static ManageableDataSource getDefaultDataSource(
198: String host, String user, String passwd, int port,
199: String database, int maxActive, int minIdle,
200: boolean validate) throws DataSourceException {
201: // this one will have to wait for another iteration over the code
202: // String url = "jdbc:mysql://" + host + ":" + port + "/" + database + "?useCursorFetch=true&defaultFetchSize=100";
203: String url = "jdbc:mysql://" + host + ":" + port + "/"
204: + database;
205: String driver = "com.mysql.jdbc.Driver";
206: return DataSourceUtil.buildDefaultDataSource(url, driver, user,
207: passwd, maxActive, minIdle,
208: validate ? "select version()" : null, false, 0);
209: }
210:
211: /**
212: * Postgis cannot create a new database.
213: *
214: * @param params
215: *
216: *
217: * @throws IOException See UnsupportedOperationException
218: * @throws UnsupportedOperationException Cannot create new database
219: */
220: public DataStore createNewDataStore(Map params) throws IOException {
221: throw new UnsupportedOperationException(
222: "MySQL cannot create a new Database");
223: }
224:
225: /**
226: * @return "MySQL"
227: */
228: public String getDisplayName() {
229: return "MySQL";
230: }
231:
232: /**
233: * Describe the nature of the datasource constructed by this factory.
234: *
235: * @return A human readable description that is suitable for inclusion in a
236: * list of available datasources. Currently uses the string "MySQL Database"
237: */
238: public String getDescription() {
239: return "MySQL Database";
240: }
241:
242: // /**
243: // *
244: // */
245: // public DataSourceMetadataEnity createMetadata( Map params ) throws IOException {
246: // String host = (String) HOST.lookUp(params);
247: // String user = (String) USER.lookUp(params);
248: // String port = (String) PORT.lookUp(params);
249: // String database = (String) DATABASE.lookUp(params);
250: // return new DataSourceMetadataEnity( host+"port", database, "MySQL connection to "+host+" as "+user );
251: // }
252:
253: /**
254: * Test to see if this datastore is available, if it has all the
255: * appropriate libraries to construct a datastore. This datastore just
256: * returns true for now. This method is used for gui apps, so as to not
257: * advertise data store capabilities they don't actually have.
258: *
259: * @return <tt>true</tt> if and only if this factory is available to create
260: * DataStores.
261: */
262: public boolean isAvailable() {
263: try {
264: Class.forName(DRIVER_CLASS);
265: } catch (ClassNotFoundException cnfe) {
266: LOGGER.warning("MySQL data sources are not available: "
267: + cnfe.getMessage());
268: return false;
269: }
270: return true;
271: }
272:
273: /**
274: * Describe parameters.
275: *
276: *
277: * @see org.geotools.data.DataStoreFactorySpi#getParametersInfo()
278: */
279: public Param[] getParametersInfo() {
280: return new Param[] { DBTYPE, HOST, PORT, DATABASE, USER,
281: PASSWD, MAXCONN, MINCONN, VALIDATECONN, NAMESPACE,
282: WKBENABLED };
283: }
284:
285: /**
286: * Returns the implementation hints. The default implementation returns en empty map.
287: */
288: public Map getImplementationHints() {
289: return Collections.EMPTY_MAP;
290: }
291: }
|