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 / JDBCResourcesStorage.java @ 47572

History | View | Annotate | Download (26.9 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.ByteArrayInputStream;
27
import java.io.ByteArrayOutputStream;
28
import java.io.File;
29
import java.io.FileInputStream;
30
import java.io.FileNotFoundException;
31
import java.io.FileOutputStream;
32
import java.io.IOException;
33
import java.io.InputStream;
34
import java.io.OutputStream;
35
import java.net.URL;
36
import java.util.ArrayList;
37
import java.util.Collections;
38
import java.util.HashMap;
39
import java.util.HashSet;
40
import java.util.List;
41
import java.util.Map;
42
import java.util.Set;
43
import org.apache.commons.codec.digest.DigestUtils;
44
import org.apache.commons.io.FileUtils;
45
import org.apache.commons.io.FilenameUtils;
46
import org.apache.commons.io.IOUtils;
47
import org.apache.commons.io.output.NullOutputStream;
48
import org.apache.commons.lang3.ArrayUtils;
49
import org.apache.commons.lang3.StringUtils;
50
import org.apache.commons.lang3.builder.ToStringBuilder;
51
import org.apache.commons.lang3.tuple.ImmutablePair;
52
import org.apache.commons.lang3.tuple.Pair;
53
import org.gvsig.expressionevaluator.ExpressionBuilder;
54
import org.gvsig.expressionevaluator.ExpressionUtils;
55
import org.gvsig.fmap.dal.DALLocator;
56
import org.gvsig.fmap.dal.DataManager;
57
import static org.gvsig.fmap.dal.DatabaseWorkspaceManager.FIELD_RESOURCES_NAME;
58
import static org.gvsig.fmap.dal.DatabaseWorkspaceManager.FIELD_RESOURCES_RESOURCE;
59
import static org.gvsig.fmap.dal.DatabaseWorkspaceManager.TABLE_RESOURCES_NAME;
60
import org.gvsig.fmap.dal.feature.EditableFeature;
61
import org.gvsig.fmap.dal.feature.Feature;
62
import org.gvsig.fmap.dal.feature.FeatureSet;
63
import org.gvsig.fmap.dal.feature.FeatureStore;
64
import org.gvsig.fmap.dal.store.jdbc.JDBCStoreParameters;
65
import org.gvsig.fmap.dal.store.jdbc.exception.SQLRuntimeException;
66
import org.gvsig.fmap.dal.store.jdbc2.JDBCHelper;
67
import org.gvsig.fmap.dal.store.jdbc2.OperationsFactory;
68
import org.gvsig.fmap.dal.store.jdbc2.spi.operations.RetrieveValueOperation;
69
import org.gvsig.tools.ToolsLocator;
70
import org.gvsig.tools.dispose.DisposeUtils;
71
import org.gvsig.tools.exception.BaseException;
72
import org.gvsig.tools.folders.FoldersManager;
73
import org.gvsig.tools.resourcesstorage.AbstractResourcesStorage;
74
import org.gvsig.tools.resourcesstorage.ResourcesStorage;
75
import org.gvsig.tools.util.CachedValue;
76
import org.slf4j.Logger;
77
import org.slf4j.LoggerFactory;
78

    
79
/**
80
 *
81
 * @author jjdelcerro
82
 */
83
@SuppressWarnings("UseSpecificCatch")
84
public class JDBCResourcesStorage extends AbstractResourcesStorage {
85

    
86
    private static final Logger LOGGER = LoggerFactory.getLogger(JDBCResourcesStorage.class);
87
    public static final String TABLENAME_SERVER_EXPLORER_MARK = "$ServerExplorer";
88

    
89
    private final JDBCHelper helper;
90

    
91
    private static class ExistsResourcesCache extends CachedValue<Map<String,Boolean>> {
92
        @Override
93
        protected void reload() {
94
//            LOGGER.info("reload ExistsResourcesCache");
95
            this.setValue(new HashMap<>());
96
        }        
97
    }
98
    
99
    private static class DataBaseResource implements Resource {
100

    
101
        private class ResourceInputStream extends InputStream {
102

    
103
            @Override
104
            public int read() throws IOException {
105
                return in.read();
106
            }
107

    
108
            @Override
109
            public void close() throws IOException {
110
                DataBaseResource.this.close();
111
            }
112
        }
113

    
114
        private class ResourceOutputStream extends OutputStream {
115

    
116
            @Override
117
            public void write(int b) throws IOException {
118
                out.write(b);
119
            }
120

    
121
            @Override
122
            public void flush() throws IOException {
123
                out.flush();
124
            }
125

    
126
            @Override
127
            public void close() throws IOException {
128
                DataBaseResource.this.close();
129
            }
130
        }
131

    
132
        private final String name;
133
        private final JDBCResourcesStorage storage;
134

    
135
        private InputStream in;
136
        private OutputStream out;
137

    
138
        public DataBaseResource(JDBCResourcesStorage storage, String name) {
139
            this.storage = storage;                    
140
            this.name = name;
141
        }
142

    
143
        @Override
144
        public String getName() {
145
          return name;
146
        }
147
        
148
        private JDBCStoreParameters getStoreParameters() {
149
            return this.storage.resourcesStoreParameters;
150
        }
151
        
152
        private String getTableName() {
153
            return this.storage.tableName;
154
        }
155
        
156
        private Map<String,Boolean> getExistsResourcesCache() {
157
            return  this.storage.existsResourcesCache.get();
158
        }
159
        
160
        @Override
161
        public boolean isReadOnly() {
162
            return this.storage.readonly;
163
        }
164
        @Override
165
        public URL getURL() {
166
            try {
167
                String url = this.getStoreParameters().getUrl();
168
                return new URL(url + "&tableName=" + this.getTableName() + "&resourceName=" + this.name);
169
            } catch (Throwable ex) {
170
                return null;
171
            }
172
        }
173
        
174
        private byte[] retrieveResource() throws Exception {
175
            ExpressionBuilder builder = ExpressionUtils.createExpressionBuilder();
176
            
177
            String filter;
178
            if (StringUtils.equalsIgnoreCase(this.getTableName(), TABLENAME_SERVER_EXPLORER_MARK)) {
179
                filter = builder.eq(
180
                        builder.column(FIELD_RESOURCES_NAME),
181
                        builder.constant(this.name)
182
                ).toString();
183

    
184
            } else {
185
                filter = builder.eq(
186
                        builder.column(FIELD_RESOURCES_NAME),
187
                        builder.constant(this.getTableName() + "." + this.name)
188
                ).toString();
189
            }
190
            
191
            OperationsFactory operations = this.storage.helper.getOperations();
192
            RetrieveValueOperation op = operations.createRetrieveValue(
193
                    operations.createTableReference(this.getStoreParameters()),
194
                    filter,
195
                    null, //order
196
                    FIELD_RESOURCES_RESOURCE
197
            );
198
            return (byte[] ) op.perform();
199
        }
200
        
201
        private byte[] retrieveResource0() throws Exception {
202
            FeatureStore store = null;
203
            try {
204
                DataManager dataManager = DALLocator.getDataManager();
205
                store = (FeatureStore) dataManager.openStore(
206
                        this.getStoreParameters().getDataStoreName(),
207
                        this.getStoreParameters()
208
                );
209
                ExpressionBuilder builder = ExpressionUtils.createExpressionBuilder();
210
                String filter;
211
                if (StringUtils.equalsIgnoreCase(this.getTableName(), TABLENAME_SERVER_EXPLORER_MARK)) {
212
                    filter = builder.eq(
213
                            builder.column(FIELD_RESOURCES_NAME),
214
                            builder.constant(this.name)
215
                    ).toString();
216

    
217
                } else {
218
                    filter = builder.eq(
219
                            builder.column(FIELD_RESOURCES_NAME),
220
                            builder.constant(this.getTableName() + "." + this.name)
221
                    ).toString();
222
                }
223
                Feature feature = store.findFirst(filter);
224
                if (feature == null) {
225
                    return null;
226
                }
227
                byte[] resource = feature.getByteArray(FIELD_RESOURCES_RESOURCE);                
228
                return resource;
229
            } finally {
230
                DisposeUtils.disposeQuietly(store);
231
            }
232
        }
233

    
234
        @Override
235
        public boolean exists() {
236
//            FeatureStore store = null;
237
            try {
238
                FoldersManager fm = ToolsLocator.getFoldersManager();
239
                Pair<String, String> key = this.getCacheID();
240
                String key_s = key.getLeft() + "/"+ key.getRight();
241
                Map<String, Boolean> erc = this.getExistsResourcesCache();
242
                if( erc.containsKey(key_s) ) {
243
                    return this.getExistsResourcesCache().get(key_s);
244
                }
245
                File f = fm.getTemporaryFile("resources-storage","jdbc", key.getLeft(), key.getRight());
246
                if( f.exists() ) {
247
                  return true;
248
                }
249
                byte[] resource = retrieveResource();
250
                boolean exists = !ArrayUtils.isEmpty(resource);
251
                if( exists ) {
252
                    putResourceInCache(resource);
253
                }
254
                this.getExistsResourcesCache().put(key_s, exists);
255
                return exists;
256
            } catch (Throwable ex) {
257
                LOGGER.warn("Can't access to the resoure '" + this.getURL() + "'.", ex);
258
//            } finally {
259
//                DisposeUtils.disposeQuietly(store);
260
            }
261
            return false;
262
        }
263

    
264
        public boolean remove() {
265
            FeatureStore store = null;
266
            try {
267
                FoldersManager fm = ToolsLocator.getFoldersManager();
268
                Pair<String, String> key = this.getCacheID();
269
                File f = fm.getTemporaryFile("resources-storage","jdbc", key.getLeft(), key.getRight());
270
                if( f.exists() ) {
271
                  f.delete();
272
                }
273
                DataManager dataManager = DALLocator.getDataManager();
274
                store = (FeatureStore) dataManager.openStore(
275
                        this.getStoreParameters().getDataStoreName(),
276
                        this.getStoreParameters()
277
                );
278
                ExpressionBuilder builder = ExpressionUtils.createExpressionBuilder();
279
                String filter;
280
                if (StringUtils.equalsIgnoreCase(this.getTableName(), TABLENAME_SERVER_EXPLORER_MARK)) {
281
                    filter = builder.eq(
282
                            builder.column(FIELD_RESOURCES_NAME),
283
                            builder.constant(this.name)
284
                    ).toString();
285

    
286
                } else {
287
                    filter = builder.eq(
288
                            builder.column(FIELD_RESOURCES_NAME),
289
                            builder.constant(this.getTableName() + "." + this.name)
290
                    ).toString();
291

    
292
                }
293
                
294
                Feature feature = store.findFirst(filter);
295
                if(feature != null){
296
                    store.edit();
297
                    store.delete(feature);
298
                    store.finishEditing();
299
                    return true;
300
                }
301
                return false;
302
            } catch (Throwable ex) {
303
                FeatureStore.cancelEditingQuietly(store);
304
                LOGGER.warn("Can't access to the resoure '" + this.getURL() + "'.", ex);
305
            } finally {
306
                DisposeUtils.disposeQuietly(store);
307
            }
308
            return false;
309
        }
310

    
311
        private Pair<String,String> getCacheID() {
312
            byte[] data = this.getStoreParameters().toByteArray();
313
            ImmutablePair<String, String> r;
314
            if (StringUtils.equalsIgnoreCase(this.getTableName(), TABLENAME_SERVER_EXPLORER_MARK)) {
315
                r = new ImmutablePair<>(
316
                        DigestUtils.md5Hex(data), 
317
                        this.name
318
                );
319
            } else {
320
                r = new ImmutablePair<>(
321
                        DigestUtils.md5Hex(data), 
322
                        this.getTableName()+"."+this.name
323
                );
324
            }
325
          return r;
326
        }
327
        
328
        private boolean removeCache() {
329
          FoldersManager fm = ToolsLocator.getFoldersManager();
330
          Pair<String, String> key = this.getCacheID();
331
          File f = fm.getTemporaryFile("resources-storage","jdbc", key.getLeft(), key.getRight());
332
          if( f.exists() ) {
333
              try {
334
                  FileUtils.forceDelete(f);
335
              } catch (IOException ex) {
336
                  return false;
337
              }
338
          }
339
          return true;
340
        }
341
        
342
        private InputStream getInputStreamFromCache() {
343
          FoldersManager fm = ToolsLocator.getFoldersManager();
344
          Pair<String, String> key = this.getCacheID();
345
          File f = fm.getTemporaryFile("resources-storage","jdbc", key.getLeft(), key.getRight());
346
          if( !f.exists() ) {
347
            InputStream is = null;
348
            FileOutputStream os = null;
349
            File f2 = null;
350
            try {
351
              is = this.getInputStream();
352
              if (is==null) {
353
                  return null;
354
              }
355
              FileUtils.forceMkdir(f.getParentFile());
356
              os = new FileOutputStream(f);
357
              IOUtils.copy(is, os);             
358
              IOUtils.closeQuietly(os);
359

    
360
              f2 = fm.getTemporaryFile("resources-storage","jdbc", key.getLeft(), "parameters");              
361
              byte[] data = this.getStoreParameters().toByteArray();
362
              os = new FileOutputStream(f2);
363
              IOUtils.write(data, os);
364
            } catch (IOException ex) {
365
              FileUtils.deleteQuietly(f);
366
              FileUtils.deleteQuietly(f2);
367
              return null;
368
            } finally {
369
              IOUtils.closeQuietly(is);
370
              IOUtils.closeQuietly(os);
371
            }
372
          }
373
          InputStream is = null;
374
          try {
375
            is = new FileInputStream(f);
376
          } catch (FileNotFoundException ex) {
377
          }
378
          return is;
379
        }
380

    
381
        private void putResourceInCache(byte[] resource) {
382
            FoldersManager fm = ToolsLocator.getFoldersManager();
383
            Pair<String, String> key = this.getCacheID();
384
            File f = fm.getTemporaryFile("resources-storage", "jdbc", key.getLeft(), key.getRight());
385
            FileOutputStream os = null;
386
            File f2 = null;
387
            try {
388
                FileUtils.forceMkdir(f.getParentFile());
389
                os = new FileOutputStream(f);
390
                IOUtils.write(resource, os);
391
                IOUtils.closeQuietly(os);
392

    
393
                f2 = fm.getTemporaryFile("resources-storage", "jdbc", key.getLeft(), "parameters");
394
                byte[] data = this.getStoreParameters().toByteArray();
395
                os = new FileOutputStream(f2);
396
                IOUtils.write(data, os);
397
            } catch (IOException ex) {
398
                FileUtils.deleteQuietly(f);
399
                FileUtils.deleteQuietly(f2);
400
            } finally {
401
                IOUtils.closeQuietly(os);
402
            }
403
        }
404
        
405
        private InputStream getInputStream() throws IOException {
406
            try {
407
                byte[] resource = retrieveResource();
408
                InputStream is = new ByteArrayInputStream(resource);
409
                return is;
410
            } catch (Throwable ex) {
411
                LOGGER.warn("Can't access to the resoure '" + this.getURL() + "'.", ex);
412
            }
413
            return null;
414
        }
415

    
416
        @Override
417
        public InputStream asInputStream() throws IOException {
418
            if (this.in != null || this.out != null) {
419
                throw new IllegalStateException("Resource is already open (" + this.getURL() + ")");
420
            }
421
            InputStream is = this.getInputStreamFromCache();
422
            if( is==null ) {
423
                is = this.getInputStream();
424
                if ( is==null) {
425
                    return null;
426
                }
427
            }
428
            this.in = is;
429
            return new ResourceInputStream();
430
        }
431

    
432
        @Override
433
        public OutputStream asOutputStream() throws IOException {
434
            if (this.in != null || this.out != null) {
435
                throw new IllegalStateException("Resource is already open (" + this.getURL() + ").");
436
            }
437
            if( this.isReadOnly()) {
438
                this.out = NullOutputStream.NULL_OUTPUT_STREAM;
439
            } else {
440
                this.out = new ByteArrayOutputStream();
441
            }
442
            return new ResourceOutputStream();
443
        }
444

    
445
        @Override
446
        public void close() {
447
            if (this.in != null) {
448
                IOUtils.closeQuietly(this.in);
449
                this.in = null;
450
            }
451
            if (!this.isReadOnly()&& this.out != null) {
452
                FeatureStore store = null;
453
                try {
454
                    DataManager dataManager = DALLocator.getDataManager();
455
                    store = (FeatureStore) dataManager.openStore(
456
                            this.getStoreParameters().getDataStoreName(),
457
                            this.getStoreParameters()
458
                    );
459
                    store.edit();
460
                    ExpressionBuilder builder = ExpressionUtils.createExpressionBuilder();
461
                    String filter;
462
                    if (StringUtils.equalsIgnoreCase(this.getTableName(), TABLENAME_SERVER_EXPLORER_MARK)) {
463
                        filter = builder.eq(
464
                                builder.column(FIELD_RESOURCES_NAME),
465
                                builder.constant(this.name)
466
                        ).toString();
467

    
468
                    } else {
469
                        filter = builder.eq(
470
                                builder.column(FIELD_RESOURCES_NAME),
471
                                builder.constant(this.getTableName() + "." + this.name)
472
                        ).toString();
473
                    }
474

    
475
                    Feature feature = store.findFirst(filter);
476
                    EditableFeature efeature;
477
                    if (feature == null) {
478
                        efeature = store.createNewFeature();
479
                        
480
                        if (StringUtils.equalsIgnoreCase(this.getTableName(), TABLENAME_SERVER_EXPLORER_MARK)) {
481
                            efeature.set(FIELD_RESOURCES_NAME, this.name);
482
                        } else {
483
                            efeature.set(FIELD_RESOURCES_NAME, this.getTableName()+"."+this.name);
484
                        }
485
                        efeature.set(FIELD_RESOURCES_RESOURCE, ((ByteArrayOutputStream)this.out).toByteArray());
486
                        store.insert(efeature);
487
                    } else {
488
                        efeature = feature.getEditable();
489
                        efeature.set(FIELD_RESOURCES_RESOURCE, ((ByteArrayOutputStream)this.out).toByteArray());
490
                        store.update(efeature);
491
                    }
492
                    store.finishEditing();
493
                    removeCache();
494
                } catch (SQLRuntimeException ex) {
495
                    FeatureStore.cancelEditingQuietly(store);
496
                    if( !ex.isTableOrViewNotFound() ) { 
497
                        LOGGER.warn("Can't write the resource '" + this.getURL() + "'.", ex);
498
                    }
499
                } catch (Throwable ex) {
500
                    FeatureStore.cancelEditingQuietly(store);
501
                    LOGGER.warn("Can't write the resource '" + this.getURL() + "'.", ex);
502
                } finally {
503
                    DisposeUtils.disposeQuietly(store);
504
                }
505
            }
506
        }
507
    }
508

    
509
    private final ResourcesStorage alternativeStorage;
510
    private final JDBCStoreParameters resourcesStoreParameters;
511
    private final String tableName;
512
    private final boolean readonly;
513
    private final ExistsResourcesCache existsResourcesCache;
514

    
515
    public JDBCResourcesStorage(
516
                JDBCHelper helper,
517
                ResourcesStorage alternativeStorage, 
518
                JDBCStoreParameters resourcesStoreParameters, 
519
                String tableName
520
        ) {
521
        this(helper, alternativeStorage, resourcesStoreParameters, tableName, false);
522
    }
523

    
524
    public JDBCResourcesStorage(
525
                JDBCHelper helper,
526
                ResourcesStorage alternativeStorage, 
527
                JDBCStoreParameters resourcesStoreParameters, 
528
                String tableName,
529
                boolean readonly
530
        ) {
531
        this.helper = helper;
532
        DisposeUtils.bind(this.helper);
533
        this.readonly = readonly;
534
        this.alternativeStorage = alternativeStorage;
535
        if( StringUtils.equals(TABLE_RESOURCES_NAME, tableName) ) {
536
            // No podemos buscar recursos de la tabla de recursos, ya que si no
537
            // al abrise la tabla de recursos entraria en bucle.
538
            this.resourcesStoreParameters = null;
539
        } else {
540
            this.resourcesStoreParameters = resourcesStoreParameters;
541
        }
542
        this.tableName = tableName;
543
        this.existsResourcesCache = new ExistsResourcesCache();
544
        this.existsResourcesCache.setExpireTime(60000); // 1 min
545
    }
546

    
547
    @Override
548
    public boolean isEmpty() {
549
        return this.resourcesStoreParameters == null;
550
    }
551

    
552
    @Override
553
    public List<String> getResourceNames() {
554
        if( this.alternativeStorage!=null ) {
555
            List<String> names = this.alternativeStorage.getResourceNames();
556
            return names;
557
        }
558
        if (this.resourcesStoreParameters == null) {
559
            return Collections.EMPTY_LIST;
560
        }
561
        
562
        FeatureStore store = null;
563
        try {
564
            DataManager dataManager = DALLocator.getDataManager();
565
            Set<String> typeNames = new HashSet<>();
566
            store = (FeatureStore) dataManager.openStore(
567
                    this.resourcesStoreParameters.getDataStoreName(),
568
                    this.resourcesStoreParameters
569
            );
570
            FeatureSet featureSet = store.getFeatureSet();
571
            for (Feature feature : featureSet) {
572
                String resName = feature.getString(FIELD_RESOURCES_NAME);
573
                if (StringUtils.equalsIgnoreCase(tableName, TABLENAME_SERVER_EXPLORER_MARK)) {
574
                    typeNames.add(resName);
575
                } else {
576
                    String resTypeName = FilenameUtils.getExtension(resName);
577
                    typeNames.add(resTypeName);
578
                }
579
            }
580
            return new ArrayList<>(typeNames);
581
        } catch (Throwable ex) {
582
            LOGGER.warn("Can't get resources for '" + this.resourcesStoreParameters.getUrl() + "'.", ex);
583
            return null;
584
            
585
        } finally {
586
            DisposeUtils.disposeQuietly(store);
587
        }
588
    }
589
    
590
    
591

    
592
    @Override
593
    public Resource getResource(String name) {
594
        if( this.alternativeStorage!=null ) {
595
            Resource r = this.alternativeStorage.getResource(name);
596
            if( r.exists() ) {
597
                return r;
598
            }
599
        }
600
        if (this.resourcesStoreParameters == null) {
601
            return null;
602
        }
603
        return new DataBaseResource(this,name);
604
    }
605

    
606
    @Override
607
    public List<Resource> getResources(String name) {
608
        if (this.resourcesStoreParameters == null) {
609
            return null;
610
        }
611
        if( this.alternativeStorage!=null ) {
612
            List<Resource> r = this.alternativeStorage.getResources(name);
613
            if( r!=null && !r.isEmpty() ) {
614
                return r;
615
            }
616
        }
617
        FeatureStore store = null;
618
        try {
619
            DataManager dataManager = DALLocator.getDataManager();
620
            store = (FeatureStore) dataManager.openStore(
621
                    this.resourcesStoreParameters.getDataStoreName(),
622
                    this.resourcesStoreParameters
623
            );
624
            ExpressionBuilder builder = ExpressionUtils.createExpressionBuilder();
625
            List<ResourcesStorage.Resource> ress = new ArrayList<>();
626
            int n = 0;
627
            while (true) {
628
                String multiresourceName;
629
                if (n == 0) {
630
                    multiresourceName = name;
631
                } else {
632
                    multiresourceName = String.valueOf(n) + "." + name ;
633
                }
634
                String filter = builder.eq(
635
                        builder.column(FIELD_RESOURCES_NAME),
636
                        builder.constant(this.tableName+"."+multiresourceName)
637
                ).toString();
638
                Feature feature = store.findFirst(filter);
639
                if( feature==null ) {
640
                    break;
641
                }
642
                ress.add(new DataBaseResource(this,multiresourceName));
643
                n++;
644
            }
645
            if (ress.isEmpty()) {
646
                return null;
647
            }
648
            return ress;
649
        } catch (Throwable ex) {
650
            LOGGER.warn("Can't get resources for '" + this.resourcesStoreParameters.getUrl()+"&resourceName="+name + "'.", ex);
651
            return null;
652
            
653
        } finally {
654
            DisposeUtils.disposeQuietly(store);
655
        }
656

    
657
    }
658

    
659
    @Override
660
    public boolean add(String resourceName, InputStream is) {
661
        DataBaseResource res = new DataBaseResource(this, resourceName);
662
        try {
663
            IOUtils.copy(is, res.asOutputStream());
664
            res.close();
665
            is.close();
666
            return true;
667
        } catch (IOException ex) {
668
            return false;
669
        }
670
    }
671

    
672
    
673
    @Override
674
    public boolean remove(String resourceName) {
675
        if( this.alternativeStorage!=null ) {
676
            try {
677
                this.alternativeStorage.remove(resourceName);
678
            } catch (Exception e) {
679
                //Do nothing
680
            }
681
        }
682
        if (this.resourcesStoreParameters == null) {
683
            return false;
684
        }
685
        DataBaseResource resource = new DataBaseResource(this,resourceName);
686
        
687
        return resource.remove();
688
    }
689
    
690
    public void clearCache() {
691
        try {
692
            byte[] data = this.resourcesStoreParameters.toByteArray();
693
            DataManager dataManager = DALLocator.getDataManager();
694
            File f = FileUtils.getFile(
695
                    dataManager.getCacheResourcesFolder().getAbsolutePath(), 
696
                    "jdbc", 
697
                    DigestUtils.md5Hex(data)
698
            );
699
            FileUtils.deleteDirectory(f);
700
        } catch (Exception ex) {
701
            LOGGER.warn("Can't remove local cache for table "+tableName, ex);
702
        }
703
    }
704

    
705
    @Override
706
    protected void doDispose() throws BaseException {
707
        super.doDispose();
708
        DisposeUtils.disposeQuietly(this.helper);
709
    }
710

    
711
    @Override
712
    public String toString() {
713
        ToStringBuilder builder = new ToStringBuilder(this);
714
        builder.append("tableName", this.tableName);
715
        builder.append("url", this.resourcesStoreParameters.getUrl());
716
        builder.append("readonly", this.readonly);
717
        return builder.toString();
718
    }
719
    
720
}