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

History | View | Annotate | Download (17.6 KB)

1 45065 jjdelcerro
/**
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 44297 jjdelcerro
package org.gvsig.fmap.dal.store.jdbc2.spi;
25
26
import java.io.ByteArrayInputStream;
27
import java.io.ByteArrayOutputStream;
28 44750 jjdelcerro
import java.io.File;
29
import java.io.FileInputStream;
30
import java.io.FileNotFoundException;
31
import java.io.FileOutputStream;
32 44297 jjdelcerro
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.List;
38 44750 jjdelcerro
import org.apache.commons.codec.digest.DigestUtils;
39
import org.apache.commons.io.FileUtils;
40 44297 jjdelcerro
import org.apache.commons.io.IOUtils;
41
import org.apache.commons.lang3.StringUtils;
42 44750 jjdelcerro
import org.apache.commons.lang3.tuple.ImmutablePair;
43
import org.apache.commons.lang3.tuple.Pair;
44 44297 jjdelcerro
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 44304 jjdelcerro
import static org.gvsig.fmap.dal.DatabaseWorkspaceManager.FIELD_RESOURCES_NAME;
49
import static org.gvsig.fmap.dal.DatabaseWorkspaceManager.FIELD_RESOURCES_RESOURCE;
50
import static org.gvsig.fmap.dal.DatabaseWorkspaceManager.TABLE_RESOURCES_NAME;
51 44297 jjdelcerro
import org.gvsig.fmap.dal.feature.EditableFeature;
52
import org.gvsig.fmap.dal.feature.Feature;
53
import org.gvsig.fmap.dal.feature.FeatureStore;
54
import org.gvsig.fmap.dal.store.jdbc.JDBCStoreParameters;
55 44750 jjdelcerro
import org.gvsig.tools.ToolsLocator;
56 44297 jjdelcerro
import org.gvsig.tools.dispose.DisposeUtils;
57 44750 jjdelcerro
import org.gvsig.tools.folders.FoldersManager;
58 44297 jjdelcerro
import org.gvsig.tools.resourcesstorage.AbstractResourcesStorage;
59
import org.gvsig.tools.resourcesstorage.ResourcesStorage;
60
import org.slf4j.Logger;
61
import org.slf4j.LoggerFactory;
62
63
/**
64
 *
65
 * @author jjdelcerro
66
 */
