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

History | View | Annotate | Download (14.4 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

    
324
        private void decompressPlugin(InputStream inputStream) throws ZipException,
325
                        IOException, InstallerInfoFileException {
326

    
327
                ZipInputStream zis = null;
328
                ZipEntry entry = null;
329
                byte data[] = new byte[BUFFER];
330
                int count = 0;
331

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

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

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

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

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

    
427
                ByteArrayOutputStream out = new ByteArrayOutputStream();
428

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

    
434
                DefaultPackageInfo installerInfo = new DefaultPackageInfo();
435
                InstallerInfoFileReader installerInfoFileReader = new InstallerInfoFileReader();
436
                installerInfoFileReader.read(installerInfo, new ByteArrayInputStream(
437
                                out.toByteArray()));
438
                if( taskStatus!=null ) {                
439
                    taskStatus.message(installerInfo.getName());
440
                }
441
                return installerInfo;
442
        }
443

    
444
        private String getPackageInfoFileName() {
445
                return InstallerProviderLocator.getProviderManager()
446
                                .getPackageInfoFileName();
447
        }
448

    
449
        public List<String> getDefaultSelectedPackages() {
450
                return defaultSelectedPackets;
451
        }
452
        
453
        public Properties getProperties() {
454
                return properties;
455
        }
456
}