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

    
2
package org.gvsig.postgresql.dal;
3

    
4
import java.sql.Connection;
5
import java.sql.SQLException;
6
import org.apache.commons.dbcp2.BasicDataSource;
7
import org.apache.commons.lang3.BooleanUtils;
8
import org.apache.commons.lang3.StringUtils;
9
import org.gvsig.expressionevaluator.GeometryExpressionBuilderHelper.GeometrySupportType;
10
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
import org.gvsig.fmap.dal.store.jdbc2.spi.SRSSolverBase;
20
import org.gvsig.fmap.dal.store.jdbc2.spi.SRSSolverDumb;
21
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
    /* friend */ static final Logger LOGGER = LoggerFactory.getLogger(PostgreSQLHelper.class);
28

    
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
        LOGGER.debug("connectionURL: {}", connectionURL);
49
        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
            if( LOGGER.isDebugEnabled() ) {
69
                LOGGER.debug("getConnection:\n" + getStatusInformation());
70
            }
71
            Connection conn;
72
            try {
73
                conn = this.dataSource.getConnection();
74
            } catch(Throwable ex) {
75
                LOGGER.debug("Error getting connection from pool.",ex);
76
                throw ex;
77
            }
78
            try {
79
                conn.setNetworkTimeout(null, this.connectionParameters.getNetworkTimeout());
80
            } catch(Throwable ex) {
81
                LOGGER.warn("Error setting the network timeout.",ex);
82
            }
83
            if( LOGGER.isDebugEnabled() ) {
84
                LOGGER.debug("Created connection: {}\n  NumActive: {}\n  NumIdle: {}",
85
                    new Object[] {
86
                        conn.hashCode(), 
87
                        this.dataSource.getNumActive(),
88
                        this.dataSource.getNumIdle()
89
                    }
90
                );
91
            }
92
            return conn;
93
        }
94
        
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
                    LOGGER.warn("Can't close connection.", ex);
102
                }
103
                if( LOGGER.isDebugEnabled() ) {
104
                    Boolean isClosed;
105
                    try {
106
                        isClosed = connection.isClosed();
107
                    } catch(Throwable th) {
108
                        isClosed = null;
109
                    }
110
                    LOGGER.debug("Closed connection: {}\n  isClosed: {}\n  NumActive: {}\n  NumIdle: {}",
111
                        new Object[] {
112
                            connectionId, 
113
                            isClosed,
114
                            this.dataSource.getNumActive(),
115
                            this.dataSource.getNumIdle()
116
                        }
117
                    );
118
                }
119
           } else if( LOGGER.isDebugEnabled() ) {
120
               LOGGER.debug("Close connection: null");
121
           }
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
            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
            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

    
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
            ds.setMaxIdle(params.getMaxIdle());
150
            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
            ds.setMaxWaitMillis(60L * 1000);
164
            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
                    throw new JDBCDriverClassNotFoundException(PostgreSQLLibrary.NAME, className);
180
                }
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
    public PostgreSQLHelper() {
192
        super(null);
193
        this.srssolver = new SRSSolverDumb(this);
194
    }
195

    
196
    public PostgreSQLHelper(JDBCConnectionParameters connectionParameters) {
197
        super(connectionParameters);
198
        this.srssolver = new SRSSolverBase(this);
199
    }
200

    
201
    @Override
202
    public Connection getConnection() throws AccessResourceException {
203
        try {
204
            if (this.connectionProvider == null) {
205
              if( this.getConnectionParameters()==null ) {
206
                return null;
207
              }
208
              this.connectionProvider = new ConnectionProvider(this.getConnectionParameters());
209
            }
210
            return this.connectionProvider.getConnection();
211
        } catch (SQLException ex) {
212
            throw new AccessResourceException(PostgreSQLLibrary.NAME, ex);
213
        }
214
    }
215

    
216
    @Override
217
    public void closeConnection(Connection connection) {
218
      if( connection!=null ) { // In test ???
219
         this.connectionProvider.closeConnection(connection);
220
      }
221
    }
222
    
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
        return PostgreSQLLibrary.NAME;
236
    }
237

    
238
    @Override
239
    public String getProviderName() {
240
        return PostgreSQLLibrary.NAME;
241
    }
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
    public GeometrySupportType getGeometrySupportType() {
258
        return GeometrySupportType.WKB;
259
    }
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
        return new PostgreSQLServerExplorerParameters();
311
    }
312
}