Statistics
| Revision:

svn-gvsig-desktop / trunk / org.gvsig.desktop / org.gvsig.desktop.compat.cdc / org.gvsig.fmap.dal / org.gvsig.fmap.dal.db / org.gvsig.fmap.dal.db.jdbc / src / main / java / org / gvsig / fmap / dal / store / jdbc / JDBCStoreProvider.java @ 40596

History | View | Annotate | Download (23.6 KB)

1
/**
2
 * gvSIG. Desktop Geographic Information System.
3
 *
4
 * Copyright (C) 2007-2013 gvSIG Association.
5
 *
6
 * This program is free software; you can redistribute it and/or
7
 * modify it under the terms of the GNU General Public License
8
 * as published by the Free Software Foundation; either version 3
9
 * of the License, or (at your option) any later version.
10
 *
11
 * This program is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 * GNU General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU General Public License
17
 * along with this program; if not, write to the Free Software
18
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19
 * MA  02110-1301, USA.
20
 *
21
 * For any additional information, do not hesitate to contact us
22
 * at info AT gvsig.com, or visit our website www.gvsig.com.
23
 */
24
package org.gvsig.fmap.dal.store.jdbc;
25

    
26
import java.security.InvalidParameterException;
27
import java.sql.Connection;
28
import java.sql.PreparedStatement;
29
import java.sql.ResultSet;
30
import java.sql.SQLException;
31
import java.sql.Statement;
32
import java.util.ArrayList;
33
import java.util.Collections;
34
import java.util.Iterator;
35
import java.util.List;
36

    
37
import org.cresques.cts.IProjection;
38
import org.gvsig.fmap.dal.DALLocator;
39
import org.gvsig.fmap.dal.DataManager;
40
import org.gvsig.fmap.dal.DataServerExplorer;
41
import org.gvsig.fmap.dal.DataStore;
42
import org.gvsig.fmap.dal.DataStoreNotification;
43
import org.gvsig.fmap.dal.DataTypes;
44
import org.gvsig.fmap.dal.exception.CloseException;
45
import org.gvsig.fmap.dal.exception.DataException;
46
import org.gvsig.fmap.dal.exception.InitializeException;
47
import org.gvsig.fmap.dal.exception.OpenException;
48
import org.gvsig.fmap.dal.exception.ReadException;
49
import org.gvsig.fmap.dal.exception.ValidateDataParametersException;
50
import org.gvsig.fmap.dal.feature.EditableFeatureType;
51
import org.gvsig.fmap.dal.feature.FeatureAttributeDescriptor;
52
import org.gvsig.fmap.dal.feature.FeatureQuery;
53
import org.gvsig.fmap.dal.feature.FeatureType;
54
import org.gvsig.fmap.dal.feature.spi.AbstractFeatureStoreProvider;
55
import org.gvsig.fmap.dal.feature.spi.FeatureProvider;
56
import org.gvsig.fmap.dal.feature.spi.FeatureReferenceProviderServices;
57
import org.gvsig.fmap.dal.feature.spi.FeatureSetProvider;
58
import org.gvsig.fmap.dal.resource.ResourceAction;
59
import org.gvsig.fmap.dal.resource.exception.ResourceExecuteException;
60
import org.gvsig.fmap.dal.resource.spi.ResourceProvider;
61
import org.gvsig.fmap.dal.spi.DataStoreProviderServices;
62
import org.gvsig.fmap.dal.store.db.DBHelper;
63
import org.gvsig.fmap.dal.store.db.FeatureTypeHelper;
64
import org.gvsig.fmap.dal.store.jdbc.exception.InvalidResultSetIdException;
65
import org.gvsig.fmap.dal.store.jdbc.exception.JDBCException;
66
import org.gvsig.fmap.dal.store.jdbc.exception.JDBCExecutePreparedSQLException;
67
import org.gvsig.fmap.dal.store.jdbc.exception.JDBCSQLException;
68
import org.gvsig.fmap.geom.Geometry;
69
import org.gvsig.fmap.geom.GeometryLocator;
70
import org.gvsig.fmap.geom.GeometryManager;
71
import org.gvsig.fmap.geom.primitive.Envelope;
72
import org.gvsig.tools.dynobject.DynObject;
73
import org.gvsig.tools.dynobject.exception.DynFieldNotFoundException;
74
import org.gvsig.tools.exception.BaseException;
75
import org.slf4j.Logger;
76
import org.slf4j.LoggerFactory;
77

    
78

    
79
/**
80
 * @author jmvivo
81
 *
82
 */
