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

History | View | Annotate | Download (24.1 KB)

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

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

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

    
78

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

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

    
89
        private List<ResultSetInfo> resulsetList;
90

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

    
94
        public static final String METADATA_DEFINITION_NAME = NAME;
95

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

    
98
        protected JDBCHelper helper;
99

    
100
        protected boolean directSQLMode;
101

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

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

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

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

    
127
                this.initFeatureType();
128
        }
129

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

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

    
155

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

    
187
                });
188
        }
189

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

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

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

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

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

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

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

    
237

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

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

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

    
253
        public final int createResultSet(final String sql, final Object[] values,
254
                        final int fetchSize)
255
                        throws DataException {
256
                logger.debug("Creating resultSet with sql: {}", sql);
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
                                        logger.debug("Created resultset id: {} (total open: {})",
272
                                                        newId, getResultsetOpenCount());
273

    
274
                                        return Integer.valueOf(newId);
275
                                }
276
                        })).intValue();
277
                }
278
        }
279

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

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

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

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

    
333
        }
334

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

    
352

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

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

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

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

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

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

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

    
454

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

    
460
                return filter;
461
        }
462

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

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

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

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

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

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

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

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

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

    
536
        /**
537
         * Return "is null" expression for current provider<br/>
538
         */
539
        protected String getIsNullExpression() {
540
            return "is null";
541
        }
542
        
543
        @Override
544
        protected FeatureProvider internalGetFeatureProviderByReference(
545
                        FeatureReferenceProviderServices reference,
546
                        FeatureType featureType)
547
                        throws DataException {
548
                StringBuilder filter = new StringBuilder();
549
                FeatureAttributeDescriptor[] pk =
550
                                getFeatureStore().getFeatureType(featureType.getId())
551
                                                .getPrimaryKey();
552

    
553
                List<Object> values = new ArrayList<Object>();
554

    
555
                int i;
556
                Object value;
557
                for (i = 0; i < pk.length; i++) {
558
                    value = reference.getKeyValue(pk[i].getName());
559
                    filter.append(helper.getSqlFieldName(pk[i]));
560
                    if (value == null) {
561
                        filter.append(" ");
562
                        filter.append(getIsNullExpression());
563
                        filter.append("");
564
                    } else {
565
                        values.add(helper.dalValueToJDBC(pk[i], value));
566
                        filter.append(" = ? ");
567
                    }
568
                    if (i < pk.length -1) {
569
                        filter.append(" AND ");
570
                    }
571
                }
572
                String sql = compoundSelect(featureType, filter.toString(), null, 1, 0);
573

    
574
                FeatureProvider data;
575
                int rsId = createResultSet(sql, values.toArray(), 1);
576
                try {
577
                        if (!resulsetNext(rsId)) {
578
                                throw new RuntimeException("Reference Not found");
579
                        }
580
                        data = createFeatureProvider(featureType);
581
                        loadFeatureProvider(data, rsId);
582
                } finally {
583
                        closeResulset(rsId);
584
                }
585

    
586
                return data;
587
        }
588

    
589
        public int getOIDType() {
590
                return DataTypes.UNKNOWN;
591
        }
592

    
593
        protected void initFeatureType() throws InitializeException {
594

    
595
                EditableFeatureType edFType = null;
596
                try {
597
                        edFType = this.getStoreServices().createFeatureType(getName());
598

    
599
                        helper.loadFeatureType(edFType, getJDBCParameters());
600

    
601
                } catch (DataException e) {
602
                        throw new InitializeException(this.getProviderName(), e);
603
                }
604

    
605
                FeatureType defaultType = edFType.getNotEditableCopy();
606
                List<FeatureType> types = Collections.singletonList(defaultType);
607
                this.getStoreServices().setFeatureTypes(types, defaultType);
608
        }
609

    
610
        protected ResultSet createNewResultSet(final String sql,
611
                        final Object[] values, final int fetchSize)
