Statistics
| Revision:

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

History | View | Annotate | Download (10.7 KB)

1

    
2
package org.gvsig.postgresql.dal;
3

    
4
import java.sql.Connection;
5
import java.sql.SQLException;
6
import org.apache.commons.dbcp.BasicDataSource;
7
import org.apache.commons.lang3.BooleanUtils;
8
import org.apache.commons.lang3.StringUtils;
9
import org.gvsig.fmap.dal.SQLBuilder;
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.postgresql.dal.operations.PostgreSQLOperationsFactory;
21
import org.slf4j.Logger;
22
import org.slf4j.LoggerFactory;
23

    
24
public class PostgreSQLHelper extends JDBCHelperBase {
25

    
26
    static final Logger logger = LoggerFactory.getLogger(PostgreSQLHelper.class);
27

    
28
    public static final String POSTGRESQL_JDBC_DRIVER = "org.postgresql.Driver";
29
    
30
    public static String getConnectionURL(PostgreSQLConnectionParameters params) {
31
        return getConnectionURL(
32
            params.getHost(),
33
            params.getPort(),
34
            params.getDBName()
35
        );
36
    }
37
    
38
    public static String getConnectionURL(String host, Integer port, String db) {
39
        if( StringUtils.isEmpty(host) ) {
40
            throw new IllegalArgumentException("Parameter 'host' can't be null.");
41
        }
42
        String connectionURL = "jdbc:postgresql://" + host;
43
        if (port != null) {
44
            connectionURL = connectionURL + ":" + port;
45
        }
46
        connectionURL = connectionURL + "/" + db;
47
        logger.debug("connectionURL: {}", connectionURL);
48
        return connectionURL;
49
    }
50

    
51
    private static class ConnectionProvider {
52

    
53
        private static boolean needRegisterDriver = true;
54

    
55
        private BasicDataSource dataSource = null;
56

    
57
        private final PostgreSQLConnectionParameters connectionParameters;
58

    
59
        public ConnectionProvider(PostgreSQLConnectionParameters connectionParameters) {
60
            this.connectionParameters = connectionParameters;
61
        }
62

    
63
        public Connection getConnection() throws SQLException {
64
            if (this.dataSource == null) {
65
                this.dataSource = this.createDataSource();               
66
            }
67
            if( logger.isDebugEnabled() ) {
68
                logger.debug("getConnection:\n" + getStatusInformation());
69
            }
70
            Connection conn;
71
            try {
72
                conn = this.dataSource.getConnection();
73
            } catch(Throwable ex) {
74
                logger.debug("Error getting connection from pool.",ex);
75
                throw ex;
76
            }
77
            if( logger.isDebugEnabled() ) {
78
                logger.debug("Created connection: {}\n  NumActive: {}\n  NumIdle: {}",
79
                    new Object[] {
80
                        conn.hashCode(), 
81
                        this.dataSource.getNumActive(),
82
                        this.dataSource.getNumIdle()
83
                    }
84
                );
85
            }
86
            return conn;
87
        }
88
        
89
        public void closeConnection(Connection connection) {
90
            if( connection != null ) {
91
                int connectionId = connection.hashCode();
92
                try {
93
                    connection.close();
94
                } catch(Throwable ex) {
95
                    logger.warn("Can't close connection.", ex);
96
                }
97
                if( logger.isDebugEnabled() ) {
98
                    Boolean isClosed;
99
                    try {
100
                        isClosed = connection.isClosed();
101
                    } catch(Throwable th) {
102
                        isClosed = null;
103
                    }
104
                    logger.debug("Closed connection: {}\n  isClosed: {}\n  NumActive: {}\n  NumIdle: {}",
105
                        new Object[] {
106
                            connectionId, 
107
                            isClosed,
108
                            this.dataSource.getNumActive(),
109
                            this.dataSource.getNumIdle()
110
                        }
111
                    );
112
                }
113
           } else if( logger.isDebugEnabled() ) {
114
               logger.debug("Close connection: null");
115
           }
116
        }
117
        
118
        public String getStatusInformation() {
119
            StringBuilder builder = new StringBuilder();
120
            builder.append("BasicDataSource pool status:\n");
121
            builder.append("  Connection URL: '").append(this.dataSource.getUrl()).append("'\n");
122
            if( this.dataSource.getInitialSize()>0 ) {
123
                builder.append("  InitialSize: ").append(this.dataSource.getInitialSize()).append(" (The initial number of connections that are created when the pool is started)\n");
124
            }
125
            if( this.dataSource.isPoolPreparedStatements() ) {
126
                builder.append("  PoolPreparedStatements: ").append(this.dataSource.isPoolPreparedStatements()).append("\n");
127
                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");
128
            }
129
            builder.append("  MaxActive: ").append(this.dataSource.getMaxActive()).append(" (The maximum number of active connections that can be allocated from this pool at the same time)\n");
130
            builder.append("  MaxIdle: ").append(this.dataSource.getMaxIdle()).append(" (The maximum number of connections that can remain idle in the pool)\n");
131
            builder.append("  NumActive:").append(this.dataSource.getNumActive()).append(" (the current number of active connections)\n");
132
            builder.append("  NumIdle:").append(this.dataSource.getNumIdle()).append(" (the current number of idle connections)\n");
133
            return builder.toString();
134
        }
135

    
136
        private BasicDataSource createDataSource() throws SQLException {
137
            if (!this.isRegistered()) {
138
                this.registerDriver();
139
            }
140
            PostgreSQLConnectionParameters params = connectionParameters;
141

    
142
            BasicDataSource ds = new BasicDataSource();
143
            ds.setMaxIdle(params.getMaxIdle());
144
            ds.setDriverClassName(params.getJDBCDriverClassName());
145
            if( params.getUseSSL() ) {
146
                String s = BooleanUtils.toStringTrueFalse(params.getUseSSL());
147
                ds.addConnectionProperty("ssl", s );
148
            }
149
            if( !StringUtils.isEmpty(params.getUser()) ) {
150
                ds.setUsername(params.getUser());
151
            }
152
            if( !StringUtils.isEmpty(params.getPassword()) ) {
153
                ds.setPassword(params.getPassword());
154
            }
155
            ds.setUrl(params.getUrl());
156

    
157
            ds.setMaxWait(60L * 1000);
158
            return ds;
159
        }
160

    
161
        private boolean isRegistered() {
162
            return needRegisterDriver;
163
        }
164

    
165
        public void registerDriver() throws SQLException {
166
            String className = this.connectionParameters.getJDBCDriverClassName();
167
            if (className == null) {
168
                return;
169
            }
170
            try {
171
                Class theClass = Class.forName(className);
172
                if (theClass == null) {
173
                    throw new JDBCDriverClassNotFoundException(PostgreSQLLibrary.NAME, className);
174
                }
175
            } catch (Exception e) {
176
                throw new SQLException("Can't register JDBC driver '" + className + "'.", e);
177
            }
178
            needRegisterDriver = false;
179
        }
180

    
181
    }
182

    
183
    private ConnectionProvider connectionProvider = null;
184
   
185
    public PostgreSQLHelper(JDBCConnectionParameters connectionParameters) {
186
        super(connectionParameters);
187
        this.srssolver = new SRSSolverBase(this);
188
    }
189

    
190
    @Override
191
    public Connection getConnection() throws AccessResourceException {
192
        try {
193
            if (this.connectionProvider == null) {
194
                this.connectionProvider = new ConnectionProvider(this.getConnectionParameters());
195
            }
196
            return this.connectionProvider.getConnection();
197
        } catch (SQLException ex) {
198
            throw new AccessResourceException(PostgreSQLLibrary.NAME, ex);
199
        }
200
    }
201

    
202
    @Override
203
    public void closeConnection(Connection connection) {
204
         this.connectionProvider.closeConnection(connection);
205
    }
206
    
207
    @Override
208
    public PostgreSQLConnectionParameters getConnectionParameters() {
209
        return (PostgreSQLConnectionParameters) super.getConnectionParameters();
210
    }
211
    
212
    @Override
213
    public String getConnectionURL() {
214
        return getConnectionURL(this.getConnectionParameters());
215
    }
216

    
217
    @Override
218
    protected String getResourceType() {
219
        return PostgreSQLLibrary.NAME;
220
    }
221

    
222
    @Override
223
    public String getProviderName() {
224
        return PostgreSQLLibrary.NAME;
225
    }
226

    
227
    @Override
228
    public JDBCSQLBuilderBase createSQLBuilder() {
229
        return new PostgreSQLBuilder(this);
230
    }
231
    
232
    @Override
233
    public OperationsFactory getOperations() {
234
        if (this.operationsFactory == null) {
235
            this.operationsFactory = new PostgreSQLOperationsFactory(this);
236
        }
237
        return operationsFactory;
238
    }
239

    
240
    @Override
241
    public SQLBuilder.GeometrySupportType getGeometrySupportType() {
242
        return SQLBuilder.GeometrySupportType.WKB;
243
    }
244

    
245
    @Override
246
    public boolean hasSpatialFunctions() {
247
        return true;
248
    }
249

    
250
    @Override
251
    public boolean canWriteGeometry(int geometryType, int geometrySubtype) {
252
        return true;
253
    }
254

    
255
    @Override
256
    public String getQuoteForIdentifiers() {
257
        return "\"";
258
    }
259

    
260
    @Override
261
    public boolean allowAutomaticValues() {
262
        return true;
263
    }
264

    
265
    @Override
266
    public boolean supportOffsetInSelect() {
267
        return true;
268
    }
269

    
270
    @Override
271
    public String getQuoteForStrings() {
272
        return "'";
273
    }
274
    
275
    @Override
276
    public String getSourceId(JDBCStoreParameters parameters) {
277
        return parameters.getDBName() + "." + 
278
               parameters.getSchema()+ "." + 
279
               parameters.getTable();
280
    }
281

    
282
    @Override
283
    public JDBCNewStoreParameters createNewStoreParameters() {
284
        return new PostgreSQLNewStoreParameters();
285
    }
286

    
287
    @Override
288
    public JDBCStoreParameters createOpenStoreParameters() {
289
        return new PostgreSQLStoreParameters();
290
    }
291

    
292
    @Override
293
    public JDBCServerExplorerParameters createServerExplorerParameters() {
294
        return new PostgreSQLServerExplorerParameters();
295
    }
296
}