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 / jdbc2 / spi / JDBCServerExplorerBase.java @ 45581

History | View | Annotate | Download (32.5 KB)

1
/**
2
 * gvSIG. Desktop Geographic Information System.
3
 *
4
 * Copyright (C) 2007-2020 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.jdbc2.spi;
25

    
26
import java.io.File;
27
import org.gvsig.fmap.dal.store.jdbc2.JDBCServerExplorer;
28
import java.util.ArrayList;
29
import java.util.Arrays;
30
import java.util.Collections;
31
import java.util.HashMap;
32
import java.util.List;
33
import java.util.Map;
34
import javax.json.JsonObject;
35
import javax.json.JsonString;
36
import javax.json.JsonValue;
37
import org.apache.commons.codec.binary.Hex;
38
import org.apache.commons.collections.map.LRUMap;
39
import org.apache.commons.lang3.BooleanUtils;
40
import org.apache.commons.lang3.ObjectUtils;
41
import org.apache.commons.lang3.StringUtils;
42
import org.apache.commons.lang3.tuple.ImmutablePair;
43
import org.apache.commons.lang3.tuple.Pair;
44
import org.gvsig.expressionevaluator.ExpressionBuilder;
45
import org.gvsig.expressionevaluator.ExpressionUtils;
46
import org.gvsig.fmap.dal.DALLocator;
47
import org.gvsig.fmap.dal.DataManager;
48
import org.gvsig.fmap.dal.DataStore;
49
import org.gvsig.fmap.dal.DataStoreParameters;
50
import org.gvsig.fmap.dal.DatabaseWorkspaceManager;
51
import static org.gvsig.fmap.dal.DatabaseWorkspaceManager.FIELD_CONFIGURATION_NAME;
52
import static org.gvsig.fmap.dal.DatabaseWorkspaceManager.FIELD_CONFIGURATION_VALUE;
53
import static org.gvsig.fmap.dal.DatabaseWorkspaceManager.TABLE_CONFIGURATION_NAME;
54
import static org.gvsig.fmap.dal.DatabaseWorkspaceManager.TABLE_RESOURCES_NAME;
55
import org.gvsig.fmap.dal.NewDataStoreParameters;
56
import org.gvsig.fmap.dal.exception.CloseException;
57
import org.gvsig.fmap.dal.exception.DataException;
58
import org.gvsig.fmap.dal.exception.InitializeException;
59
import org.gvsig.fmap.dal.exception.OpenException;
60
import org.gvsig.fmap.dal.exception.RemoveException;
61
import org.gvsig.fmap.dal.feature.EditableFeatureType;
62
import org.gvsig.fmap.dal.feature.FeatureType;
63
import org.gvsig.fmap.dal.SQLBuilder;
64
import org.gvsig.fmap.dal.SQLBuilder.Privilege;
65
import org.gvsig.fmap.dal.feature.EditableFeature;
66
import org.gvsig.fmap.dal.feature.Feature;
67
import org.gvsig.fmap.dal.feature.FeatureStore;
68
import org.gvsig.fmap.dal.feature.NewFeatureStoreParameters;
69
import org.gvsig.fmap.dal.resource.spi.ResourceProvider;
70
import org.gvsig.fmap.dal.serverexplorer.db.spi.AbstractDBServerExplorer;
71
import org.gvsig.fmap.dal.serverexplorer.filesystem.FilesystemStoreParameters;
72
import org.gvsig.fmap.dal.spi.DataManagerProviderServices;
73
import org.gvsig.fmap.dal.spi.DataServerExplorerProviderServices;
74
import org.gvsig.fmap.dal.store.jdbc.JDBCConnectionParameters;
75
import org.gvsig.fmap.dal.store.jdbc.JDBCNewStoreParameters;
76
import org.gvsig.fmap.dal.store.jdbc.JDBCServerExplorerParameters;
77
import org.gvsig.fmap.dal.store.jdbc.JDBCStoreParameters;
78
import org.gvsig.fmap.dal.store.jdbc.exception.JDBCExecuteSQLException;
79
import org.gvsig.fmap.dal.store.jdbc2.JDBCHelper;
80
import org.gvsig.fmap.dal.store.jdbc2.OperationsFactory;
81
import org.gvsig.fmap.dal.store.jdbc2.spi.operations.CanCreateTablesOperation;
82
import org.gvsig.fmap.dal.store.jdbc2.spi.operations.CreateTableOperation;
83
import org.gvsig.fmap.dal.store.jdbc2.spi.operations.FetchFeatureTypeOperation;
84
import org.gvsig.fmap.dal.store.jdbc2.spi.operations.ListTablesOperation;
85
import org.gvsig.fmap.dal.store.jdbc2.spi.operations.DropTableOperation;
86
import org.gvsig.fmap.dal.store.jdbc2.spi.operations.ExecuteOperation;
87
import org.gvsig.fmap.dal.store.jdbc2.spi.operations.UpdateTableStatisticsOperation;
88
import org.gvsig.json.Json;
89
import org.gvsig.json.JsonObjectBuilder;
90
import org.gvsig.tools.dispose.DisposeUtils;
91
import org.gvsig.tools.exception.BaseException;
92
import org.gvsig.tools.resourcesstorage.EmptyResourcesStorage;
93
import org.gvsig.tools.resourcesstorage.ResourcesStorage;
94
import org.gvsig.tools.util.CachedValue;
95
import org.slf4j.Logger;
96
import org.slf4j.LoggerFactory;
97

    
98
@SuppressWarnings("UseSpecificCatch")
99
public class JDBCServerExplorerBase extends AbstractDBServerExplorer implements JDBCServerExplorer {
100

    
101
    private static final Logger LOG = LoggerFactory.getLogger(JDBCServerExplorerBase.class);
102
    private static final String CONFIG_NAME_CUSTOM_RESOURCES = "CUSTOM_RESOURCES";
103

    
104
    protected JDBCHelper helper = null;
105

    
106
    private Boolean canAdd;
107

    
108
    private static final Map<String, CachedValue<List<JDBCStoreParameters>>> CACHED_TABLES = Collections.synchronizedMap(new LRUMap(10));
109
    private static final Map<String, CachedValue<CustomResourcesConfig>> CACHED_CUSTOM_RESOURCES_CONFIG = Collections.synchronizedMap(new LRUMap(10));
110

    
111
    private static class CustomResourcesConfig {
112

    
113
        private static final String CUSTOM_RESOURCES_CACHETIME = "CacheTime";
114
        private static final String CUSTOM_RESOURCES_MAPPING = "Mapping";
115

    
116

    
117
        private int cacheTime;
118
        private Map<String, String> mapping;
119

    
120
        public CustomResourcesConfig(String jsonConfig) {
121
            this.cacheTime = 30*60*1000; // 30min
122
            this.mapping = new HashMap<>();
123
            if (StringUtils.isNotBlank(jsonConfig)) {
124
                try {
125
                    JsonObject config = Json.createObject(jsonConfig);
126
                    this.cacheTime = config.getInt(CUSTOM_RESOURCES_CACHETIME, this.cacheTime);
127
                    if (!config.containsKey(CUSTOM_RESOURCES_MAPPING)) {
128
                        JsonObject m = config.getJsonObject(CUSTOM_RESOURCES_MAPPING);
129
                        for (Map.Entry<String, JsonValue> entry : m.entrySet()) {
130
                            String key = entry.getKey();
131
                            JsonValue value = entry.getValue();
132
                            if (value instanceof JsonString) {
133
                                this.mapping.put(key, ((JsonString) value).getString());
134
                            }
135
                        }
136
                    }
137
                } catch (Exception ex) {
138
                    LOG.debug("Can't parse json from "+CONFIG_NAME_CUSTOM_RESOURCES+" variable", ex);
139
                    // Do nothing.
140
                }
141
            }
142
        }
143

    
144
        public String toJsonString() {
145
            JsonObjectBuilder builder = Json.createObjectBuilder();
146
            builder.add(CUSTOM_RESOURCES_CACHETIME, cacheTime);
147
            JsonObjectBuilder m = Json.createObjectBuilder();
148
            for (Map.Entry<String, String> entry : mapping.entrySet()) {
149
                String key = entry.getKey();
150
                String value = entry.getValue();
151
                m.add(key, value);
152
            }
153
            builder.add(CUSTOM_RESOURCES_MAPPING, m);
154
            return builder.build().toString();
155
        }
156

    
157
        public int getCacheExpireTimeInMillis() {
158
            return cacheTime;
159
        }
160

    
161
        public String getResourcesTablename(String tablename) {
162
            String resourceTablename = mapping.get(tablename);
163
            return resourceTablename;
164
        }
165

    
166
        public void addResourceMapping(String tablename, String resourcesTablename) {
167
            this.mapping.put(tablename, resourcesTablename);
168
        }
169

    
170
        private boolean isInternalTable(String storeName) {
171
            if (DatabaseWorkspaceManager.isInternalTable(storeName)) {
172
                return true;
173
            }
174
            for (String resourcesTablename : this.mapping.values()) {
175
                if( StringUtils.equals(storeName, resourcesTablename) ) {
176
                    return true;
177
                }
178
            }
179
            return false;
180
        }
181
    }
182
    
183
    private static class CachedCustomResourcesConfig extends CachedValue<CustomResourcesConfig> {
184

    
185
        private final JDBCStoreParameters openParameters;
186

    
187
        private CachedCustomResourcesConfig(JDBCStoreParameters openParameters) {
188
            this.openParameters = openParameters;
189
            this.setExpireTime(30*60*1000); // 30min
190
        }
191

    
192
        @Override
193
        protected void reload() {
194
            String jsonConfig = getConfigValue(this.openParameters, CONFIG_NAME_CUSTOM_RESOURCES);
195
            CustomResourcesConfig config = new CustomResourcesConfig(jsonConfig);        
196
            this.setExpireTime(config.getCacheExpireTimeInMillis());
197
            this.setValue(config);
198
        }
199
        
200
    }
201

    
202
    private static class CachedTablesValue extends CachedValue<List<JDBCStoreParameters>> {
203

    
204
        private final int mode;
205
        private final JDBCServerExplorerParameters serverParameters;
206
        private final boolean informationTables;
207
        private final JDBCHelper helper;
208

    
209
        public CachedTablesValue(JDBCHelper helper, int mode, JDBCServerExplorerParameters serverParameters, boolean informationTables) {
210
            this.mode = mode;
211
            this.serverParameters = serverParameters;
212
            this.informationTables = informationTables;
213
            this.helper = helper;
214
        }
215

    
216
        public CachedTablesValue(JDBCHelper helper, int mode, JDBCServerExplorerParameters serverParameters, boolean informationTables, long expireTime) {
217
            this.mode = mode;
218
            this.setExpireTime(expireTime);
219
            this.serverParameters = serverParameters;
220
            this.informationTables = informationTables;
221
            this.helper = helper;
222
        }
223

    
224
        @Override
225
        protected void reload() {
226
            List<JDBCStoreParameters> tables = null;
227
            OperationsFactory operations = helper.getOperations();
228
            if (operations == null) {
229
                this.setValue(null);
230
                LOG.debug("Sets tables to null to force reload tables from new ServerExplorar.");
231
                return;
232
            }
233
            try {
234
                ListTablesOperation listTables = operations.createListTables(
235
                        this.mode, serverParameters, informationTables
236
                );
237
                tables = (List<JDBCStoreParameters>) listTables.perform();
238
            } catch (Exception ex) {
239
                LOG.debug("Can't reload cached list of tables.", ex);
240
            }
241
            this.setValue(tables);
242
        }
243
    }
244

    
245
    public JDBCServerExplorerBase(
246
            JDBCServerExplorerParameters parameters,
247
            DataServerExplorerProviderServices services,
248
            JDBCHelper helper
249
    ) throws InitializeException {
250
        super(parameters, services);
251
        this.helper = helper;
252
    }
253

    
254
    @Override
255
    public String getProviderName() {
256
        return this.getHelper().getProviderName();
257
    }
258

    
259
    @Override
260
    public String getStoreName() {
261
        return this.getHelper().getProviderName();
262
    }
263

    
264
    protected DataManagerProviderServices getManager() {
265
        return (DataManagerProviderServices) DALLocator.getDataManager();
266
    }
267

    
268
    @Override
269
    public JDBCServerExplorerParameters getParameters() {
270
        return (JDBCServerExplorerParameters) super.getParameters();
271
    }
272

    
273
    @Override
274
    public boolean closeResourceRequested(ResourceProvider resource) {
275
        this.getHelper().getResulSetControler().pack();
276
        return true;
277
    }
278

    
279
    @Override
280
    public void resourceChanged(ResourceProvider resource) {
281
        // Nothing to do
282
    }
283

    
284
    protected JDBCHelper getHelper() {
285
        return helper;
286
    }
287

    
288
    protected OperationsFactory getOperations() {
289
        return this.getHelper().getOperations();
290
    }
291

    
292
    @Override
293
    public DataStore open(DataStoreParameters params) throws DataException {
294
        checkIsMine(params);
295
        DataStore store = super.open(params);
296
        return store;
297
    }
298

    
299
    @Override
300
    public List list(int mode) throws DataException {
301
        boolean informationTables = BooleanUtils.isTrue(
302
                this.getParameters().getShowInformationDBTables()
303
        );
304

    
305
        JDBCServerExplorerParameters serverParams = this.getParameters();
306

    
307
        String key = buildKeyForCachedTables(mode, serverParams, informationTables);
308
        CachedValue<List<JDBCStoreParameters>> tablesValue = CACHED_TABLES.get(key);
309
        List<JDBCStoreParameters> tables = null;
310
        if (tablesValue != null) {
311
            tables = tablesValue.get();
312
        }
313
        if (tables != null) {
314
            return tables;
315
        }
316
        tablesValue = new CachedTablesValue(this.helper, mode, serverParams, informationTables, 60000); //60"
317
        CACHED_TABLES.put(key, tablesValue);
318
        tables = tablesValue.get();
319
        return tables;
320
    }
321

    
322
    public String buildKeyForCachedTables(int mode, JDBCServerExplorerParameters params, boolean informationTables) {
323
        JDBCServerExplorerParameters clonedParams = (JDBCServerExplorerParameters) params.getCopy();
324
        clonedParams.setSchema(null); //ListTableOperation no usa el schema
325

    
326
        StringBuilder builder = new StringBuilder();
327
        builder.append(String.valueOf(mode));
328
        builder.append(Hex.encodeHex(clonedParams.toByteArray()));
329
        builder.append(String.valueOf(informationTables));
330
        String key = builder.toString();
331
        return key;
332
    }
333

    
334
    @Override
335
    public void remove(DataStoreParameters theParams) throws RemoveException {
336
        JDBCStoreParameters params = (JDBCStoreParameters) theParams;
337
        DropTableOperation removeTable = this.getOperations().createDropTable(
338
                this.getOperations().createTableReference(params)
339
        );
340
        if ((Boolean) removeTable.perform()) {
341
            this.dropCachedTables();
342
        }
343
    }
344

    
345
    @Override
346
    public JDBCStoreParameters getOpenParameters() throws DataException {
347
        JDBCStoreParameters params = this.helper.createOpenStoreParameters(this.getParameters());
348
        return params;
349
    }
350

    
351
    @Override
352
    public NewDataStoreParameters getAddParameters(String storeName)
353
            throws DataException {
354
        JDBCNewStoreParameters params = this.getAddParameters();
355
        params.setTable(storeName);
356
        return params;
357
    }
358

    
359
    @Override
360
    public JDBCNewStoreParameters getAddParameters() throws DataException {
361
        JDBCServerExplorerParameters parameters = getParameters();
362
        JDBCNewStoreParameters params = this.helper.createNewStoreParameters();
363
        params.setHost(parameters.getHost());
364
        params.setPort(parameters.getPort());
365
        params.setDBName(parameters.getDBName());
366
        params.setUser(parameters.getUser());
367
        params.setPassword(parameters.getPassword());
368
        params.setCatalog(parameters.getCatalog());
369
        params.setSchema(parameters.getSchema());
370
        params.setJDBCDriverClassName(parameters.getJDBCDriverClassName());
371
        params.setUrl(parameters.getUrl());
372
        if (parameters instanceof FilesystemStoreParameters) {
373
            File f = ((FilesystemStoreParameters) parameters).getFile();
374
            ((FilesystemStoreParameters) params).setFile(f);
375
        }
376

    
377
        params.setDefaultFeatureType(this.getServerExplorerProviderServices()
378
                .createNewFeatureType());
379

    
380
        return params;
381
    }
382

    
383
    protected void checkIsMine(DataStoreParameters dsp) {
384
        if (!(dsp instanceof JDBCConnectionParameters)) {
385
            throw new IllegalArgumentException(
386
                    "not instance of FilesystemStoreParameters");
387
        }
388
        JDBCServerExplorerParameters parameters = getParameters();
389

    
390
        JDBCConnectionParameters pgp = (JDBCConnectionParameters) dsp;
391
        if (!StringUtils.equals(pgp.getHost(), parameters.getHost())) {
392
            throw new IllegalArgumentException("wrong explorer: Host (mine: "
393
                    + parameters.getHost() + " other:" + pgp.getHost() + ")");
394
        }
395
        if (!ObjectUtils.equals(pgp.getPort(), parameters.getPort())) {
396
            throw new IllegalArgumentException("wrong explorer: Port (mine: "
397
                    + parameters.getPort() + " other:" + pgp.getPort() + ")");
398
        }
399
        if (!StringUtils.equals(pgp.getDBName(), parameters.getDBName())) {
400
            throw new IllegalArgumentException("wrong explorer: DBName (mine: "
401
                    + parameters.getDBName() + " other:" + pgp.getDBName()
402
                    + ")");
403
        }
404
        if (!StringUtils.isEmpty(parameters.getCatalog())) {
405
            if (!StringUtils.equals(pgp.getCatalog(), parameters.getCatalog())) {
406
                throw new IllegalArgumentException(
407
                        "wrong explorer: Catalog (mine: "
408
                        + parameters.getCatalog() + " other:"
409
                        + pgp.getCatalog() + ")");
410
            }
411
        }
412
        if (!StringUtils.isEmpty(parameters.getSchema())) {
413
            if (!StringUtils.equals(pgp.getSchema(), parameters.getSchema())) {
414
                throw new IllegalArgumentException(
415
                        "wrong explorer: Schema (mine: "
416
                        + parameters.getSchema() + " other:"
417
                        + pgp.getSchema() + ")");
418
            }
419
        }
420
    }
421

    
422
    @Override
423
    public void open() throws OpenException {
424

    
425
    }
426

    
427
    @Override
428
    public void close() throws CloseException {
429

    
430
    }
431

    
432
    @Override
433
    protected void doDispose() throws BaseException {
434
        helper.dispose();
435
        helper = null;
436
    }
437

    
438
    @Override
439
    public boolean canAdd() {
440
        if (this.canAdd == null) {
441
            CanCreateTablesOperation canAdd_ = this.getOperations().createCanCreateTables();
442
            this.canAdd = (Boolean) canAdd_.perform();
443
        }
444
        return this.canAdd;
445
    }
446

    
447
    @Override
448
    public FeatureType getFeatureType(DataStoreParameters theParams)
449
            throws DataException {
450

    
451
        JDBCStoreParameters params = (JDBCStoreParameters) theParams;
452

    
453
        checkIsMine(params);
454

    
455
        EditableFeatureType fetureType
456
                = this.getServerExplorerProviderServices().createNewFeatureType();
457

    
458
        List<String> primaryKeys = null;
459
        if (params.getPkFields() != null) {
460
            primaryKeys = Arrays.asList(params.getPkFields());
461
        }
462

    
463
        FetchFeatureTypeOperation fetch = this.getOperations().createFetchFeatureType(
464
                fetureType,
465
                this.getOperations().createTableReference(params),
466
                primaryKeys,
467
                params.getDefaultGeometryField(),
468
                params.getCRS()
469
        );
470
        fetch.perform();
471
        return fetureType;
472
    }
473

    
474
    @Override
475
    public boolean add(String providerName, NewDataStoreParameters theParams, boolean overwrite)
476
            throws DataException {
477

    
478
        List<Pair<String, Privilege>> userAndPrivileges = new ArrayList<>();
479
        JDBCNewStoreParameters params = (JDBCNewStoreParameters) theParams;
480
        if (!StringUtils.isEmpty(params.getAllRole())) {
481
            userAndPrivileges.add(
482
                    new ImmutablePair<>(params.getAllRole(), Privilege.ALL)
483
            );
484
        }
485
        if (!StringUtils.isEmpty(params.getDeleteRole())) {
486
            userAndPrivileges.add(
487
                    new ImmutablePair<>(params.getDeleteRole(), Privilege.DELETE)
488
            );
489
        }
490
        if (!StringUtils.isEmpty(params.getInsertRole())) {
491
            userAndPrivileges.add(
492
                    new ImmutablePair<>(params.getInsertRole(), Privilege.INSERT)
493
            );
494
        }
495
        if (!StringUtils.isEmpty(params.getReferenceRole())) {
496
            userAndPrivileges.add(
497
                    new ImmutablePair<>(params.getReferenceRole(), Privilege.REFERENCE)
498
            );
499
        }
500
        if (!StringUtils.isEmpty(params.getSelectRole())) {
501
            userAndPrivileges.add(
502
                    new ImmutablePair<>(params.getSelectRole(), Privilege.SELECT)
503
            );
504
        }
505
        if (!StringUtils.isEmpty(params.getTriggerRole())) {
506
            userAndPrivileges.add(
507
                    new ImmutablePair<>(params.getTriggerRole(), Privilege.TRIGGER)
508
            );
509
        }
510
        if (!StringUtils.isEmpty(params.getTruncateRole())) {
511
            userAndPrivileges.add(
512
                    new ImmutablePair<>(params.getTruncateRole(), Privilege.TRUNCATE)
513
            );
514
        }
515
        if (!StringUtils.isEmpty(params.getUpdateRole())) {
516
            userAndPrivileges.add(
517
                    new ImmutablePair<>(params.getUpdateRole(), Privilege.UPDATE)
518
            );
519
        }
520
        List<String> additionalSQLs = new ArrayList<>();
521
        if (!StringUtils.isEmpty(params.getPostCreatingStatement())) {
522
            additionalSQLs.add(params.getPostCreatingStatement());
523
        }
524
        CreateTableOperation createTable = this.getOperations().createTable(
525
                this.getOperations().createTableReference(params),
526
                params.getDefaultFeatureType(),
527
                userAndPrivileges,
528
                additionalSQLs
529
        );
530

    
531
        boolean isOk = (boolean) createTable.perform();
532
        if (!isOk) {
533
            return false;
534
        }
535

    
536
        // We collect the featureType of the operation because 
537
        // the provider has been able to make changes to it
538
        params.setDefaultFeatureType(createTable.getType());
539

    
540
        if (theParams instanceof NewFeatureStoreParameters) {
541
            DataManager dataManager = DALLocator.getDataManager();
542
            ResourcesStorage resources = this.getResourcesStorage(theParams);
543
            dataManager.writeDALResource(resources, ((NewFeatureStoreParameters) theParams).getDefaultFeatureType());
544
        }
545
        this.dropCachedTables();
546
        return true;
547
    }
548

    
549
    private void dropCachedTables() {
550
        boolean informationTables = BooleanUtils.isTrue(
551
                this.getParameters().getShowInformationDBTables()
552
        );
553
        CACHED_TABLES.remove(buildKeyForCachedTables(MODE_ALL, this.getParameters(), informationTables));
554
        CACHED_TABLES.remove(buildKeyForCachedTables(MODE_FEATURE, this.getParameters(), informationTables));
555
        CACHED_TABLES.remove(buildKeyForCachedTables(MODE_GEOMETRY, this.getParameters(), informationTables));
556
    }
557

    
558
    @Override
559
    public List getDataStoreProviderNames() {
560
        List x = new ArrayList(1);
561
        x.add(this.getProviderName());
562
        return x;
563
    }
564

    
565
    @Override
566
    public void updateTableStatistics(String database, String schema, String table) throws JDBCExecuteSQLException {
567
        UpdateTableStatisticsOperation updateStatistics = this.getOperations().createUpdateTableStatistics(
568
                this.getOperations().createTableReference(database, schema, table, null)
569
        );
570
        updateStatistics.perform();
571
    }
572

    
573
    @Override
574
    public Object execute(String sql) {
575
        ExecuteOperation execute = this.getOperations().createExecute(sql);
576
        return execute.perform();
577
    }
578

    
579
    @Override
580
    public JDBCStoreParameters get(String name) throws DataException {
581
        JDBCStoreParameters params = this.getOpenParameters();
582
        params.setTable(name);
583
        return params;
584
    }
585

    
586
    @Override
587
    public SQLBuilder createSQLBuilder() {
588
        JDBCSQLBuilderBase builder = this.getHelper().createSQLBuilder();
589
        return builder;
590
    }
591

    
592
    private CustomResourcesConfig getCustomResourcesConfig() {
593
        JDBCServerExplorerParameters serverParams = this.getParameters();
594
        String key = buildKeyForCachedTables(MODE_ALL, serverParams, false);
595
        CachedValue<CustomResourcesConfig> cachedConfig = CACHED_CUSTOM_RESOURCES_CONFIG.get(key);
596
        if (cachedConfig != null) {
597
            CustomResourcesConfig config = cachedConfig.get();
598
            return config;
599
        }
600
        JDBCStoreParameters params = this.helper.createOpenStoreParameters(this.getParameters());
601
        cachedConfig = new CachedCustomResourcesConfig(params);
602
        CACHED_CUSTOM_RESOURCES_CONFIG.put(key, cachedConfig);
603
        return cachedConfig.get();
604
    }
605

    
606
    private ResourcesStorage getResourcesStorage(DataStoreParameters parameters, String storeName) {
607
        if (DatabaseWorkspaceManager.isInternalTable(storeName)) {
608
            EmptyResourcesStorage resourcesStorage = new EmptyResourcesStorage();
609
            return resourcesStorage;
610
        }
611
        String resourcesTablename = null;
612
        try { 
613
            ResourcesStorage alternateResourcesStorage = null;
614
            DataManager dataManager = DALLocator.getDataManager();
615
            DatabaseWorkspaceManager workspace = dataManager.getDatabaseWorkspace(parameters);
616
            if (workspace != null) {
617
                alternateResourcesStorage = workspace.getAlternativeResourcesStorage(storeName);
618
            }
619
            
620
            CustomResourcesConfig config = getCustomResourcesConfig();
621
            if( config!=null ) {
622
                if( config.isInternalTable(storeName) ) {
623
                    EmptyResourcesStorage theResourcesStorage = new EmptyResourcesStorage();
624
                    return theResourcesStorage;
625
                }
626
                resourcesTablename = config.getResourcesTablename(storeName);
627
                if( StringUtils.isNotBlank(resourcesTablename) ) {
628
                    JDBCStoreParameters params = this.getOpenParameters();
629
                    params.setTable(resourcesTablename);
630
                    JDBCResourcesStorage resourcesStorage = new JDBCResourcesStorage(
631
                            alternateResourcesStorage,
632
                            params,
633
                            storeName
634
                    );
635
                    return resourcesStorage;
636
                }
637
            }
638
            // TODO: Habria que ver de localizar los parametros sin tener que hacer un list.
639
            resourcesTablename = TABLE_RESOURCES_NAME;
640
            List<JDBCStoreParameters> tables = this.list();
641
            for (JDBCStoreParameters params : tables) {
642
                String theTableName = params.getTable();
643
                if (StringUtils.equals(theTableName, resourcesTablename)) {
644
                    JDBCResourcesStorage theResourcesStorage = new JDBCResourcesStorage(
645
                            alternateResourcesStorage,
646
                            params,
647
                            storeName
648
                    );
649
                    return theResourcesStorage;
650
                }
651
            }
652
        } catch (Throwable ex) {
653
            LOG.warn("Can't retrieve reources storage for table '" + storeName + "' in '" + this.getParameters().getUrl() + " ("+resourcesTablename+").", ex);
654
        }
655
        EmptyResourcesStorage theResourcesStorage = new EmptyResourcesStorage();
656
        return theResourcesStorage;
657
    }
658

    
659
    @Override
660
    public ResourcesStorage getResourcesStorage() {
661
        JDBCStoreParameters params;
662
        try {
663
            params = this.getOpenParameters();
664
            params.setTable(DatabaseWorkspaceManager.TABLE_RESOURCES_NAME);
665
            JDBCResourcesStorage theResourcesStorage = new JDBCResourcesStorage(
666
                    null,
667
                    params,
668
                    "$ServerExplorer"
669
            );
670
            return theResourcesStorage;
671
        } catch (DataException ex) {
672
            return null;
673
        }
674
    }
675

    
676
    @Override
677
    public ResourcesStorage getResourcesStorage(DataStoreParameters parameters) {
678
        if (parameters == null) {
679
            throw new IllegalArgumentException("null is a valid value for parameters.");
680
        }
681
        String tableName;
682
        if (parameters instanceof JDBCNewStoreParameters) {
683
            tableName = ((JDBCNewStoreParameters) parameters).getTable();
684
        } else if (parameters instanceof JDBCStoreParameters) {
685
            tableName = ((JDBCStoreParameters) parameters).getTable();
686
        } else {
687
            throw new IllegalArgumentException("Required a JDBCStoreParameters or JDBCNewStoreParameters parameters, received " + parameters.getClass().getName() + ".");
688
        }
689
        return this.getResourcesStorage(parameters, tableName);
690
    }
691

    
692
    @Override
693
    public ResourcesStorage getResourcesStorage(DataStore dataStore) {
694
        return this.getResourcesStorage(
695
                (JDBCStoreParameters) dataStore.getParameters(),
696
                dataStore.getName()
697
        );
698
    }
699

    
700
    @Override
701
    public boolean exists(DataStoreParameters parameters) throws DataException {
702
        JDBCStoreParameters params = (JDBCStoreParameters) parameters;
703
        JDBCSQLBuilderBase builder = this.getHelper().createSQLBuilder();
704
        SQLBuilder.TableNameBuilder searchTable = builder.createTableNameBuilder()
705
                .database(params.getDBName())
706
                .schema(params.getSchema())
707
                .name(params.getTable());
708
        SQLBuilder.TableNameBuilder table = builder.createTableNameBuilder();
709

    
710
        List<JDBCStoreParameters> l = this.list();
711
        for (JDBCStoreParameters current : l) {
712
            table.database(current.getDBName())
713
                    .schema(current.getSchema())
714
                    .name(current.getTable());
715
            if (table.equals(searchTable)) {
716
                return true;
717
            }
718
        }
719
        return false;
720
    }
721

    
722
    @Override
723
    public void setCustomResources(String tableName, String resourcesTableName) {
724
        CustomResourcesConfig config = getCustomResourcesConfig();
725
        if( config==null ) {
726
            throw new RuntimeException("Can't retrieve alternative resources configuration");
727
        }
728
        config.addResourceMapping(tableName, resourcesTableName);
729
        JDBCStoreParameters params = this.helper.createOpenStoreParameters(this.getParameters());
730
        setConfigValue(params, CONFIG_NAME_CUSTOM_RESOURCES, config.toJsonString());
731
    }
732

    
733
    private static boolean setConfigValue(JDBCStoreParameters params, String name, String value) {
734
        FeatureStore store = null;
735
        try {
736
            DataManager dataManager = DALLocator.getDataManager();
737
            params.setTable(TABLE_CONFIGURATION_NAME);
738
            store = (FeatureStore) dataManager.openStore(
739
                    params.getProviderName(), 
740
                    params
741
            );
742
        } catch (Exception ex) {
743
            LOG.trace("Can't read configuration value '"+name+"'", ex);
744
            // Do noting
745
//        } finally {
746
//            DisposeUtils.disposeQuietly(store);
747
        }
748
        if( store == null ) {
749
            return false;
750
        }
751
        try {
752
            store.edit();
753
            ExpressionBuilder builder = ExpressionUtils.createExpressionBuilder();
754
            String filter = builder.eq(
755
                    builder.column(FIELD_CONFIGURATION_NAME),
756
                    builder.constant(name)
757
            ).toString();
758
            Feature feature = store.findFirst(filter);
759
            EditableFeature efeature;
760
            if (feature == null) {
761
                efeature = store.createNewFeature();
762
                efeature.set(FIELD_CONFIGURATION_NAME, name);
763
                efeature.set(FIELD_CONFIGURATION_VALUE, value);
764
                store.insert(efeature);
765
            } else {
766
                efeature = feature.getEditable();
767
                efeature.set(FIELD_CONFIGURATION_VALUE, value);
768
                store.update(efeature);
769
            }
770
            store.finishEditing();
771
            return true;
772
        } catch (Exception ex) {
773
            LOG.debug("Can't write configuration value for '"+name+"'", ex);
774
            return false;
775
        } finally {
776
            DisposeUtils.disposeQuietly(store);
777
        }
778
    }
779
    
780
    private static String getConfigValue(JDBCStoreParameters params, String name) {
781
        FeatureStore store = null;
782
        try {
783
            DataManager dataManager = DALLocator.getDataManager();
784
            params.setTable(TABLE_CONFIGURATION_NAME);
785
            store = (FeatureStore) dataManager.openStore(
786
                    params.getProviderName(), 
787
                    params
788
            );
789
        } catch (Exception ex) {
790
            LOG.trace("Can't read configuration value '"+name+"'", ex);
791
            // Do noting
792
//        } finally {
793
//            DisposeUtils.disposeQuietly(store);
794
        }
795
        if( store == null ) {
796
            return null;
797
        }
798
        try {
799
            ExpressionBuilder builder = ExpressionUtils.createExpressionBuilder();
800
            String filter = builder.eq(
801
                    builder.column(FIELD_CONFIGURATION_NAME),
802
                    builder.constant(name)
803
            ).toString();
804
            Feature feature = store.findFirst(filter);
805
            if( feature == null ) {
806
                return null;
807
            }
808
            String value = feature.getString(FIELD_CONFIGURATION_VALUE);
809
            return value;
810
            
811
        } catch (Exception ex) {
812
            LOG.debug("Can't read configuration value '"+name+"'", ex);
813
            return null;
814
        } finally {
815
            DisposeUtils.disposeQuietly(store);
816
        }
817
    }
818
    
819
}