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

History | View | Annotate | Download (32.3 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 int cacheTime;
114
        private Map<String, String> mapping;
115

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

    
140
        public String toJsonString() {
141
            JsonObjectBuilder builder = Json.createObjectBuilder();
142
            builder.add("cacheTime", cacheTime);
143
            JsonObjectBuilder m = Json.createObjectBuilder();
144
            for (Map.Entry<String, String> entry : mapping.entrySet()) {
145
                String key = entry.getKey();
146
                String value = entry.getValue();
147
                m.add(key, value);
148
            }
149
            builder.add("mapping", m);
150
            return builder.build().toString();
151
        }
152

    
153
        public int getCacheExpireTimeInMillis() {
154
            return cacheTime;
155
        }
156

    
157
        public String getResourcesTablename(String tablename) {
158
            String resourceTablename = mapping.get(tablename);
159
            return resourceTablename;
160
        }
161

    
162
        public void addResourceMapping(String tablename, String resourcesTablename) {
163
            this.mapping.put(tablename, resourcesTablename);
164
        }
165

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

    
181
        private final JDBCStoreParameters openParameters;
182

    
183
        private CachedCustomResourcesConfig(JDBCStoreParameters openParameters) {
184
            this.openParameters = openParameters;
185
            this.setExpireTime(30*60*1000); // 30min
186
        }
187

    
188
        @Override
189
        protected void reload() {
190
            String jsonConfig = getConfigValue(this.openParameters, CONFIG_NAME_CUSTOM_RESOURCES);
191
            CustomResourcesConfig config = new CustomResourcesConfig(jsonConfig);        
192
            this.setExpireTime(config.getCacheExpireTimeInMillis());
193
            this.setValue(config);
194
        }
195
        
196
    }
