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 @ 40435

History | View | Annotate | Download (23.6 KB)

1
/* gvSIG. Geographic Information System of the Valencian Government
2
*
3
* Copyright (C) 2007-2008 Infrastructures and Transports Department
4
* of the Valencian Government (CIT)
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 2
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
*/
22

    
23
/*
24
* AUTHORS (In addition to CIT):
25
* 2009 IVER T.I   {{Task}}
26
*/
27

    
28
/**
29
 *
30
 */
31
package org.gvsig.fmap.dal.store.jdbc;
32

    
33
import java.security.InvalidParameterException;
34
import java.sql.Connection;
35
import java.sql.PreparedStatement;
36
import java.sql.ResultSet;
37
import java.sql.SQLException;
38
import java.sql.Statement;
39
import java.util.ArrayList;
40
import java.util.Collections;
41
import java.util.Iterator;
42
import java.util.List;
43

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

    
85

    
86
/**
87
 * @author jmvivo
88
 *
89
 */
90
public class JDBCStoreProvider extends AbstractFeatureStoreProvider
91
                implements JDBCHelperUser {
92

    
93
        final static private Logger logger = LoggerFactory
94
                        .getLogger(JDBCStoreProvider.class);
95

    
96
        private List<ResultSetInfo> resulsetList;
97

    
98
        public static String NAME = "JDBC";
99
        public static String DESCRIPTION = "JDBC source";
100

    
101
        public static final String METADATA_DEFINITION_NAME = NAME;
102

    
103
        private long mlsecondsToZombie = 1000 * 60 * 10; // 10 Min
104

    
105
        protected JDBCHelper helper;
106

    
107
        protected boolean directSQLMode;
108

    
109
        private Long totalCount = null;
110
        private GeometryManager geomManager = null;
111

    
112
        public JDBCStoreProvider(JDBCStoreParameters params,
113
                        DataStoreProviderServices storeServices) throws InitializeException {
114
                this(
115
                                params, 
116
                                storeServices,
117
                                DBHelper.newMetadataContainer(METADATA_DEFINITION_NAME)
118
                );
119
        }
120

    
121
        protected JDBCStoreProvider(JDBCStoreParameters params,
122
                        DataStoreProviderServices storeServices, DynObject metadata)
123
                        throws InitializeException {
124
                super(params, storeServices, metadata);
125
                geomManager = GeometryLocator.getGeometryManager();
126
                
127
                resulsetList = new ArrayList<ResultSetInfo>(10);
128

    
129
                helper = createHelper();
130
                if (params.getSQL() != null && (params.getSQL()).trim().length() > 0) {
131
                        directSQLMode = true;
132
                }
133

    
134
                this.initFeatureType();
135
        }
136

    
137
        public Object getDynValue(String name) throws DynFieldNotFoundException {
138
                try {
139
                        if( DataStore.METADATA_ENVELOPE.equalsIgnoreCase(name) ) {
140
                                Envelope env = this.getEnvelope();
141
                                if( env != null ) {
142
                                        return env;
143
                                }
144
                        } else if( DataStore.METADATA_CRS.equalsIgnoreCase(name) ) {
145
                                IProjection proj;
146
                                proj = this.getFeatureStore().getDefaultFeatureType().getDefaultSRS();
147
                                if( proj != null ) {
148
                                        return proj;
149
                                }
150
                        }
151
                } catch (DataException e) {
152
                        throw new RuntimeException(e);
153
                }
154
                return super.getDynValue(name);
155
        }
156
        
157

    
158
        protected JDBCStoreParameters getJDBCParameters() {
159
                return (JDBCStoreParameters) this.getParameters();
160
        }
161

    
162

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

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

    
210
                } else {
211
                        try {
212
                                data.set(attr.getIndex(), rs.getObject(attr.getIndex() + 1));
213
                        } catch (SQLException e) {
214
                                throw new JDBCSQLException(e);
215
                        }
216
                }
217
        }