612
                        throws DataException {
613
                this.open();
614
                return (ResultSet) getResource().execute(new ResourceAction() {
615
                        public Object run() throws Exception {
616
                                Connection conn = null;
617
                                PreparedStatement st = null;
618
                                ResultSet rs = null;
619
                                try {
620

    
621
                                        conn = helper.getConnection();
622
                                        conn.setAutoCommit(false);
623
                                        st = conn.prepareStatement(sql);
624

    
625
                                        if (values != null) {
626
                                                Object value;
627
                                                for (int i = 0; i < values.length; i++) {
628
                                                        value = values[i];
629
                                                        if (value instanceof Geometry) {
630
                                                                byte[] bytes;
631
                                                                try {
632
                                                                        bytes = ((Geometry) value).convertToWKB();
633
                                                                } catch (BaseException e) {
634
                                                                        throw new InvalidParameterException();
635
                                                                }
636
                                                                st.setBytes(i + 1, bytes);
637
                                                        }
638
                                                        st.setObject(i + 1, value);
639
                                                }
640
                                        }
641

    
642
                                        if (fetchSize > 0) {
643
                                                st.setFetchSize(fetchSize);
644
                                        }
645
                                        rs = st.executeQuery();
646
                                        if (fetchSize > 0) {
647
                                                rs.setFetchSize(fetchSize);
648
                                        }
649
                                        return rs;
650
                                } catch (SQLException e) {
651
                                        try {
652
                                                rs.close();
653
                                        } catch (Exception e1) {
654
                                        }
655
                                        try {
656
                                                st.close();
657
                                        } catch (Exception e1) {
658
                                        }
659
                                        try {
660
                                                conn.close();
661
                                        } catch (Exception e1) {
662
                                        }
663
                                        throw new JDBCExecutePreparedSQLException(sql,values,e);
664
                                }
665
                        }
666
                });
667
        }
668

    
669
        protected boolean closeResource(ResourceProvider resource) {
670
                try {
671
                        this.helper.close();
672
                } catch (CloseException e) {
673
                        logger.error("Exception in close Request", e);
674
                }
675
                return !this.helper.isOpen();
676
        }
677

    
678
        protected String compoundCountSelect(String filter) {
679

    
680
                // Select
681
                StringBuilder sql = new StringBuilder();
682
                sql.append("Select count(");
683
                String[] pkFields = getJDBCParameters().getPkFields();
684
                if (pkFields != null && pkFields.length == 1) {
685
                        sql.append(helper.escapeFieldName(pkFields[0]));
686
                } else {
687
                        sql.append('*');
688

    
689
                }
690
                sql.append(") ");
691

    
692
                sql.append("from ");
693
                if (this.directSQLMode) {
694
                        sql.append("(");
695
                        sql.append(getJDBCParameters().getSQL());
696
                        sql.append(") as _subquery_alias_ ");
697
                } else {
698
                        sql.append(getJDBCParameters().tableID());
699
                }
700
                sql.append(' ');
701

    
702
                appendWhere(sql, filter);
703

    
704
                return sql.toString();
705
        }
706

    
707
        protected void appendWhere(StringBuilder sql, String filter) {
708
                filter = fixFilter(filter);
709
                String initialFilter = getJDBCParameters().getBaseFilter();
710
                if ((initialFilter != null && initialFilter.length() != 0)
711
                                || (filter != null && filter.length() != 0)) {
712
                        sql.append("where (");
713

    
714
                        if (initialFilter != null && initialFilter.length() != 0
715
                                        && filter != null && filter.length() != 0) {
716
                                // initialFilter + filter
717
                                sql.append('(');
718
                                sql.append(initialFilter);
719
                                sql.append(") and (");
720
                                sql.append(filter);
721
                                sql.append(')');
722
                        } else if (initialFilter != null && initialFilter.length() != 0) {
723
                                // initialFilter only
724
                                sql.append(initialFilter);
725
                        } else {
726
                                // filter only
727
                                sql.append(filter);
728
                        }
729
                        sql.append(") ");
730
                }
731
        }
732

    
733
        public void closeDone() throws DataException {
734
                // Do nothing
735
        }
736

    
737
        public void opendDone() throws DataException {
738
                // Nothing to do
739
        }
740

    
741
        public Envelope getEnvelope() throws DataException {
742
                this.open();
743
                String defaultGeometryAttributeName;
744
                defaultGeometryAttributeName = this.getFeatureStore()
745
                        .getDefaultFeatureType()
746
                                .getDefaultGeometryAttributeName();
747
                if( defaultGeometryAttributeName != null ) {
748
                        return this.helper.getFullEnvelopeOfField(
749
                                        this.getJDBCParameters(),
750
                                        defaultGeometryAttributeName, 
751
                                        this.getJDBCParameters().getWorkingArea()
752
                                );
753
                }
754
                return null;
755
        }
756

    
757
        public void resourceChanged(ResourceProvider resource) {
758
                this.getStoreServices().notifyChange(
759
                                DataStoreNotification.RESOURCE_CHANGED,
760
                                resource);
761
        }
