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

History | View | Annotate | Download (34.7 KB)

1 43020 jjdelcerro
/**
2
 * gvSIG. Desktop Geographic Information System.
3
 *
4 45065 jjdelcerro
 * Copyright (C) 2007-2020 gvSIG Association.
5 43020 jjdelcerro
 *
6 45065 jjdelcerro
 * 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 43020 jjdelcerro
 *
11 45065 jjdelcerro
 * 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 43020 jjdelcerro
 *
16 45065 jjdelcerro
 * 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 43020 jjdelcerro
 *
21 45065 jjdelcerro
 * For any additional information, do not hesitate to contact us
22
 * at info AT gvsig.com, or visit our website www.gvsig.com.
23 43020 jjdelcerro
 */
24
package org.gvsig.fmap.dal.store.jdbc2.spi;
25
26 43377 jjdelcerro
import java.io.File;
27 43020 jjdelcerro
import java.util.ArrayList;
28
import java.util.Arrays;
29 45152 fdiaz
import java.util.Collections;
30 45578 jjdelcerro
import java.util.HashMap;
31 43020 jjdelcerro
import java.util.List;
32 45152 fdiaz
import java.util.Map;
33 45578 jjdelcerro
import javax.json.JsonObject;
34
import javax.json.JsonString;
35
import javax.json.JsonValue;
36 45152 fdiaz
import org.apache.commons.codec.binary.Hex;
37
import org.apache.commons.collections.map.LRUMap;
38 43020 jjdelcerro
import org.apache.commons.lang3.BooleanUtils;
39
import org.apache.commons.lang3.ObjectUtils;
40
import org.apache.commons.lang3.StringUtils;
41
import org.apache.commons.lang3.tuple.ImmutablePair;
42
import org.apache.commons.lang3.tuple.Pair;
43 45578 jjdelcerro
import org.gvsig.expressionevaluator.ExpressionBuilder;
44
import org.gvsig.expressionevaluator.ExpressionUtils;
45 43020 jjdelcerro
import org.gvsig.fmap.dal.DALLocator;
46 44328 jjdelcerro
import org.gvsig.fmap.dal.DataManager;
47 43020 jjdelcerro
import org.gvsig.fmap.dal.DataStore;
48
import org.gvsig.fmap.dal.DataStoreParameters;
49 44346 jjdelcerro
import org.gvsig.fmap.dal.DatabaseWorkspaceManager;
50 45578 jjdelcerro
import static org.gvsig.fmap.dal.DatabaseWorkspaceManager.FIELD_CONFIGURATION_NAME;
51
import static org.gvsig.fmap.dal.DatabaseWorkspaceManager.FIELD_CONFIGURATION_VALUE;
52
import static org.gvsig.fmap.dal.DatabaseWorkspaceManager.TABLE_CONFIGURATION_NAME;
53 44304 jjdelcerro
import static org.gvsig.fmap.dal.DatabaseWorkspaceManager.TABLE_RESOURCES_NAME;
54 43020 jjdelcerro
import org.gvsig.fmap.dal.NewDataStoreParameters;
55 45614 fdiaz
import org.gvsig.fmap.dal.SQLBuilder;
56
import org.gvsig.fmap.dal.SQLBuilder.Privilege;
57 43020 jjdelcerro
import org.gvsig.fmap.dal.exception.CloseException;
58
import org.gvsig.fmap.dal.exception.DataException;
59
import org.gvsig.fmap.dal.exception.InitializeException;
60
import org.gvsig.fmap.dal.exception.OpenException;
61
import org.gvsig.fmap.dal.exception.RemoveException;
62 45614 fdiaz
import org.gvsig.fmap.dal.feature.EditableFeature;
63 43020 jjdelcerro
import org.gvsig.fmap.dal.feature.EditableFeatureType;
64 45578 jjdelcerro
import org.gvsig.fmap.dal.feature.Feature;
65
import org.gvsig.fmap.dal.feature.FeatureStore;
66 45614 fdiaz
import org.gvsig.fmap.dal.feature.FeatureType;
67 44328 jjdelcerro
import org.gvsig.fmap.dal.feature.NewFeatureStoreParameters;
68 43020 jjdelcerro
import org.gvsig.fmap.dal.resource.spi.ResourceProvider;
69
import org.gvsig.fmap.dal.serverexplorer.db.spi.AbstractDBServerExplorer;
70 43377 jjdelcerro
import org.gvsig.fmap.dal.serverexplorer.filesystem.FilesystemStoreParameters;
71 43020 jjdelcerro
import org.gvsig.fmap.dal.spi.DataManagerProviderServices;
72
import org.gvsig.fmap.dal.spi.DataServerExplorerProviderServices;
73
import org.gvsig.fmap.dal.store.jdbc.JDBCConnectionParameters;
74
import org.gvsig.fmap.dal.store.jdbc.JDBCNewStoreParameters;
75
import org.gvsig.fmap.dal.store.jdbc.JDBCServerExplorerParameters;
76
import org.gvsig.fmap.dal.store.jdbc.JDBCStoreParameters;
77
import org.gvsig.fmap.dal.store.jdbc.exception.JDBCExecuteSQLException;
78
import org.gvsig.fmap.dal.store.jdbc2.JDBCHelper;
79 45614 fdiaz
import org.gvsig.fmap.dal.store.jdbc2.JDBCServerExplorer;
80 43020 jjdelcerro
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 45614 fdiaz
import org.gvsig.fmap.dal.store.jdbc2.spi.operations.DropTableOperation;
84
import org.gvsig.fmap.dal.store.jdbc2.spi.operations.ExecuteOperation;
85 43020 jjdelcerro
import org.gvsig.fmap.dal.store.jdbc2.spi.operations.FetchFeatureTypeOperation;
86
import org.gvsig.fmap.dal.store.jdbc2.spi.operations.ListTablesOperation;
87
import org.gvsig.fmap.dal.store.jdbc2.spi.operations.UpdateTableStatisticsOperation;
88 45578 jjdelcerro
import org.gvsig.json.Json;
89
import org.gvsig.json.JsonObjectBuilder;
90
import org.gvsig.tools.dispose.DisposeUtils;
91 43020 jjdelcerro
import org.gvsig.tools.exception.BaseException;
92 44297 jjdelcerro
import org.gvsig.tools.resourcesstorage.EmptyResourcesStorage;
93
import org.gvsig.tools.resourcesstorage.ResourcesStorage;
94 45152 fdiaz
import org.gvsig.tools.util.CachedValue;
95 43020 jjdelcerro
import org.slf4j.Logger;
96
import org.slf4j.LoggerFactory;
97
98 44297 jjdelcerro
@SuppressWarnings("UseSpecificCatch")
99 43020 jjdelcerro
public class JDBCServerExplorerBase extends AbstractDBServerExplorer implements JDBCServerExplorer {
100
101
    private static final Logger LOG = LoggerFactory.getLogger(JDBCServerExplorerBase.class);
102 45578 jjdelcerro
    private static final String CONFIG_NAME_CUSTOM_RESOURCES = "CUSTOM_RESOURCES";
103 43020 jjdelcerro
104
    protected JDBCHelper helper = null;
105 45578 jjdelcerro
106 43020 jjdelcerro
    private Boolean canAdd;
107 45578 jjdelcerro
108 45156 jjdelcerro
    private static final Map<String, CachedValue<List<JDBCStoreParameters>>> CACHED_TABLES = Collections.synchronizedMap(new LRUMap(10));
109 45578 jjdelcerro
    private static final Map<String, CachedValue<CustomResourcesConfig>> CACHED_CUSTOM_RESOURCES_CONFIG = Collections.synchronizedMap(new LRUMap(10));
110
111
    private static class CustomResourcesConfig {
112
113 45581 fdiaz
        private static final String CUSTOM_RESOURCES_CACHETIME = "CacheTime";
114
        private static final String CUSTOM_RESOURCES_MAPPING = "Mapping";
115
116
117 45578 jjdelcerro
        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 45581 fdiaz
                    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 45578 jjdelcerro
                        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 45581 fdiaz
            builder.add(CUSTOM_RESOURCES_CACHETIME, cacheTime);
147 45578 jjdelcerro
            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 45581 fdiaz
            builder.add(CUSTOM_RESOURCES_MAPPING, m);
154 45578 jjdelcerro
            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 45152 fdiaz
183 45578 jjdelcerro
    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 45481 fdiaz
    private static class CachedTablesValue extends CachedValue<List<JDBCStoreParameters>> {
203 45578 jjdelcerro
204 45152 fdiaz
        private final int mode;
205 45165 jjdelcerro
        private final JDBCServerExplorerParameters serverParameters;
206 45152 fdiaz
        private final boolean informationTables;
207 45614 fdiaz
        private JDBCHelper helper;
208 45627 fdiaz
        private final int tablesOrViews;
209 45578 jjdelcerro
210 45627 fdiaz
        public CachedTablesValue(JDBCHelper helper, int mode, JDBCServerExplorerParameters serverParameters, boolean informationTables, int tablesOrViews) {
211 45152 fdiaz
            this.mode = mode;
212 45165 jjdelcerro
            this.serverParameters = serverParameters;
213 45152 fdiaz
            this.informationTables = informationTables;
214 45481 fdiaz
            this.helper = helper;
215 45627 fdiaz
            this.tablesOrViews = tablesOrViews;
216 45152 fdiaz
        }
217 45578 jjdelcerro
218 45627 fdiaz
        public CachedTablesValue(JDBCHelper helper, int mode, JDBCServerExplorerParameters serverParameters, boolean informationTables, long expireTime, int tablesOrViews) {
219 45152 fdiaz
            this.mode = mode;
220
            this.setExpireTime(expireTime);
221 45165 jjdelcerro
            this.serverParameters = serverParameters;
222 45152 fdiaz
            this.informationTables = informationTables;
223 45481 fdiaz
            this.helper = helper;
224 45627 fdiaz
            this.tablesOrViews = tablesOrViews;
225 45152 fdiaz
        }
226 45578 jjdelcerro
227 45152 fdiaz
        @Override
228
        protected void reload() {
229 45156 jjdelcerro
            List<JDBCStoreParameters> tables = null;
230 45614 fdiaz
            if(helper == null){
231
                this.setValue(tables);
232
                return;
233
            }
234 45481 fdiaz
            OperationsFactory operations = helper.getOperations();
235 45578 jjdelcerro
            if (operations == null) {
236 45481 fdiaz
                this.setValue(null);
237
                LOG.debug("Sets tables to null to force reload tables from new ServerExplorar.");
238
                return;
239
            }
240 45156 jjdelcerro
            try {
241 45481 fdiaz
                ListTablesOperation listTables = operations.createListTables(
242 45627 fdiaz
                        this.mode, serverParameters, informationTables, tablesOrViews
243 45156 jjdelcerro
                );
244
                tables = (List<JDBCStoreParameters>) listTables.perform();
245 45578 jjdelcerro
            } catch (Exception ex) {
246 45481 fdiaz
                LOG.debug("Can't reload cached list of tables.", ex);
247 45156 jjdelcerro
            }
248 45152 fdiaz
            this.setValue(tables);
249
        }
250 45614 fdiaz
251
        public JDBCHelper getHelper(){
252
            return this.helper;
253
        }
254
255
        public void dispose() {
256
            this.helper = null;
257
        }
258 45152 fdiaz
    }
259
260 43020 jjdelcerro
    public JDBCServerExplorerBase(
261
            JDBCServerExplorerParameters parameters,
262
            DataServerExplorerProviderServices services,
263
            JDBCHelper helper
264 45578 jjdelcerro
    ) throws InitializeException {
265 43020 jjdelcerro
        super(parameters, services);
266
        this.helper = helper;
267
    }
268
269
    @Override
270
    public String getProviderName() {
271
        return this.getHelper().getProviderName();
272
    }
273
274
    @Override
275
    public String getStoreName() {
276
        return this.getHelper().getProviderName();
277
    }
278
279
    protected DataManagerProviderServices getManager() {
280
        return (DataManagerProviderServices) DALLocator.getDataManager();
281
    }
282 45578 jjdelcerro
283 43020 jjdelcerro
    @Override
284
    public JDBCServerExplorerParameters getParameters() {
285
        return (JDBCServerExplorerParameters) super.getParameters();
286
    }
287 45578 jjdelcerro
288 43020 jjdelcerro
    @Override
289
    public boolean closeResourceRequested(ResourceProvider resource) {
290
        this.getHelper().getResulSetControler().pack();
291
        return true;
292
    }
293
294
    @Override
295
    public void resourceChanged(ResourceProvider resource) {
296
        // Nothing to do
297
    }
298
299
    protected JDBCHelper getHelper() {
300
        return helper;
301
    }
302 45578 jjdelcerro
303 43020 jjdelcerro
    protected OperationsFactory getOperations() {
304
        return this.getHelper().getOperations();
305
    }
306
307
    @Override
308
    public DataStore open(DataStoreParameters params) throws DataException {
309
        checkIsMine(params);
310
        DataStore store = super.open(params);
311
        return store;
312
    }
313
314
    @Override
315
    public List list(int mode) throws DataException {
316 45627 fdiaz
        return list(mode, SHOW_TABLES_AND_VIEWS);
317
    }
318
319
    @Override
320
    public List list(int mode, int tablesOrViews) throws DataException {
321 43020 jjdelcerro
        boolean informationTables = BooleanUtils.isTrue(
322
                this.getParameters().getShowInformationDBTables()
323
        );
324 45578 jjdelcerro
325 45165 jjdelcerro
        JDBCServerExplorerParameters serverParams = this.getParameters();
326 45152 fdiaz
327 45627 fdiaz
        String key = buildKeyForCachedTables(mode, serverParams, informationTables, tablesOrViews);
328 45156 jjdelcerro
        CachedValue<List<JDBCStoreParameters>> tablesValue = CACHED_TABLES.get(key);
329
        List<JDBCStoreParameters> tables = null;
330 45578 jjdelcerro
        if (tablesValue != null) {
331 45156 jjdelcerro
            tables = tablesValue.get();
332 45152 fdiaz
        }
333 45578 jjdelcerro
        if (tables != null) {
334 45156 jjdelcerro
            return tables;
335
        }
336 45627 fdiaz
        tablesValue = new CachedTablesValue(this.helper, mode, serverParams, informationTables, 60000, tablesOrViews); //60"
337 45156 jjdelcerro
        CACHED_TABLES.put(key, tablesValue);
338
        tables = tablesValue.get();
339
        return tables;
340 43020 jjdelcerro
    }
341
342 45627 fdiaz
    public String buildKeyForCachedTables(int mode, JDBCServerExplorerParameters params, boolean informationTables, int tablesOrViews) {
343 45165 jjdelcerro
        JDBCServerExplorerParameters clonedParams = (JDBCServerExplorerParameters) params.getCopy();
344 45152 fdiaz
        clonedParams.setSchema(null); //ListTableOperation no usa el schema
345 45578 jjdelcerro
346 45152 fdiaz
        StringBuilder builder = new StringBuilder();
347
        builder.append(String.valueOf(mode));
348
        builder.append(Hex.encodeHex(clonedParams.toByteArray()));
349
        builder.append(String.valueOf(informationTables));
350 45627 fdiaz
        builder.append(String.valueOf(tablesOrViews));
351 45152 fdiaz
        String key = builder.toString();
352
        return key;
353
    }
354 45578 jjdelcerro
355 43020 jjdelcerro
    @Override
356
    public void remove(DataStoreParameters theParams) throws RemoveException {
357
        JDBCStoreParameters params = (JDBCStoreParameters) theParams;
358
        DropTableOperation removeTable = this.getOperations().createDropTable(
359 44058 jjdelcerro
                this.getOperations().createTableReference(params)
360 43020 jjdelcerro
        );
361 45578 jjdelcerro
        if ((Boolean) removeTable.perform()) {
362 45165 jjdelcerro
            this.dropCachedTables();
363 45152 fdiaz
        }
364 43020 jjdelcerro
    }
365
366
    @Override
367
    public JDBCStoreParameters getOpenParameters() throws DataException {
368 45165 jjdelcerro
        JDBCStoreParameters params = this.helper.createOpenStoreParameters(this.getParameters());
369 43020 jjdelcerro
        return params;
370
    }
371
372
    @Override
373 44304 jjdelcerro
    public NewDataStoreParameters getAddParameters(String storeName)
374
            throws DataException {
375
        JDBCNewStoreParameters params = this.getAddParameters();
376
        params.setTable(storeName);
377
        return params;
378
    }
379
380
    @Override
381 43020 jjdelcerro
    public JDBCNewStoreParameters getAddParameters() throws DataException {
382
        JDBCServerExplorerParameters parameters = getParameters();
383
        JDBCNewStoreParameters params = this.helper.createNewStoreParameters();
384
        params.setHost(parameters.getHost());
385
        params.setPort(parameters.getPort());
386
        params.setDBName(parameters.getDBName());
387
        params.setUser(parameters.getUser());
388
        params.setPassword(parameters.getPassword());
389
        params.setCatalog(parameters.getCatalog());
390
        params.setSchema(parameters.getSchema());
391
        params.setJDBCDriverClassName(parameters.getJDBCDriverClassName());
392
        params.setUrl(parameters.getUrl());
393 45578 jjdelcerro
        if (parameters instanceof FilesystemStoreParameters) {
394 43377 jjdelcerro
            File f = ((FilesystemStoreParameters) parameters).getFile();
395
            ((FilesystemStoreParameters) params).setFile(f);
396
        }
397 43020 jjdelcerro
398
        params.setDefaultFeatureType(this.getServerExplorerProviderServices()
399
                .createNewFeatureType());
400
401
        return params;
402
    }
403
404
    protected void checkIsMine(DataStoreParameters dsp) {
405
        if (!(dsp instanceof JDBCConnectionParameters)) {
406
            throw new IllegalArgumentException(
407
                    "not instance of FilesystemStoreParameters");
408
        }
409
        JDBCServerExplorerParameters parameters = getParameters();
410
411
        JDBCConnectionParameters pgp = (JDBCConnectionParameters) dsp;
412 45578 jjdelcerro
        if (!StringUtils.equals(pgp.getHost(), parameters.getHost())) {
413 43020 jjdelcerro
            throw new IllegalArgumentException("wrong explorer: Host (mine: "
414
                    + parameters.getHost() + " other:" + pgp.getHost() + ")");
415
        }
416 45578 jjdelcerro
        if (!ObjectUtils.equals(pgp.getPort(), parameters.getPort())) {
417 43020 jjdelcerro
            throw new IllegalArgumentException("wrong explorer: Port (mine: "
418
                    + parameters.getPort() + " other:" + pgp.getPort() + ")");
419
        }
420 45578 jjdelcerro
        if (!StringUtils.equals(pgp.getDBName(), parameters.getDBName())) {
421 43020 jjdelcerro
            throw new IllegalArgumentException("wrong explorer: DBName (mine: "
422
                    + parameters.getDBName() + " other:" + pgp.getDBName()
423
                    + ")");
424
        }
425 45578 jjdelcerro
        if (!StringUtils.isEmpty(parameters.getCatalog())) {
426
            if (!StringUtils.equals(pgp.getCatalog(), parameters.getCatalog())) {
427 43020 jjdelcerro
                throw new IllegalArgumentException(
428
                        "wrong explorer: Catalog (mine: "
429
                        + parameters.getCatalog() + " other:"
430
                        + pgp.getCatalog() + ")");
431
            }
432
        }
433 45578 jjdelcerro
        if (!StringUtils.isEmpty(parameters.getSchema())) {
434
            if (!StringUtils.equals(pgp.getSchema(), parameters.getSchema())) {
435 43020 jjdelcerro
                throw new IllegalArgumentException(
436
                        "wrong explorer: Schema (mine: "
437
                        + parameters.getSchema() + " other:"
438
                        + pgp.getSchema() + ")");
439
            }
440
        }
441
    }
442
443
    @Override
444
    public void open() throws OpenException {
445
446
    }
447
448
    @Override
449
    public void close() throws CloseException {
450
451
    }
452
453
    @Override
454
    protected void doDispose() throws BaseException {
455 45614 fdiaz
        synchronized (CACHED_TABLES) {
456
            List<String> toRemove = new ArrayList<>();
457
            for (Map.Entry<String, CachedValue<List<JDBCStoreParameters>>> entry : CACHED_TABLES.entrySet()) {
458
                CachedTablesValue value = (CachedTablesValue) entry.getValue();
459
                if (value.getHelper() == this.helper) {
460
                    toRemove.add(entry.getKey());
461
                    value.dispose();
462
                }
463
            }
464
            for (String key : toRemove) {
465
                CACHED_TABLES.remove(key);
466
            }
467
            helper.dispose();
468
            helper = null;
469
        }
470 43020 jjdelcerro
    }
471
472
    @Override
473
    public boolean canAdd() {
474
        if (this.canAdd == null) {
475 44058 jjdelcerro
            CanCreateTablesOperation canAdd_ = this.getOperations().createCanCreateTables();
476
            this.canAdd = (Boolean) canAdd_.perform();
477 43020 jjdelcerro
        }
478
        return this.canAdd;
479
    }
480
481
    @Override
482
    public FeatureType getFeatureType(DataStoreParameters theParams)
483
            throws DataException {
484 45578 jjdelcerro
485
        JDBCStoreParameters params = (JDBCStoreParameters) theParams;
486
487 43020 jjdelcerro
        checkIsMine(params);
488
489 45578 jjdelcerro
        EditableFeatureType fetureType
490
                = this.getServerExplorerProviderServices().createNewFeatureType();
491
492 43020 jjdelcerro
        List<String> primaryKeys = null;
493 45578 jjdelcerro
        if (params.getPkFields() != null) {
494 43020 jjdelcerro
            primaryKeys = Arrays.asList(params.getPkFields());
495
        }
496 45578 jjdelcerro
497 43020 jjdelcerro
        FetchFeatureTypeOperation fetch = this.getOperations().createFetchFeatureType(
498 45578 jjdelcerro
                fetureType,
499 44058 jjdelcerro
                this.getOperations().createTableReference(params),
500 43020 jjdelcerro
                primaryKeys,
501
                params.getDefaultGeometryField(),
502
                params.getCRS()
503
        );
504
        fetch.perform();
505
        return fetureType;
506
    }
507
508
    @Override
509
    public boolean add(String providerName, NewDataStoreParameters theParams, boolean overwrite)
510
            throws DataException {
511
512
        List<Pair<String, Privilege>> userAndPrivileges = new ArrayList<>();
513 45578 jjdelcerro
        JDBCNewStoreParameters params = (JDBCNewStoreParameters) theParams;
514
        if (!StringUtils.isEmpty(params.getAllRole())) {
515
            userAndPrivileges.add(
516
                    new ImmutablePair<>(params.getAllRole(), Privilege.ALL)
517 43020 jjdelcerro
            );
518
        }
519 45578 jjdelcerro
        if (!StringUtils.isEmpty(params.getDeleteRole())) {
520
            userAndPrivileges.add(
521
                    new ImmutablePair<>(params.getDeleteRole(), Privilege.DELETE)
522 43020 jjdelcerro
            );
523
        }
524 45578 jjdelcerro
        if (!StringUtils.isEmpty(params.getInsertRole())) {
525
            userAndPrivileges.add(
526
                    new ImmutablePair<>(params.getInsertRole(), Privilege.INSERT)
527 43020 jjdelcerro
            );
528
        }
529 45578 jjdelcerro
        if (!StringUtils.isEmpty(params.getReferenceRole())) {
530
            userAndPrivileges.add(
531
                    new ImmutablePair<>(params.getReferenceRole(), Privilege.REFERENCE)
532 43020 jjdelcerro
            );
533
        }
534 45578 jjdelcerro
        if (!StringUtils.isEmpty(params.getSelectRole())) {
535
            userAndPrivileges.add(
536
                    new ImmutablePair<>(params.getSelectRole(), Privilege.SELECT)
537 43020 jjdelcerro
            );
538
        }
539 45578 jjdelcerro
        if (!StringUtils.isEmpty(params.getTriggerRole())) {
540
            userAndPrivileges.add(
541
                    new ImmutablePair<>(params.getTriggerRole(), Privilege.TRIGGER)
542 43020 jjdelcerro
            );
543
        }
544 45578 jjdelcerro
        if (!StringUtils.isEmpty(params.getTruncateRole())) {
545
            userAndPrivileges.add(
546
                    new ImmutablePair<>(params.getTruncateRole(), Privilege.TRUNCATE)
547 43020 jjdelcerro
            );
548
        }
549 45578 jjdelcerro
        if (!StringUtils.isEmpty(params.getUpdateRole())) {
550
            userAndPrivileges.add(
551
                    new ImmutablePair<>(params.getUpdateRole(), Privilege.UPDATE)
552 43020 jjdelcerro
            );
553
        }
554 45578 jjdelcerro
        List<String> additionalSQLs = new ArrayList<>();
555
        if (!StringUtils.isEmpty(params.getPostCreatingStatement())) {
556 43020 jjdelcerro
            additionalSQLs.add(params.getPostCreatingStatement());
557
        }
558
        CreateTableOperation createTable = this.getOperations().createTable(
559 44058 jjdelcerro
                this.getOperations().createTableReference(params),
560 43020 jjdelcerro
                params.getDefaultFeatureType(),
561 45578 jjdelcerro
                userAndPrivileges,
562 43020 jjdelcerro
                additionalSQLs
563
        );
564 45152 fdiaz
565 44328 jjdelcerro
        boolean isOk = (boolean) createTable.perform();
566 45578 jjdelcerro
        if (!isOk) {
567 44328 jjdelcerro
            return false;
568
        }
569 45578 jjdelcerro
570 45152 fdiaz
        // We collect the featureType of the operation because
571
        // the provider has been able to make changes to it
572
        params.setDefaultFeatureType(createTable.getType());
573
574 45578 jjdelcerro
        if (theParams instanceof NewFeatureStoreParameters) {
575 44328 jjdelcerro
            DataManager dataManager = DALLocator.getDataManager();
576
            ResourcesStorage resources = this.getResourcesStorage(theParams);
577
            dataManager.writeDALResource(resources, ((NewFeatureStoreParameters) theParams).getDefaultFeatureType());
578
        }
579 45165 jjdelcerro
        this.dropCachedTables();
580 44328 jjdelcerro
        return true;
581 43020 jjdelcerro
    }
582 45578 jjdelcerro
583 45165 jjdelcerro
    private void dropCachedTables() {
584
        boolean informationTables = BooleanUtils.isTrue(
585 45578 jjdelcerro
                this.getParameters().getShowInformationDBTables()
586 45165 jjdelcerro
        );
587 45614 fdiaz
        synchronized(CACHED_TABLES){
588 45627 fdiaz
            CACHED_TABLES.remove(buildKeyForCachedTables(MODE_ALL, this.getParameters(), informationTables, SHOW_TABLES_AND_VIEWS));
589
            CACHED_TABLES.remove(buildKeyForCachedTables(MODE_FEATURE, this.getParameters(), informationTables, SHOW_TABLES_AND_VIEWS));
590
            CACHED_TABLES.remove(buildKeyForCachedTables(MODE_GEOMETRY, this.getParameters(), informationTables, SHOW_TABLES_AND_VIEWS));
591
            CACHED_TABLES.remove(buildKeyForCachedTables(MODE_ALL, this.getParameters(), informationTables, SHOW_TABLES));
592
            CACHED_TABLES.remove(buildKeyForCachedTables(MODE_FEATURE, this.getParameters(), informationTables, SHOW_TABLES));
593
            CACHED_TABLES.remove(buildKeyForCachedTables(MODE_GEOMETRY, this.getParameters(), informationTables, SHOW_TABLES));
594
            CACHED_TABLES.remove(buildKeyForCachedTables(MODE_ALL, this.getParameters(), informationTables, SHOW_VIEWS));
595
            CACHED_TABLES.remove(buildKeyForCachedTables(MODE_FEATURE, this.getParameters(), informationTables, SHOW_VIEWS));
596
            CACHED_TABLES.remove(buildKeyForCachedTables(MODE_GEOMETRY, this.getParameters(), informationTables, SHOW_VIEWS));
597 45614 fdiaz
        }
598 45165 jjdelcerro
    }
599 43020 jjdelcerro
600
    @Override
601
    public List getDataStoreProviderNames() {
602
        List x = new ArrayList(1);
603
        x.add(this.getProviderName());
604
        return x;
605
    }
606
607
    @Override
608
    public void updateTableStatistics(String database, String schema, String table) throws JDBCExecuteSQLException {
609
        UpdateTableStatisticsOperation updateStatistics = this.getOperations().createUpdateTableStatistics(
610 44058 jjdelcerro
                this.getOperations().createTableReference(database, schema, table, null)
611 43020 jjdelcerro
        );
612
        updateStatistics.perform();
613
    }
614
615
    @Override
616 45425 jjdelcerro
    public Object execute(String sql) {
617 43377 jjdelcerro
        ExecuteOperation execute = this.getOperations().createExecute(sql);
618 45425 jjdelcerro
        return execute.perform();
619 43377 jjdelcerro
    }
620
621
    @Override
622 44297 jjdelcerro
    public JDBCStoreParameters get(String name) throws DataException {
623 43020 jjdelcerro
        JDBCStoreParameters params = this.getOpenParameters();
624
        params.setTable(name);
625
        return params;
626
    }
627
628
    @Override
629
    public SQLBuilder createSQLBuilder() {
630 44632 jjdelcerro
        JDBCSQLBuilderBase builder = this.getHelper().createSQLBuilder();
631
        return builder;
632 43020 jjdelcerro
    }
633 44297 jjdelcerro
634 45578 jjdelcerro
    private CustomResourcesConfig getCustomResourcesConfig() {
635
        JDBCServerExplorerParameters serverParams = this.getParameters();
636 45627 fdiaz
        String key = buildKeyForCachedTables(MODE_ALL, serverParams, false, SHOW_TABLES_AND_VIEWS); //???
637 45578 jjdelcerro
        CachedValue<CustomResourcesConfig> cachedConfig = CACHED_CUSTOM_RESOURCES_CONFIG.get(key);
638
        if (cachedConfig != null) {
639
            CustomResourcesConfig config = cachedConfig.get();
640
            return config;
641
        }
642
        JDBCStoreParameters params = this.helper.createOpenStoreParameters(this.getParameters());
643
        cachedConfig = new CachedCustomResourcesConfig(params);
644
        CACHED_CUSTOM_RESOURCES_CONFIG.put(key, cachedConfig);
645
        return cachedConfig.get();
646
    }
647
648 44328 jjdelcerro
    private ResourcesStorage getResourcesStorage(DataStoreParameters parameters, String storeName) {
649 45578 jjdelcerro
        if (DatabaseWorkspaceManager.isInternalTable(storeName)) {
650
            EmptyResourcesStorage resourcesStorage = new EmptyResourcesStorage();
651
            return resourcesStorage;
652
        }
653
        String resourcesTablename = null;
654
        try {
655 44346 jjdelcerro
            ResourcesStorage alternateResourcesStorage = null;
656 45578 jjdelcerro
            DataManager dataManager = DALLocator.getDataManager();
657
            DatabaseWorkspaceManager workspace = dataManager.getDatabaseWorkspace(parameters);
658
            if (workspace != null) {
659
                alternateResourcesStorage = workspace.getAlternativeResourcesStorage(storeName);
660
            }
661
662
            CustomResourcesConfig config = getCustomResourcesConfig();
663
            if( config!=null ) {
664
                if( config.isInternalTable(storeName) ) {
665
                    EmptyResourcesStorage theResourcesStorage = new EmptyResourcesStorage();
666
                    return theResourcesStorage;
667 44297 jjdelcerro
                }
668 45578 jjdelcerro
                resourcesTablename = config.getResourcesTablename(storeName);
669
                if( StringUtils.isNotBlank(resourcesTablename) ) {
670
                    JDBCStoreParameters params = this.getOpenParameters();
671
                    params.setTable(resourcesTablename);
672
                    JDBCResourcesStorage resourcesStorage = new JDBCResourcesStorage(
673
                            alternateResourcesStorage,
674
                            params,
675
                            storeName
676
                    );
677
                    return resourcesStorage;
678
                }
679 44297 jjdelcerro
            }
680 45578 jjdelcerro
            // TODO: Habria que ver de localizar los parametros sin tener que hacer un list.
681
            resourcesTablename = TABLE_RESOURCES_NAME;
682
            List<JDBCStoreParameters> tables = this.list();
683
            for (JDBCStoreParameters params : tables) {
684
                String theTableName = params.getTable();
685
                if (StringUtils.equals(theTableName, resourcesTablename)) {
686
                    JDBCResourcesStorage theResourcesStorage = new JDBCResourcesStorage(
687
                            alternateResourcesStorage,
688
                            params,
689
                            storeName
690
                    );
691
                    return theResourcesStorage;
692 44346 jjdelcerro
                }
693
            }
694 45578 jjdelcerro
        } catch (Throwable ex) {
695
            LOG.warn("Can't retrieve reources storage for table '" + storeName + "' in '" + this.getParameters().getUrl() + " ("+resourcesTablename+").", ex);
696 44297 jjdelcerro
        }
697 44328 jjdelcerro
        EmptyResourcesStorage theResourcesStorage = new EmptyResourcesStorage();
698 45578 jjdelcerro
        return theResourcesStorage;
699 44297 jjdelcerro
    }
700 45578 jjdelcerro
701 44632 jjdelcerro
    @Override
702 44419 jjdelcerro
    public ResourcesStorage getResourcesStorage() {
703
        JDBCStoreParameters params;
704
        try {
705
            params = this.getOpenParameters();
706 44439 jjdelcerro
            params.setTable(DatabaseWorkspaceManager.TABLE_RESOURCES_NAME);
707 44419 jjdelcerro
            JDBCResourcesStorage theResourcesStorage = new JDBCResourcesStorage(
708
                    null,
709
                    params,
710 44750 jjdelcerro
                    "$ServerExplorer"
711 44419 jjdelcerro
            );
712
            return theResourcesStorage;
713
        } catch (DataException ex) {
714
            return null;
715
        }
716
    }
717 45578 jjdelcerro
718 44328 jjdelcerro
    @Override
719
    public ResourcesStorage getResourcesStorage(DataStoreParameters parameters) {
720 45578 jjdelcerro
        if (parameters == null) {
721 44328 jjdelcerro
            throw new IllegalArgumentException("null is a valid value for parameters.");
722
        }
723
        String tableName;
724 45578 jjdelcerro
        if (parameters instanceof JDBCNewStoreParameters) {
725
            tableName = ((JDBCNewStoreParameters) parameters).getTable();
726
        } else if (parameters instanceof JDBCStoreParameters) {
727
            tableName = ((JDBCStoreParameters) parameters).getTable();
728 44328 jjdelcerro
        } else {
729 45578 jjdelcerro
            throw new IllegalArgumentException("Required a JDBCStoreParameters or JDBCNewStoreParameters parameters, received " + parameters.getClass().getName() + ".");
730 44328 jjdelcerro
        }
731
        return this.getResourcesStorage(parameters, tableName);
732
    }
733 45578 jjdelcerro
734 44328 jjdelcerro
    @Override
735
    public ResourcesStorage getResourcesStorage(DataStore dataStore) {
736
        return this.getResourcesStorage(
737 45578 jjdelcerro
                (JDBCStoreParameters) dataStore.getParameters(),
738 44328 jjdelcerro
                dataStore.getName()
739
        );
740
    }
741 44329 jjdelcerro
742
    @Override
743
    public boolean exists(DataStoreParameters parameters) throws DataException {
744
        JDBCStoreParameters params = (JDBCStoreParameters) parameters;
745
        JDBCSQLBuilderBase builder = this.getHelper().createSQLBuilder();
746
        SQLBuilder.TableNameBuilder searchTable = builder.createTableNameBuilder()
747
                .database(params.getDBName())
748
                .schema(params.getSchema())
749
                .name(params.getTable());
750
        SQLBuilder.TableNameBuilder table = builder.createTableNameBuilder();
751 45578 jjdelcerro
752 44329 jjdelcerro
        List<JDBCStoreParameters> l = this.list();
753
        for (JDBCStoreParameters current : l) {
754
            table.database(current.getDBName())
755 45578 jjdelcerro
                    .schema(current.getSchema())
756
                    .name(current.getTable());
757
            if (table.equals(searchTable)) {
758 44329 jjdelcerro
                return true;
759
            }
760
        }
761
        return false;
762
    }
763
764 45578 jjdelcerro
    @Override
765
    public void setCustomResources(String tableName, String resourcesTableName) {
766
        CustomResourcesConfig config = getCustomResourcesConfig();
767
        if( config==null ) {
768
            throw new RuntimeException("Can't retrieve alternative resources configuration");
769
        }
770
        config.addResourceMapping(tableName, resourcesTableName);
771
        JDBCStoreParameters params = this.helper.createOpenStoreParameters(this.getParameters());
772
        setConfigValue(params, CONFIG_NAME_CUSTOM_RESOURCES, config.toJsonString());
773
    }
774
775
    private static boolean setConfigValue(JDBCStoreParameters params, String name, String value) {
776
        FeatureStore store = null;
777
        try {
778
            DataManager dataManager = DALLocator.getDataManager();
779
            params.setTable(TABLE_CONFIGURATION_NAME);
780
            store = (FeatureStore) dataManager.openStore(
781
                    params.getProviderName(),
782
                    params
783
            );
784
        } catch (Exception ex) {
785
            LOG.trace("Can't read configuration value '"+name+"'", ex);
786
            // Do noting
787 45581 fdiaz
//        } finally {
788
//            DisposeUtils.disposeQuietly(store);
789 45578 jjdelcerro
        }
790
        if( store == null ) {
791
            return false;
792
        }
793
        try {
794
            store.edit();
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
            EditableFeature efeature;
802
            if (feature == null) {
803
                efeature = store.createNewFeature();
804
                efeature.set(FIELD_CONFIGURATION_NAME, name);
805
                efeature.set(FIELD_CONFIGURATION_VALUE, value);
806
                store.insert(efeature);
807
            } else {
808
                efeature = feature.getEditable();
809
                efeature.set(FIELD_CONFIGURATION_VALUE, value);
810
                store.update(efeature);
811
            }
812
            store.finishEditing();
813
            return true;
814
        } catch (Exception ex) {
815 45581 fdiaz
            LOG.debug("Can't write configuration value for '"+name+"'", ex);
816 45578 jjdelcerro
            return false;
817
        } finally {
818
            DisposeUtils.disposeQuietly(store);
819
        }
820
    }
821
822
    private static String getConfigValue(JDBCStoreParameters params, String name) {
823
        FeatureStore store = null;
824
        try {
825
            DataManager dataManager = DALLocator.getDataManager();
826
            params.setTable(TABLE_CONFIGURATION_NAME);
827
            store = (FeatureStore) dataManager.openStore(
828
                    params.getProviderName(),
829
                    params
830
            );
831
        } catch (Exception ex) {
832
            LOG.trace("Can't read configuration value '"+name+"'", ex);
833
            // Do noting
834 45581 fdiaz
//        } finally {
835
//            DisposeUtils.disposeQuietly(store);
836 45578 jjdelcerro
        }
837
        if( store == null ) {
838
            return null;
839
        }
840
        try {
841
            ExpressionBuilder builder = ExpressionUtils.createExpressionBuilder();
842
            String filter = builder.eq(
843
                    builder.column(FIELD_CONFIGURATION_NAME),
844
                    builder.constant(name)
845
            ).toString();
846
            Feature feature = store.findFirst(filter);
847
            if( feature == null ) {
848
                return null;
849
            }
850
            String value = feature.getString(FIELD_CONFIGURATION_VALUE);
851
            return value;
852
853
        } catch (Exception ex) {
854 45581 fdiaz
            LOG.debug("Can't read configuration value '"+name+"'", ex);
855 45578 jjdelcerro
            return null;
856
        } finally {
857
            DisposeUtils.disposeQuietly(store);
858
        }
859
    }
860
861 43020 jjdelcerro
}