218

    
219
        public long getTimeToResulSetZombie() {
220
                return mlsecondsToZombie;
221
        }
222

    
223
        public void setTimeToResulSetZombie(long mlSeconds) {
224
                mlsecondsToZombie = mlSeconds;
225
        }
226

    
227
        private class ResultSetInfo{
228
                private ResultSet resultSet = null;
229
                private long lastUse = 0;
230

    
231
                public ResultSetInfo(ResultSet resulSet) {
232
                        this.resultSet = resulSet;
233
                        used();
234
                }
235

    
236
                private void used() {
237
                        lastUse = System.currentTimeMillis();
238
                }
239

    
240

    
241
                public ResultSet get() {
242
                        used();
243
                        return resultSet;
244
                }
245

    
246
                public boolean isZombie() {
247
                        return System.currentTimeMillis() - lastUse > mlsecondsToZombie;
248
                }
249
        }
250

    
251
        public final int createResultSet(String sql, int fetchSize)
252
                        throws DataException {
253
        return createResultSet(sql, null, fetchSize);
254
        }
255

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

    
277
                                        return Integer.valueOf(newId);
278
                                }
279
                        })).intValue();
280
                }
281
        }
282

    
283
        private int getNewId() {
284
                int newId;
285
                if (resulsetList.size() < 1) {
286
                        return -1;
287
                }
288
                for (newId = 0; newId < resulsetList.size(); newId++) {
289
                        if (resulsetList.get(newId) == null) {
290
                                return newId;
291
                        }
292
                }
293
                return -1;
294
        }
295

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

    
315
                }
316
        }
317
        
318
        protected final void forceCloseResultSet(int rsID)
319
                        throws ResourceExecuteException, JDBCException,
320
                        InvalidResultSetIdException {
321
                logger.warn("Close forced of resultSet ({})", rsID);
322
                closeResulset(rsID);
323
        }
324

    
325
        protected final ResultSet getResultSet(int resultsetID)
326
                        throws InvalidResultSetIdException {
327
                if (resultsetID >= resulsetList.size()) {
328
                        throw new InvalidResultSetIdException(resultsetID);
329
                }
330
                ResultSetInfo rsInfo = resulsetList.get(resultsetID);
331
                if (rsInfo == null) {
332
                        throw new InvalidResultSetIdException(resultsetID);
333
                }
334
                return rsInfo.get();
335

    
336
        }
337

    
338
        private ResultSet dropResultSet(int resultsetID)
339
                        throws InvalidResultSetIdException {
340
                if (resultsetID >= resulsetList.size()) {
341
                        throw new InvalidResultSetIdException(resultsetID);
342
                }
343
                ResultSetInfo rsInfo = (ResultSetInfo) resulsetList.get(resultsetID);
344
                if (rsInfo == null) {
345
                        throw new InvalidResultSetIdException(resultsetID);
346
                }
347
                if (resultsetID == resulsetList.size() - 1) {
348
                        resulsetList.remove(resultsetID);
349
                } else {
350
                        resulsetList.set(resultsetID, null);
351
                }
352
                return rsInfo.get();
353
        }
354

    
355

    
356
        public final boolean resulsetNext(final int resultsetID)
357
                        throws JDBCException,
358
                        InvalidResultSetIdException, ResourceExecuteException {
359
                return ((Boolean) getResource().execute(new ResourceAction() {
360
                        public Object run() throws Exception {
361
                            boolean bool = getResultSet(resultsetID).next();
362
                                return Boolean.valueOf(bool);
363
                        }
364
                })).booleanValue();
365
        }
366

    
367
        public final void closeResulset(final int resultsetID)
368
                        throws JDBCException,