762

    
763
        public boolean allowAutomaticValues() {
764
                return this.helper.allowAutomaticValues();
765
        }
766

    
767
        public DataServerExplorer getExplorer() throws ReadException {
768
                DataManager manager = DALLocator.getDataManager();
769
                JDBCServerExplorerParameters exParams;
770
                JDBCStoreParameters params = getJDBCParameters();
771
                try {
772
                        exParams = (JDBCServerExplorerParameters) manager
773
                                        .createServerExplorerParameters(JDBCServerExplorer.NAME);
774
                        exParams.setHost(params.getHost());
775
                        exParams.setPort(params.getPort());
776
                        exParams.setDBName(params.getDBName());
777
                        exParams.setUser(params.getUser());
778
                        exParams.setPassword(params.getPassword());
779
                        exParams.setUrl(params.getUrl());
780
                        exParams.setCatalog(params.getCatalog());
781
                        exParams.setSchema(params.getSchema());
782
                        exParams.setJDBCDriverClassName(params.getJDBCDriverClassName());
783

    
784
                        return manager.openServerExplorer(JDBCServerExplorer.NAME,exParams);
785
                } catch (DataException e) {
786
                        throw new ReadException(this.getProviderName(), e);
787
                } catch (ValidateDataParametersException e) {
788
                        throw new ReadException(this.getProviderName(), e);
789
                }
790
        }
791

    
792
        @Override
793
        protected void doDispose() throws BaseException {
794
                this.close();
795
                resulsetList = null;
796
                this.helper.dispose();
797
                super.doDispose();
798
        }
799

    
800
        public Object createNewOID() {
801
                return null;
802
        }
803

    
804
        public String compoundSelect(FeatureType type, String filter, String order,
805
                        long limit, long offset) throws DataException {
806
                StringBuilder sql = new StringBuilder();
807
                JDBCStoreParameters params = getJDBCParameters();
808
                        FeatureAttributeDescriptor[] fields = type
809
                                        .getAttributeDescriptors();
810

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

    
820
                        FeatureAttributeDescriptor[] pkFields = getStoreServices()
821
                                        .getProviderFeatureType(type.getId()).getPrimaryKey();
822

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

    
842
                        // table
843
                        sql.append("from ");
844
                        if (directSQLMode) {
845
                            sql.append(" (");
846
                            sql.append(params.getSQL());
847
                            sql.append(") as _subquery_alias_ ");
848
                        } else {
849
                            sql.append(params.tableID());
850
                        }
851
                        sql.append(' ');
852

    
853
                        // Where
854
                        appendWhere(sql, filter);
855

    
856
                        // Order
857
                        if ((params.getBaseOrder() != null && params.getBaseOrder()
858
                                        .length() != 0)
859
                                        || (order != null && order.length() != 0)) {
860
                                sql.append("order by ");
861

    
862
                                if (order != null && order.length() != 0) {
863
                                        // order
864
                                        sql.append(order);
865
                                } else {
866
                                        // initial order
867
                                        sql.append(params.getBaseOrder());
868
                                }
869
                                sql.append(' ');
870
                        }
871
                // limit offset
872
                if (limit > 0 || offset > 0) {
873
                        sql.append(helper.compoundLimitAndOffset(limit,offset));
874
                }
875
                return sql.toString();
876
        }
877

    
878
        public long getFeatureCount() throws DataException {
879
                return getCount(null);
880
        }
881

    
882
        public String getProviderName() {
883
                return NAME;
884
        }
885

    
886
        public boolean hasGeometrySupport() {
887
                return false;
888
        }
889

    
890
        public FeatureSetProvider createSet(FeatureQuery query,
891
                        FeatureType featureType) throws DataException {
892

    
893
                return new JDBCSetProvider(this, query, featureType);
894
        }
895

    
896
        public Object getSourceId() {
897
                return this.getJDBCParameters().getSourceId();
898
        }
899
        
900
        public String getName() {
901
                return this.getJDBCParameters().tableID();
902
        }
903
        
904
        public String getFullName() {
905
                return this.getJDBCParameters().getHost()+":"+this.getJDBCParameters().getDBName()+":"+this.getJDBCParameters().tableID();
906
        }
907
        
908

    
909
        public ResourceProvider getResource() {
910
                return getHelper().getResource();
911
        }
912
        
913
        protected boolean isDirectSQLMode(){
914
            return directSQLMode;
915
        }
916
}