Statistics
| Revision:

root / branches / v2_0_0_prep / libraries / libFMap_daldb / src / org / gvsig / fmap / dal / store / jdbc / JDBCStoreProvider.java @ 29326

History | View | Annotate | Download (23 KB)

1
/* gvSIG. Geographic Information System of the Valencian Government
2
*
3
* Copyright (C) 2007-2008 Infrastructures and Transports Department
4
* of the Valencian Government (CIT)
5
*
6
* This program is free software; you can redistribute it and/or
7
* modify it under the terms of the GNU General Public License
8
* as published by the Free Software Foundation; either version 2
9
* of the License, or (at your option) any later version.
10
*
11
* This program is distributed in the hope that it will be useful,
12
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
* GNU General Public License for more details.
15
*
16
* You should have received a copy of the GNU General Public License
17
* along with this program; if not, write to the Free Software
18
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19
* MA  02110-1301, USA.
20
*
21
*/
22

    
23
/*
24
* AUTHORS (In addition to CIT):
25
* 2009 IVER T.I   {{Task}}
26
*/
27

    
28
/**
29
 *
30
 */
31
package org.gvsig.fmap.dal.store.jdbc;
32

    
33
import java.security.InvalidParameterException;
34
import java.sql.Connection;
35
import java.sql.PreparedStatement;
36
import java.sql.ResultSet;
37
import java.sql.SQLException;
38
import java.sql.Statement;
39
import java.util.ArrayList;
40
import java.util.Iterator;
41
import java.util.List;
42

    
43
import org.cresques.cts.IProjection;
44
import org.gvsig.fmap.dal.DALLocator;
45
import org.gvsig.fmap.dal.DataManager;
46
import org.gvsig.fmap.dal.DataServerExplorer;
47
import org.gvsig.fmap.dal.DataStoreNotification;
48
import org.gvsig.fmap.dal.DataTypes;
49
import org.gvsig.fmap.dal.exception.CloseException;
50
import org.gvsig.fmap.dal.exception.DataException;
51
import org.gvsig.fmap.dal.exception.InitializeException;
52
import org.gvsig.fmap.dal.exception.OpenException;
53
import org.gvsig.fmap.dal.exception.ReadException;
54
import org.gvsig.fmap.dal.exception.ValidateDataParametersException;
55
import org.gvsig.fmap.dal.feature.EditableFeatureType;
56
import org.gvsig.fmap.dal.feature.FeatureAttributeDescriptor;
57
import org.gvsig.fmap.dal.feature.FeatureQuery;
58
import org.gvsig.fmap.dal.feature.FeatureStore;
59
import org.gvsig.fmap.dal.feature.FeatureType;
60
import org.gvsig.fmap.dal.feature.spi.AbstractFeatureStoreProvider;
61
import org.gvsig.fmap.dal.feature.spi.FeatureProvider;
62
import org.gvsig.fmap.dal.feature.spi.FeatureReferenceProviderServices;
63
import org.gvsig.fmap.dal.feature.spi.FeatureSetProvider;
64
import org.gvsig.fmap.dal.resource.Resource;
65
import org.gvsig.fmap.dal.resource.exception.ResourceBeginException;
66
import org.gvsig.fmap.dal.resource.spi.ResourceProvider;
67
import org.gvsig.fmap.dal.spi.DataStoreProviderServices;
68
import org.gvsig.fmap.dal.store.jdbc.exception.InvalidResultSetIdException;
69
import org.gvsig.fmap.dal.store.jdbc.exception.JDBCException;
70
import org.gvsig.fmap.dal.store.jdbc.exception.JDBCExecuteSQLException;
71
import org.gvsig.fmap.dal.store.jdbc.exception.JDBCSQLException;
72
import org.gvsig.fmap.geom.Geometry;
73
import org.gvsig.fmap.geom.operation.towkb.ToWKB;
74
import org.gvsig.fmap.geom.primitive.Envelope;
75
import org.gvsig.tools.ToolsLocator;
76
import org.gvsig.tools.dynobject.DynClass;
77
import org.gvsig.tools.dynobject.DynObject;
78
import org.gvsig.tools.dynobject.DynObjectManager;
79
import org.gvsig.tools.exception.BaseException;
80
import org.slf4j.Logger;
81
import org.slf4j.LoggerFactory;
82

    
83

    
84
/**
85
 * @author jmvivo
86
 *
87
 */
