Statistics
| Revision:

svn-gvsig-desktop / trunk / org.gvsig.desktop / org.gvsig.desktop.library / org.gvsig.installer / org.gvsig.installer.lib / org.gvsig.installer.lib.impl / src / main / java / org / gvsig / installer / lib / impl / utils / Decompress.java @ 40991

History | View | Annotate | Download (13.3 KB)

1
/**
2
 * gvSIG. Desktop Geographic Information System.
3
 *
4
 * Copyright (C) 2007-2013 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
/*
25
 * AUTHORS (In addition to CIT):
26
 * 2010 {Prodevelop}   {Task}
27
 */
28

    
29
package org.gvsig.installer.lib.impl.utils;
30

    
31
import java.io.ByteArrayInputStream;
32
import java.io.ByteArrayOutputStream;
33
import java.io.File;
34
import java.io.FileOutputStream;
35
import java.io.IOException;
36
import java.io.InputStream;
37
import java.util.ArrayList;
38
import java.util.List;
39
import java.util.Map;
40
import java.util.zip.ZipEntry;
41
import java.util.zip.ZipException;
42
import java.util.zip.ZipInputStream;
43

    
44
import org.slf4j.Logger;
45
import org.slf4j.LoggerFactory;
46
import org.apache.commons.io.FileUtils;
47
import org.apache.commons.io.FilenameUtils;
48
import org.gvsig.installer.lib.api.PackageInfo;
49
import org.gvsig.installer.lib.api.execution.InstallPackageServiceException;
50
import org.gvsig.installer.lib.impl.DefaultPackageInfo;
51
import org.gvsig.installer.lib.impl.info.InstallerInfoFileReader;
52
import org.gvsig.installer.lib.spi.InstallerInfoFileException;
53
import org.gvsig.installer.lib.spi.InstallerProviderLocator;
54
import org.gvsig.tools.ToolsLocator;
55
import org.gvsig.tools.service.ServiceException;
56
import org.gvsig.tools.task.SimpleTaskStatus;
57
import org.gvsig.tools.task.TaskStatusManager;
58

    
59
/**
60
 * @author <a href="mailto:jpiera@gvsig.org">Jorge Piera Llodr&aacute;</a>
61
 */
