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

History | View | Annotate | Download (14.7 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.Properties;
41
import java.util.zip.ZipEntry;
42
import java.util.zip.ZipException;
43
import java.util.zip.ZipInputStream;
44

    
45
import org.slf4j.Logger;
46
import org.slf4j.LoggerFactory;
47
import org.apache.commons.io.FileUtils;
48
import org.apache.commons.io.FilenameUtils;
49
import org.apache.commons.io.IOUtils;
50
import org.gvsig.installer.lib.api.PackageInfo;
51
import org.gvsig.installer.lib.api.execution.InstallPackageServiceException;
52
import org.gvsig.installer.lib.impl.DefaultPackageInfo;
53
import org.gvsig.installer.lib.impl.info.InstallerInfoFileReader;
54
import org.gvsig.installer.lib.spi.InstallerInfoFileException;
55
import org.gvsig.installer.lib.spi.InstallerProviderLocator;
56
import org.gvsig.tools.service.ServiceException;
57
import org.gvsig.tools.task.SimpleTaskStatus;
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
        private Properties properties;
81
        private SimpleTaskStatus taskStatus = null;
82
        
83
        public Decompress() {
84
            this.properties = new Properties();
85
        }
86
        
87
        public Decompress(SimpleTaskStatus taskStatus) {
88
            this();
89
            this.taskStatus = taskStatus;
90
        }
91
        
92
        public void decompressPlugins(InputStream is, File outputDirectory)
93
                        throws InstallPackageServiceException {
94
                option = OPTION_DECOMPRESS;
95
                this.outputDirectory = outputDirectory;
96

    
97
                decompressFolderOfPlugins(is);
98
        }
99

    
100
        public void readPackageSetInstallInfos(InputStream is,
101
                        List<PackageInfo> installerInfos,
102
                        Map<PackageInfo, String> zipEntriesMap)
103
                        throws InstallPackageServiceException {
104
                option = OPTION_READ_INSTALLINFO;
105
                this.readedIinstallerInfos = installerInfos;
106
                this.zipEntriesMap = zipEntriesMap;
107
                decompressFolderOfPlugins(is);
108
        }
109

    
110
        public void readPackageInstallInfo(InputStream is,
111
                        List<PackageInfo> installerInfos,
112
                        Map<PackageInfo, String> zipEntriesMap, String name)
113
                        throws InstallPackageServiceException {
114
                option = OPTION_READ_INSTALLINFO;
115
                this.readedIinstallerInfos = installerInfos;
116
                this.zipEntriesMap = zipEntriesMap;
117
                decompressFolderOfPluginFromPackage(is, name);
118
        }
119

    
120
        public class InstallerPluginReadException extends
121
                        InstallPackageServiceException {
122

    
123
                private static final long serialVersionUID = -6065359474790792680L;
124

    
125
                private static final String message = "Error reading the plugin";
126

    
127
                private static final String KEY = "_Error_reading_the_plugin";
128

    
129
                public InstallerPluginReadException(ServiceException e) {
130
                        super(message, e, KEY, serialVersionUID);
131
                }
132

    
133
        }
134

    
135
        public void decompressPlugin(InputStream is, File outputDirectory)
136
                        throws InstallPackageServiceException {
137
                try {
138
                        option = OPTION_DECOMPRESS;
139
                        this.outputDirectory = outputDirectory;
140
                        FileUtils.forceMkdir(outputDirectory);
141
                        logger.debug("decompress plugin to '"+outputDirectory.getAbsolutePath()+"'.");
142
                        decompressPlugin(is);
143
                } catch (Exception e) {
144
                        logger.warn("Can't decompress plugin in '"+outputDirectory+"'.", e);
145
                        throw new InstallPackageServiceException(e);
146
                }
147
        }
148

    
149
        public class InstallerPluginReadErrorException extends
150
                        InstallPackageServiceException {
151

    
152
                private static final long serialVersionUID = 4505298394252120334L;
153

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

    
156
                private static final String KEY = "_Error_reading_the_plugin";
157

    
158
                public InstallerPluginReadErrorException(Exception e, String packageName) {
159
                        super(message, e, KEY, serialVersionUID);
160
                        setValue("name", packageName);
161
                }
162

    
163
        }
164

    
165
        public InputStream searchPlugin(InputStream is, String zipEntry)
166
                        throws InstallPackageServiceException {
167
                ZipEntry entry = null;
168
                String name = "";
169

    
170
                try {
171
                        ZipInputStream zipInputStream = new ZipInputStream(is);
172

    
173
                        while ((entry = zipInputStream.getNextEntry()) != null) {
174
                                name = entry.getName();
175
                                if (entry.getName().equals(zipEntry)) {
176
                                        return zipInputStream;
177
                                }
178
                                zipInputStream.closeEntry();
179
                        }
180
                        zipInputStream.closeEntry();
181

    
182
                        zipInputStream.close();
183
                } catch (Exception e) {
184
                        throw new InstallerPluginReadErrorException(e, name);
185
                }
186
                return null;
187
        }
188

    
189
        public void installFromStream(InputStream is, PackageInfo installerInfo)
190
                        throws InstallPackageServiceException {
191
                option = OPTION_INSTALL;
192
                this.selectedInstallerInfos = new ArrayList<PackageInfo>();
193
                this.selectedInstallerInfos.add(installerInfo);
194
                decompressFolderOfPlugins(is);
195
        }
196

    
197
        public void installFromStream(InputStream is,
198
                        List<PackageInfo> installerInfos)
199
                        throws InstallPackageServiceException {
200
                option = OPTION_INSTALL;
201
                this.selectedInstallerInfos = installerInfos;
202
                decompressFolderOfPlugins(is);
203
        }
204

    
205
        private void decompressFolderOfPlugins(InputStream is)
206
                        throws InstallPackageServiceException {
207
                ZipInputStream zipInputStream = new ZipInputStream(is);
208
                ZipEntry entry = null;
209

    
210
                String name = "";
211

    
212
                try {
213
                        while ((entry = zipInputStream.getNextEntry()) != null) {
214
                                name = entry.getName();
215
                                if (entry.getName().equals("defaultPackages")
216
                                                || entry.getName().equals("defaultSelection")) {
217
                                        int count;
218
                                        byte data[] = new byte[BUFFER];
219
                                        ByteArrayOutputStream out = new ByteArrayOutputStream();
220

    
221
                                        while ((count = zipInputStream.read(data, 0, BUFFER)) != -1) {
222
                                                out.write(data, 0, count);
223
                                        }
224

    
225
                                        String str = out.toString().replace("\r", "");
226
                                        String lineas[] = str.split("\\n");
227
                                        List<String> defaultPackagesList = new ArrayList<String>();
228

    
229
                                        for (int i = 0; i < lineas.length; i++) {
230
                                            
231
                                            String trim_lineas = lineas[i].trim();
232
                                            if (! ((trim_lineas.startsWith("#") || trim_lineas.startsWith(";")))) {
233
                                                // not a comment
234
                                                defaultPackagesList.add(lineas[i]);
235
                                            }
236
                                                
237
                                        }
238

    
239
                                        defaultSelectedPackets = defaultPackagesList;
240
                                        out.flush();
241
                                } else if (entry.getName().equals("packages.properties") ) {
242
                                    int count;
243
                                    byte data[] = new byte[BUFFER];
244
                                    ByteArrayOutputStream out = new ByteArrayOutputStream();
245

    
246
                                    while ((count = zipInputStream.read(data, 0, BUFFER)) != -1) {
247
                                            out.write(data, 0, count);
248
                                    }
249
                                    InputStream in = new ByteArrayInputStream(out.toByteArray());
250
                                    properties.load(in);
251
                                    IOUtils.closeQuietly(in);
252
                                    IOUtils.closeQuietly(out);
253
                                } else {
254
//                                        logger.debug("Extracting all Plugins, plugin: " + name);
255
                                        if (option == OPTION_INSTALL) {
256

    
257
                                        } else {
258
                                                if (option == OPTION_DECOMPRESS) {
259
                                                        logger.info("decompress plugin " + name);
260
                                                        decompressPlugin(zipInputStream);
261
                                                } else if (option == OPTION_READ_INSTALLINFO) {
262
                                                        readPlugin(zipInputStream, entry.getName());
263
                                                }
264
                                        }
265
                                }
266
                                zipInputStream.closeEntry();
267
                        }
268
                        zipInputStream.close();
269

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

    
275
        private void decompressFolderOfPluginFromPackage(InputStream is, String name)
276
                        throws InstallPackageServiceException {
277

    
278
                try {
279
                        if (option == OPTION_INSTALL) {
280

    
281
                        } else {
282
                                if (option == OPTION_DECOMPRESS) {
283
                                        decompressPlugin(is);
284
                                } else {
285
                                        if (option == OPTION_READ_INSTALLINFO) {
286
                                                readPlugin(is, name);
287
                                        }
288
                                }
289
                        }
290

    
291
                } catch (Exception e) {
292
                        throw new InstallerPluginReadErrorException(e, name);
293
                }
294
        }
295

    
296
        private void readPlugin(InputStream is, String zipEntryName)
297
                        throws ZipException, IOException, InstallerInfoFileException {
298
                ZipEntry entry = null;
299
                int installerInfoNumber = zipEntriesMap.size();
300
                String packageInfoName = getPackageInfoFileName();
301
                String unixPackageInfoPath = "/".concat(packageInfoName);
302
                String windowsPackageInfoPath = "\\".concat(packageInfoName);
303
                ZipInputStream zis = new ZipInputStream(is);
304
                while ((entry = zis.getNextEntry()) != null) {
305
                        logger.debug("Extracting: " + entry.getName());
306

    
307
                        String name = entry.getName();
308
                        // Just in case, but we are going to create them always using
309
                        // the unix file separator
310
                        if (name.endsWith(unixPackageInfoPath)
311
                                        || name.endsWith(windowsPackageInfoPath)) {
312
                                PackageInfo installerInfo = readInstallInfo(zis);
313
                                zipEntriesMap.put(installerInfo, zipEntryName);
314
                                readedIinstallerInfos.add(installerInfo);
315
                        }
316
                        zis.closeEntry();
317
                }
318
                // Don't close the stream as if it is a zip file contained
319
                // into another zip file, closing of the child Zip?nputStream
320
                // will close also the parent's.
321
                // zis.close();
322

    
323
                if (installerInfoNumber == zipEntriesMap.size()) {
324
                        PackageInfo installerInfo = new DefaultPackageInfo();
325
                        installerInfo.setCode(zipEntryName);
326
                        installerInfo.setName(zipEntryName);
327
                        zipEntriesMap.put(installerInfo, zipEntryName);
328
                        readedIinstallerInfos.add(installerInfo);
329
                }
330
        }
331

    
332
        private void decompressPlugin(InputStream inputStream) throws ZipException,
333
                        IOException, InstallerInfoFileException {
334

    
335
                ZipInputStream zis = null;
336
                ZipEntry entry = null;
337
                byte data[] = new byte[BUFFER];
338
                int count = 0;
339

    
340
                int countRootFolders = 0;
341
                String entryName = "(header)";
342
                try {
343
                        long readed = 0;
344
                        if( taskStatus!=null ) {
345
                            taskStatus.push();
346
                        }
347
                        zis = new ZipInputStream(inputStream);
348
                        while ((entry = zis.getNextEntry()) != null) {
349
                                entryName = FilenameUtils.separatorsToSystem(entry.getName());
350
                                if( taskStatus!=null ) {
351
                                    taskStatus.message(entryName);
352
                                }
353
        
354
                                File file = new File(outputDirectory, entryName);
355
                                if (file.exists()) {
356
                                        logger.info("delete " + file.getAbsolutePath());
357
                                        FileUtils.forceDelete(file);
358
                                }
359
                                if (entry.isDirectory()) {
360
                                        String s = FilenameUtils.getPathNoEndSeparator(entryName);
361
                                        if( !s.contains(File.separator) ) {  
362
                                                if( ++countRootFolders > 1 ) {
363
                                                        logger.warn("More than one root folder ("+entryName+") in the package; it may be an error.");
364
                                                }
365
                                        }
366
                                        logger.debug("makedirs " + file.getAbsolutePath());
367
                                        if( !file.mkdirs() ) {
368
                                           throw new IOException("Can't create folder '"+file.getAbsolutePath()+"'.");
369
                                        }
370
                                } else {
371
                                        createParentFolder(file);
372
                                        logger.debug("extracting " + file.getAbsolutePath());
373
                                        FileOutputStream fos = new FileOutputStream(file);
374
                                        while ((count = zis.read(data, 0, BUFFER)) != -1) {
375
                                                fos.write(data, 0, count);
376
                                                readed += count;
377
                                                if( taskStatus!=null ) {
378
                                                    taskStatus.setCurValue(readed);
379
                                                }
380
                                        }
381
                                        fos.flush();
382
                                        fos.close();
383
                                }
384
                        }
385
                        zis.close();
386
                } catch(IOException ex) {
387
                        logger.warn("Problems uncompresing plugin (last entry '"+entryName+"'.",ex);
388
                        throw ex;
389
                        
390
                } catch(RuntimeException ex) {
391
                        logger.warn("Problems uncompresing plugin (last entry '"+entryName+"'.",ex);
392
                        throw ex;
393
                } finally {
394
                    if( taskStatus!=null ) {
395
                        taskStatus.pop();
396
                    }
397
                }
398
        }
399

    
400
        private void createParentFolder(File file) {
401
                File parentFile = file.getParentFile();
402
                if (!parentFile.exists()) {
403
                        parentFile.mkdirs();
404
                }
405
        }
406

    
407
        public boolean delete(File dir) {
408
                if (dir.isDirectory()) {
409
                        String[] children = dir.list();
410
                        for (int i = 0; i < children.length; i++) {
411
                                boolean success = delete(new File(dir, children[i]));
412
                                if (!success) {
413
                                        return false;
414
                                }
415
                        }
416
                }
417
                return dir.delete();
418
        }
419

    
420
        public PackageInfo readInstallerInfo(InputStream is)
421
                        throws InstallerInfoFileException {
422
                try {
423
                        return readInstallInfo(new ZipInputStream(is));
424
                } catch (IOException e) {
425
                        throw new InstallerInfoFileException("error_reading_installerinfo",
426
                                        e);
427
                }
428
        }
429

    
430
        private PackageInfo readInstallInfo(ZipInputStream zipInputStream)
431
                        throws IOException, InstallerInfoFileException {
432
                int count;
433
                byte data[] = new byte[BUFFER];
434

    
435
                ByteArrayOutputStream out = new ByteArrayOutputStream();
436

    
437
                while ((count = zipInputStream.read(data, 0, BUFFER)) != -1) {
438
                        out.write(data, 0, count);
439
                }
440
                out.flush();
441

    
442
                DefaultPackageInfo installerInfo = new DefaultPackageInfo();
443
                InstallerInfoFileReader installerInfoFileReader = new InstallerInfoFileReader();
444
                installerInfoFileReader.read(installerInfo, new ByteArrayInputStream(
445
                                out.toByteArray()));
446
                if( taskStatus!=null ) {                
447
                    taskStatus.message(installerInfo.getName());
448
                }
449
                return installerInfo;
450
        }
451

    
452
        private String getPackageInfoFileName() {
453
                return InstallerProviderLocator.getProviderManager()
454
                                .getPackageInfoFileName();
455
        }
456

    
457
        public List<String> getDefaultSelectedPackages() {
458
                return defaultSelectedPackets;
459
        }
460
        
461
        public Properties getProperties() {
462
                return properties;
463
        }
464
}