Statistics
| Revision:

svn-gvsig-desktop / tags / v2_0_0_Build_2021 / libraries / libFMap_daldb / src / org / gvsig / fmap / dal / store / jdbc / JDBCStoreProvider.java @ 34088

History | View | Annotate | Download (23.5 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
                            boolean bool = getResultSet(resultsetID).next();
361
                                return Boolean.valueOf(bool);
362
                        }
363
                })).booleanValue();
364
        }
365

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

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

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

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

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

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

    
456

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

    
462
                return filter;
463
        }
464

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
577
                return data;
578
        }
579

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

    
584
        protected void initFeatureType() throws InitializeException {
585

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

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

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

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

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

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

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

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

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

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

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

    
687
                sql.append("from ");
688

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

    
692
                appendWhere(sql, filter);
693

    
694
                return sql.toString();
695
        }
696

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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