Statistics
| Revision:

svn-gvsig-desktop / branches / v2_0_0_prep / libraries / libFMap_daldb / src / org / gvsig / fmap / dal / store / jdbc / JDBCStoreProvider.java @ 33717

History | View | Annotate | Download (23.4 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.JDBCSQLException;
74
import org.gvsig.fmap.geom.Geometry;
75
import org.gvsig.fmap.geom.operation.towkb.ToWKB;
76
import org.gvsig.fmap.geom.primitive.Envelope;
77
import org.gvsig.metadata.MetadataLocator;
78
import org.gvsig.metadata.MetadataManager;
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

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

    
120
        protected JDBCStoreProvider(JDBCStoreParameters params,
121
                        DataStoreProviderServices storeServices, DynObject metadata)
122
                        throws InitializeException {
123
                super(params, storeServices, metadata);
124

    
125
                resulsetList = new ArrayList<ResultSetInfo>(10);
126

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

    
132
                this.initFeatureType();
133
        }
134

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

    
156
        protected JDBCStoreParameters getJDBCParameters() {
157
                return (JDBCStoreParameters) this.getParameters();
158
        }
159

    
160

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

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

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

    
217
        public long getTimeToResulSetZombie() {
218
                return mlsecondsToZombie;
219
        }
220

    
221
        public void setTimeToResulSetZombie(long mlSeconds) {
222
                mlsecondsToZombie = mlSeconds;
223
        }
224

    
225
        private class ResultSetInfo{
226
                private ResultSet resultSet = null;
227
                private long lastUse = 0;
228

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

    
234
                private void used() {
235
                        lastUse = System.currentTimeMillis();
236
                }
237

    
238

    
239
                public ResultSet get() {
240
                        used();
241
                        return resultSet;
242
                }
243

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

    
249
        public final int createResultSet(String sql, int fetchSize)
250
                        throws DataException {
251
                return createResultSet(sql, null, -1);
252
        }
253

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

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

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

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

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

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

    
335
        }
336

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

    
354

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

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

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

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

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

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

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

    
455

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

    
461
                return filter;
462
        }
463

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

    
468
        protected JDBCHelper getHelper() {
469
                return helper;
470
        }
471

    
472
        protected void resetCount() {
473
                totalCount = null;
474
        }
475

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

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

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

    
521
        public void close() throws CloseException {
522
                helper.close();
523
        }
524

    
525
        public void open() throws OpenException {
526
                helper.open();
527
        }
528

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

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

    
547
                List<Object> values = new ArrayList<Object>();
548

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

    
562
                String sql = compoundSelect(featureType, filter.toString(), null, 1, 0);
563

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

    
576
                return data;
577
        }
578

    
579
        public int getOIDType() {
580
                return DataTypes.UNKNOWN;
581
        }
582

    
583
        protected void initFeatureType() throws InitializeException {
584

    
585
                EditableFeatureType edFType = null;
586
                try {
587
                        edFType = this.getStoreServices().createFeatureType();
588

    
589
                        helper.loadFeatureType(edFType, getJDBCParameters());
590

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

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

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

    
611
                                        conn = helper.getConnection();
612
                                        conn.setAutoCommit(false);
613
                                        st = conn.prepareStatement(sql);
614

    
615
                                        if (values != null) {
616
                                                Object value;
617
                                                for (int i = 0; i < values.length; i++) {
618
                                                        value = values[i];
619
                                                        if (value instanceof Geometry) {
620
                                                                byte[] bytes;
621
                                                                try {
622
                                                                        bytes =
623
                                                                                        (byte[]) ((Geometry) value).invokeOperation(
624
                                                                                                        ToWKB.CODE, null);
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 JDBCSQLException(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
                        if (filter != null || order != null) {
799
                                throw new UnsupportedOperationException();
800
                        }
801
                        sql.append(params.getSQL());
802
                        sql.append(' ');
803
                } else {
804
                        FeatureAttributeDescriptor[] fields = type
805
                                        .getAttributeDescriptors();
806

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

    
816
                        FeatureAttributeDescriptor[] pkFields = getStoreServices()
817
                                        .getProviderFeatureType(type.getId()).getPrimaryKey();
818

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

    
838
                        // table
839
                        sql.append("from ");
840
                        sql.append(params.tableID());
841
                        sql.append(' ');
842

    
843
                        // Where
844
                        appendWhere(sql, filter);
845

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

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

    
869
        public long getFeatureCount() throws DataException {
870
                return getCount(null);
871
        }
872

    
873
        public String getProviderName() {
874
                return NAME;
875
        }
876

    
877
        public boolean hasGeometrySupport() {
878
                return false;
879
        }
880

    
881
        public FeatureSetProvider createSet(FeatureQuery query,
882
                        FeatureType featureType) throws DataException {
883

    
884
                return new JDBCSetProvider(this, query, featureType);
885
        }
886

    
887
        public Object getSourceId() {
888
                return this.getJDBCParameters().getSourceId();
889
        }
890

    
891
        public String getName() {
892
                return this.getJDBCParameters().tableID();
893
        }
894
        
895
        public String getFullName() {
896
                return this.getJDBCParameters().getHost()+":"+this.getJDBCParameters().getDBName()+":"+this.getJDBCParameters().tableID();
897
        }
898
        
899

    
900
        public ResourceProvider getResource() {
901
                return getHelper().getResource();
902
        }
903
}