Statistics
| Revision:

svn-gvsig-desktop / trunk / org.gvsig.desktop / org.gvsig.desktop.compat.cdc / org.gvsig.fmap.dal / org.gvsig.fmap.dal.spi / src / main / java / org / gvsig / fmap / dal / spi / ZipResourcesStorage.java @ 44698

History | View | Annotate | Download (7.61 KB)

1
package org.gvsig.fmap.dal.spi;
2

    
3
import java.io.ByteArrayInputStream;
4
import java.io.ByteArrayOutputStream;
5
import java.io.File;
6
import java.io.IOException;
7
import java.io.InputStream;
8
import java.io.OutputStream;
9
import java.net.URI;
10
import java.net.URISyntaxException;
11
import java.net.URL;
12
import java.nio.file.FileSystem;
13
import java.nio.file.FileSystems;
14
import java.nio.file.Files;
15
import java.nio.file.Path;
16
import java.nio.file.StandardCopyOption;
17
import java.util.Collections;
18
import java.util.Objects;
19
import java.util.zip.ZipEntry;
20
import java.util.zip.ZipFile;
21
import org.apache.commons.io.FilenameUtils;
22
import org.apache.commons.io.IOUtils;
23
import org.apache.commons.lang3.StringUtils;
24
import org.gvsig.fmap.dal.AbstractDataResource;
25
import org.gvsig.tools.resourcesstorage.AbstractResourcesStorage;
26
import org.gvsig.tools.resourcesstorage.ResourcesStorage.Resource;
27
import org.slf4j.Logger;
28
import org.slf4j.LoggerFactory;
29

    
30
/**
31
 *
32
 * @author jjdelcerro
33
 */
