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

History | View | Annotate | Download (16.7 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.security.MessageDigest;
37
import java.util.ArrayList;
38
import java.util.List;
39
import org.apache.commons.codec.digest.DigestUtils;
40
import org.apache.commons.io.FileUtils;
41
import org.apache.commons.io.IOUtils;
42
import org.apache.commons.lang3.StringUtils;
43
import org.apache.commons.lang3.tuple.ImmutablePair;
44
import org.apache.commons.lang3.tuple.Pair;
45
import org.gvsig.expressionevaluator.ExpressionBuilder;
46
import org.gvsig.expressionevaluator.ExpressionUtils;
47
import org.gvsig.fmap.dal.DALLocator;
48
import org.gvsig.fmap.dal.DataManager;
49
import static org.gvsig.fmap.dal.DatabaseWorkspaceManager.FIELD_RESOURCES_NAME;
50
import static org.gvsig.fmap.dal.DatabaseWorkspaceManager.FIELD_RESOURCES_RESOURCE;
51
import static org.gvsig.fmap.dal.DatabaseWorkspaceManager.TABLE_RESOURCES_NAME;
52
import org.gvsig.fmap.dal.feature.EditableFeature;
53
import org.gvsig.fmap.dal.feature.Feature;
54
import org.gvsig.fmap.dal.feature.FeatureStore;
55
import org.gvsig.fmap.dal.store.jdbc.JDBCStoreParameters;
56
import org.gvsig.tools.ToolsLocator;
57
import org.gvsig.tools.dispose.DisposeUtils;
58
import org.gvsig.tools.folders.FoldersManager;
59
import org.gvsig.tools.resourcesstorage.AbstractResourcesStorage;
60
import org.gvsig.tools.resourcesstorage.ResourcesStorage;
61
import org.slf4j.Logger;
62
import org.slf4j.LoggerFactory;
63

    
64
/**
65
 *
66
 * @author jjdelcerro
67
 */
68
@SuppressWarnings("UseSpecificCatch")
69
public class JDBCResourcesStorage extends AbstractResourcesStorage {
70

    
71
    private static final Logger LOGGER = LoggerFactory.getLogger(JDBCResourcesStorage.class);
72

    
73
    private static class DataBaseResource implements Resource {
74

    
75
        private class ResourceInputStream extends InputStream {
76

    
77
            @Override
78
            public int read() throws IOException {
79
                return in.read();
80
            }
81

    
82
            @Override
83
            public void close() throws IOException {
84
                DataBaseResource.this.close();
85
            }
86
        }
87

    
88
        private class ResourceOutputStream extends OutputStream {
89

    
90
            @Override
91
            public void write(int b) throws IOException {
92
                out.write(b);
93
            }
94

    
95
            @Override
96
            public void flush() throws IOException {
97
                out.flush();
98
            }
99

    
100
            @Override
101
            public void close() throws IOException {
102
                DataBaseResource.this.close();
103
            }
104
        }
105

    
106
        private final JDBCStoreParameters storeParameters;
107
        private final String tableName;
108
        private final String name;
109

    
110
        private InputStream in;
111
        private ByteArrayOutputStream out;
112

    
113
        public DataBaseResource(JDBCStoreParameters storeParameters, String tableName, String name) {
114
            this.storeParameters = storeParameters;
115
            this.tableName = tableName;
116
            this.name = name;
117
        }
118

    
119
        @Override
120
        public String getName() {
121
          return name;
122
        }
123
        
124
        @Override
125
        public boolean isReadOnly() {
126
            return false;
127
        }
128
        @Override
129
        public URL getURL() {
130
            try {
131
                String url = this.storeParameters.getUrl();
132
                return new URL(url + "&tableName=" + this.tableName + "&resourceName=" + this.name);
133
            } catch (Throwable ex) {
134
                return null;
135
            }
136
        }
137

    
138
        @Override
139
        public boolean exists() {
140
            FeatureStore store = null;
141
            try {
142
                FoldersManager fm = ToolsLocator.getFoldersManager();
143
                Pair<String, String> key = this.getCacheID();
144
                File f = fm.getTemporaryFile("resources-storage","jdbc", key.getLeft(), key.getRight());
145
                if( f.exists() ) {
146
                  return true;
147
                }
148
                DataManager dataManager = DALLocator.getDataManager();
149
                store = (FeatureStore) dataManager.openStore(
150
                        this.storeParameters.getDataStoreName(),
151
                        this.storeParameters
152
                );
153
                ExpressionBuilder builder = ExpressionUtils.createExpressionBuilder();
154
                String filter = builder.eq(
155
                        builder.column(FIELD_RESOURCES_NAME),
156
                        builder.constant(this.tableName+"."+this.name)
157
                ).toString();
158
                Feature feature = store.findFirst(filter);
159
                return feature!=null;
160
            } catch (Throwable ex) {
161
                LOGGER.warn("Can't access to the resoure '" + this.getURL() + "'.", ex);
162
            } finally {
163
                DisposeUtils.disposeQuietly(store);
164
            }
165
            return false;
166
        }
167

    
168
        public boolean remove() {
169
            FeatureStore store = null;
170
            try {
171
                FoldersManager fm = ToolsLocator.getFoldersManager();
172
                Pair<String, String> key = this.getCacheID();
173
                File f = fm.getTemporaryFile("resources-storage","jdbc", key.getLeft(), key.getRight());
174
                if( f.exists() ) {
175
                  f.delete();
176
                }
177
                DataManager dataManager = DALLocator.getDataManager();
178
                store = (FeatureStore) dataManager.openStore(
179
                        this.storeParameters.getDataStoreName(),
180
                        this.storeParameters
181
                );
182
                ExpressionBuilder builder = ExpressionUtils.createExpressionBuilder();
183
                String filter = builder.eq(
184
                        builder.column(FIELD_RESOURCES_NAME),
185
                        builder.constant(this.tableName+"."+this.name)
186
                ).toString();
187
                Feature feature = store.findFirst(filter);
188
                if(feature != null){
189
                    store.edit();
190
                    store.delete(feature);
191
                    store.finishEditing();
192
                    return true;
193
                }
194
                return false;
195
            } catch (Throwable ex) {
196
                LOGGER.warn("Can't access to the resoure '" + this.getURL() + "'.", ex);
197
            } finally {
198
                DisposeUtils.disposeQuietly(store);
199
            }
200
            return false;
201
        }
202

    
203
        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
        private InputStream getInputStreamFromCache() {
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
            InputStream is = null;
218
            FileOutputStream os = null;
219
            try {
220
              is = this.getInputStream();
221
              FileUtils.forceMkdir(f.getParentFile());
222
              os = new FileOutputStream(f);
223
              IOUtils.copy(is, os);              
224
              
225
              File f2 = fm.getTemporaryFile("resources-storage","jdbc", key.getLeft(), "parameters");              
226
              byte[] data = this.storeParameters.toByteArray();
227
              os = new FileOutputStream(f2);
228
              IOUtils.write(data, os);
229
            } catch (IOException ex) {
230
              return null;
231
            } finally {
232
              IOUtils.closeQuietly(is);
233
              IOUtils.closeQuietly(os);
234
            }
235
          }
236
          InputStream is = null;
237
          try {
238
            is = new FileInputStream(f);
239
          } catch (FileNotFoundException ex) {
240
          }
241
          return is;
242
        }
243
        
244
        private InputStream getInputStream() throws IOException {
245
            FeatureStore store = null;
246
            try {
247
                DataManager dataManager = DALLocator.getDataManager();
248
                store = (FeatureStore) dataManager.openStore(
249
                        this.storeParameters.getDataStoreName(),
250
                        this.storeParameters
251
                );
252
                ExpressionBuilder builder = ExpressionUtils.createExpressionBuilder();
253
                String filter = builder.eq(
254
                        builder.column(FIELD_RESOURCES_NAME),
255
                        builder.constant(this.tableName+"."+this.name)
256
                ).toString();
257
                Feature feature = store.findFirst(filter);
258
                if (feature == null) {
259
                    return null;
260
                }
261
                byte[] resource = feature.getByteArray(FIELD_RESOURCES_RESOURCE);
262
                InputStream is = new ByteArrayInputStream(resource);
263
                return is;
264
            } catch (Throwable ex) {
265
                LOGGER.warn("Can't access to the resoure '" + this.getURL() + "'.", ex);
266
            } finally {
267
                DisposeUtils.disposeQuietly(store);
268
            }
269
            return null;
270
        }
271

    
272
        @Override
273
        public InputStream asInputStream() throws IOException {
274
            if (this.in != null || this.out != null) {
275
                throw new IllegalStateException("Resource is already open (" + this.getURL() + ")");
276
            }
277
            InputStream is = this.getInputStreamFromCache();
278
            if( is==null ) {
279
              is = this.getInputStream();
280
            }
281
            this.in = is;
282
            return new ResourceInputStream();
283
        }
284

    
285
        @Override
286
        public OutputStream asOutputStream() throws IOException {
287
            if (this.in != null || this.out != null) {
288
                throw new IllegalStateException("Resource is already open (" + this.getURL() + ").");
289
            }
290
            this.out = new ByteArrayOutputStream();
291
            return new ResourceOutputStream();
292
        }
293

    
294
        @Override
295
        public void close() {
296
            if (this.in != null) {
297
                IOUtils.closeQuietly(this.in);
298
                this.in = null;
299
            }
300
            if (this.out != null) {
301
                FeatureStore store = null;
302
                try {
303
                    DataManager dataManager = DALLocator.getDataManager();
304
                    store = (FeatureStore) dataManager.openStore(
305
                            this.storeParameters.getDataStoreName(),
306
                            this.storeParameters
307
                    );
308
                    store.edit();
309
                    ExpressionBuilder builder = ExpressionUtils.createExpressionBuilder();
310
                    String filter = builder.eq(
311
                            builder.column(FIELD_RESOURCES_NAME),
312
                            builder.constant(this.tableName+"."+this.name)
313
                    ).toString();
314
                    Feature feature = store.findFirst(filter);
315
                    EditableFeature efeature;
316
                    if (feature == null) {
317
                        efeature = store.createNewFeature();
318
                        efeature.set(FIELD_RESOURCES_NAME, this.tableName+"."+this.name);
319
                        efeature.set(FIELD_RESOURCES_RESOURCE, this.out.toByteArray());
320
                        store.insert(efeature);
321
                    } else {
322
                        efeature = feature.getEditable();
323
                        efeature.set(FIELD_RESOURCES_RESOURCE, this.out.toByteArray());
324
                        store.update(efeature);
325
                    }
326
                    store.finishEditing();
327

    
328
                } catch (Throwable ex) {
329
                    LOGGER.warn("Can't write the resoure '" + this.getURL() + "'.", ex);
330
                } finally {
331
                    DisposeUtils.disposeQuietly(store);
332
                }
333
            }
334
        }
335
    }
336

    
337
    private final ResourcesStorage alternativeStorge;
338
    private final JDBCStoreParameters resourcesStoreParameters;
339
    private final String tableName;
340

    
341
    public JDBCResourcesStorage(ResourcesStorage alternativeStorge, JDBCStoreParameters resourcesStoreParameters, String tableName) {
342
        this.alternativeStorge = alternativeStorge;
343
        if( StringUtils.equals(TABLE_RESOURCES_NAME, tableName) ) {
344
            // No podemos buscar recursos de la tabla de recursos, ya que si no
345
            // al abrise la tabla de recursos entraria en bucle.
346
            this.resourcesStoreParameters = null;
347
        } else {
348
            this.resourcesStoreParameters = resourcesStoreParameters;
349
        }
350
        this.tableName = tableName;
351
    }
352

    
353
    @Override
354
    public boolean isEmpty() {
355
        return this.resourcesStoreParameters == null;
356
    }
357

    
358
    @Override
359
    public Resource getResource(String name) {
360
        if( this.alternativeStorge!=null ) {
361
            Resource r = this.alternativeStorge.getResource(name);
362
            if( r.exists() ) {
363
                return r;
364
            }
365
        }
366
        if (this.resourcesStoreParameters == null) {
367
            return null;
368
        }
369
        return new DataBaseResource(
370
                this.resourcesStoreParameters, 
371
                this.tableName, 
372
                name
373
        );
374
    }
375

    
376
    @Override
377
    public List<Resource> getResources(String name) {
378
        if (this.resourcesStoreParameters == null) {
379
            return null;
380
        }
381
        if( this.alternativeStorge!=null ) {
382
            List<Resource> r = this.alternativeStorge.getResources(name);
383
            if( r!=null && !r.isEmpty() ) {
384
                return r;
385
            }
386
        }
387
        FeatureStore store = null;
388
        try {
389
            DataManager dataManager = DALLocator.getDataManager();
390
            store = (FeatureStore) dataManager.openStore(
391
                    this.resourcesStoreParameters.getDataStoreName(),
392
                    this.resourcesStoreParameters
393
            );
394
            ExpressionBuilder builder = ExpressionUtils.createExpressionBuilder();
395
            List<ResourcesStorage.Resource> ress = new ArrayList<>();
396
            int n = 0;
397
            while (true) {
398
                String multiresourceName;
399
                if (n == 0) {
400
                    multiresourceName = name;
401
                } else {
402
                    multiresourceName = String.valueOf(n) + "." + name ;
403
                }
404
                String filter = builder.eq(
405
                        builder.column(FIELD_RESOURCES_NAME),
406
                        builder.constant(this.tableName+"."+multiresourceName)
407
                ).toString();
408
                Feature feature = store.findFirst(filter);
409
                if( feature==null ) {
410
                    break;
411
                }
412
                ress.add(new DataBaseResource(
413
                        this.resourcesStoreParameters, 
414
                        this.tableName,
415
                        multiresourceName
416
                    )
417
                );
418
                n++;
419
            }
420
            if (ress.isEmpty()) {
421
                return null;
422
            }
423
            return ress;
424
        } catch (Throwable ex) {
425
            LOGGER.warn("Can't get resources for '" + this.resourcesStoreParameters.getUrl()+"&resourceName="+name + "'.", ex);
426
            return null;
427
            
428
        } finally {
429
            DisposeUtils.disposeQuietly(store);
430
        }
431

    
432
    }
433

    
434
    @Override
435
    public boolean remove(String resourceName) {
436
        if( this.alternativeStorge!=null ) {
437
            try {
438
                this.alternativeStorge.remove(resourceName);
439
            } catch (Exception e) {
440
                //Do nothing
441
            }
442
        }
443
        if (this.resourcesStoreParameters == null) {
444
            return false;
445
        }
446
        DataBaseResource resource = new DataBaseResource(
447
                this.resourcesStoreParameters,
448
                this.tableName, 
449
                resourceName
450
        );
451
        
452
        return resource.remove();
453
    }
454
}