369
                        InvalidResultSetIdException, ResourceExecuteException {
370
                synchronized (this) {
371
                        getResource().execute(new ResourceAction() {
372
                                public Object run() throws Exception {
373
                                        ResultSet rs = dropResultSet(resultsetID);
374
                                        closeResulset(rs);
375
                                        return null;
376
                                }
377
                        });
378
                        if (logger.isDebugEnabled()) {
379
                                logger.debug(" id: " + resultsetID + " (total "
380
                                                + getResultsetOpenCount() + ")");
381
                        }
382
                        checksResulsets();
383
                }
384
        }
385

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

    
407
        protected void closeResulset(final ResultSet rs) throws JDBCException,
408
                        ResourceExecuteException {
409
                getResource().execute(new ResourceAction() {
410
                        public Object run() throws Exception {
411
                                Statement st = rs.getStatement();
412
                                Connection con = st.getConnection();
413
                                try {
414
                                        rs.close();
415
                                } finally {
416
                                        // TODO revisar esto
417
                                        try{ st.close();  } catch (Exception ex){ };
418
                                        try{ con.close(); } catch (Exception ex){ };
419
                                }
420
                                return null;
421
                        }
422
                });
423
        }
424

    
425
        private int getResultsetOpenCount() {
426
                int count = 0;
427
                Iterator<ResultSetInfo> iter = resulsetList.iterator();
428
                while (iter.hasNext()) {
429
                        if (iter.next() != null) {
430
                                count++;
431
                        }
432
                }
433
                return count;
434
        }
435

    
436
        protected final int openResulsetCount() {
437
                int count = 0;
438
                Iterator<ResultSetInfo> iter = resulsetList.iterator();
439
                while (iter.hasNext()) {
440
                        if (iter.next() != null) {
441
                                count++;
442
                        }
443
                }
444
                return count;
445
        }
446

    
447
        public boolean closeResourceRequested(ResourceProvider resource) {
448
                try {
449
                        checksResulsets();
450
                        return openResulsetCount() == 0 && closeResource(resource);
451
                } catch (DataException e) {
452
                        logger.error("Exception throws", e);
453
                        return false;
454
                }
455
        }
456

    
457

    
458
        protected String fixFilter(String filter) {
459
                if (filter == null) {
460
                        return null;
461
                }
462

    
463
                return filter;
464
        }
465

    
466
        protected JDBCHelper createHelper() throws InitializeException {
467
                return new JDBCHelper(this, getJDBCParameters());
468
        }
469

    
470
        protected JDBCHelper getHelper() {
471
                return helper;
472
        }
473

    
474
        protected void resetCount() {
475
                totalCount = null;
476
        }
477

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

    
500
                long count = ((Long) getResource().execute(new ResourceAction() {
501
                        public Object run() throws Exception {
502
                                long count = 0;
503
                                ResultSet rs = createNewResultSet(sql, null, 1);
504
                                try {
505
                                        if (rs.next()) {
506
                                                count = rs.getLong(1);
507
                                        }
508
                                } catch (SQLException e) {
509
                                        throw new JDBCSQLException(e);
510
                                } finally {
511
                                        closeResulset(rs);
512
                                }
513
                                return Long.valueOf(count);
514
                        }
515
                })).longValue();
516

    
517
                if (filter == null) {
518
                        totalCount = new Long(count);
519
                }
520
                return count;
521
        }
522

    
523
        public void close() throws CloseException {
524
                helper.close();
525
        }
526

    
527
        public void open() throws OpenException {
528
                helper.open();
529
        }
530

    
531
        @Override
532
        protected FeatureProvider internalGetFeatureProviderByReference(
533
                        FeatureReferenceProviderServices reference) throws DataException {
534
                return internalGetFeatureProviderByReference(reference,
535
                                getFeatureStore()
536
                                .getDefaultFeatureType());
537
        }
538

    
539
        @Override
540
        protected FeatureProvider internalGetFeatureProviderByReference(
541
                        FeatureReferenceProviderServices reference,
542
                        FeatureType featureType)
