001: /*
002: * GeoTools - OpenSource mapping toolkit
003: * http://geotools.org
004: * (C) 2005-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.referencing.factory.epsg;
017:
018: // J2SE dependencies
019: import java.io.File;
020: import java.io.IOException;
021: import java.io.InputStream;
022: import java.io.FileInputStream;
023: import java.util.Properties;
024: import java.sql.Connection;
025: import java.sql.SQLException;
026: import javax.sql.DataSource;
027:
028: // Geotools dependencies
029: import org.geotools.util.logging.Logging;
030: import org.geotools.factory.Hints;
031: import org.geotools.referencing.factory.AbstractAuthorityFactory;
032:
033: // PostgreSQL dependencies
034: import org.postgresql.ds.common.BaseDataSource;
035: import org.postgresql.jdbc3.Jdbc3SimpleDataSource;
036:
037: /**
038: * Connection to the EPSG database in PostgreSQL database engine using JDBC. The EPSG
039: * database can be downloaded from <A HREF="http://www.epsg.org">http://www.epsg.org</A>.
040: * It should have been imported into a PostgreSQL database, which doesn't need to be on
041: * the local machine.
042: * <p>
043: * <h3>Connection parameters</h3>
044: * The preferred way to specify connection parameters is through the JNDI interface.
045: * However, this datasource provides the following alternative as a convenience: if a
046: * {@value #CONFIGURATION_FILE} file is found in current directory or in the user's home
047: * directory, then the following properties are fetch. Note that the default value may change
048: * in a future version if a public server become available.
049: * <P>
050: * <TABLE BORDER="1">
051: * <TR>
052: * <TH>Property</TH>
053: * <TH>Type</TH>
054: * <TH>Description</TH>
055: * <TH>Geotools Default</TH>
056: * </TR>
057: * <TR>
058: * <TD>{@code serverName}</TD>
059: * <TD>String</TD>
060: * <TD>PostgreSQL database server host name</TD>
061: * <TD>{@code localhost}</TD>
062: * </TR>
063: * <TR>
064: * <TD>{@code databaseName}</TD>
065: * <TD>String</TD>
066: * <TD>PostgreSQL database name</TD>
067: * <TD>{@code EPSG}</TD>
068: * </TR>
069: * <TR>
070: * <TD>{@code schema}</TD>
071: * <TD>String</TD>
072: * <TD>The schema for the EPSG tables</TD>
073: * <TD></TD>
074: * </TR>
075: * <TR>
076: * <TD>{@code portNumber}</TD>
077: * <TD>int</TD>
078: * <TD>TCP port which the PostgreSQL database server is listening on</TD>
079: * <TD>{@code 5432}</TD>
080: * </TR>
081: * <TR>
082: * <TD>{@code user}</TD>
083: * <TD>String</TD>
084: * <TD>User used to make database connections</TD>
085: * <TD>{@code GeoTools}</TD>
086: * </TR>
087: * <TR>
088: * <TD>{@code password}</TD>
089: * <TD>String</TD>
090: * <TD>Password used to make database connections</TD>
091: * <TD>{@code GeoTools}</TD></TR>
092: * </TABLE>
093: * <P>
094: * The database version is given in the
095: * {@linkplain org.opengis.metadata.citation.Citation#getEdition edition attribute}
096: * of the {@linkplain org.opengis.referencing.AuthorityFactory#getAuthority authority}.
097: * The postgreSQL database should be read only.
098: * <P>
099: * Just having this class accessible in the classpath, together with the registration in
100: * the {@code META-INF/services/} directory, is suffisient to get a working EPSG authority
101: * factory backed by this database. Vendors can create a copy of this class, modify it and
102: * bundle it with their own distribution if they want to connect their users to an other
103: * database.
104: *
105: * @since 2.4
106: * @source $URL: http://svn.geotools.org/geotools/tags/2.4.1/modules/plugin/epsg-postgresql/src/main/java/org/geotools/referencing/factory/epsg/ThreadedPostgreSQLEpsgFactory.java $
107: * @version $Id: ThreadedPostgreSQLEpsgFactory.java 27848 2007-11-12 13:10:32Z desruisseaux $
108: * @author Didier Richard
109: * @author Martin Desruisseaux
110: *
111: * @tutorial http://docs.codehaus.org/display/GEOTOOLS/How+to+install+the+EPSG+database+in+PostgreSQL
112: */
113: public class ThreadedPostgreSQLEpsgFactory extends ThreadedEpsgFactory {
114: /**
115: * The user configuration file. This class search first for the first file found in the
116: * following directories:
117: * <ul>
118: * <li>The current directory</li>
119: * <li>The user's home directory</li>
120: * </ul>
121: */
122: public static final String CONFIGURATION_FILE = "EPSG-DataSource.properties";
123:
124: /**
125: * The schema name, or {@code null} if none.
126: */
127: private String schema;
128:
129: /**
130: * Creates a new instance of this factory.
131: */
132: public ThreadedPostgreSQLEpsgFactory() {
133: this (null);
134: }
135:
136: /**
137: * Creates a new instance of this factory with the specified hints.
138: * The priority is set to a lower value than the {@linkplain FactoryOnAccess}'s one
139: * in order to give the priority to any "official" database installed locally by the
140: * user, when available.
141: */
142: public ThreadedPostgreSQLEpsgFactory(final Hints hints) {
143: super (hints, PRIORITY + 5);
144: }
145:
146: /**
147: * Loads the {@linkplain #CONFIGURATION_FILE configuration file}.
148: */
149: private static Properties load() {
150: final Properties p = new Properties();
151: File file = new File(CONFIGURATION_FILE);
152: if (!file.isFile()) {
153: file = new File(System.getProperty("user.home", "."),
154: CONFIGURATION_FILE);
155: if (!file.isFile()) {
156: // Returns an empty set of properties.
157: return p;
158: }
159: }
160: try {
161: final InputStream in = new FileInputStream(file);
162: p.load(in);
163: in.close();
164: } catch (IOException exception) {
165: Logging.unexpectedException(
166: "org.geotools.referencing.factory",
167: ThreadedPostgreSQLEpsgFactory.class, "<init>",
168: exception);
169: // Continue. We will try to work with whatever properties are available.
170: }
171: return p;
172: }
173:
174: /**
175: * Returns a data source for the PostgreSQL database.
176: */
177: protected DataSource createDataSource() throws SQLException {
178: DataSource candidate = super .createDataSource();
179: if (candidate instanceof BaseDataSource) {
180: // Any kind of DataSource from the PostgreSQL driver.
181: return candidate;
182: }
183: final Jdbc3SimpleDataSource source = new Jdbc3SimpleDataSource();
184: final Properties p = load();
185: int portNumber;
186: try {
187: portNumber = Integer.parseInt(p.getProperty("portNumber",
188: "5432"));
189: } catch (NumberFormatException exception) {
190: portNumber = 5432;
191: Logging.unexpectedException(
192: "org.geotools.referencing.factory",
193: ThreadedPostgreSQLEpsgFactory.class, "<init>",
194: exception);
195: }
196: source.setPortNumber(portNumber);
197: source.setServerName(p.getProperty("serverName", "localhost"));
198: source.setDatabaseName(p.getProperty("databaseName", "EPSG"));
199: source.setUser(p.getProperty("user", "Geotools"));
200: source.setPassword(p.getProperty("password", "Geotools"));
201: schema = p.getProperty("schema", null);
202: return source;
203: }
204:
205: /**
206: * Returns the backing-store factory for PostgreSQL syntax.
207: *
208: * @param hints A map of hints, including the low-level factories to use for CRS creation.
209: * @return The EPSG factory using PostgreSQL syntax.
210: * @throws SQLException if connection to the database failed.
211: */
212: protected AbstractAuthorityFactory createBackingStore(
213: final Hints hints) throws SQLException {
214: final Connection connection = getDataSource().getConnection();
215: final FactoryUsingAnsiSQL factory = new FactoryUsingAnsiSQL(
216: hints, connection);
217: if (schema != null) {
218: factory.setSchema(schema);
219: }
220: return factory;
221: }
222: }
|