62
public class Decompress {
63

    
64
        private static final int OPTION_DECOMPRESS = 1;
65
        private static final int OPTION_READ_INSTALLINFO = 2;
66
        private static final int OPTION_INSTALL = 3;
67

    
68
        private int option = 0;
69

    
70
        private int BUFFER = 2048;
71

    
72
        private static final Logger logger = LoggerFactory
73
                        .getLogger(Decompress.class);
74

    
75
        private List<PackageInfo> readedIinstallerInfos = null;
76
        private File outputDirectory = null;
77
        private List<PackageInfo> selectedInstallerInfos = null;
78
        private Map<PackageInfo, String> zipEntriesMap = null;
79
        private List<String> defaultSelectedPackets = null;
80

    
81
        public Decompress() {
82

    
83
        }
84

    
85
        public void decompressPlugins(InputStream is, File outputDirectory)
86
                        throws InstallPackageServiceException {
87
                option = OPTION_DECOMPRESS;
88
                this.outputDirectory = outputDirectory;
89

    
90
                decompressFolderOfPlugins(is);
91
        }
92

    
93
        public void readPackageSetInstallInfos(InputStream is,
94
                        List<PackageInfo> installerInfos,
95
                        Map<PackageInfo, String> zipEntriesMap)
96
                        throws InstallPackageServiceException {
97
                option = OPTION_READ_INSTALLINFO;
98
                this.readedIinstallerInfos = installerInfos;
99
                this.zipEntriesMap = zipEntriesMap;
100
                decompressFolderOfPlugins(is);
101
        }
102

    
103
        public void readPackageInstallInfo(InputStream is,
104
                        List<PackageInfo> installerInfos,
105
                        Map<PackageInfo, String> zipEntriesMap, String name)
106
                        throws InstallPackageServiceException {
107
                option = OPTION_READ_INSTALLINFO;
108
                this.readedIinstallerInfos = installerInfos;
109
                this.zipEntriesMap = zipEntriesMap;
110
                decompressFolderOfPluginFromPackage(is, name);
111
        }
112

    
113
        public class InstallerPluginReadException extends
114
                        InstallPackageServiceException {
115

    
116
                private static final long serialVersionUID = -6065359474790792680L;
117

    
118
                private static final String message = "Error reading the plugin";
119

    
120
                private static final String KEY = "_Error_reading_the_plugin";
121

    
122
                public InstallerPluginReadException(ServiceException e) {
123
                        super(message, e, KEY, serialVersionUID);
124
                }
125

    
126
        }
127

    
128
        public void decompressPlugin(InputStream is, File outputDirectory)
129
                        throws InstallPackageServiceException {
130
                try {
131
                        option = OPTION_DECOMPRESS;
132
                        this.outputDirectory = outputDirectory;
133
                        FileUtils.forceMkdir(outputDirectory);
134
                        logger.debug("decompress plugin to '"+outputDirectory.getAbsolutePath()+"'.");
135
                        decompressPlugin(is);
136
                } catch (Exception e) {
137
                        logger.warn("Can't decompress plugin in '"+outputDirectory+"'.", e);
138
                        throw new InstallPackageServiceException(e);
139
                }
140
        }
141

    
142
        public class InstallerPluginReadErrorException extends
143
                        InstallPackageServiceException {
144

    
145
                private static final long serialVersionUID = 4505298394252120334L;
146

    
147
                private static final String message = "Error reading the plugin '%(name)s'";
148

    
149
                private static final String KEY = "_Error_reading_the_plugin";
150

    
151
                public InstallerPluginReadErrorException(Exception e, String packageName) {
152
                        super(message, e, KEY, serialVersionUID);
153
                        setValue("name", packageName);
154
                }
155

    
156
        }
157

    
158
        public InputStream searchPlugin(InputStream is, String zipEntry)
159
                        throws InstallPackageServiceException {
160
                ZipEntry entry = null;
161
                String name = "";
162

    
163
                try {
164
                        ZipInputStream zipInputStream = new ZipInputStream(is);
165

    
166
                        while ((entry = zipInputStream.getNextEntry()) != null) {
167
                                name = entry.getName();
168
                                if (entry.getName().equals(zipEntry)) {
169
                                        return zipInputStream;
170
                                }
171
                                zipInputStream.closeEntry();
172
                        }
173
                        zipInputStream.closeEntry();
174

    
175
                        zipInputStream.close();
176
                } catch (Exception e) {
177
                        throw new InstallerPluginReadErrorException(e, name);
178
                }
179
                return null;
180
        }
181

    
182
        public void installFromStream(InputStream is, PackageInfo installerInfo)
183
                        throws InstallPackageServiceException {
184
                option = OPTION_INSTALL;
185
                this.selectedInstallerInfos = new ArrayList<PackageInfo>();
186
                this.selectedInstallerInfos.add(installerInfo);
187
                decompressFolderOfPlugins(is);
188
        }
189

    
190
        public void installFromStream(InputStream is,
191
                        List<PackageInfo> installerInfos)
192
                        throws InstallPackageServiceException {
193
                option = OPTION_INSTALL;
194
                this.selectedInstallerInfos = installerInfos;
195
                decompressFolderOfPlugins(is);
196
        }
197

    
198
        private void decompressFolderOfPlugins(InputStream is)
199
                        throws InstallPackageServiceException {
200
                ZipInputStream zipInputStream = new ZipInputStream(is);
201
                ZipEntry entry = null;
202

    
203
                String name = "";
204

    
205
                try {
206
                        while ((entry = zipInputStream.getNextEntry()) != null) {
207
                                name = entry.getName();
208
                                if (entry.getName().equals("defaultPackages")
209
                                                || entry.getName().equals("defaultSelection")) {
210
                                        int count;
211
                                        byte data[] = new byte[BUFFER];
212
                                        ByteArrayOutputStream out = new ByteArrayOutputStream();
213

    
214
                                        while ((count = zipInputStream.read(data, 0, BUFFER)) != -1) {
215
                                                out.write(data, 0, count);
216
                                        }
217

    
218
                                        String str = out.toString().replace("\r", "");
219
                                        String lineas[] = str.split("\\n");
220
                                        List<String> defaultPackagesList = new ArrayList<String>();
221

    
222
                                        for (int i = 0; i < lineas.length; i++) {
223
                                            
224
                                            String trim_lineas = lineas[i].trim();
225
                                            if (! ((trim_lineas.startsWith("#") || trim_lineas.startsWith(";")))) {
226
                                                // not a comment
227
                                                defaultPackagesList.add(lineas[i]);
228
                                            }
229
                                                
230
                                        }
231

    
232
                                        defaultSelectedPackets = defaultPackagesList;
233
                                        out.flush();
234
                                } else {
235
//                                        logger.debug("Extracting all Plugins, plugin: " + name);
236
                                        if (option == OPTION_INSTALL) {
237

    
238
                                        } else {
239
                                                if (option == OPTION_DECOMPRESS) {
240
                                                        logger.info("decompress plugin " + name);
241
                                                        decompressPlugin(zipInputStream);
242
                                                } else if (option == OPTION_READ_INSTALLINFO) {
243
                                                        readPlugin(zipInputStream, entry.getName());
244
                                                }
245
                                        }
246
                                }
247
                                zipInputStream.closeEntry();
248
                        }
249
                        zipInputStream.close();
250

    
251
                } catch (Exception e) {
252
                        throw new InstallerPluginReadErrorException(e, name);
253
                }
254
        }
255

    
256
        private void decompressFolderOfPluginFromPackage(InputStream is, String name)
257
                        throws InstallPackageServiceException {
258

    
259
                try {
260
                        if (option == OPTION_INSTALL) {
261

    
262
                        } else {
263
                                if (option == OPTION_DECOMPRESS) {
264
                                        decompressPlugin(is);
265
                                } else {
266
                                        if (option == OPTION_READ_INSTALLINFO) {
267
                                                readPlugin(is, name);
268
                                        }
269
                                }
270
                        }
271

    
272
                } catch (Exception e) {
273
                        throw new InstallerPluginReadErrorException(e, name);
274
                }
275
        }
276

    
277
        private void readPlugin(InputStream is, String zipEntryName)
278
                        throws ZipException, IOException, InstallerInfoFileException {
279
                ZipEntry entry = null;
280
                int installerInfoNumber = zipEntriesMap.size();
281
                String packageInfoName = getPackageInfoFileName();
282
                String unixPackageInfoPath = "/".concat(packageInfoName);
283
                String windowsPackageInfoPath = "\\".concat(packageInfoName);
284
                ZipInputStream zis = new ZipInputStream(is);
285
                while ((entry = zis.getNextEntry()) != null) {
286
                        logger.debug("Extracting: " + entry.getName());
287

    
288
                        String name = entry.getName();
289
                        // Just in case, but we are going to create them always using
290
                        // the unix file separator
291
                        if (name.endsWith(unixPackageInfoPath)
292
                                        || name.endsWith(windowsPackageInfoPath)) {
293
                                PackageInfo installerInfo = readInstallInfo(zis);
294
                                zipEntriesMap.put(installerInfo, zipEntryName);
295
                                readedIinstallerInfos.add(installerInfo);
296
                        }
297
                        zis.closeEntry();
298
                }
299
                // Don't close the stream as if it is a zip file contained
300
                // into another zip file, closing of the child Zip?nputStream
301
                // will close also the parent's.
302
                // zis.close();
303

    
304
                if (installerInfoNumber == zipEntriesMap.size()) {
305
                        PackageInfo installerInfo = new DefaultPackageInfo();
306
                        installerInfo.setCode(zipEntryName);
307
                        installerInfo.setName(zipEntryName);
308
                        zipEntriesMap.put(installerInfo, zipEntryName);
309
                        readedIinstallerInfos.add(installerInfo);
310
                }
311
        }
312

    
313
        private void decompressPlugin(InputStream inputStream) throws ZipException,
314
                        IOException, InstallerInfoFileException {
315

    
316
                ZipInputStream zis = null;
317
                ZipEntry entry = null;
318
                byte data[] = new byte[BUFFER];
319
                int count = 0;
320

    
321
                TaskStatusManager manager = ToolsLocator.getTaskStatusManager();
322
                SimpleTaskStatus taskStatus = manager
323
                                .createDefaultSimpleTaskStatus("Uncompressing...");
324
                
325
                manager.add(taskStatus);
326
                int countRootFolders = 0;
327
                String entryName = "(header)";
328
                try {
329
                        long readed = 0;
330
        
331
                        // // First read all the contents size
332
                        // zis = new ZipInputStream(inputStream);
333
                        // while ((entry = zis.getNextEntry()) != null) {
334
                        // count += entry.getSize();
335
                        // }
336
                        // // zis.close();
337
                        // taskStatus.setRangeOfValues(0, count);
338
        
339
                        // Return the stream to the initial position
340
                        zis = new ZipInputStream(inputStream);
341
                        while ((entry = zis.getNextEntry()) != null) {
342
                                entryName = FilenameUtils.separatorsToSystem(entry.getName());
343
                                taskStatus.message(entryName);
344
        
345
                                File file = new File(outputDirectory, entryName);
346
                                if (file.exists()) {
347
                                        logger.info("delete " + file.getAbsolutePath());
348
                                        FileUtils.forceDelete(file);
349
                                }
350
                                if (entry.isDirectory()) {
351
                                        String s = FilenameUtils.getPathNoEndSeparator(entryName);
352
                                        if( !s.contains(File.separator) ) {  
353
                                                if( ++countRootFolders > 1 ) {
354
                                                        logger.warn("More than one root folder ("+entryName+") in the package; it may be an error.");
355
                                                }
356
                                        }
357
                                        logger.debug("makedirs " + file.getAbsolutePath());
358
                                        file.mkdirs();
359
                                } else {
360
                                        createParentFolder(file);
361
                                        logger.debug("extracting " + file.getAbsolutePath());
362
                                        FileOutputStream fos = new FileOutputStream(file);
363
                                        while ((count = zis.read(data, 0, BUFFER)) != -1) {
364
                                                fos.write(data, 0, count);
365
                                                readed += count;
366
                                                taskStatus.setCurValue(readed);
367
                                        }
368
                                        fos.flush();
369
                                        fos.close();
370
                                }
371
                        }
372
                        zis.close();
373
                } catch(IOException ex) {
374
                        logger.warn("Problems uncompresing plugin (last entry '"+entryName+"'.",ex);
375
                        throw ex;
376
                        
377
                } catch(RuntimeException ex) {
378
                        logger.warn("Problems uncompresing plugin (last entry '"+entryName+"'.",ex);
379
                        throw ex;
380
                        
381
                } finally {
382
                    
383
                    taskStatus.remove();
384
                    
385
                }
386
                
387
        
388
        }
389

    
390
        private void createParentFolder(File file) {
391
                File parentFile = file.getParentFile();
392
                if (!parentFile.exists()) {
393
                        parentFile.mkdirs();
394
                }
395
        }
396

    
397
        public boolean delete(File dir) {
398
                if (dir.isDirectory()) {
399
                        String[] children = dir.list();
400
                        for (int i = 0; i < children.length; i++) {
401
                                boolean success = delete(new File(dir, children[i]));
402
                                if (!success) {
403
                                        return false;
404
                                }
405
                        }
406
                }
407
                return dir.delete();
408
        }
409

    
410
        public PackageInfo readInstallerInfo(InputStream is)
411
                        throws InstallerInfoFileException {
412
                try {
413
                        return readInstallInfo(new ZipInputStream(is));
414
                } catch (IOException e) {
415
                        throw new InstallerInfoFileException("error_reading_installerinfo",
416
                                        e);
417
                }
418
        }
419

    
420
        private PackageInfo readInstallInfo(ZipInputStream zipInputStream)
421
                        throws IOException, InstallerInfoFileException {
422
                int count;
423
                byte data[] = new byte[BUFFER];
424

    
425
                ByteArrayOutputStream out = new ByteArrayOutputStream();
426

    
427
                while ((count = zipInputStream.read(data, 0, BUFFER)) != -1) {
428
                        out.write(data, 0, count);
429
                }
430
                out.flush();
431

    
432
                DefaultPackageInfo installerInfo = new DefaultPackageInfo();
433
                InstallerInfoFileReader installerInfoFileReader = new InstallerInfoFileReader();
434
                installerInfoFileReader.read(installerInfo, new ByteArrayInputStream(
435
                                out.toByteArray()));
436

    
437
                return installerInfo;
438
        }
439

    
440
        private String getPackageInfoFileName() {
441
                return InstallerProviderLocator.getProviderManager()
442
                                .getPackageInfoFileName();
443
        }
444

    
445
        public List<String> getDefaultSelectedPackages() {
446
                return defaultSelectedPackets;
447
        }
448
}