001: /*
002: * Geotools2 - OpenSource mapping toolkit
003: * http://geotools.org
004: * (C) 2002, 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: */
017: package org.geotools.data.geometryless;
018:
019: import java.io.IOException;
020: import java.nio.charset.Charset;
021: import java.sql.SQLException;
022: import java.util.Map;
023: import java.util.logging.Logger;
024:
025: import org.geotools.data.DataSourceException;
026: import org.geotools.data.DataStore;
027: import javax.sql.DataSource; // import org.geotools.data.jdbc.ConnectionPool;
028: import org.geotools.data.jdbc.datasource.DataSourceUtil;
029: import org.geotools.data.jdbc.datasource.ManageableDataSource;
030: import org.geotools.data.sql.ViewRegisteringFactoryHelper;
031: import org.geotools.factory.AbstractFactory;
032:
033: /**
034: * Creates a Geometryless JDBC based on the conection params.
035: *
036: * <p>
037: * This factory should be registered in the META-INF/ folder, under services/
038: * in the DataStoreFactorySpi file.
039: * </p>
040: *
041: * @author Rob Atkinson, Social Change Online
042: * @source $URL: http://svn.geotools.org/geotools/tags/2.4.1/modules/unsupported/geometryless/src/main/java/org/geotools/data/geometryless/JDBCDataStoreFactory.java $
043: */
044: public class JDBCDataStoreFactory extends AbstractFactory implements
045: org.geotools.data.DataStoreFactorySpi {
046:
047: private static final Logger LOGGER = org.geotools.util.logging.Logging
048: .getLogger("org.geotools.data.geometryless");
049:
050: /** Specified JDBC driver class. */
051: static final Param DRIVER = new Param("driver", String.class,
052: "Java Class name of installed ConnectionPool driver", true,
053: "org.geotools.data.geometryless.wrapper.PGConnectionPool");
054:
055: /** Specified JDBC driver class calling URL */
056: static final Param URLPREFIX = new Param("urlprefix", String.class,
057: "eg jdbc:mysql://", true,
058: "jdbc:postgresql://localhost:5432/postgres");
059:
060: /** Param, package visibiity for JUnit tests */
061: static final Param DBTYPE = new Param("dbtype", String.class,
062: "must be 'jdbc'", true, "jdbc");
063:
064: /** Param, package visibiity for JUnit tests */
065: static final Param USER = new Param("user", String.class,
066: "user name to login as", true, "");
067:
068: /** Param, package visibiity for JUnit tests */
069: static final Param PASSWD = new Param("passwd", String.class,
070: "password used to login", true, "");
071:
072: /**
073: * Param, package visibiity for JUnit tests.
074: *
075: * <p>
076: * Example of a non simple Param type where custom parse method is
077: * required.
078: * </p>
079: *
080: * <p>
081: * When we convert to BeanInfo custom PropertyEditors will be required for
082: * this Param.
083: * </p>
084: */
085: static final Param CHARSET = new Param("charset", Charset.class,
086: "character set", false, Charset.forName("ISO-8859-1")) {
087: public Object parse(String text) throws IOException {
088: return Charset.forName(text);
089: }
090:
091: public String text(Object value) {
092: return ((Charset) value).name();
093: }
094: };
095:
096: /** Param, package visibiity for JUnit tests */
097: static final Param NAMESPACE = new Param("namespace", String.class,
098: "namespace prefix used", false);
099:
100: /** Param, package visibiity for JUnit tests */
101: static final Param SCHEMA = new Param("schema", String.class,
102: "database schema", false);
103:
104: /** Array with all of the params */
105: static final Param[] arrayParameters = { DBTYPE, SCHEMA, USER,
106: PASSWD, CHARSET, NAMESPACE, DRIVER, URLPREFIX };
107:
108: /**
109: * Creates a new instance of - this constructor needed for factory finder apparently
110: */
111: public JDBCDataStoreFactory() {
112:
113: }
114:
115: /**
116: * Creates a new instance of PostgisDataStoreFactory
117: */
118: public JDBCDataStoreFactory(Map hints) {
119: if (hints != null)
120: this .hints.putAll(hints);
121: }
122:
123: /**
124: * Checks to see if all the postgis params are there.
125: *
126: * <p>
127: * Should have:
128: * </p>
129: *
130: * <ul>
131: * <li>
132: * dbtype: equal to postgis
133: * </li>
134: * <li>
135: * host
136: * </li>
137: * <li>
138: * user
139: * </li>
140: * <li>
141: * passwd
142: * </li>
143: * <li>
144: * database
145: * </li>
146: * <li>
147: * charset
148: * </li>
149: * </ul>
150: *
151: *
152: * @param params Set of parameters needed for a jdbc data store.
153: *
154: * @return <code>true</code> if dbtype equals jdbc, and contains keys
155: * for host, user, passwd, and database.
156: */
157: public boolean canProcess(Map params) {
158: Object value;
159:
160: if (params != null) {
161: for (int i = 0; i < arrayParameters.length; i++) {
162: if (!(((value = params.get(arrayParameters[i].key)) != null) && (arrayParameters[i].type
163: .isInstance(value)))) {
164: if (arrayParameters[i].required) {
165: LOGGER
166: .config("JDBCDataStoreFactory: canProcess() Cannot find param "
167: + arrayParameters[i].key
168: + ":"
169: + arrayParameters[i].type
170: + value);
171: return (false);
172: }
173: }
174: }
175: } else {
176: LOGGER
177: .finer("JDBCDataStoreFactory: can Process Cannot find params ");
178: return (false);
179: }
180:
181: if (!(((String) params.get("dbtype")).equalsIgnoreCase("jdbc"))) {
182: return (false);
183: } else {
184: return (true);
185: }
186: }
187:
188: /**
189: * Construct a postgis data store using the params.
190: *
191: * @param params The full set of information needed to construct a live
192: * data source. Should have dbtype equal to postgis, as well as
193: * host, user, passwd, database, and table.
194: *
195: * @return The created DataSource, this may be null if the required
196: * resource was not found or if insufficent parameters were given.
197: * Note that canProcess() should have returned false if the
198: * problem is to do with insuficent parameters.
199: *
200: * @throws IOException See DataSourceException
201: * @throws DataSourceException Thrown if there were any problems creating
202: * or connecting the datasource.
203: */
204: public DataStore createDataStore(Map params) throws IOException {
205: if (canProcess(params)) {
206: } else {
207: throw new IOException("The parameteres map isn't correct!!");
208: }
209:
210: // String host = (String) HOST.lookUp(params);
211: String user = (String) USER.lookUp(params);
212: String passwd = (String) PASSWD.lookUp(params);
213: // String port = (String) PORT.lookUp(params);
214: // String database = (String) DATABASE.lookUp(params);
215: Charset charSet = (Charset) CHARSET.lookUp(params);
216: String schema = (String) SCHEMA.lookUp(params);
217:
218: String namespace = (String) NAMESPACE.lookUp(params);
219: String driver = (String) DRIVER.lookUp(params);
220: String urlprefix = (String) URLPREFIX.lookUp(params);
221:
222: // Try processing params first so we can get an error message
223: // back to the user
224: //
225: if (!canProcess(params)) {
226: return null;
227: }
228: /*
229: *
230: * All this stuff replaced with the DataSource implementation
231: *
232: * which is basically exactly the same pattern here...
233: *
234: * JDBCConnectionFactory connFact = new JDBCConnectionFactory( urlprefix, driver );
235:
236: // MySQLConnectionFactory connFact = new MySQLConnectionFactory(host, Integer.parseInt(port), database);
237:
238: connFact.setLogin(user, passwd);
239:
240: if (charSet != null) {
241: connFact.setCharSet(charSet.name());
242: }
243:
244: ConnectionPool pool;
245:
246: try {
247: pool = connFact.getConnectionPool();
248:
249: java.sql.Connection c = pool.getConnection();
250: if( c == null )
251: {
252: throw new SQLException("Pool created but connection null ");
253: }
254: else {
255: c.close();
256: }
257: } catch (SQLException e) {
258: throw new DataSourceException("Could not create connection", e);
259: }
260: */
261:
262: DataSource dataSource = DataSourceUtil.buildDefaultDataSource(
263: urlprefix, driver, user, passwd, null);
264:
265: JDBCDataStore dataStore;
266: if (namespace != null) {
267: dataStore = new JDBCDataStore(dataSource, schema, namespace);
268: } else {
269: dataStore = new JDBCDataStore(dataSource);
270: }
271:
272: ViewRegisteringFactoryHelper
273: .registerSqlViews(dataStore, params);
274:
275: return dataStore;
276: }
277:
278: /**
279: * The datastore cannot create a new database.
280: *
281: * @param params
282: *
283: *
284: * @throws IOException See UnsupportedOperationException
285: * @throws UnsupportedOperationException Cannot create new database
286: */
287: public DataStore createNewDataStore(Map params) throws IOException {
288: throw new UnsupportedOperationException(
289: "Generic JDBC datastore cannot create a new Database");
290: }
291:
292: /**
293: * Describe the nature of the datasource constructed by this factory.
294: *
295: * @return A human readable description that is suitable for inclusion in a
296: * list of available datasources.
297: */
298: public String getDescription() {
299: return "Generic JDBC database";
300: }
301:
302: public String getDisplayName() {
303: return "GeometrylessJDBC - no geometry per feature";
304: }
305:
306: // public DataSourceMetadataEnity createMetadata( Map params ) throws IOException {
307: // String host = (String) HOST.lookUp(params);
308: // String user = (String) USER.lookUp(params);
309: // String port = (String) PORT.lookUp(params);
310: // String database = (String) DATABASE.lookUp(params);
311: // return new DataSourceMetadataEnity( host+":"+port, database, "Connection to "+getDisplayName()+" on "+host+" as "+user );
312: // }
313: /**
314: * Test to see if this datastore is available, if it has all the
315: * appropriate libraries to construct a datastore. This datastore just
316: * returns true for now. This method is used for gui apps, so as to not
317: * advertise data store capabilities they don't actually have.
318: *
319: * @return <tt>true</tt> if and only if this factory is available to create
320: * DataStores.
321: */
322: public boolean isAvailable() {
323: /* try {
324: Class.forName(DRIVER);
325: } catch (ClassNotFoundException cnfe) {
326: return false;
327: }
328: */
329: return true;
330: }
331:
332: /**
333: * Describe parameters.
334: *
335: *
336: * @see org.geotools.data.DataStoreFactorySpi#getParametersInfo()
337: */
338: public Param[] getParametersInfo() {
339: return new Param[] { DBTYPE, SCHEMA, USER, PASSWD, CHARSET,
340: NAMESPACE, DRIVER, URLPREFIX
341:
342: };
343: }
344: }
|