Statistics
| Revision:

root / trunk / org.gvsig.postgresql / org.gvsig.postgresql.provider / src / main / java / org / gvsig / postgresql / dal / PostgreSQLHelper.java @ 650

History | View | Annotate | Download (11.3 KB)

1 362 jjdelcerro
2
package org.gvsig.postgresql.dal;
3
4
import java.sql.Connection;
5
import java.sql.SQLException;
6 650 fdiaz
import org.apache.commons.dbcp2.BasicDataSource;
7 362 jjdelcerro
import org.apache.commons.lang3.BooleanUtils;
8
import org.apache.commons.lang3.StringUtils;
9 570 jjdelcerro
import org.gvsig.expressionevaluator.GeometryExpressionBuilderHelper.GeometrySupportType;
10 362 jjdelcerro
import org.gvsig.fmap.dal.resource.exception.AccessResourceException;
11
import org.gvsig.fmap.dal.store.jdbc.JDBCConnectionParameters;
12
import org.gvsig.fmap.dal.store.jdbc.JDBCNewStoreParameters;
13
import org.gvsig.fmap.dal.store.jdbc.JDBCServerExplorerParameters;
14
import org.gvsig.fmap.dal.store.jdbc.JDBCStoreParameters;
15
import org.gvsig.fmap.dal.store.jdbc.exception.JDBCDriverClassNotFoundException;
16
import org.gvsig.fmap.dal.store.jdbc2.OperationsFactory;
17
import org.gvsig.fmap.dal.store.jdbc2.spi.JDBCHelperBase;
18
import org.gvsig.fmap.dal.store.jdbc2.spi.JDBCSQLBuilderBase;
19 433 jjdelcerro
import org.gvsig.fmap.dal.store.jdbc2.spi.SRSSolverBase;
20 576 jjdelcerro
import org.gvsig.fmap.dal.store.jdbc2.spi.SRSSolverDumb;
21 362 jjdelcerro
import org.gvsig.postgresql.dal.operations.PostgreSQLOperationsFactory;
22
import org.slf4j.Logger;
23
import org.slf4j.LoggerFactory;
24
25
public class PostgreSQLHelper extends JDBCHelperBase {
26
27 570 jjdelcerro
    /* friend */ static final Logger LOGGER = LoggerFactory.getLogger(PostgreSQLHelper.class);
28 362 jjdelcerro
29
    public static final String POSTGRESQL_JDBC_DRIVER = "org.postgresql.Driver";
30
31
    public static String getConnectionURL(PostgreSQLConnectionParameters params) {
32
        return getConnectionURL(
33
            params.getHost(),
34
            params.getPort(),
35
            params.getDBName()
36
        );
37
    }
38
39
    public static String getConnectionURL(String host, Integer port, String db) {
40
        if( StringUtils.isEmpty(host) ) {
41
            throw new IllegalArgumentException("Parameter 'host' can't be null.");
42
        }
43
        String connectionURL = "jdbc:postgresql://" + host;
44
        if (port != null) {
45
            connectionURL = connectionURL + ":" + port;
46
        }
47
        connectionURL = connectionURL + "/" + db;
48 570 jjdelcerro
        LOGGER.debug("connectionURL: {}", connectionURL);
49 362 jjdelcerro
        return connectionURL;
50
    }
51
52
    private static class ConnectionProvider {
53
54
        private static boolean needRegisterDriver = true;
55
56
        private BasicDataSource dataSource = null;
57
58
        private final PostgreSQLConnectionParameters connectionParameters;
59
60
        public ConnectionProvider(PostgreSQLConnectionParameters connectionParameters) {
61
            this.connectionParameters = connectionParameters;
62
        }
63
64
        public Connection getConnection() throws SQLException {
65
            if (this.dataSource == null) {
66
                this.dataSource = this.createDataSource();
67
            }
68 570 jjdelcerro
            if( LOGGER.isDebugEnabled() ) {
69
                LOGGER.debug("getConnection:\n" + getStatusInformation());
70 433 jjdelcerro
            }
71
            Connection conn;
72
            try {
73
                conn = this.dataSource.getConnection();
74
            } catch(Throwable ex) {
75 570 jjdelcerro
                LOGGER.debug("Error getting connection from pool.",ex);
76 433 jjdelcerro
                throw ex;
77
            }
78 650 fdiaz
            try {
79
                conn.setNetworkTimeout(null, this.connectionParameters.getNetworkTimeout());
80
            } catch(Throwable ex) {
81
                LOGGER.warn("Error setting the network timeout.",ex);
82
            }
83 570 jjdelcerro
            if( LOGGER.isDebugEnabled() ) {
84
                LOGGER.debug("Created connection: {}\n  NumActive: {}\n  NumIdle: {}",
85 433 jjdelcerro
                    new Object[] {
86
                        conn.hashCode(),
87
                        this.dataSource.getNumActive(),
88
                        this.dataSource.getNumIdle()
89
                    }
90
                );
91
            }
92 362 jjdelcerro
            return conn;
93
        }
94 433 jjdelcerro
95
        public void closeConnection(Connection connection) {
96
            if( connection != null ) {
97
                int connectionId = connection.hashCode();
98
                try {
99
                    connection.close();
100
                } catch(Throwable ex) {
101 570 jjdelcerro
                    LOGGER.warn("Can't close connection.", ex);
102 433 jjdelcerro
                }
103 570 jjdelcerro
                if( LOGGER.isDebugEnabled() ) {
104 433 jjdelcerro
                    Boolean isClosed;
105
                    try {
106
                        isClosed = connection.isClosed();
107
                    } catch(Throwable th) {
108
                        isClosed = null;
109
                    }
110 570 jjdelcerro
                    LOGGER.debug("Closed connection: {}\n  isClosed: {}\n  NumActive: {}\n  NumIdle: {}",
111 433 jjdelcerro
                        new Object[] {
112
                            connectionId,
113
                            isClosed,
114
                            this.dataSource.getNumActive(),
115
                            this.dataSource.getNumIdle()
116
                        }
117
                    );
118
                }
119 570 jjdelcerro
           } else if( LOGGER.isDebugEnabled() ) {
120
               LOGGER.debug("Close connection: null");
121 433 jjdelcerro
           }
122
        }
123
124
        public String getStatusInformation() {
125
            StringBuilder builder = new StringBuilder();
126
            builder.append("BasicDataSource pool status:\n");
127
            builder.append("  Connection URL: '").append(this.dataSource.getUrl()).append("'\n");
128
            if( this.dataSource.getInitialSize()>0 ) {
129
                builder.append("  InitialSize: ").append(this.dataSource.getInitialSize()).append(" (The initial number of connections that are created when the pool is started)\n");
130
            }
131
            if( this.dataSource.isPoolPreparedStatements() ) {
132
                builder.append("  PoolPreparedStatements: ").append(this.dataSource.isPoolPreparedStatements()).append("\n");
133
                builder.append("  MaxOpenPreparedStatements: ").append(this.dataSource.getMaxOpenPreparedStatements()).append(" (The maximum number of open statements that can be allocated from the statement pool at the same time, or non-positive for no limit)\n");
134
            }
135 650 fdiaz
            builder.append("  MaxTotal: ").append(this.dataSource.getMaxTotal()).append(" (The maximum number of active connections that can be allocated from this pool at the same time)\n");
136 433 jjdelcerro
            builder.append("  MaxIdle: ").append(this.dataSource.getMaxIdle()).append(" (The maximum number of connections that can remain idle in the pool)\n");
137
            builder.append("  NumActive:").append(this.dataSource.getNumActive()).append(" (the current number of active connections)\n");
138
            builder.append("  NumIdle:").append(this.dataSource.getNumIdle()).append(" (the current number of idle connections)\n");
139
            return builder.toString();
140
        }
141 362 jjdelcerro
142
        private BasicDataSource createDataSource() throws SQLException {
143
            if (!this.isRegistered()) {
144
                this.registerDriver();
145
            }
146
            PostgreSQLConnectionParameters params = connectionParameters;
147
148
            BasicDataSource ds = new BasicDataSource();
149 433 jjdelcerro
            ds.setMaxIdle(params.getMaxIdle());
150 362 jjdelcerro
            ds.setDriverClassName(params.getJDBCDriverClassName());
151
            if( params.getUseSSL() ) {
152
                String s = BooleanUtils.toStringTrueFalse(params.getUseSSL());
153
                ds.addConnectionProperty("ssl", s );
154
            }
155
            if( !StringUtils.isEmpty(params.getUser()) ) {
156
                ds.setUsername(params.getUser());
157
            }
158
            if( !StringUtils.isEmpty(params.getPassword()) ) {
159
                ds.setPassword(params.getPassword());
160
            }
161
            ds.setUrl(params.getUrl());
162
163 650 fdiaz
            ds.setMaxWaitMillis(60L * 1000);
164 362 jjdelcerro
            return ds;
165
        }
166
167
        private boolean isRegistered() {
168
            return needRegisterDriver;
169
        }
170
171
        public void registerDriver() throws SQLException {
172
            String className = this.connectionParameters.getJDBCDriverClassName();
173
            if (className == null) {
174
                return;
175
            }
176
            try {
177
                Class theClass = Class.forName(className);
178
                if (theClass == null) {
179 364 jjdelcerro
                    throw new JDBCDriverClassNotFoundException(PostgreSQLLibrary.NAME, className);
180 362 jjdelcerro
                }
181
            } catch (Exception e) {
182
                throw new SQLException("Can't register JDBC driver '" + className + "'.", e);
183
            }
184
            needRegisterDriver = false;
185
        }
186
187
    }
188
189
    private ConnectionProvider connectionProvider = null;
190
191 576 jjdelcerro
    public PostgreSQLHelper() {
192
        super(null);
193
        this.srssolver = new SRSSolverDumb(this);
194
    }
195
196 362 jjdelcerro
    public PostgreSQLHelper(JDBCConnectionParameters connectionParameters) {
197
        super(connectionParameters);
198 433 jjdelcerro
        this.srssolver = new SRSSolverBase(this);
199 362 jjdelcerro
    }
200
201
    @Override
202
    public Connection getConnection() throws AccessResourceException {
203
        try {
204
            if (this.connectionProvider == null) {
205 576 jjdelcerro
              if( this.getConnectionParameters()==null ) {
206
                return null;
207
              }
208
              this.connectionProvider = new ConnectionProvider(this.getConnectionParameters());
209 362 jjdelcerro
            }
210
            return this.connectionProvider.getConnection();
211
        } catch (SQLException ex) {
212 364 jjdelcerro
            throw new AccessResourceException(PostgreSQLLibrary.NAME, ex);
213 362 jjdelcerro
        }
214
    }
215 433 jjdelcerro
216
    @Override
217
    public void closeConnection(Connection connection) {
218 576 jjdelcerro
      if( connection!=null ) { // In test ???
219 433 jjdelcerro
         this.connectionProvider.closeConnection(connection);
220 576 jjdelcerro
      }
221 433 jjdelcerro
    }
222 362 jjdelcerro
223
    @Override
224
    public PostgreSQLConnectionParameters getConnectionParameters() {
225
        return (PostgreSQLConnectionParameters) super.getConnectionParameters();
226
    }
227
228
    @Override
229
    public String getConnectionURL() {
230
        return getConnectionURL(this.getConnectionParameters());
231
    }
232
233
    @Override
234
    protected String getResourceType() {
235 364 jjdelcerro
        return PostgreSQLLibrary.NAME;
236 362 jjdelcerro
    }
237
238
    @Override
239
    public String getProviderName() {
240 364 jjdelcerro
        return PostgreSQLLibrary.NAME;
241 362 jjdelcerro
    }
242
243
    @Override
244
    public JDBCSQLBuilderBase createSQLBuilder() {
245
        return new PostgreSQLBuilder(this);
246
    }
247
248
    @Override
249
    public OperationsFactory getOperations() {
250
        if (this.operationsFactory == null) {
251
            this.operationsFactory = new PostgreSQLOperationsFactory(this);
252
        }
253
        return operationsFactory;
254
    }
255
256
    @Override
257 511 jjdelcerro
    public GeometrySupportType getGeometrySupportType() {
258
        return GeometrySupportType.WKB;
259 362 jjdelcerro
    }
260
261
    @Override
262
    public boolean hasSpatialFunctions() {
263
        return true;
264
    }
265
266
    @Override
267
    public boolean canWriteGeometry(int geometryType, int geometrySubtype) {
268
        return true;
269
    }
270
271
    @Override
272
    public String getQuoteForIdentifiers() {
273
        return "\"";
274
    }
275
276
    @Override
277
    public boolean allowAutomaticValues() {
278
        return true;
279
    }
280
281
    @Override
282
    public boolean supportOffsetInSelect() {
283
        return true;
284
    }
285
286
    @Override
287
    public String getQuoteForStrings() {
288
        return "'";
289
    }
290
291
    @Override
292
    public String getSourceId(JDBCStoreParameters parameters) {
293
        return parameters.getDBName() + "." +
294
               parameters.getSchema()+ "." +
295
               parameters.getTable();
296
    }
297
298
    @Override
299
    public JDBCNewStoreParameters createNewStoreParameters() {
300
        return new PostgreSQLNewStoreParameters();
301
    }
302
303
    @Override
304
    public JDBCStoreParameters createOpenStoreParameters() {
305
        return new PostgreSQLStoreParameters();
306
    }
307
308
    @Override
309
    public JDBCServerExplorerParameters createServerExplorerParameters() {
310 385 jjdelcerro
        return new PostgreSQLServerExplorerParameters();
311 362 jjdelcerro
    }
312
}