Statistics
| Revision:

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

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.expressionevaluator.ExpressionBuilder.GeometrySupportType;
10
import org.gvsig.fmap.dal.SQLBuilder;
11
import org.gvsig.fmap.dal.resource.exception.AccessResourceException;
12
import org.gvsig.fmap.dal.store.jdbc.JDBCConnectionParameters;
13
import org.gvsig.fmap.dal.store.jdbc.JDBCNewStoreParameters;
14
import org.gvsig.fmap.dal.store.jdbc.JDBCServerExplorerParameters;
15
import org.gvsig.fmap.dal.store.jdbc.JDBCStoreParameters;
16
import org.gvsig.fmap.dal.store.jdbc.exception.JDBCDriverClassNotFoundException;
17
import org.gvsig.fmap.dal.store.jdbc2.OperationsFactory;
18
import org.gvsig.fmap.dal.store.jdbc2.spi.JDBCHelperBase;
19
import org.gvsig.fmap.dal.store.jdbc2.spi.JDBCSQLBuilderBase;
20
import org.gvsig.fmap.dal.store.jdbc2.spi.SRSSolverBase;
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
    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
            if( logger.isDebugEnabled() ) {
79
                logger.debug("Created connection: {}\n  NumActive: {}\n  NumIdle: {}",
80
                    new Object[] {
81
                        conn.hashCode(), 
82
                        this.dataSource.getNumActive(),
83
                        this.dataSource.getNumIdle()
84
                    }
85
                );
86
            }
87
            return conn;
88
        }
89
        
90
        public void closeConnection(Connection connection) {
91
            if( connection != null ) {
92
                int connectionId = connection.hashCode();
93
                try {
94
                    connection.close();
95
                } catch(Throwable ex) {
96
                    logger.warn("Can't close connection.", ex);
97
                }
98
                if( logger.isDebugEnabled() ) {
99
                    Boolean isClosed;
100
                    try {
101
                        isClosed = connection.isClosed();
102
                    } catch(Throwable th) {
103
                        isClosed = null;
104
                    }
105
                    logger.debug("Closed connection: {}\n  isClosed: {}\n  NumActive: {}\n  NumIdle: {}",
106
                        new Object[] {
107
                            connectionId, 
108
                            isClosed,
109
                            this.dataSource.getNumActive(),
110
                            this.dataSource.getNumIdle()
111
                        }
112
                    );
113
                }
114
           } else if( logger.isDebugEnabled() ) {
115
               logger.debug("Close connection: null");
116
           }
117
        }
118
        
119
        public String getStatusInformation() {
120
            StringBuilder builder = new StringBuilder();
121
            builder.append("BasicDataSource pool status:\n");
122
            builder.append("  Connection URL: '").append(this.dataSource.getUrl()).append("'\n");
123
            if( this.dataSource.getInitialSize()>0 ) {
124
                builder.append("  InitialSize: ").append(this.dataSource.getInitialSize()).append(" (The initial number of connections that are created when the pool is started)\n");
125
            }
126
            if( this.dataSource.isPoolPreparedStatements() ) {
127
                builder.append("  PoolPreparedStatements: ").append(this.dataSource.isPoolPreparedStatements()).append("\n");
128
                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");
129
            }
130
            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");
131
            builder.append("  MaxIdle: ").append(this.dataSource.getMaxIdle()).append(" (The maximum number of connections that can remain idle in the pool)\n");
132
            builder.append("  NumActive:").append(this.dataSource.getNumActive()).append(" (the current number of active connections)\n");
133
            builder.append("  NumIdle:").append(this.dataSource.getNumIdle()).append(" (the current number of idle connections)\n");
134
            return builder.toString();
135
        }
136

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

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

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

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

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

    
182
    }
183

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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