543
                        throws DataException {
544
                StringBuilder filter = new StringBuilder();
545
                FeatureAttributeDescriptor[] pk =
546
                                getFeatureStore().getFeatureType(featureType.getId())
547
                                                .getPrimaryKey();
548

    
549
                List<Object> values = new ArrayList<Object>();
550

    
551
                int i;
552
                for (i = 0; i < pk.length - 1; i++) {
553
                        values.add(
554
                                        helper.dalValueToJDBC(pk[i],
555
                                        reference.getKeyValue(pk[i].getName())));
556
                        filter.append(helper.getSqlFieldName(pk[i]));
557
                        filter.append(" = ? AND ");
558
                }
559
                values.add(helper.dalValueToJDBC(pk[i],
560
                                reference.getKeyValue(pk[i].getName())));
561
                filter.append(helper.getSqlFieldName(pk[i]));
562
                filter.append(" = ? ");
563

    
564
                String sql = compoundSelect(featureType, filter.toString(), null, 1, 0);
565

    
566
                FeatureProvider data;
567
                int rsId = createResultSet(sql, values.toArray(), 1);
568
                try {
569
                        if (!resulsetNext(rsId)) {
570
                                throw new RuntimeException("Reference Not found");
571
                        }
572
                        data = createFeatureProvider(featureType);
573
                        loadFeatureProvider(data, rsId);
574
                } finally {
575
                        closeResulset(rsId);
576
                }
577

    
578
                return data;
579
        }
580

    
581
        public int getOIDType() {
582
                return DataTypes.UNKNOWN;
583
        }
584

    
585
        protected void initFeatureType() throws InitializeException {
586

    
587
                EditableFeatureType edFType = null;
588
                try {
589
                        edFType = this.getStoreServices().createFeatureType();
590

    
591
                        helper.loadFeatureType(edFType, getJDBCParameters());
592

    
593
                } catch (DataException e) {
594
                        throw new InitializeException(this.getProviderName(), e);
595
                }
596

    
597
                FeatureType defaultType = edFType.getNotEditableCopy();
598
                List<FeatureType> types = Collections.singletonList(defaultType);
599
                this.getStoreServices().setFeatureTypes(types, defaultType);
600
        }
601

    
602
        protected ResultSet createNewResultSet(final String sql,
603
                        final Object[] values, final int fetchSize)
604
                        throws DataException {
605
                this.open();
606
                return (ResultSet) getResource().execute(new ResourceAction() {
607
                        public Object run() throws Exception {
608
                                Connection conn = null;
609
                                PreparedStatement st = null;
610
                                ResultSet rs = null;
611
                                try {
612

    
613
                                        conn = helper.getConnection();
614
                                        conn.setAutoCommit(false);
615
                                        st = conn.prepareStatement(sql);
616

    
617
                                        if (values != null) {
618
                                                Object value;
619
                                                for (int i = 0; i < values.length; i++) {
620
                                                        value = values[i];
621
                                                        if (value instanceof Geometry) {
622
                                                                byte[] bytes;
623
                                                                try {
624
                                                                        bytes = ((Geometry) value).convertToWKB();
625
                                                                } catch (BaseException e) {
626
                                                                        throw new InvalidParameterException();
627
                                                                }
628
                                                                st.setBytes(i + 1, bytes);
629
                                                        }
630
                                                        st.setObject(i + 1, value);
631
                                                }
632
                                        }
633

    
634
                                        if (fetchSize > 0) {
635
                                                st.setFetchSize(fetchSize);
636
                                        }
637
                                        rs = st.executeQuery();
638
                                        if (fetchSize > 0) {
639
                                                rs.setFetchSize(fetchSize);
640
                                        }
641
                                        return rs;
642
                                } catch (SQLException e) {
643
                                        try {
644
                                                rs.close();
645
                                        } catch (Exception e1) {
646
                                        }
647
                                        try {
648
                                                st.close();
649
                                        } catch (Exception e1) {
650
                                        }
651
                                        try {
652
                                                conn.close();
653
                                        } catch (Exception e1) {
654
                                        }
655
                                        throw new JDBCExecutePreparedSQLException(sql,values,e);
656
                                }
657
                        }
658
                });
659
        }