34
@SuppressWarnings("UseSpecificCatch")
35
public class ZipResourcesStorage extends AbstractResourcesStorage {
36

    
37
    private static final Logger LOGGER = LoggerFactory.getLogger(ZipResourcesStorage.class);
38

    
39
    public class ZipFileResource
40
            extends AbstractDataResource
41
            implements Resource {
42

    
43
        private class ResourceInputStream extends InputStream {
44

    
45
            @Override
46
            public int read() throws IOException {
47
                return in.read();
48
            }
49

    
50
            @Override
51
            public void close() throws IOException {
52
                ZipFileResource.this.close();
53
            }
54
        }
55

    
56
        private class ResourceOutputStream extends OutputStream {
57

    
58
            @Override
59
            public void write(int b) throws IOException {
60
                out.write(b);
61
            }
62

    
63
            @Override
64
            public void flush() throws IOException {
65
                out.flush();
66
            }
67

    
68
            @Override
69
            public void close() throws IOException {
70
                ZipFileResource.this.close();
71
            }
72
        }
73

    
74
        private final File zipFile;
75
        private final String tableName;
76
        private final String resourceName;
77
        private ZipFile zip;
78
        private InputStream in;
79
        private ByteArrayOutputStream out;
80

    
81
        public ZipFileResource(File zipFile, String tableName, String resourceName) {
82
            this.zipFile = zipFile;
83
            this.tableName = tableName;
84
            this.resourceName = resourceName;
85
            this.zip = null;
86
            this.in = null;
87
            this.out = null;
88
            if (StringUtils.isBlank(this.tableName)) {
89
                LOGGER.warn("The table name is empty (URL=" + this.getURL() + ").");
90
            }
91
            if (StringUtils.isBlank(this.resourceName)) {
92
                LOGGER.warn("The resource name is empty (URL=" + this.getURL() + ").");
93
            }
94
        }
95

    
96
        public String getName() {
97
          return this.resourceName;
98
        }
99
        
100
        @Override
101
        public boolean isReadOnly() {
102
            return false;
103
        }
104
        
105
        @Override
106
        public final URL getURL() {
107
            try {
108
                return new URL("jar:" + this.zipFile.toURI().toString() + "!/" + this.tableName + "." + this.resourceName);
109
            } catch (Exception ex) {
110
                return null;
111
            }
112
        }
113

    
114
        @Override
115
        public boolean exists() {
116
            try {
117
                if (!this.zipFile.exists()) {
118
                    return false;
119
                }
120
                ZipFile z = new ZipFile(zipFile);
121
                try {
122
                    ZipEntry entry = z.getEntry(this.tableName + "." + this.resourceName);
123
                    if (entry == null) {
124
                        return false;
125
                    }
126
                    return true;
127
                } finally {
128
                    IOUtils.closeQuietly(z);
129
                }
130
            } catch (Exception ex) {
131
                LOGGER.warn("Can't access to the resource (" + Objects.toString(this.getURL()) + ").", ex);
132
                return false;
133
            }
134
        }
135

    
136
        @Override
137
        public InputStream asInputStream() throws IOException {
138
            if (!this.zipFile.exists()) {
139
                return null;
140
            }
141
            if (this.in != null || this.out != null) {
142
                throw new IllegalStateException("Resource is already open (" + this.zipFile.toString() + "!" + this.tableName + ")");
143
            }
144
            try {
145
                if (this.zip == null) {
146
                    this.zip = new ZipFile(zipFile);
147
                }
148
                ZipEntry entry = this.zip.getEntry(this.tableName + "." + this.resourceName);
149
                if (entry == null) {
150
                    return null;
151
                }
152
                this.in = this.zip.getInputStream(entry);
153
                return new ResourceInputStream();
154
            } catch (Exception ex) {
155
                LOGGER.warn("Can't create input stream (" + Objects.toString(this.getURL()) + ").", ex);
156
                return null;
157
            }
158
        }
159

    
160
        @Override
161
        public OutputStream asOutputStream() throws IOException {
162
            if (this.in != null || this.out != null) {
163
                throw new IllegalStateException("Resource is already open (" + Objects.toString(this.getURL()) + ").");
164
            }
165
            this.out = new ByteArrayOutputStream();
166
            return new ResourceOutputStream();
167
        }
168

    
169
        @Override
170
        public void close() {
171
            if (this.in != null) {
172
                IOUtils.closeQuietly(this.in);
173
                this.in = null;
174
            }
175
            if (this.out != null) {
176
                ByteArrayInputStream contents = new ByteArrayInputStream(this.out.toByteArray());
177
                try {
178
                    this.updateZipEntry(zipFile, this.tableName + "." + this.resourceName, contents);
179
                } catch (Exception ex) {
180
                    LOGGER.warn("Can't write resource (" + Objects.toString(this.getURL()) + ").", ex);
181
                } finally {
182
                    IOUtils.closeQuietly(contents);
183
                    IOUtils.closeQuietly(this.out);
184
                    this.out = null;
185
                }
186
            }
187
            if (this.zip != null) {
188
                IOUtils.closeQuietly(this.zip);
189
                this.zip = null;
190
            }
191
        }
192

    
193
        private void updateZipEntry(File zip, String entryName, InputStream entryContents) throws URISyntaxException, IOException {
194
            FileSystem zipfs = null;
195
            try {
196
                URI zipfsuri = new URI("jar:" + zip.toURI().toString());
197
                zipfs = FileSystems.newFileSystem(zipfsuri, Collections.singletonMap("create", "true"));
198
                Path entryPath = zipfs.getPath(entryName);
199
                Files.copy(entryContents, entryPath, StandardCopyOption.REPLACE_EXISTING);
200
            } finally {
201
                IOUtils.closeQuietly(zipfs);
202
            }
203
        }
204
    }
205

    
206
    private final File zipFile;
207
    private final String tableName;
208
    
209
    public ZipResourcesStorage(String pathName, String tableName) {
210
        this.zipFile = new File(pathName + ".gvres");
211
        this.tableName = tableName;
212
    }
213
    
214
    public static boolean existsStorage(String pathName) {
215
        File theZipFile = new File(pathName + ".gvres");
216
        return theZipFile.exists();
217
    }
218

    
219
    @Override
220
    public Resource getResource(String resourceName) {
221
        ZipFileResource res = new ZipFileResource(
222
                this.zipFile,
223
                this.tableName,
224
                resourceName
225
        );
226
        return res;
227
    }
228

    
229
    @Override
230
    public boolean isEmpty() {
231
        return !this.zipFile.exists();
232
    }
233

    
234
}