83
public class JDBCStoreProvider extends AbstractFeatureStoreProvider
84
                implements JDBCHelperUser {
85

    
86
        final static private Logger logger = LoggerFactory
87
                        .getLogger(JDBCStoreProvider.class);
88

    
89
        private List<ResultSetInfo> resulsetList;
90

    
91
        public static String NAME = "JDBC";
92
        public static String DESCRIPTION = "JDBC source";
93

    
94
        public static final String METADATA_DEFINITION_NAME = NAME;
95

    
96
        private long mlsecondsToZombie = 1000 * 60 * 10; // 10 Min
97

    
98
        protected JDBCHelper helper;
99

    
100
        protected boolean directSQLMode;
101

    
102
        private Long totalCount = null;
103
        private GeometryManager geomManager = null;
104

    
105
        public JDBCStoreProvider(JDBCStoreParameters params,
106
                        DataStoreProviderServices storeServices) throws InitializeException {
107
                this(
108
                                params, 
109
                                storeServices,
110
                                DBHelper.newMetadataContainer(METADATA_DEFINITION_NAME)
111
                );
112
        }
113

    
114
        protected JDBCStoreProvider(JDBCStoreParameters params,
115
                        DataStoreProviderServices storeServices, DynObject metadata)
116
                        throws InitializeException {
117
                super(params, storeServices, metadata);
118
                geomManager = GeometryLocator.getGeometryManager();
119
                
120
                resulsetList = new ArrayList<ResultSetInfo>(10);
121

    
122
                helper = createHelper();
123
                if (params.getSQL() != null && (params.getSQL()).trim().length() > 0) {
124
                        directSQLMode = true;
125
                }
126

    
127
                this.initFeatureType();
128
        }
129

    
130
        public Object getDynValue(String name) throws DynFieldNotFoundException {
131
                try {
132
                        if( DataStore.METADATA_ENVELOPE.equalsIgnoreCase(name) ) {
133
                                Envelope env = this.getEnvelope();
134
                                if( env != null ) {
135
                                        return env;
136
                                }
137
                        } else if( DataStore.METADATA_CRS.equalsIgnoreCase(name) ) {
138
                                IProjection proj;
139
                                proj = this.getFeatureStore().getDefaultFeatureType().getDefaultSRS();
140
                                if( proj != null ) {
141
                                        return proj;
142
                                }
143
                        }
144
                } catch (DataException e) {
145
                        throw new RuntimeException(e);
146
                }
147
                return super.getDynValue(name);
148
        }
149
        
150

    
151
        protected JDBCStoreParameters getJDBCParameters() {
152
                return (JDBCStoreParameters) this.getParameters();
153
        }
154

    
155

    
156
        /**
157
         * Load data form a resulset.<br>
158
         *
159
         * <strong>Note:</strong><br>
160
         * this method have to perform <code>resouceBegin</code> at the begining and
161
         * <code>resourceEnd</code> at the end of execution.
162
         *
163
         *
164
         * @param data
165
         * @param resulsetID
166
         *
167
         * @return
168
         * @throws DataException
169
         */
170
        public void loadFeatureProvider(final FeatureProvider data, final int resultsetID)
171
                        throws DataException {
172
                getResource().execute(new ResourceAction() {
173
                        public Object run() throws Exception {
174
                                ResultSet rs = getResultSet(resultsetID);
175
                                FeatureAttributeDescriptor attr;
176
                                Iterator<FeatureAttributeDescriptor> iter = FeatureTypeHelper.iterator(data.getType());
177
                                while (iter.hasNext()) {
178
                                        attr = iter.next();
179
                                        loadFeatureProviderValue(data, rs, attr);
180
                                }
181
                                return null;
182
                        }
183
                });
184
        }
185

    
186
        protected void loadFeatureProviderValue(FeatureProvider data, ResultSet rs,
187
                        FeatureAttributeDescriptor attr) throws DataException {
188
                if (attr.getType() == DataTypes.GEOMETRY) {
189
                        byte[] buffer;
190
                        try {
191
                                buffer = rs.getBytes(attr.getIndex() + 1);
192
                                if (buffer == null) {
193
                                        data.set(attr.getIndex(), null);
194
                                } else {
195
                                        data.set(attr.getIndex(), this.helper.getGeometry(buffer));
196
                                }
197
                        } catch (SQLException e) {
198
                                throw new JDBCSQLException(e);
199
                        } catch (BaseException e) {
200
                                throw new ReadException(getProviderName(), e);
201
                        }
202

    
203
                } else {
204
                        try {
205
                                data.set(attr.getIndex(), rs.getObject(attr.getIndex() + 1));
206
                        } catch (SQLException e) {
207
                                throw new JDBCSQLException(e);
208
                        }
209
                }
210
        }
211

    
212
        public long getTimeToResulSetZombie() {
213
                return mlsecondsToZombie;
214
        }
215

    
216
        public void setTimeToResulSetZombie(long mlSeconds) {
217
                mlsecondsToZombie = mlSeconds;
218
        }
219

    
220
        private class ResultSetInfo{
221
                private ResultSet resultSet = null;
222
                private long lastUse = 0;
223

    
224
                public ResultSetInfo(ResultSet resulSet) {
225
                        this.resultSet = resulSet;
226
                        used();
227
                }
228

    
229
                private void used() {
230
                        lastUse = System.currentTimeMillis();
231
                }
232

    
233

    
234
                public ResultSet get() {
235
                        used();
236
                        return resultSet;
237
                }
238

    
239
                public boolean isZombie() {
240
                        return System.currentTimeMillis() - lastUse > mlsecondsToZombie;
241
                }
242
        }
243

    
244
        public final int createResultSet(String sql, int fetchSize)
245
                        throws DataException {
246
        return createResultSet(sql, null, fetchSize);
247
        }
248

    
249
        public final int createResultSet(final String sql, final Object[] values,
250
                        final int fetchSize)
251
                        throws DataException {
252
                logger.debug("Creating resultSet with sql: {}", sql);
253
                synchronized (this) {
254
                        checksResulsets();
255
                        return ((Integer) getResource().execute(new ResourceAction() {
256
                                public Object run() throws Exception {
257
                                        ResultSetInfo newRs =
258
                                                        new ResultSetInfo(createNewResultSet(sql, values,
259
                                                                        fetchSize));
260
                                        int newId = getNewId();
261
                                        if (newId < 0) {
262
                                                newId = resulsetList.size();
263
                                                resulsetList.add(newRs);
264
                                        } else {
265
                                                resulsetList.set(newId, newRs);
266
                                        }
267
                                        logger.debug("Created resultset id: {} (total open: {})",
268
                                                        newId, getResultsetOpenCount());
269

    
270
                                        return Integer.valueOf(newId);
271
                                }
272
                        })).intValue();
273
                }
274
        }
275

    
276
        private int getNewId() {
277
                int newId;
278
                if (resulsetList.size() < 1) {
279
                        return -1;
280
                }
281
                for (newId = 0; newId < resulsetList.size(); newId++) {
282
                        if (resulsetList.get(newId) == null) {
283
                                return newId;
284
                        }
285
                }
286
                return -1;
287
        }
288

    
289
        protected final void forceCloseAllResultSet()
290
                        throws ResourceExecuteException,
291
                        JDBCException {
292
                synchronized (this) {
293
                        // FIXME: Esto no deberia funcionar. 
294
                        Iterator iter = resulsetList.iterator();
295
                        Integer rsID = null;
296
                        while (iter.hasNext()) {
297
                                rsID = (Integer) iter.next();
298
                                if (rsID != null) {
299
                                        try {
300
                                                forceCloseResultSet(rsID.intValue());
301
                                        } catch (InvalidResultSetIdException e) {
302
                                                continue;
303
                                        }
304
                                }
305
                                iter.remove();
306
                        }
307

    
308
                }
309
        }
310
        
311
        protected final void forceCloseResultSet(int rsID)
312
                        throws ResourceExecuteException, JDBCException,
313
                        InvalidResultSetIdException {
314
                logger.warn("Close forced of resultSet ({})", rsID);
315
                closeResulset(rsID);
316
        }
317

    
318
        protected final ResultSet getResultSet(int resultsetID)
319
                        throws InvalidResultSetIdException {
320
                if (resultsetID >= resulsetList.size()) {
321
                        throw new InvalidResultSetIdException(resultsetID);
322
                }
323
                ResultSetInfo rsInfo = resulsetList.get(resultsetID);
324
                if (rsInfo == null) {
325
                        throw new InvalidResultSetIdException(resultsetID);
326
                }
327
                return rsInfo.get();
328

    
329
        }
330

    
331
        private ResultSet dropResultSet(int resultsetID)
332
                        throws InvalidResultSetIdException {
333
                if (resultsetID >= resulsetList.size()) {
334
                        throw new InvalidResultSetIdException(resultsetID);
335
                }
336
                ResultSetInfo rsInfo = (ResultSetInfo) resulsetList.get(resultsetID);
337
                if (rsInfo == null) {
338
                        throw new InvalidResultSetIdException(resultsetID);
339
                }
340
                if (resultsetID == resulsetList.size() - 1) {
341
                        resulsetList.remove(resultsetID);
342
                } else {
343
                        resulsetList.set(resultsetID, null);
344
                }
345
                return rsInfo.get();
346
        }
347

    
348

    
349
        public final boolean resulsetNext(final int resultsetID)
350
                        throws JDBCException,
351
                        InvalidResultSetIdException, ResourceExecuteException {
352
                return ((Boolean) getResource().execute(new ResourceAction() {
353
                        public Object run() throws Exception {
354
                            boolean bool = getResultSet(resultsetID).next();
355
                                return Boolean.valueOf(bool);
356
                        }
357
                })).booleanValue();
358
        }
359

    
360
        public final void closeResulset(final int resultsetID)
361
                        throws JDBCException,
362
                        InvalidResultSetIdException, ResourceExecuteException {
363
                synchronized (this) {
364
                        getResource().execute(new ResourceAction() {
365
                                public Object run() throws Exception {
366
                                        ResultSet rs = dropResultSet(resultsetID);
367
                                        closeResulset(rs);
368
                                        return null;
369
                                }
370
                        });
371
                        if (logger.isDebugEnabled()) {
372
                                logger.debug(" id: " + resultsetID + " (total "
373
                                                + getResultsetOpenCount() + ")");
374
                        }
375
                        checksResulsets();
376
                }
377
        }
378

    
379
        public final void checksResulsets() throws JDBCException,
380
                        InvalidResultSetIdException, ResourceExecuteException {
381
                synchronized (this) {
382
                        getResource().execute(new ResourceAction() {
383
                                public Object run() throws Exception {
384
                                        ResultSetInfo rsInfo;
385
                                        for (int i = 0; i < resulsetList.size(); i++) {
386
                                                rsInfo = (ResultSetInfo) resulsetList.get(i);
387
                                                if (rsInfo == null) {
388
                                                        continue;
389
                                                }
390
                                                if (rsInfo.isZombie()) {
391
                                                        forceCloseResultSet(i);
392
                                                }
393
                                        }
394
                                        return null;
395
                                }
396
                        });
397
                }
398
        }
399

    
400
        protected void closeResulset(final ResultSet rs) throws JDBCException,
401
                        ResourceExecuteException {
402
                getResource().execute(new ResourceAction() {
403
                        public Object run() throws Exception {
404
                                Statement st = rs.getStatement();
405
                                Connection con = st.getConnection();
406
                                try {
407
                                        rs.close();
408
                                } finally {
409
                                        // TODO revisar esto
410
                                        try{ st.close();  } catch (Exception ex){ };
411
                                        try{ con.close(); } catch (Exception ex){ };
412
                                }
413
                                return null;
414
                        }
415
                });
416
        }
417

    
418
        private int getResultsetOpenCount() {
419
                int count = 0;
420
                Iterator<ResultSetInfo> iter = resulsetList.iterator();
421
                while (iter.hasNext()) {
422
                        if (iter.next() != null) {
423
                                count++;
424
                        }
425
                }
426
                return count;
427
        }
428

    
429
        protected final int openResulsetCount() {
430
                int count = 0;
431
                Iterator<ResultSetInfo> iter = resulsetList.iterator();
432
                while (iter.hasNext()) {
433
                        if (iter.next() != null) {
434
                                count++;
435
                        }
436
                }
437
                return count;
438
        }
439

    
440
        public boolean closeResourceRequested(ResourceProvider resource) {
441
                try {
442
                        checksResulsets();
443
                        return openResulsetCount() == 0 && closeResource(resource);
444
                } catch (DataException e) {
445
                        logger.error("Exception throws", e);
446
                        return false;
447
                }
448
        }
449

    
450

    
451
        protected String fixFilter(String filter) {
452
                if (filter == null) {
453
                        return null;
454
                }
455

    
456
                return filter;
457
        }
458

    
459
        protected JDBCHelper createHelper() throws InitializeException {
460
                return new JDBCHelper(this, getJDBCParameters());
461
        }
462

    
463
        protected JDBCHelper getHelper() {
464
                return helper;
465
        }
466

    
467
        protected void resetCount() {
468
                totalCount = null;
469
        }
470

    
471
        /**
472
         * Get feature count for a <code>filter</code>.<br>
473
         *
474
         * <code>filter</code> can be <code>null</code>.<br>
475
         *
476
         * <strong>Note:</strong><br>
477
         * this method have to perform <code>resouceBegin</code> at the begining and
478
         * <code>resourceEnd</code> at the end of execution.
479
         *
480
         *
481
         * @param filter
482
         * @return
483
         * @throws DataException
484
         */
485
        protected long getCount(String filter)
486
                        throws DataException {
487
                this.open();
488
                if (filter == null && totalCount != null) {
489
                        return totalCount.longValue();
490
                }
491
                final String sql = compoundCountSelect(filter);
492

    
493
                long count = ((Long) getResource().execute(new ResourceAction() {
494
                        public Object run() throws Exception {
495
                                long count = 0;
496
                                ResultSet rs = createNewResultSet(sql, null, 1);
497
                                try {
498
                                        if (rs.next()) {
499
                                                count = rs.getLong(1);
500
                                        }
501
                                } catch (SQLException e) {
502
                                        throw new JDBCSQLException(e);
503
                                } finally {
504
                                        closeResulset(rs);
505
                                }
506
                                return Long.valueOf(count);
507
                        }
508
                })).longValue();
509

    
510
                if (filter == null) {
511
                        totalCount = new Long(count);
512
                }
513
                return count;
514
        }
515

    
516
        public void close() throws CloseException {
517
                helper.close();
518
        }
519

    
520
        public void open() throws OpenException {
521
                helper.open();
522
        }
523

    
524
        @Override
525
        protected FeatureProvider internalGetFeatureProviderByReference(
526
                        FeatureReferenceProviderServices reference) throws DataException {
527
                return internalGetFeatureProviderByReference(reference,
528
                                getFeatureStore()
529
                                .getDefaultFeatureType());
530
        }
531

    
532
        @Override
533
        protected FeatureProvider internalGetFeatureProviderByReference(
534
                        FeatureReferenceProviderServices reference,
535
                        FeatureType featureType)
536
                        throws DataException {
537
                StringBuilder filter = new StringBuilder();
538
                FeatureAttributeDescriptor[] pk =
539
                                getFeatureStore().getFeatureType(featureType.getId())
540
                                                .getPrimaryKey();
541

    
542
                List<Object> values = new ArrayList<Object>();
543

    
544
                int i;
545
                for (i = 0; i < pk.length - 1; i++) {
546
                        values.add(
547
                                        helper.dalValueToJDBC(pk[i],
548
                                        reference.getKeyValue(pk[i].getName())));
549
                        filter.append(helper.getSqlFieldName(pk[i]));
550
                        filter.append(" = ? AND ");
551
                }
552
                values.add(helper.dalValueToJDBC(pk[i],
553
                                reference.getKeyValue(pk[i].getName())));
554
                filter.append(helper.getSqlFieldName(pk[i]));
555
                filter.append(" = ? ");
556

    
557
                String sql = compoundSelect(featureType, filter.toString(), null, 1, 0);
558

    
559
                FeatureProvider data;
560
                int rsId = createResultSet(sql, values.toArray(), 1);
561
                try {
562
                        if (!resulsetNext(rsId)) {
563
                                throw new RuntimeException("Reference Not found");
564
                        }
565
                        data = createFeatureProvider(featureType);
566
                        loadFeatureProvider(data, rsId);
567
                } finally {
568
                        closeResulset(rsId);
569
                }
570

    
571
                return data;
572
        }
573

    
574
        public int getOIDType() {
575
                return DataTypes.UNKNOWN;
576
        }
577

    
578
        protected void initFeatureType() throws InitializeException {
579

    
580
                EditableFeatureType edFType = null;
581
                try {
582
                        edFType = this.getStoreServices().createFeatureType();
583

    
584
                        helper.loadFeatureType(edFType, getJDBCParameters());
585

    
586
                } catch (DataException e) {
587
                        throw new InitializeException(this.getProviderName(), e);
588
                }
589

    
590
                FeatureType defaultType = edFType.getNotEditableCopy();
591
                List<FeatureType> types = Collections.singletonList(defaultType);
592
                this.getStoreServices().setFeatureTypes(types, defaultType);
593
        }
594

    
595
        protected ResultSet createNewResultSet(final String sql,
596
                        final Object[] values, final int fetchSize)
597
                        throws DataException {
598
                this.open();
599
                return (ResultSet) getResource().execute(new ResourceAction() {
600
                        public Object run() throws Exception {
601
                                Connection conn = null;
602
                                PreparedStatement st = null;
603
                                ResultSet rs = null;
604
                                try {
605

    
606
                                        conn = helper.getConnection();
607
                                        conn.setAutoCommit(false);
608
                                        st = conn.prepareStatement(sql);
609

    
610
                                        if (values != null) {
611
                                                Object value;
612
                                                for (int i = 0; i < values.length; i++) {
613
                                                        value = values[i];
614
                                                        if (value instanceof Geometry) {
615
                                                                byte[] bytes;
616
                                                                try {
617
                                                                        bytes = ((Geometry) value).convertToWKB();
618
                                                                } catch (BaseException e) {
619
                                                                        throw new InvalidParameterException();
620
                                                                }
621
                                                                st.setBytes(i + 1, bytes);
622
                                                        }
623
                                                        st.setObject(i + 1, value);
624
                                                }
625
                                        }
626

    
627
                                        if (fetchSize > 0) {
628
                                                st.setFetchSize(fetchSize);
629
                                        }
630
                                        rs = st.executeQuery();
631
                                        if (fetchSize > 0) {
632
                                                rs.setFetchSize(fetchSize);
633
                                        }
634
                                        return rs;
635
                                } catch (SQLException e) {
636
                                        try {
637
                                                rs.close();
638
                                        } catch (Exception e1) {
639
                                        }
640
                                        try {
641
                                                st.close();
642
                                        } catch (Exception e1) {
643
                                        }
644
                                        try {
645
                                                conn.close();
646
                                        } catch (Exception e1) {
647
                                        }
648
                                        throw new JDBCExecutePreparedSQLException(sql,values,e);
649
                                }
650
                        }
651
                });
652
        }
653

    
654
        protected boolean closeResource(ResourceProvider resource) {
655
                try {
656
                        this.helper.close();
657
                } catch (CloseException e) {
658
                        logger.error("Exception in close Request", e);
659
                }
660
                return !this.helper.isOpen();
661
        }
662

    
663
        protected String compoundCountSelect(String filter) {
664
                if (this.directSQLMode) {
665
                        return null;
666
                }
667
                // Select
668
                StringBuilder sql = new StringBuilder();
669
                sql.append("Select count(");
670
                String[] pkFields = getJDBCParameters().getPkFields();
671
                if (pkFields != null && pkFields.length == 1) {
672
                        sql.append(helper.escapeFieldName(pkFields[0]));
673
                } else {
674
                        sql.append('*');
675

    
676
                }
677
                sql.append(") ");
678

    
679
                sql.append("from ");
680

    
681
                sql.append(getJDBCParameters().tableID());
682
                sql.append(' ');
683

    
684
                appendWhere(sql, filter);
685

    
686
                return sql.toString();
687
        }
688

    
689
        protected void appendWhere(StringBuilder sql, String filter) {
690
                filter = fixFilter(filter);
691
                String initialFilter = getJDBCParameters().getBaseFilter();
692
                if ((initialFilter != null && initialFilter.length() != 0)
693
                                || (filter != null && filter.length() != 0)) {
694
                        sql.append("where (");
695

    
696
                        if (initialFilter != null && initialFilter.length() != 0
697
                                        && filter != null && filter.length() != 0) {
698
                                // initialFilter + filter
699
                                sql.append('(');
700
                                sql.append(initialFilter);
701
                                sql.append(") and (");
702
                                sql.append(filter);
703
                                sql.append(')');
704
                        } else if (initialFilter != null && initialFilter.length() != 0) {
705
                                // initialFilter only
706
                                sql.append(initialFilter);
707
                        } else {
708
                                // filter only
709
                                sql.append(filter);
710
                        }
711
                        sql.append(") ");
712
                }
713
        }
714

    
715
        public void closeDone() throws DataException {
716
                // Do nothing
717
        }
718

    
719
        public void opendDone() throws DataException {
720
                // Nothing to do
721
        }
722

    
723
        public Envelope getEnvelope() throws DataException {
724
                this.open();
725
                String defaultGeometryAttributeName;
726
                defaultGeometryAttributeName = this.getFeatureStore()
727
                        .getDefaultFeatureType()
728
                                .getDefaultGeometryAttributeName();
729
                if( defaultGeometryAttributeName != null ) {
730
                        return this.helper.getFullEnvelopeOfField(
731
                                        this.getJDBCParameters(),
732
                                        defaultGeometryAttributeName, 
733
                                        this.getJDBCParameters().getWorkingArea()
734
                                );
735
                }
736
                return null;
737
        }
738

    
739
        public void resourceChanged(ResourceProvider resource) {
740
                this.getStoreServices().notifyChange(
741
                                DataStoreNotification.RESOURCE_CHANGED,
742
                                resource);
743
        }
744

    
745
        public boolean allowAutomaticValues() {
746
                return this.helper.allowAutomaticValues();
747
        }
748

    
749
        public DataServerExplorer getExplorer() throws ReadException {
750
                DataManager manager = DALLocator.getDataManager();
751
                JDBCServerExplorerParameters exParams;
752
                JDBCStoreParameters params = getJDBCParameters();
753
                try {
754
                        exParams = (JDBCServerExplorerParameters) manager
755
                                        .createServerExplorerParameters(JDBCServerExplorer.NAME);
756
                        exParams.setHost(params.getHost());
757
                        exParams.setPort(params.getPort());
758
                        exParams.setDBName(params.getDBName());
759
                        exParams.setUser(params.getUser());
760
                        exParams.setPassword(params.getPassword());
761
                        exParams.setUrl(params.getUrl());
762
                        exParams.setCatalog(params.getCatalog());
763
                        exParams.setSchema(params.getSchema());
764
                        exParams.setJDBCDriverClassName(params.getJDBCDriverClassName());
765

    
766
                        return manager.openServerExplorer(JDBCServerExplorer.NAME,exParams);
767
                } catch (DataException e) {
768
                        throw new ReadException(this.getProviderName(), e);
769
                } catch (ValidateDataParametersException e) {
770
                        throw new ReadException(this.getProviderName(), e);
771
                }
772
        }
773

    
774
        @Override
775
        protected void doDispose() throws BaseException {
776
                this.close();
777
                resulsetList = null;
778
                this.helper.dispose();
779
                super.doDispose();
780
        }
781

    
782
        public Object createNewOID() {
783
                return null;
784
        }
785

    
786
        public String compoundSelect(FeatureType type, String filter, String order,
787
                        long limit, long offset) throws DataException {
788
                StringBuilder sql = new StringBuilder();
789
                JDBCStoreParameters params = getJDBCParameters();
790
                if (directSQLMode) {
791
                        sql.append(params.getSQL());
792
                        sql.append(' ');
793
                } else {
794
                        FeatureAttributeDescriptor[] fields = type
795
                                        .getAttributeDescriptors();
796

    
797
                        // Select
798
                        sql.append("Select ");
799
                        for (int i = 0; i < fields.length - 1; i++) {
800
                                sql.append(helper.getSqlFieldName(fields[i]));
801
                                sql.append(", ");
802
                        }
803
                        sql.append(helper.getSqlFieldName(fields[fields.length - 1]));
804
                        sql.append(' ');
805

    
806
                        FeatureAttributeDescriptor[] pkFields = getStoreServices()
807
                                        .getProviderFeatureType(type.getId()).getPrimaryKey();
808

    
809
                        if (pkFields != null && pkFields.length > 0) {
810
                                // checks for pk fields are in select
811
                                boolean toAdd;
812
                                for (int i = 0; i < pkFields.length; i++) {
813
                                        toAdd = true;
814
                                        for (int j = 0; j < fields.length; j++) {
815
                                                if (pkFields[i].getName().equals(fields[j].getName())) {
816
                                                        toAdd = false;
817
                                                        break;
818
                                                }
819
                                                if (toAdd) {
820
                                                        sql.append(", ");
821
                                                        sql.append(helper.getSqlFieldName(pkFields[i]));
822
                                                }
823
                                        }
824
                                }
825
                                sql.append(' ');
826
                        }
827

    
828
                        // table
829
                        sql.append("from ");
830
                        sql.append(params.tableID());
831
                        sql.append(' ');
832

    
833
                        // Where
834
                        appendWhere(sql, filter);
835

    
836
                        // Order
837
                        if ((params.getBaseOrder() != null && params.getBaseOrder()
838
                                        .length() != 0)
839
                                        || (order != null && order.length() != 0)) {
840
                                sql.append("order by ");
841

    
842
                                if (order != null && order.length() != 0) {
843
                                        // order
844
                                        sql.append(order);
845
                                } else {
846
                                        // initial order
847
                                        sql.append(params.getBaseOrder());
848
                                }
849
                                sql.append(' ');
850
                        }
851
                }
852
                // limit offset
853
                if (limit > 0 || offset > 0) {
854
                        sql.append(helper.compoundLimitAndOffset(limit,offset));
855
                }
856
                return sql.toString();
857
        }
858

    
859
        public long getFeatureCount() throws DataException {
860
                return getCount(null);
861
        }
862

    
863
        public String getProviderName() {
864
                return NAME;
865
        }
866

    
867
        public boolean hasGeometrySupport() {
868
                return false;
869
        }
870

    
871
        public FeatureSetProvider createSet(FeatureQuery query,
872
                        FeatureType featureType) throws DataException {
873

    
874
                return new JDBCSetProvider(this, query, featureType);
875
        }
876

    
877
        public Object getSourceId() {
878
                return this.getJDBCParameters().getSourceId();
879
        }
880
        
881
        public String getName() {
882
                return this.getJDBCParameters().tableID();
883
        }
884
        
885
        public String getFullName() {
886
                return this.getJDBCParameters().getHost()+":"+this.getJDBCParameters().getDBName()+":"+this.getJDBCParameters().tableID();
887
        }
888
        
889

    
890
        public ResourceProvider getResource() {
891
                return getHelper().getResource();
892
        }
893
        
894
        protected boolean isDirectSQLMode(){
895
            return directSQLMode;
896
        }
897
}