660

    
661
        protected boolean closeResource(ResourceProvider resource) {
662
                try {
663
                        this.helper.close();
664
                } catch (CloseException e) {
665
                        logger.error("Exception in close Request", e);
666
                }
667
                return !this.helper.isOpen();
668
        }
669

    
670
        protected String compoundCountSelect(String filter) {
671
                if (this.directSQLMode) {
672
                        return null;
673
                }
674
                // Select
675
                StringBuilder sql = new StringBuilder();
676
                sql.append("Select count(");
677
                String[] pkFields = getJDBCParameters().getPkFields();
678
                if (pkFields != null && pkFields.length == 1) {
679
                        sql.append(helper.escapeFieldName(pkFields[0]));
680
                } else {
681
                        sql.append('*');
682

    
683
                }
684
                sql.append(") ");
685

    
686
                sql.append("from ");
687

    
688
                sql.append(getJDBCParameters().tableID());
689
                sql.append(' ');
690

    
691
                appendWhere(sql, filter);
692

    
693
                return sql.toString();
694
        }
695

    
696
        protected void appendWhere(StringBuilder sql, String filter) {
697
                filter = fixFilter(filter);
698
                String initialFilter = getJDBCParameters().getBaseFilter();
699
                if ((initialFilter != null && initialFilter.length() != 0)
700
                                || (filter != null && filter.length() != 0)) {
701
                        sql.append("where (");
702

    
703
                        if (initialFilter != null && initialFilter.length() != 0
704
                                        && filter != null && filter.length() != 0) {
705
                                // initialFilter + filter
706
                                sql.append('(');
707
                                sql.append(initialFilter);
708
                                sql.append(") and (");
709
                                sql.append(filter);
710
                                sql.append(')');
711
                        } else if (initialFilter != null && initialFilter.length() != 0) {
712
                                // initialFilter only
713
                                sql.append(initialFilter);
714
                        } else {
715
                                // filter only
716
                                sql.append(filter);
717
                        }
718
                        sql.append(") ");
719
                }
720
        }
721

    
722
        public void closeDone() throws DataException {
723
                // Do nothing
724
        }
725

    
726
        public void opendDone() throws DataException {
727
                // Nothing to do
728
        }
729

    
730
        public Envelope getEnvelope() throws DataException {
731
                this.open();
732
                String defaultGeometryAttributeName;
733
                defaultGeometryAttributeName = this.getFeatureStore()
734
                        .getDefaultFeatureType()
735
                                .getDefaultGeometryAttributeName();
736
                if( defaultGeometryAttributeName != null ) {
737
                        return this.helper.getFullEnvelopeOfField(
738
                                        this.getJDBCParameters(),
739
                                        defaultGeometryAttributeName, 
740
                                        this.getJDBCParameters().getWorkingArea()
741
                                );
742
                }
743
                return null;
744
        }
745

    
746
        public void resourceChanged(ResourceProvider resource) {
747
                this.getStoreServices().notifyChange(
748
                                DataStoreNotification.RESOURCE_CHANGED,
749
                                resource);
750
        }
751

    
752
        public boolean allowAutomaticValues() {
753
                return this.helper.allowAutomaticValues();
754
        }
755

    
756
        public DataServerExplorer getExplorer() throws ReadException {
757
                DataManager manager = DALLocator.getDataManager();
758
                JDBCServerExplorerParameters exParams;
759
                JDBCStoreParameters params = getJDBCParameters();
760
                try {
761
                        exParams = (JDBCServerExplorerParameters) manager
762
                                        .createServerExplorerParameters(JDBCServerExplorer.NAME);
763
                        exParams.setHost(params.getHost());
764
                        exParams.setPort(params.getPort());
765
                        exParams.setDBName(params.getDBName());
766
                        exParams.setUser(params.getUser());
767
                        exParams.setPassword(params.getPassword());
768
                        exParams.setUrl(params.getUrl());
769
                        exParams.setCatalog(params.getCatalog());
770
                        exParams.setSchema(params.getSchema());
771
                        exParams.setJDBCDriverClassName(params.getJDBCDriverClassName());
772

    
773
                        return manager.openServerExplorer(JDBCServerExplorer.NAME,exParams);
774
                } catch (DataException e) {
775
                        throw new ReadException(this.getProviderName(), e);
776
                } catch (ValidateDataParametersException e) {
777
                        throw new ReadException(this.getProviderName(), e);
778
                }
779
        }
