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

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 generic store";
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
                synchronized (this) {
257
                        checksResulsets();
258
                        return ((Integer) getResource().execute(new ResourceAction() {
259
                                public Object run() throws Exception {
260
                                        ResultSetInfo newRs =
261
                                                        new ResultSetInfo(createNewResultSet(sql, values,
262
                                                                        fetchSize));
263
                                        int newId = getNewId();
264
                                        if (newId < 0) {
265
                                                newId = resulsetList.size();
266
                                                resulsetList.add(newRs);
267
                                        } else {
268
                                                resulsetList.set(newId, newRs);
269
                                        }
270
                                        logger.debug("Created resultset id: {} (total open: {})",
271
                                                        newId, getResultsetOpenCount());
272

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

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

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

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

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

    
332
        }
333

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

    
351

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

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

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

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

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

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

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

    
453

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

    
459
                return filter;
460
        }
461

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

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

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

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

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

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

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

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

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

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

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

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

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

    
585
                return data;
586
        }
587

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

    
592
        protected void initFeatureType() throws InitializeException {
593

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

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

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

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

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

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

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

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

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

    
677
        protected String compoundCountSelect(String filter) {
678

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

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

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

    
701
                appendWhere(sql, filter);
702

    
703
                return sql.toString();
704
        }
705

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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