197

    
198
    private static class CachedTablesValue extends CachedValue<List<JDBCStoreParameters>> {
199

    
200
        private final int mode;
201
        private final JDBCServerExplorerParameters serverParameters;
202
        private final boolean informationTables;
203
        private final JDBCHelper helper;
204

    
205
        public CachedTablesValue(JDBCHelper helper, int mode, JDBCServerExplorerParameters serverParameters, boolean informationTables) {
206
            this.mode = mode;
207
            this.serverParameters = serverParameters;
208
            this.informationTables = informationTables;
209
            this.helper = helper;
210
        }
211

    
212
        public CachedTablesValue(JDBCHelper helper, int mode, JDBCServerExplorerParameters serverParameters, boolean informationTables, long expireTime) {
213
            this.mode = mode;
214
            this.setExpireTime(expireTime);
215
            this.serverParameters = serverParameters;
216
            this.informationTables = informationTables;
217
            this.helper = helper;
218
        }
219

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

    
241
    public JDBCServerExplorerBase(
242
            JDBCServerExplorerParameters parameters,
243
            DataServerExplorerProviderServices services,
244
            JDBCHelper helper
245
    ) throws InitializeException {
246
        super(parameters, services);
247
        this.helper = helper;
248
    }
249

    
250
    @Override
251
    public String getProviderName() {
252
        return this.getHelper().getProviderName();
253
    }
254

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

    
260
    protected DataManagerProviderServices getManager() {
261
        return (DataManagerProviderServices) DALLocator.getDataManager();
262
    }
263

    
264
    @Override
265
    public JDBCServerExplorerParameters getParameters() {
266
        return (JDBCServerExplorerParameters) super.getParameters();
267
    }
268

    
269
    @Override
270
    public boolean closeResourceRequested(ResourceProvider resource) {
271
        this.getHelper().getResulSetControler().pack();
272
        return true;
273
    }
274

    
275
    @Override
276
    public void resourceChanged(ResourceProvider resource) {
277
        // Nothing to do
278
    }
279

    
280
    protected JDBCHelper getHelper() {
281
        return helper;
282
    }
283

    
284
    protected OperationsFactory getOperations() {
285
        return this.getHelper().getOperations();
286
    }
287

    
288
    @Override
289
    public DataStore open(DataStoreParameters params) throws DataException {
290
        checkIsMine(params);
291
        DataStore store = super.open(params);
292
        return store;
293
    }
294

    
295
    @Override
296
    public List list(int mode) throws DataException {
297
        boolean informationTables = BooleanUtils.isTrue(
298
                this.getParameters().getShowInformationDBTables()
299
        );
300

    
301
        JDBCServerExplorerParameters serverParams = this.getParameters();
302

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

    
318
    public String buildKeyForCachedTables(int mode, JDBCServerExplorerParameters params, boolean informationTables) {
319
        JDBCServerExplorerParameters clonedParams = (JDBCServerExplorerParameters) params.getCopy();
320
        clonedParams.setSchema(null); //ListTableOperation no usa el schema
321

    
322
        StringBuilder builder = new StringBuilder();
323
        builder.append(String.valueOf(mode));
324
        builder.append(Hex.encodeHex(clonedParams.toByteArray()));
325
        builder.append(String.valueOf(informationTables));
326
        String key = builder.toString();
327
        return key;
328
    }
329

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

    
341
    @Override
342
    public JDBCStoreParameters getOpenParameters() throws DataException {
343
        JDBCStoreParameters params = this.helper.createOpenStoreParameters(this.getParameters());
344
        return params;
345
    }
346

    
347
    @Override
348
    public NewDataStoreParameters getAddParameters(String storeName)
349
            throws DataException {
350
        JDBCNewStoreParameters params = this.getAddParameters();
351
        params.setTable(storeName);
352
        return params;
353
    }
354

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

    
373
        params.setDefaultFeatureType(this.getServerExplorerProviderServices()
374
                .createNewFeatureType());
375

    
376
        return params;
377
    }
378

    
379
    protected void checkIsMine(DataStoreParameters dsp) {
380
        if (!(dsp instanceof JDBCConnectionParameters)) {
381
            throw new IllegalArgumentException(
382
                    "not instance of FilesystemStoreParameters");
383
        }
384
        JDBCServerExplorerParameters parameters = getParameters();
385

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

    
418
    @Override
419
    public void open() throws OpenException {
420

    
421
    }
422

    
423
    @Override
424
    public void close() throws CloseException {
425

    
426
    }
427

    
428
    @Override
429
    protected void doDispose() throws BaseException {
430
        helper.dispose();
431
        helper = null;
432
    }
433

    
434
    @Override
435
    public boolean canAdd() {
436
        if (this.canAdd == null) {
437
            CanCreateTablesOperation canAdd_ = this.getOperations().createCanCreateTables();
438
            this.canAdd = (Boolean) canAdd_.perform();
439
        }
440
        return this.canAdd;
441
    }
442

    
443
    @Override
444
    public FeatureType getFeatureType(DataStoreParameters theParams)
445
            throws DataException {
446

    
447
        JDBCStoreParameters params = (JDBCStoreParameters) theParams;
448

    
449
        checkIsMine(params);
450

    
451
        EditableFeatureType fetureType
452
                = this.getServerExplorerProviderServices().createNewFeatureType();
453

    
454
        List<String> primaryKeys = null;
455
        if (params.getPkFields() != null) {
456
            primaryKeys = Arrays.asList(params.getPkFields());
457
        }
458

    
459
        FetchFeatureTypeOperation fetch = this.getOperations().createFetchFeatureType(
460
                fetureType,
461
                this.getOperations().createTableReference(params),
462
                primaryKeys,
463
                params.getDefaultGeometryField(),
464
                params.getCRS()
465
        );
466
        fetch.perform();
467
        return fetureType;
468
    }
469

    
470
    @Override
471
    public boolean add(String providerName, NewDataStoreParameters theParams, boolean overwrite)
472
            throws DataException {
473

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

    
527
        boolean isOk = (boolean) createTable.perform();
528
        if (!isOk) {
529
            return false;
530
        }
531

    
532
        // We collect the featureType of the operation because 
533
        // the provider has been able to make changes to it
534
        params.setDefaultFeatureType(createTable.getType());
535

    
536
        if (theParams instanceof NewFeatureStoreParameters) {
537
            DataManager dataManager = DALLocator.getDataManager();
538
            ResourcesStorage resources = this.getResourcesStorage(theParams);
539
            dataManager.writeDALResource(resources, ((NewFeatureStoreParameters) theParams).getDefaultFeatureType());
540
        }
541
        this.dropCachedTables();
542
        return true;
543
    }
544

    
545
    private void dropCachedTables() {
546
        boolean informationTables = BooleanUtils.isTrue(
547
                this.getParameters().getShowInformationDBTables()
548
        );
549
        CACHED_TABLES.remove(buildKeyForCachedTables(MODE_ALL, this.getParameters(), informationTables));
550
        CACHED_TABLES.remove(buildKeyForCachedTables(MODE_FEATURE, this.getParameters(), informationTables));
551
        CACHED_TABLES.remove(buildKeyForCachedTables(MODE_GEOMETRY, this.getParameters(), informationTables));
552
    }
553

    
554
    @Override
555
    public List getDataStoreProviderNames() {
556
        List x = new ArrayList(1);
557
        x.add(this.getProviderName());
558
        return x;
559
    }
560

    
561
    @Override
562
    public void updateTableStatistics(String database, String schema, String table) throws JDBCExecuteSQLException {
563
        UpdateTableStatisticsOperation updateStatistics = this.getOperations().createUpdateTableStatistics(
564
                this.getOperations().createTableReference(database, schema, table, null)
565
        );
566
        updateStatistics.perform();
567
    }
568

    
569
    @Override
570
    public Object execute(String sql) {
571
        ExecuteOperation execute = this.getOperations().createExecute(sql);
572
        return execute.perform();
573
    }
574

    
575
    @Override
576
    public JDBCStoreParameters get(String name) throws DataException {
577
        JDBCStoreParameters params = this.getOpenParameters();
578
        params.setTable(name);
579
        return params;
580
    }
581

    
582
    @Override
583
    public SQLBuilder createSQLBuilder() {
584
        JDBCSQLBuilderBase builder = this.getHelper().createSQLBuilder();
585
        return builder;
586
    }
587

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

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

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

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

    
688
    @Override
689
    public ResourcesStorage getResourcesStorage(DataStore dataStore) {
690
        return this.getResourcesStorage(
691
                (JDBCStoreParameters) dataStore.getParameters(),
692
                dataStore.getName()
693
        );
694
    }
695

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

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

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

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