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

History | View | Annotate | Download (24 KB)

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

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

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

    
78

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

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

    
89
        private List<ResultSetInfo> resulsetList;
90

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

    
94
        public static final String METADATA_DEFINITION_NAME = NAME;
95

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

    
98
        protected JDBCHelper helper;
99

    
100
        protected boolean directSQLMode;
101

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

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

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

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

    
127
                this.initFeatureType();
128
        }
129

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

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

    
155

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

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

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

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

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

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

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

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

    
233

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

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

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

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

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

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

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

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

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

    
329
        }
330

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

    
348

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

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

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

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

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

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

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

    
450

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

    
456
                return filter;
457
        }
458

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

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

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

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

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

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

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

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

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

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

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

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

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

    
582
                return data;
583
        }
584

    
585
        public int getOIDType() {
586
                return DataTypes.UNKNOWN;
587
        }
588

    
589
        protected void initFeatureType() throws InitializeException {
590

    
591
                EditableFeatureType edFType = null;
592
                try {
593
                        edFType = this.getStoreServices().createFeatureType(getName());
594

    
595
                        helper.loadFeatureType(edFType, getJDBCParameters());
596

    
597
                } catch (DataException e) {
598
                        throw new InitializeException(this.getProviderName(), e);
599
                }
600

    
601
                FeatureType defaultType = edFType.getNotEditableCopy();
602
                List<FeatureType> types = Collections.singletonList(defaultType);
603
                this.getStoreServices().setFeatureTypes(types, defaultType);
604
        }
605

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

    
617
                                        conn = helper.getConnection();
618
                                        conn.setAutoCommit(false);
619
                                        st = conn.prepareStatement(sql);
620

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

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

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

    
674
        protected String compoundCountSelect(String filter) {
675

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

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

    
688
                sql.append("from ");
689
                if (this.directSQLMode) {
690
                        sql.append("(");
691
                        sql.append(getJDBCParameters().getSQL());
692
                        sql.append(") as _subquery_alias_ ");
693
                } else {
694
                        sql.append(getJDBCParameters().tableID());
695
                }
696
                sql.append(' ');
697

    
698
                appendWhere(sql, filter);
699

    
700
                return sql.toString();
701
        }
702

    
703
        protected void appendWhere(StringBuilder sql, String filter) {
704
                filter = fixFilter(filter);
705
                String initialFilter = getJDBCParameters().getBaseFilter();
706
                if ((initialFilter != null && initialFilter.length() != 0)
707
                                || (filter != null && filter.length() != 0)) {
708
                        sql.append("where (");
709

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

    
729
        public void closeDone() throws DataException {
730
                // Do nothing
731
        }
732

    
733
        public void opendDone() throws DataException {
734
                // Nothing to do
735
        }
736

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

    
753
        public void resourceChanged(ResourceProvider resource) {
754
                this.getStoreServices().notifyChange(
755
                                DataStoreNotification.RESOURCE_CHANGED,
756
                                resource);
757
        }
758

    
759
        public boolean allowAutomaticValues() {
760
                return this.helper.allowAutomaticValues();
761
        }
762

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

    
780
                        return manager.openServerExplorer(JDBCServerExplorer.NAME,exParams);
781
                } catch (DataException e) {
782
                        throw new ReadException(this.getProviderName(), e);
783
                } catch (ValidateDataParametersException e) {
784
                        throw new ReadException(this.getProviderName(), e);
785
                }
786
        }
787

    
788
        @Override
789
        protected void doDispose() throws BaseException {
790
                this.close();
791
                resulsetList = null;
792
                this.helper.dispose();
793
                super.doDispose();
794
        }
795

    
796
        public Object createNewOID() {
797
                return null;
798
        }
799

    
800
        public String compoundSelect(FeatureType type, String filter, String order,
801
                        long limit, long offset) throws DataException {
802
                StringBuilder sql = new StringBuilder();
803
                JDBCStoreParameters params = getJDBCParameters();
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
                                        }
830
                                        if (toAdd) {
831
                                                sql.append(", ");
832
                                                sql.append(helper.getSqlFieldName(pkFields[i]));
833
                                        }
834
                                }
835
                                sql.append(' ');
836
                        }
837

    
838
                        // table
839
                        sql.append("from ");
840
                        if (directSQLMode) {
841
                            sql.append(" (");
842
                            sql.append(params.getSQL());
843
                            sql.append(") as _subquery_alias_ ");
844
                        } else {
845
                            sql.append(params.tableID());
846
                        }
847
                        sql.append(' ');
848

    
849
                        // Where
850
                        appendWhere(sql, filter);
851

    
852
                        // Order
853
                        if ((params.getBaseOrder() != null && params.getBaseOrder()
854
                                        .length() != 0)
855
                                        || (order != null && order.length() != 0)) {
856
                                sql.append("order by ");
857

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

    
874
        public long getFeatureCount() throws DataException {
875
                return getCount(null);
876
        }
877

    
878
        public String getProviderName() {
879
                return NAME;
880
        }
881

    
882
        public boolean hasGeometrySupport() {
883
                return false;
884
        }
885

    
886
        public FeatureSetProvider createSet(FeatureQuery query,
887
                        FeatureType featureType) throws DataException {
888

    
889
                return new JDBCSetProvider(this, query, featureType);
890
        }
891

    
892
        public Object getSourceId() {
893
                return this.getJDBCParameters().getSourceId();
894
        }
895
        
896
        public String getName() {
897
                return this.getJDBCParameters().tableID();
898
        }
899
        
900
        public String getFullName() {
901
                return this.getJDBCParameters().getHost()+":"+this.getJDBCParameters().getDBName()+":"+this.getJDBCParameters().tableID();
902
        }
903
        
904

    
905
        public ResourceProvider getResource() {
906
                return getHelper().getResource();
907
        }
908
        
909
        protected boolean isDirectSQLMode(){
910
            return directSQLMode;
911
        }
912
}