Statistics
| Revision:

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

History | View | Annotate | Download (11 KB)

1

    
2
package org.gvsig.postgresql.dal;
3

    
4
import java.sql.Connection;
5
import java.sql.PreparedStatement;
6
import java.sql.SQLException;
7
import java.util.ArrayList;
8
import java.util.List;
9
import org.apache.commons.dbcp.BasicDataSource;
10
import org.apache.commons.lang3.BooleanUtils;
11
import org.apache.commons.lang3.StringUtils;
12
import org.cresques.cts.IProjection;
13
import org.gvsig.fmap.dal.DataTypes;
14
import org.gvsig.fmap.dal.ExpressionBuilder;
15
import org.gvsig.fmap.dal.SQLBuilder;
16
import org.gvsig.fmap.dal.feature.FeatureAttributeDescriptor;
17
import org.gvsig.fmap.dal.feature.FeatureType;
18
import org.gvsig.fmap.dal.feature.spi.FeatureProvider;
19
import org.gvsig.fmap.dal.resource.exception.AccessResourceException;
20
import org.gvsig.fmap.dal.store.jdbc.JDBCConnectionParameters;
21
import org.gvsig.fmap.dal.store.jdbc.JDBCNewStoreParameters;
22
import org.gvsig.fmap.dal.store.jdbc.JDBCServerExplorerParameters;
23
import org.gvsig.fmap.dal.store.jdbc.JDBCStoreParameters;
24
import org.gvsig.fmap.dal.store.jdbc.exception.JDBCDriverClassNotFoundException;
25
import org.gvsig.fmap.dal.store.jdbc2.JDBCUtils;
26
import org.gvsig.fmap.dal.store.jdbc2.OperationsFactory;
27
import org.gvsig.fmap.dal.store.jdbc2.spi.JDBCHelperBase;
28
import org.gvsig.fmap.dal.store.jdbc2.spi.JDBCSQLBuilderBase;
29
import org.gvsig.fmap.dal.store.jdbc2.spi.JDBCSRSsBase;
30
import org.gvsig.fmap.geom.Geometry;
31
import org.gvsig.fmap.geom.aggregate.MultiLine;
32
import org.gvsig.fmap.geom.aggregate.MultiPoint;
33
import org.gvsig.fmap.geom.aggregate.MultiPolygon;
34
import org.gvsig.fmap.geom.exception.CreateGeometryException;
35
import org.gvsig.fmap.geom.primitive.Primitive;
36
import org.gvsig.fmap.geom.type.GeometryType;
37
import org.gvsig.postgresql.dal.operations.PostgreSQLOperationsFactory;
38
import org.slf4j.Logger;
39
import org.slf4j.LoggerFactory;
40

    
41
public class PostgreSQLHelper extends JDBCHelperBase {
42

    
43
    static final Logger logger = LoggerFactory.getLogger(PostgreSQLHelper.class);
44

    
45
    public static final String NAME = "PostgreSQL";
46
    public static final String POSTGRESQL_JDBC_DRIVER = "org.postgresql.Driver";
47
    
48
    public static String getConnectionURL(PostgreSQLConnectionParameters params) {
49
        return getConnectionURL(
50
            params.getHost(),
51
            params.getPort(),
52
            params.getDBName()
53
        );
54
    }
55
    
56
    public static String getConnectionURL(String host, Integer port, String db) {
57
        if( StringUtils.isEmpty(host) ) {
58
            throw new IllegalArgumentException("Parameter 'host' can't be null.");
59
        }
60
        String connectionURL = "jdbc:postgresql://" + host;
61
        if (port != null) {
62
            connectionURL = connectionURL + ":" + port;
63
        }
64
        connectionURL = connectionURL + "/" + db;
65
        logger.debug("connectionURL: {}", connectionURL);
66
        return connectionURL;
67
    }
68

    
69
    private static class ConnectionProvider {
70

    
71
        private static boolean needRegisterDriver = true;
72

    
73
        private BasicDataSource dataSource = null;
74

    
75
        private final PostgreSQLConnectionParameters connectionParameters;
76

    
77
        public ConnectionProvider(PostgreSQLConnectionParameters connectionParameters) {
78
            this.connectionParameters = connectionParameters;
79
        }
80

    
81
        public Connection getConnection() throws SQLException {
82
            if (this.dataSource == null) {
83
                this.dataSource = this.createDataSource();               
84
            }
85
            Connection conn = this.dataSource.getConnection();
86
            return conn;
87
        }
88

    
89
        private BasicDataSource createDataSource() throws SQLException {
90
            if (!this.isRegistered()) {
91
                this.registerDriver();
92
            }
93
            PostgreSQLConnectionParameters params = connectionParameters;
94

    
95
            BasicDataSource ds = new BasicDataSource();
96
            ds.setDriverClassName(params.getJDBCDriverClassName());
97
            if( params.getUseSSL() ) {
98
                String s = BooleanUtils.toStringTrueFalse(params.getUseSSL());
99
                ds.addConnectionProperty("ssl", s );
100
            }
101
            if( !StringUtils.isEmpty(params.getUser()) ) {
102
                ds.setUsername(params.getUser());
103
            }
104
            if( !StringUtils.isEmpty(params.getPassword()) ) {
105
                ds.setPassword(params.getPassword());
106
            }
107
            ds.setUrl(params.getUrl());
108

    
109
            ds.setMaxWait(60L * 1000);
110
            return ds;
111
        }
112

    
113
        private boolean isRegistered() {
114
            return needRegisterDriver;
115
        }
116

    
117
        public void registerDriver() throws SQLException {
118
            String className = this.connectionParameters.getJDBCDriverClassName();
119
            if (className == null) {
120
                return;
121
            }
122
            try {
123
                Class theClass = Class.forName(className);
124
                if (theClass == null) {
125
                    throw new JDBCDriverClassNotFoundException(NAME, className);
126
                }
127
            } catch (Exception e) {
128
                throw new SQLException("Can't register JDBC driver '" + className + "'.", e);
129
            }
130
            needRegisterDriver = false;
131
        }
132

    
133
    }
134

    
135
    private ConnectionProvider connectionProvider = null;
136
   
137
    public PostgreSQLHelper(JDBCConnectionParameters connectionParameters) {
138
        super(connectionParameters);
139
        this.srss = new JDBCSRSsBase(this);
140
    }
141

    
142
    @Override
143
    public Connection getConnection() throws AccessResourceException {
144
        try {
145
            if (this.connectionProvider == null) {
146
                this.connectionProvider = new ConnectionProvider(this.getConnectionParameters());
147
            }
148
            return this.connectionProvider.getConnection();
149
        } catch (SQLException ex) {
150
            throw new AccessResourceException(NAME, ex);
151
        }
152
    }
153
    
154
    @Override
155
    public PostgreSQLConnectionParameters getConnectionParameters() {
156
        return (PostgreSQLConnectionParameters) super.getConnectionParameters();
157
    }
158
    
159
    @Override
160
    public String getConnectionURL() {
161
        return getConnectionURL(this.getConnectionParameters());
162
    }
163

    
164
    @Override
165
    protected String getResourceType() {
166
        return NAME;
167
    }
168

    
169
    @Override
170
    public String getProviderName() {
171
        return NAME;
172
    }
173

    
174
    @Override
175
    public JDBCSQLBuilderBase createSQLBuilder() {
176
        return new PostgreSQLBuilder(this);
177
    }
178
    
179
    @Override
180
    public OperationsFactory getOperations() {
181
        if (this.operationsFactory == null) {
182
            this.operationsFactory = new PostgreSQLOperationsFactory(this);
183
        }
184
        return operationsFactory;
185
    }
186

    
187
    @Override
188
    public SQLBuilder.GeometrySupportType getGeometrySupportType() {
189
        return SQLBuilder.GeometrySupportType.WKB;
190
    }
191

    
192
    @Override
193
    public boolean hasSpatialFunctions() {
194
        return true;
195
    }
196

    
197
    @Override
198
    public boolean canWriteGeometry(int geometryType, int geometrySubtype) {
199
        return true;
200
    }
201

    
202
    @Override
203
    public String getQuoteForIdentifiers() {
204
        return "\"";
205
    }
206

    
207
    @Override
208
    public boolean allowAutomaticValues() {
209
        return true;
210
    }
211

    
212
    @Override
213
    public boolean supportOffsetInSelect() {
214
        return true;
215
    }
216

    
217
    @Override
218
    public String getQuoteForStrings() {
219
        return "'";
220
    }
221
    
222
    @Override
223
    public String getSourceId(JDBCStoreParameters parameters) {
224
        return parameters.getDBName() + "." + 
225
               parameters.getSchema()+ "." + 
226
               parameters.getTable();
227
    }
228

    
229
    @Override
230
    public JDBCNewStoreParameters createNewStoreParameters() {
231
        return new PostgreSQLNewStoreParameters();
232
    }
233

    
234
    @Override
235
    public JDBCStoreParameters createOpenStoreParameters() {
236
        return new PostgreSQLStoreParameters();
237
    }
238

    
239
    @Override
240
    public JDBCServerExplorerParameters createServerExplorerParameters() {
241
        return new PostgreSQLExplorerParameters();
242
    }
243

    
244
    public void setPreparedStatementParameters(PreparedStatement st, JDBCSQLBuilderBase sqlbuilder, FeatureType type, FeatureProvider feature) {
245
        try {
246
            List<Object> values = new ArrayList<>();
247
            for (ExpressionBuilder.Parameter parameter : sqlbuilder.getParameters()) {
248
                Object value;
249
                if (parameter.is_constant()) {
250
                    value = parameter.getValue();
251
                } else {
252
                    String name = parameter.getName();
253
                    value = feature.get(name);
254
                    FeatureAttributeDescriptor attr = type.getAttributeDescriptor(name);
255
                    if( attr.getType()==DataTypes.GEOMETRY ) {
256
                        value = forceGeometry(attr.getGeomType(), (Geometry) value);
257
                    }
258
                }
259
                values.add(value);
260
            }
261
            JDBCUtils.setObjects(st, values, sqlbuilder.geometry_support_type());
262
        } catch (Exception ex) {
263
            String f = "unknow";
264
            try {
265
                f = feature.toString();
266
            } catch (Exception ex2) {
267
                // Do nothing
268
            }
269
            throw new RuntimeException("Can't set parameters to prepared statement from the feature (" + f + ")", ex);
270
        }
271
    }
272
    
273
    private Geometry forceGeometry(GeometryType geomtype, Geometry geom) throws CreateGeometryException {
274
        switch( geomtype.getType() ) {
275
        case Geometry.TYPES.MULTIPOLYGON:
276
            if( geom.getType()==Geometry.TYPES.POLYGON ) {
277
                MultiPolygon x = getGeometryManager().createMultiPolygon(geomtype.getSubType());
278
                x.addPrimitive((Primitive) geom);
279
                geom = x;
280
            }
281
            break;
282
        case Geometry.TYPES.MULTILINE:
283
            if( geom.getType()==Geometry.TYPES.LINE ) {
284
                MultiLine x = getGeometryManager().createMultiLine(geomtype.getSubType());
285
                x.addPrimitive((Primitive) geom);
286
                geom = x;
287
            }
288
            break;
289
        case Geometry.TYPES.MULTIPOINT:
290
            if( geom.getType()==Geometry.TYPES.POINT ) {
291
                MultiLine x = getGeometryManager().createMultiLine(geomtype.getSubType());
292
                x.addPrimitive((Primitive) geom);
293
                geom = x;
294
            }
295
            break;
296
        case Geometry.TYPES.POLYGON:
297
            if( geom.getType()==Geometry.TYPES.MULTIPOLYGON ) {
298
                MultiPolygon x = (MultiPolygon) geom;
299
                if( x.getPrimitivesNumber()==1 ) {
300
                    geom = x.getPrimitiveAt(0);
301
                }
302
            }
303
            break;
304
        case Geometry.TYPES.LINE:
305
            if( geom.getType()==Geometry.TYPES.MULTILINE ) {
306
                MultiLine x = (MultiLine) geom;
307
                if( x.getPrimitivesNumber()==1 ) {
308
                    geom = x.getPrimitiveAt(0);
309
                }
310
            }
311
            break;
312
        case Geometry.TYPES.POINT:
313
            if( geom.getType()==Geometry.TYPES.MULTIPOINT ) {
314
                MultiPoint x = (MultiPoint) geom;
315
                if( x.getPrimitivesNumber()==1 ) {
316
                    geom = x.getPrimitiveAt(0);
317
                }
318
            }
319
        }
320
        return geom;
321
    }
322
    
323

    
324
}