88
public class JDBCStoreProvider extends AbstractFeatureStoreProvider
89
                implements JDBCHelperUser {
90

    
91
        final static private Logger logger = LoggerFactory
92
                        .getLogger(JDBCStoreProvider.class);
93

    
94
        private List resulsetList;
95

    
96
        public static String NAME = "JDBC";
97
        private static final String DYNCLASS_NAME = "JDBCStore";
98
        public static String DESCRIPTION = "JDBC source";
99
        private static DynClass DYNCLASS = null;
100

    
101
        private long mlsecondsToZombie = 1000 * 60 * 10; // 10 Min
102

    
103
        protected JDBCHelper helper;
104

    
105
        protected boolean directSQLMode;
106

    
107
        private Long totalCount = null;
108

    
109

    
110
        public JDBCStoreProvider(JDBCStoreParameters params,
111
                        DataStoreProviderServices storeServices) throws InitializeException {
112
                this(params, storeServices, ToolsLocator.getDynObjectManager()
113
                                .createDynObject(DYNCLASS));
114
        }
115

    
116
        protected JDBCStoreProvider(JDBCStoreParameters params,
117
                        DataStoreProviderServices storeServices, DynObject metadata)
118
                        throws InitializeException {
119
                super(params, storeServices, metadata);
120

    
121
                resulsetList = new ArrayList(10);
122

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

    
128

    
129
                this.setDynValue("DefaultSRS", null);
130
                this.setDynValue("Envelope", null);
131
                this.initFeatureType();
132
        }
133

    
134

    
135

    
136
        protected JDBCStoreParameters getJDBCParameters() {
137
                return (JDBCStoreParameters) this.getParameters();
138
        }
139

    
140

    
141
        protected static void registerDynClass() {
142
                DynObjectManager dynman = ToolsLocator.getDynObjectManager();
143
                DynClass dynClass;
144
                if (DYNCLASS == null) {
145
                        dynClass = dynman.add(DYNCLASS_NAME, DESCRIPTION);
146

    
147
                        dynClass.extend(dynman.get(FeatureStore.DYNCLASS_NAME));
148
                        DYNCLASS = dynClass;
149
                }
150
        }
151

    
152
        /**
153
         * Load data form a resulset.<br>
154
         *
155
         * <strong>Note:</strong><br>
156
         * this method have to perform <code>resouceBegin</code> at the begining and
157
         * <code>resourceEnd</code> at the end of execution.
158
         *
159
         *
160
         * @param data
161
         * @param resulsetID
162
         *
163
         * @return
164
         * @throws DataException
165
         */
166
        public void loadFeatureProvider(FeatureProvider data, int resultsetID)
167
                        throws DataException {
168
                this.resourceBegin();
169
                try {
170
                        ResultSet rs = getResultSet(resultsetID);
171
                        FeatureAttributeDescriptor attr;
172
                        Iterator iter = data.getType().iterator();
173
                        while (iter.hasNext()) {
174
                                attr = (FeatureAttributeDescriptor) iter.next();
175
                                loadFeatureProviderValue(data, rs, attr);
176
                        }
177
                } finally {
178
                        this.resourceEnd();
179
                }
180

    
181

    
182

    
183
        }
184

    
185

    
186
        protected void loadFeatureProviderValue(FeatureProvider data, ResultSet rs,
187
                        FeatureAttributeDescriptor attr) throws DataException {
188
                if (attr.getDataType() == 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(getName(), 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)
245
                        throws DataException {
246
                return createResultSet(sql, null);
247
        }
248

    
249
        public final int createResultSet(String sql, Object[] values)
250
                        throws DataException {
251
                synchronized (this) {
252
                        checksResulsets();
253
                        resourceBegin();
254
                        try {
255
                                ResultSetInfo newRs = new ResultSetInfo(createNewResultSet(sql,
256
                                                values));
257
                                int newId = getNewId();
258
                                if (newId < 0) {
259
                                        newId = resulsetList.size();
260
                                        resulsetList.add(newRs);
261
                                } else {
262
                                        resulsetList.set(newId, newRs);
263
                                }
264
                                if (logger.isDebugEnabled()) {
265
                                        logger.debug(" id: {} (total {})", newId,
266
                                                        getResultsetOpenCount());
267
                                }
268

    
269
                                return newId;
270
                        } finally {
271
                                resourceEnd();
272
                        }
273

    
274
                }
275
        }
276

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

    
290
        protected final void forceCloseAllResultSet()
291
                        throws ResourceBeginException,
292
                        JDBCException {
293
                synchronized (this) {
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 ResourceBeginException, 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 = (ResultSetInfo) 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(int resultsetID) throws JDBCException,
350
                        InvalidResultSetIdException, ResourceBeginException {
351
                ResultSet rs = getResultSet(resultsetID);
352
                resourceBegin();
353
                try {
354
                        return rs.next();
355
                } catch (SQLException e) {
356
                        throw new JDBCSQLException(e);
357
                } finally {
358
                        resourceEnd();
359
                }
360
        }
361

    
362
        public final void closeResulset(int resultsetID)
363
                        throws JDBCException,
364
                        InvalidResultSetIdException, ResourceBeginException {
365
                synchronized (this) {
366
                        resourceBegin();
367
                        try {
368
                                ResultSet rs = dropResultSet(resultsetID);
369
                                closeResulset(rs);
370
                                if (logger.isDebugEnabled()) {
371
                                        logger.debug(" id: " + resultsetID + " (total "
372
                                                        + getResultsetOpenCount() + ")");
373
                                }
374

    
375
                        } finally {
376
                                resourceEnd();
377
                        }
378
                        checksResulsets();
379
                }
380
        }
381

    
382
        public final void checksResulsets() throws JDBCException,
383
                        InvalidResultSetIdException, ResourceBeginException {
384
                synchronized (this) {
385
                        resourceBegin();
386
                        try {
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

    
398
                        } finally {
399
                                resourceEnd();
400
                        }
401

    
402
                }
403
        }
404

    
405

    
406
        private int getResultsetOpenCount() {
407
                int count = 0;
408
                Iterator iter = resulsetList.iterator();
409
                while (iter.hasNext()) {
410
                        if (iter.next() != null) {
411
                                count++;
412
                        }
413
                }
414
                return count;
415
        }
416

    
417
        protected void closeResulset(ResultSet rs) throws JDBCException,
418
                        ResourceBeginException {
419
                resourceBegin();
420
                try {
421
                        Statement st = rs.getStatement();
422
                        Connection con = st.getConnection();
423
                        try {
424
                                rs.close();
425
                        } finally {
426
                                // TODO revisar esto
427
                                try{ st.close();  } catch (Exception ex){ };
428
                                try{ con.close(); } catch (Exception ex){ };
429
                        }
430
                } catch (SQLException e) {
431
                        throw new JDBCSQLException(e);
432
                } finally {
433
                        resourceEnd();
434
                }
435

    
436
        }
437

    
438
        protected final int openResulsetCount() {
439
                int count = 0;
440
                Iterator iter = resulsetList.iterator();
441
                while (iter.hasNext()) {
442
                        if (iter.next() != null) {
443
                                count++;
444
                        }
445
                }
446
                return count;
447
        }
448

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

    
459

    
460
        protected String fixFilter(String filter) {
461
                if (filter == null) {
462
                        return null;
463
                }
464

    
465
                return filter;
466
        }
467

    
468
        protected JDBCHelper createHelper() throws InitializeException {
469
                return new JDBCHelper(this, getJDBCParameters());
470
        }
471

    
472
        protected JDBCHelper getHelper() {
473
                return helper;
474
        }
475

    
476
        protected void resetCount() {
477
                totalCount = null;
478
        }
479

    
480
        /**
481
         * Get feature count for a <code>filter</code>.<br>
482
         *
483
         * <code>filter</code> can be <code>null</code>.<br>
484
         *
485
         * <strong>Note:</strong><br>
486
         * this method have to perform <code>resouceBegin</code> at the begining and
487
         * <code>resourceEnd</code> at the end of execution.
488
         *
489
         *
490
         * @param filter
491
         * @return
492
         * @throws DataException
493
         */
494
        protected long getCount(String filter) throws DataException {
495
                this.open();
496
                if (filter == null && totalCount != null) {
497
                        return totalCount.longValue();
498
                }
499
                long count = 0;
500
                String sql = compoundCountSelect(filter);
501
                resourceBegin();
502
                try {
503
                        ResultSet rs = createNewResultSet(sql, null);
504
                        try {
505
                                if (rs.next()) {
506
                                        count = rs.getLong(1);
507
                                }
508
                        } catch (SQLException e) {
509
                                throw new JDBCSQLException(e);
510
                        } finally {
511
                                closeResulset(rs);
512
                        }
513
                } finally {
514
                        resourceEnd();
515
                }
516
                if (filter == null) {
517
                        totalCount = new Long(count);
518
                }
519
                return count;
520
        }
521

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

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

    
530

    
531
        public FeatureProvider getFeatureProviderByReference(
532
                        FeatureReferenceProviderServices reference) throws DataException {
533
                return getFeatureProviderByReference(reference, getFeatureStore()
534
                                .getDefaultFeatureType());
535
        }
536

    
537
        public FeatureProvider getFeatureProviderByReference(
538
                        FeatureReferenceProviderServices reference, FeatureType featureType)
539
                        throws DataException {
540
                open();
541
                resourceBegin();
542
                try {
543
                        StringBuilder filter = new StringBuilder();
544
                        FeatureAttributeDescriptor[] pk = getFeatureStore().getFeatureType(
545
                                        featureType.getId()).getPrimaryKey();
546

    
547
                        List values = new ArrayList();
548

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

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

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

    
577
                        return data;
578

    
579
                } finally {
580
                        resourceEnd();
581
                }
582

    
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();
594

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

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

    
601
                FeatureType defaultType = edFType.getNotEditableCopy();
602
                List types = new ArrayList(1);
603
                types.add(defaultType);
604
                this.getStoreServices().setFeatureTypes(types, defaultType);
605
                try {
606
                        loadMetadata();
607
                } catch (DataException e) {
608
                        throw new InitializeException(e);
609
                }
610
        }
611

    
612
        protected ResultSet createNewResultSet(String sql, Object[] values)
613
                        throws DataException {
614
                this.open();
615
                Connection conn = null;
616
                PreparedStatement st = null;
617
                ResultSet rs = null;
618
                this.resourceBegin();
619
                try {
620
                        conn = this.helper.getConnection();
621
                        st = conn.prepareStatement(sql);
622

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

    
641
                        }
642

    
643
                        try {
644
                                rs = st.executeQuery();
645
                        } catch (SQLException e1) {
646
                                try {st.close();} catch (Exception e2) {};
647
                                try {conn.close();} catch (Exception e2) {}        ;
648
                                throw new JDBCExecuteSQLException(sql, e1);
649
                        }
650
                        rs.setFetchSize(5000); // TODO add to params?
651
                        return rs;
652
                } catch (SQLException e) {
653
                        // TODO throw exception ???
654
                        try {rs.close();} catch (Exception e1) {};
655
                        try {st.close();} catch (Exception e1) {};
656
                        try {conn.close();} catch (Exception e1) {};
657
                        throw new JDBCSQLException(e);
658
                } finally {
659
                        this.resourceEnd();
660
                }
661
        }
662

    
663
        /**
664
         * Permform a {@link Resource#begin()} to the current provider resources.
665
         *
666
         */
667

    
668
        protected void resourceBegin() throws ResourceBeginException {
669
                this.helper.begin();
670

    
671
        }
672

    
673
        /**
674
         * Permform a {@link Resource#end()} to the current provider resources.
675
         */
676

    
677
        protected void resourceEnd() {
678
                this.helper.end();
679
        }
680

    
681
        protected boolean closeResource(ResourceProvider resource) {
682
                try {
683
                        this.helper.close();
684
                } catch (CloseException e) {
685
                        logger.error("Exception in close Request", e);
686
                }
687
                return !this.helper.isOpen();
688
        }
689

    
690
        protected String compoundCountSelect(String filter) {
691
                if (this.directSQLMode) {
692
                        return null;
693
                }
694
                // Select
695
                StringBuilder sql = new StringBuilder();
696
                sql.append("Select count(");
697
                String[] pkFields = getJDBCParameters().getPkFields();
698
                if (pkFields != null && pkFields.length == 1) {
699
                        sql.append(helper.escapeFieldName(pkFields[0]));
700
                } else {
701
                        sql.append('*');
702

    
703
                }
704
                sql.append(") ");
705

    
706
                sql.append("from ");
707

    
708
                sql.append(getJDBCParameters().tableID());
709
                sql.append(' ');
710

    
711
                appendWhere(sql, filter);
712

    
713
                return sql.toString();
714
        }
715

    
716
        protected void appendWhere(StringBuilder sql, String filter) {
717
                filter = fixFilter(filter);
718
                String initialFilter = getJDBCParameters().getInitialFilter();
719
                if ((initialFilter != null && initialFilter.length() != 0)
720
                                || (filter != null && filter.length() != 0)) {
721
                        sql.append("where (");
722

    
723
                        if (initialFilter != null && initialFilter.length() != 0
724
                                        && filter != null && filter.length() != 0) {
725
                                // initialFilter + filter
726
                                sql.append('(');
727
                                sql.append(initialFilter);
728
                                sql.append(") and (");
729
                                sql.append(filter);
730
                                sql.append(')');
731
                        } else if (initialFilter != null && initialFilter.length() != 0) {
732
                                // initialFilter only
733
                                sql.append(initialFilter);
734
                        } else {
735
                                // filter only
736
                                sql.append(filter);
737
                        }
738
                        sql.append(") ");
739
                }
740
        }
741

    
742
        protected void loadMetadata() throws DataException {
743
                IProjection srs = getJDBCParameters().getSRS();
744

    
745
                if (srs == null) {
746
                        srs = getFeatureStore().getDefaultFeatureType().getDefaultSRS();
747
                }
748

    
749
                this.setDynValue("DefaultSRS", srs);
750

    
751
                String defGeomName = this.getFeatureStore().getDefaultFeatureType()
752
                                .getDefaultGeometryAttributeName();
753
                Envelope env = null;
754
                if (defGeomName != null && defGeomName.length() > 0) {
755
                        env = this.helper.getFullEnvelopeOfField(this.getJDBCParameters(),
756
                                        defGeomName, this.getJDBCParameters().getWorkingArea());
757

    
758
                }
759
                this.setDynValue("Envelope", env);
760

    
761
        }
762

    
763
        public void closeDone() throws DataException {
764
                clearMetadata();
765

    
766
        }
767

    
768
        public void opendDone() throws DataException {
769
                // Nothing to do
770
        }
771

    
772
        public Envelope getEnvelope() throws DataException {
773
                this.open();
774
                return (Envelope) this.getDynValue("Envelope");
775
        }
776

    
777
        public void resourceChanged(ResourceProvider resource) {
778
                this.getStoreServices().notifyChange(
779
                                DataStoreNotification.RESOURCE_CHANGED,
780
                                resource);
781
        }
782

    
783
        protected void clearMetadata() {
784
                this.setDynValue("DefaultSRS", null);
785
                this.setDynValue("Envelope", null);
786
        }
787

    
788
        public boolean allowAutomaticValues() {
789
                return this.helper.allowAutomaticValues();
790
        }
791

    
792
        public DataServerExplorer getExplorer() throws ReadException {
793
                DataManager manager = DALLocator.getDataManager();
794
                JDBCServerExplorerParameters exParams;
795
                JDBCStoreParameters params = getJDBCParameters();
796
                try {
797
                        exParams = (JDBCServerExplorerParameters) manager
798
                                        .createServerExplorerParameters(JDBCServerExplorer.NAME);
799
                        exParams.setHost(params.getHost());
800
                        exParams.setPort(params.getPort());
801
                        exParams.setDBName(params.getDBName());
802
                        exParams.setUser(params.getUser());
803
                        exParams.setPassword(params.getPassword());
804
                        exParams.setUrl(params.getUrl());
805
                        exParams.setCatalog(params.getCatalog());
806
                        exParams.setSchema(params.getSchema());
807
                        exParams.setJDBCDriverClassName(params.getJDBCDriverClassName());
808

    
809
                        return manager.createServerExplorer(exParams);
810
                } catch (DataException e) {
811
                        throw new ReadException(this.getName(), e);
812
                } catch (ValidateDataParametersException e) {
813
                        // TODO Auto-generated catch block
814
                        throw new ReadException(this.getName(), e);
815
                }
816
        }
817

    
818
        public void dispose() throws CloseException {
819
                this.close();
820
                resulsetList = null;
821
                this.helper.dispose();
822
                super.dispose();
823
        }
824

    
825
        public Object createNewOID() {
826
                return null;
827
        }
828

    
829
        public String compoundSelect(FeatureType type, String filter, String order,
830
                        long limit, long offset) throws DataException {
831
                StringBuilder sql = new StringBuilder();
832
                JDBCStoreParameters params = getJDBCParameters();
833
                if (directSQLMode) {
834
                        if (filter != null || order != null) {
835
                                // FIXME Exception
836
                                throw new UnsupportedOperationException();
837
                        }
838
                        sql.append(params.getSQL());
839
                        sql.append(' ');
840
                } else {
841
                        FeatureAttributeDescriptor[] fields = type
842
                                        .getAttributeDescriptors();
843

    
844
                        // Select
845
                        sql.append("Select ");
846
                        for (int i = 0; i < fields.length - 1; i++) {
847
                                sql.append(helper.getSqlFieldName(fields[i]));
848
                                sql.append(", ");
849
                        }
850
                        sql.append(helper.getSqlFieldName(fields[fields.length - 1]));
851
                        sql.append(' ');
852

    
853
                        FeatureAttributeDescriptor[] pkFields = getStoreServices()
854
                                        .getProviderFeatureType(type.getId()).getPrimaryKey();
855

    
856
                        if (pkFields != null && pkFields.length > 0) {
857
                                // checks for pk fields are in select
858
                                boolean toAdd;
859
                                for (int i = 0; i < pkFields.length; i++) {
860
                                        toAdd = true;
861
                                        for (int j = 0; j < fields.length; j++) {
862
                                                if (pkFields[i].getName().equals(fields[j].getName())) {
863
                                                        toAdd = false;
864
                                                        break;
865
                                                }
866
                                                if (toAdd) {
867
                                                        sql.append(", ");
868
                                                        sql.append(helper.getSqlFieldName(pkFields[i]));
869
                                                }
870
                                        }
871
                                }
872
                                sql.append(' ');
873
                        }
874

    
875
                        // table
876
                        sql.append("from ");
877
                        sql.append(params.tableID());
878
                        sql.append(' ');
879

    
880
                        // Where
881
                        appendWhere(sql, filter);
882

    
883
                        // Order
884
                        if ((params.getInitialOrder() != null && params.getInitialOrder()
885
                                        .length() != 0)
886
                                        || (order != null && order.length() != 0)) {
887
                                sql.append("order by ");
888

    
889
                                if (order != null && order.length() != 0) {
890
                                        // order
891
                                        sql.append(order);
892
                                } else {
893
                                        // initial order
894
                                        sql.append(params.getInitialOrder());
895
                                }
896
                                sql.append(' ');
897
                        }
898
                }
899
                // limit offset
900
                if (limit >= 1 || offset >= 1) {
901
                        sql.append(helper.compoundLimitAndOffset(limit,offset));
902
                }
903
                return sql.toString();
904
        }
905

    
906
        public long getFeatureCount() throws DataException {
907
                return getCount(null);
908
        }
909

    
910
        public String getName() {
911
                return NAME;
912
        }
913

    
914
        public boolean hasGeometrySupport() {
915
                return false;
916
        }
917

    
918
        public FeatureSetProvider createSet(FeatureQuery query,
919
                        FeatureType featureType) throws DataException {
920

    
921
                return new JDBCSetProvider(this, query, featureType);
922
        }
923

    
924
        public Object getSourceId() {
925
                return this.getJDBCParameters().getSourceId();
926
        }
927

    
928
}