780

    
781
        @Override
782
        protected void doDispose() throws BaseException {
783
                this.close();
784
                resulsetList = null;
785
                this.helper.dispose();
786
                super.doDispose();
787
        }
788

    
789
        public Object createNewOID() {
790
                return null;
791
        }
792

    
793
        public String compoundSelect(FeatureType type, String filter, String order,
794
                        long limit, long offset) throws DataException {
795
                StringBuilder sql = new StringBuilder();
796
                JDBCStoreParameters params = getJDBCParameters();
797
                if (directSQLMode) {
798
                        sql.append(params.getSQL());
799
                        sql.append(' ');
800
                } else {
801
                        FeatureAttributeDescriptor[] fields = type
802
                                        .getAttributeDescriptors();
803

    
804
                        // Select
805
                        sql.append("Select ");
806
                        for (int i = 0; i < fields.length - 1; i++) {
807
                                sql.append(helper.getSqlFieldName(fields[i]));
808
                                sql.append(", ");
809
                        }
810
                        sql.append(helper.getSqlFieldName(fields[fields.length - 1]));
811
                        sql.append(' ');
812

    
813
                        FeatureAttributeDescriptor[] pkFields = getStoreServices()
814
                                        .getProviderFeatureType(type.getId()).getPrimaryKey();
815

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

    
835
                        // table
836
                        sql.append("from ");
837
                        sql.append(params.tableID());
838
                        sql.append(' ');
839

    
840
                        // Where
841
                        appendWhere(sql, filter);
842

    
843
                        // Order
844
                        if ((params.getBaseOrder() != null && params.getBaseOrder()
845
                                        .length() != 0)
846
                                        || (order != null && order.length() != 0)) {
847
                                sql.append("order by ");
848

    
849
                                if (order != null && order.length() != 0) {
850
                                        // order
851
                                        sql.append(order);
852
                                } else {
853
                                        // initial order
854
                                        sql.append(params.getBaseOrder());
855
                                }
856
                                sql.append(' ');
857
                        }
858
                }
859
                // limit offset
860
                if (limit > 0 || offset > 0) {
861
                        sql.append(helper.compoundLimitAndOffset(limit,offset));
862
                }
863
                return sql.toString();
864
        }
865

    
866
        public long getFeatureCount() throws DataException {
867
                return getCount(null);
868
        }
869

    
870
        public String getProviderName() {
871
                return NAME;
872
        }
873

    
874
        public boolean hasGeometrySupport() {
875
                return false;
876
        }
877

    
878
        public FeatureSetProvider createSet(FeatureQuery query,
879
                        FeatureType featureType) throws DataException {
880

    
881
                return new JDBCSetProvider(this, query, featureType);
882
        }
883

    
884
        public Object getSourceId() {
885
                return this.getJDBCParameters().getSourceId();
886
        }
887
        
888
        public String getName() {
889
                return this.getJDBCParameters().tableID();
890
        }
891
        
892
        public String getFullName() {
893
                return this.getJDBCParameters().getHost()+":"+this.getJDBCParameters().getDBName()+":"+this.getJDBCParameters().tableID();
894
        }
895
        
896

    
897
        public ResourceProvider getResource() {
898
                return getHelper().getResource();
899
        }
900
        
901
        protected boolean isDirectSQLMode(){
902
            return directSQLMode;
903
        }
904
}