67
@SuppressWarnings("UseSpecificCatch")
68
public class JDBCResourcesStorage extends AbstractResourcesStorage {
69
70
    private static final Logger LOGGER = LoggerFactory.getLogger(JDBCResourcesStorage.class);
71
72
    private static class DataBaseResource implements Resource {
73
74
        private class ResourceInputStream extends InputStream {
75
76
            @Override
77
            public int read() throws IOException {
78
                return in.read();
79
            }
80
81
            @Override
82
            public void close() throws IOException {
83
                DataBaseResource.this.close();
84
            }
85
        }
86
87
        private class ResourceOutputStream extends OutputStream {
88
89
            @Override
90
            public void write(int b) throws IOException {
91
                out.write(b);
92
            }
93
94
            @Override
95
            public void flush() throws IOException {
96
                out.flush();
97
            }
98
99
            @Override
100
            public void close() throws IOException {
101
                DataBaseResource.this.close();
102
            }
103
        }
104
105
        private final JDBCStoreParameters storeParameters;
106
        private final String tableName;
107
        private final String name;
108
109 44750 jjdelcerro
        private InputStream in;
110 44297 jjdelcerro
        private ByteArrayOutputStream out;
111
112
        public DataBaseResource(JDBCStoreParameters storeParameters, String tableName, String name) {
113
            this.storeParameters = storeParameters;
114
            this.tableName = tableName;
115
            this.name = name;
116
        }
117
118 44750 jjdelcerro
        @Override
119 44698 jjdelcerro
        public String getName() {
120
          return name;
121
        }
122
123 44297 jjdelcerro
        @Override
124
        public boolean isReadOnly() {
125
            return false;
126
        }
127
        @Override
128
        public URL getURL() {
129
            try {
130
                String url = this.storeParameters.getUrl();
131
                return new URL(url + "&tableName=" + this.tableName + "&resourceName=" + this.name);
132
            } catch (Throwable ex) {
133
                return null;
134
            }
135
        }
136
137
        @Override
138
        public boolean exists() {
139
            FeatureStore store = null;
140
            try {
141 44750 jjdelcerro
                FoldersManager fm = ToolsLocator.getFoldersManager();
142
                Pair<String, String> key = this.getCacheID();
143
                File f = fm.getTemporaryFile("resources-storage","jdbc", key.getLeft(), key.getRight());
144
                if( f.exists() ) {
145
                  return true;
146
                }
147 44297 jjdelcerro
                DataManager dataManager = DALLocator.getDataManager();
148
                store = (FeatureStore) dataManager.openStore(
149
                        this.storeParameters.getDataStoreName(),
150
                        this.storeParameters
151
                );
152
                ExpressionBuilder builder = ExpressionUtils.createExpressionBuilder();
153
                String filter = builder.eq(
154 44304 jjdelcerro
                        builder.column(FIELD_RESOURCES_NAME),
155 44346 jjdelcerro
                        builder.constant(this.tableName+"."+this.name)
156 44297 jjdelcerro
                ).toString();
157
                Feature feature = store.findFirst(filter);
158
                return feature!=null;
159
            } catch (Throwable ex) {
160
                LOGGER.warn("Can't access to the resoure '" + this.getURL() + "'.", ex);
161
            } finally {
162
                DisposeUtils.disposeQuietly(store);
163
            }
164
            return false;
165
        }
166
167 45152 fdiaz
        public boolean remove() {
168
            FeatureStore store = null;
169
            try {
170
                FoldersManager fm = ToolsLocator.getFoldersManager();
171
                Pair<String, String> key = this.getCacheID();
172
                File f = fm.getTemporaryFile("resources-storage","jdbc", key.getLeft(), key.getRight());
173
                if( f.exists() ) {
174
                  f.delete();
175
                }
176
                DataManager dataManager = DALLocator.getDataManager();
177
                store = (FeatureStore) dataManager.openStore(
178
                        this.storeParameters.getDataStoreName(),
179
                        this.storeParameters
180
                );
181
                ExpressionBuilder builder = ExpressionUtils.createExpressionBuilder();
182
                String filter = builder.eq(
183
                        builder.column(FIELD_RESOURCES_NAME),
184
                        builder.constant(this.tableName+"."+this.name)
185
                ).toString();
186
                Feature feature = store.findFirst(filter);
187
                if(feature != null){
188
                    store.edit();
189
                    store.delete(feature);
190
                    store.finishEditing();
191
                    return true;
192
                }
193
                return false;
194
            } catch (Throwable ex) {
195 45442 jjdelcerro
                FeatureStore.cancelEditingQuietly(store);
196 45152 fdiaz
                LOGGER.warn("Can't access to the resoure '" + this.getURL() + "'.", ex);
197
            } finally {
198
                DisposeUtils.disposeQuietly(store);
199
            }
200
            return false;
201
        }
202
203 44750 jjdelcerro
        private Pair<String,String> getCacheID() {
204
          byte[] data = this.storeParameters.toByteArray();
205
          ImmutablePair<String, String> r = new ImmutablePair<>(
206
                  DigestUtils.md5Hex(data),
207
                  this.tableName+"."+this.name
208
          );
209
          return r;
210
        }
211
212 45154 jjdelcerro
        private boolean removeCache() {
213
          FoldersManager fm = ToolsLocator.getFoldersManager();
214
          Pair<String, String> key = this.getCacheID();
215
          File f = fm.getTemporaryFile("resources-storage","jdbc", key.getLeft(), key.getRight());
216
          if( f.exists() ) {
217
              try {
218
                  FileUtils.forceDelete(f);
219
              } catch (IOException ex) {
220
                  return false;
221
              }
222
          }
223
          return true;
224
        }
225
226 44750 jjdelcerro
        private InputStream getInputStreamFromCache() {
227
          FoldersManager fm = ToolsLocator.getFoldersManager();
228
          Pair<String, String> key = this.getCacheID();
229
          File f = fm.getTemporaryFile("resources-storage","jdbc", key.getLeft(), key.getRight());
230
          if( !f.exists() ) {
231
            InputStream is = null;
232
            FileOutputStream os = null;
233 45338 omartinez
            File f2 = null;
234 44750 jjdelcerro
            try {
235
              is = this.getInputStream();
236 45338 omartinez
              if (is==null) {
237
                  return null;
238
              }
239 44750 jjdelcerro
              FileUtils.forceMkdir(f.getParentFile());
240
              os = new FileOutputStream(f);
241
              IOUtils.copy(is, os);
242
243 45338 omartinez
              f2 = fm.getTemporaryFile("resources-storage","jdbc", key.getLeft(), "parameters");
244 44750 jjdelcerro
              byte[] data = this.storeParameters.toByteArray();
245
              os = new FileOutputStream(f2);
246
              IOUtils.write(data, os);
247
            } catch (IOException ex) {
248 45338 omartinez
              FileUtils.deleteQuietly(f);
249
              FileUtils.deleteQuietly(f2);
250 44750 jjdelcerro
              return null;
251
            } finally {
252
              IOUtils.closeQuietly(is);
253
              IOUtils.closeQuietly(os);
254 44297 jjdelcerro
            }
255 44750 jjdelcerro
          }
256
          InputStream is = null;
257
          try {
258
            is = new FileInputStream(f);
259
          } catch (FileNotFoundException ex) {
260
          }
261
          return is;
262
        }
263
264
        private InputStream getInputStream() throws IOException {
265 44297 jjdelcerro
            FeatureStore store = null;
266
            try {
267
                DataManager dataManager = DALLocator.getDataManager();
268
                store = (FeatureStore) dataManager.openStore(
269
                        this.storeParameters.getDataStoreName(),
270
                        this.storeParameters
271
                );
272
                ExpressionBuilder builder = ExpressionUtils.createExpressionBuilder();
273
                String filter = builder.eq(
274 44304 jjdelcerro
                        builder.column(FIELD_RESOURCES_NAME),
275 44346 jjdelcerro
                        builder.constant(this.tableName+"."+this.name)
276 44297 jjdelcerro
                ).toString();
277
                Feature feature = store.findFirst(filter);
278
                if (feature == null) {
279
                    return null;
280
                }
281 44304 jjdelcerro
                byte[] resource = feature.getByteArray(FIELD_RESOURCES_RESOURCE);
282 44750 jjdelcerro
                InputStream is = new ByteArrayInputStream(resource);
283
                return is;
284 44297 jjdelcerro
            } catch (Throwable ex) {
285
                LOGGER.warn("Can't access to the resoure '" + this.getURL() + "'.", ex);
286
            } finally {
287
                DisposeUtils.disposeQuietly(store);
288
            }
289
            return null;
290
        }
291
292
        @Override
293 44750 jjdelcerro
        public InputStream asInputStream() throws IOException {
294
            if (this.in != null || this.out != null) {
295
                throw new IllegalStateException("Resource is already open (" + this.getURL() + ")");
296
            }
297
            InputStream is = this.getInputStreamFromCache();
298
            if( is==null ) {
299 45338 omartinez
                is = this.getInputStream();
300
                if ( is==null) {
301
                    return null;
302
                }
303 44750 jjdelcerro
            }
304
            this.in = is;
305
            return new ResourceInputStream();
306
        }
307
308
        @Override
309 44297 jjdelcerro
        public OutputStream asOutputStream() throws IOException {
310
            if (this.in != null || this.out != null) {
311
                throw new IllegalStateException("Resource is already open (" + this.getURL() + ").");
312
            }
313
            this.out = new ByteArrayOutputStream();
314
            return new ResourceOutputStream();
315
        }
316
317
        @Override
318
        public void close() {
319
            if (this.in != null) {
320
                IOUtils.closeQuietly(this.in);
321
                this.in = null;
322
            }
323
            if (this.out != null) {
324
                FeatureStore store = null;
325
                try {
326
                    DataManager dataManager = DALLocator.getDataManager();
327
                    store = (FeatureStore) dataManager.openStore(
328
                            this.storeParameters.getDataStoreName(),
329
                            this.storeParameters
330
                    );
331
                    store.edit();
332
                    ExpressionBuilder builder = ExpressionUtils.createExpressionBuilder();
333
                    String filter = builder.eq(
334 44304 jjdelcerro
                            builder.column(FIELD_RESOURCES_NAME),
335 44346 jjdelcerro
                            builder.constant(this.tableName+"."+this.name)
336 44297 jjdelcerro
                    ).toString();
337
                    Feature feature = store.findFirst(filter);
338
                    EditableFeature efeature;
339
                    if (feature == null) {
340
                        efeature = store.createNewFeature();
341 44346 jjdelcerro
                        efeature.set(FIELD_RESOURCES_NAME, this.tableName+"."+this.name);
342 44304 jjdelcerro
                        efeature.set(FIELD_RESOURCES_RESOURCE, this.out.toByteArray());
343 44297 jjdelcerro
                        store.insert(efeature);
344
                    } else {
345
                        efeature = feature.getEditable();
346 44304 jjdelcerro
                        efeature.set(FIELD_RESOURCES_RESOURCE, this.out.toByteArray());
347 44297 jjdelcerro
                        store.update(efeature);
348
                    }
349
                    store.finishEditing();
350 45154 jjdelcerro
                    removeCache();
351 44297 jjdelcerro
                } catch (Throwable ex) {
352 45442 jjdelcerro
                    FeatureStore.cancelEditingQuietly(store);
353 44297 jjdelcerro
                    LOGGER.warn("Can't write the resoure '" + this.getURL() + "'.", ex);
354
                } finally {
355
                    DisposeUtils.disposeQuietly(store);
356
                }
357
            }
358
        }
359
    }
360
361 44346 jjdelcerro
    private final ResourcesStorage alternativeStorge;
362 44297 jjdelcerro
    private final JDBCStoreParameters resourcesStoreParameters;
363
    private final String tableName;
364
365 44346 jjdelcerro
    public JDBCResourcesStorage(ResourcesStorage alternativeStorge, JDBCStoreParameters resourcesStoreParameters, String tableName) {
366
        this.alternativeStorge = alternativeStorge;
367 44304 jjdelcerro
        if( StringUtils.equals(TABLE_RESOURCES_NAME, tableName) ) {
368 44297 jjdelcerro
            // No podemos buscar recursos de la tabla de recursos, ya que si no
369
            // al abrise la tabla de recursos entraria en bucle.
370
            this.resourcesStoreParameters = null;
371
        } else {
372
            this.resourcesStoreParameters = resourcesStoreParameters;
373
        }
374
        this.tableName = tableName;
375
    }
376
377
    @Override
378
    public boolean isEmpty() {
379
        return this.resourcesStoreParameters == null;
380
    }
381
382
    @Override
383
    public Resource getResource(String name) {
384 44346 jjdelcerro
        if( this.alternativeStorge!=null ) {
385
            Resource r = this.alternativeStorge.getResource(name);
386
            if( r.exists() ) {
387
                return r;
388
            }
389
        }
390 44297 jjdelcerro
        if (this.resourcesStoreParameters == null) {
391
            return null;
392
        }
393
        return new DataBaseResource(
394
                this.resourcesStoreParameters,
395
                this.tableName,
396
                name
397
        );
398
    }
399
400
    @Override
401
    public List<Resource> getResources(String name) {
402
        if (this.resourcesStoreParameters == null) {
403
            return null;
404
        }
405 44346 jjdelcerro
        if( this.alternativeStorge!=null ) {
406
            List<Resource> r = this.alternativeStorge.getResources(name);
407
            if( r!=null && !r.isEmpty() ) {
408
                return r;
409
            }
410
        }
411 44297 jjdelcerro
        FeatureStore store = null;
412
        try {
413
            DataManager dataManager = DALLocator.getDataManager();
414
            store = (FeatureStore) dataManager.openStore(
415
                    this.resourcesStoreParameters.getDataStoreName(),
416
                    this.resourcesStoreParameters
417
            );
418
            ExpressionBuilder builder = ExpressionUtils.createExpressionBuilder();
419
            List<ResourcesStorage.Resource> ress = new ArrayList<>();
420
            int n = 0;
421
            while (true) {
422
                String multiresourceName;
423
                if (n == 0) {
424
                    multiresourceName = name;
425
                } else {
426 44346 jjdelcerro
                    multiresourceName = String.valueOf(n) + "." + name ;
427 44297 jjdelcerro
                }
428
                String filter = builder.eq(
429 44304 jjdelcerro
                        builder.column(FIELD_RESOURCES_NAME),
430 44346 jjdelcerro
                        builder.constant(this.tableName+"."+multiresourceName)
431 44297 jjdelcerro
                ).toString();
432
                Feature feature = store.findFirst(filter);
433
                if( feature==null ) {
434
                    break;
435
                }
436
                ress.add(new DataBaseResource(
437
                        this.resourcesStoreParameters,
438
                        this.tableName,
439
                        multiresourceName
440
                    )
441
                );
442
                n++;
443
            }
444
            if (ress.isEmpty()) {
445
                return null;
446
            }
447
            return ress;
448
        } catch (Throwable ex) {
449
            LOGGER.warn("Can't get resources for '" + this.resourcesStoreParameters.getUrl()+"&resourceName="+name + "'.", ex);
450
            return null;
451
452
        } finally {
453
            DisposeUtils.disposeQuietly(store);
454
        }
455
456
    }
457
458 45152 fdiaz
    @Override
459
    public boolean remove(String resourceName) {
460
        if( this.alternativeStorge!=null ) {
461
            try {
462
                this.alternativeStorge.remove(resourceName);
463
            } catch (Exception e) {
464
                //Do nothing
465
            }
466
        }
467
        if (this.resourcesStoreParameters == null) {
468
            return false;
469
        }
470
        DataBaseResource resource = new DataBaseResource(
471
                this.resourcesStoreParameters,
472
                this.tableName,
473
                resourceName
474
        );
475
476
        return resource.remove();
477
    }
478 44297 jjdelcerro
}