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 / execution / DefaultInstallPackageService.java @ 43126

History | View | Annotate | Download (21.8 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 modify it under
7
 * the terms of the GNU General Public License as published by the Free Software
8
 * Foundation; either version 3 of the License, or (at your option) any later
9
 * version.
10
 *
11
 * This program is distributed in the hope that it will be useful, but WITHOUT
12
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13
 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
14
 * details.
15
 *
16
 * You should have received a copy of the GNU General Public License along with
17
 * this program; if not, write to the Free Software Foundation, Inc., 51
18
 * Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19
 *
20
 * For any additional information, do not hesitate to contact us at info AT
21
 * gvsig.com, or visit our website www.gvsig.com.
22
 */
23
/*
24
 * AUTHORS (In addition to CIT):
25
 * 2010 {Prodevelop}   {Task}
26
 */
27
package org.gvsig.installer.lib.impl.execution;
28

    
29
import java.io.BufferedInputStream;
30
import java.io.File;
31
import java.io.FileFilter;
32
import java.io.FileInputStream;
33
import java.io.FileNotFoundException;
34
import java.io.IOException;
35
import java.io.InputStream;
36
import java.net.MalformedURLException;
37
import java.net.URL;
38
import java.util.ArrayList;
39
import java.util.Collections;
40
import java.util.HashMap;
41
import java.util.HashSet;
42
import java.util.List;
43
import java.util.Map;
44
import java.util.Properties;
45
import java.util.Set;
46
import org.apache.commons.lang3.StringUtils;
47

    
48
import org.slf4j.Logger;
49
import org.slf4j.LoggerFactory;
50

    
51
import org.gvsig.installer.lib.api.InstallerManager;
52
import org.gvsig.installer.lib.api.PackageInfo;
53
import org.gvsig.installer.lib.api.Version;
54
import org.gvsig.installer.lib.api.creation.MakePluginPackageServiceException;
55
import org.gvsig.installer.lib.api.execution.InstallPackageService;
56
import org.gvsig.installer.lib.api.execution.InstallPackageServiceException;
57
import org.gvsig.installer.lib.impl.DefaultInstallerManager;
58
import org.gvsig.installer.lib.impl.utils.Download;
59
import org.gvsig.installer.lib.spi.InstallPackageProviderServices;
60
import org.gvsig.installer.lib.spi.InstallerProviderLocator;
61
import org.gvsig.installer.lib.spi.InstallerProviderManager;
62
import org.gvsig.installer.lib.spi.execution.InstallPackageProvider;
63
import org.gvsig.tools.exception.BaseException;
64
import org.gvsig.tools.service.Manager;
65
import org.gvsig.tools.service.ServiceException;
66
import org.gvsig.tools.task.SimpleTaskStatus;
67

    
68
/**
69
 * @author <a href="mailto:jpiera@gvsig.org">Jorge Piera Llodr&aacute;</a>
70
 */
71
public class DefaultInstallPackageService extends Thread implements
72
        InstallPackageService {
73

    
74
    private static final Logger LOG = LoggerFactory
75
            .getLogger(DefaultInstallPackageService.class);
76

    
77
    private static final String PACKAGE_FILE_NAME = "packages.gvspki";
78

    
79
    private Map<PackageInfo, File> packageInfoFileMap = null;
80
    private Map<PackageInfo, String> zipEntriesMap = null;
81
    private List<PackageInfo> packageInfos = null;
82
    private InstallerManager manager;
83
    private InstallPackageProviderServices installerProviderServices = null;
84

    
85
    public DefaultInstallPackageService(DefaultInstallerManager manager) {
86
        super();
87
        this.manager = manager;
88
        this.reset();
89
    }
90

    
91
    public void reset() {
92
        packageInfoFileMap = new HashMap<PackageInfo, File>();
93
        packageInfos = new ArrayList<PackageInfo>();
94
        zipEntriesMap = new HashMap<PackageInfo, String>();
95
        installerProviderServices = InstallerProviderLocator
96
                .getProviderManager().createInstallerProviderServices();
97
    }
98

    
99
    public class InstallerApplicationDirectoryNotFoundException extends
100
            InstallPackageServiceException {
101

    
102
        private static final long serialVersionUID = -1130408094135962456L;
103

    
104
        private static final String message = "Aplication directory '%(directory)s' not found";
105

    
106
        private static final String KEY = "_aplication_directory_XdirectoryX_not_found";
107

    
108
        public InstallerApplicationDirectoryNotFoundException(File file) {
109
            super(message, KEY, serialVersionUID);
110
            setValue("directory", file.toString());
111
        }
112

    
113
    }
114

    
115
    public class InstallerNoDirectoryException extends
116
            InstallPackageServiceException {
117

    
118
        private static final long serialVersionUID = -8685263049644983769L;
119

    
120
        private static final String message = "'%(directory)s' is not a directory";
121

    
122
        private static final String KEY = "_XdirectoryX_is_not_a_directory";
123

    
124
        public InstallerNoDirectoryException(File file) {
125
            super(message, KEY, serialVersionUID);
126
            setValue("directory", file.toString());
127
        }
128

    
129
    }
130

    
131
    public class InstallerFileNotFoundException extends
132
            InstallPackageServiceException {
133

    
134
        private static final long serialVersionUID = 556517830330132149L;
135

    
136
        private static final String message = "File '%(file)s' not found";
137

    
138
        private static final String KEY = "_file_XfileX_not_found";
139

    
140
        public InstallerFileNotFoundException(File file) {
141
            super(message, KEY, serialVersionUID);
142
            setValue("file", file.toString());
143
        }
144

    
145
    }
146

    
147
    public class InstallerBundleNotFoundException extends
148
            InstallPackageServiceException {
149

    
150
        private static final long serialVersionUID = 5065410511582625301L;
151

    
152
        private static final String message = "File '%(file)s' not found";
153

    
154
        private static final String KEY = "_file_XfileX_not_found";
155

    
156
        public InstallerBundleNotFoundException(File file,
157
                FileNotFoundException e) {
158
            super(message, e, KEY, serialVersionUID);
159
            setValue("file", file.toString());
160
        }
161

    
162
    }
163

    
164
    public class InstallerIOException extends InstallPackageServiceException {
165

    
166
        private static final long serialVersionUID = 3153613550157712363L;
167

    
168
        private static final String message = "IO error installing the file '%(file)s'";
169

    
170
        private static final String KEY = "_IO_error installing_file_XfileX_";
171

    
172
        public InstallerIOException(File file, IOException e) {
173
            super(message, e, KEY, serialVersionUID);
174
            setValue("file", file.toString());
175
        }
176

    
177
    }
178

    
179
    public class InstallerFileDownloadException extends
180
            InstallPackageServiceException {
181

    
182
        private static final long serialVersionUID = 8640183295766490512L;
183

    
184
        private static final String message = "File '%(url)s' download error";
185

    
186
        private static final String KEY = "_File_XurlX_download_error";
187

    
188
        public InstallerFileDownloadException(URL url, IOException e) {
189
            super(message, e, KEY, serialVersionUID);
190
            setValue("url", url.toString());
191
        }
192

    
193
    }
194

    
195
    public class InstallerPackageNotFoundException extends
196
            InstallPackageServiceException {
197

    
198
        private static final long serialVersionUID = 1726608498886963868L;
199

    
200
        private static final String message = "Package not found";
201

    
202
        private static final String KEY = "_package_not_found";
203

    
204
        public InstallerPackageNotFoundException() {
205
            super(message, KEY, serialVersionUID);
206
        }
207

    
208
    }
209

    
210
    public class InstallerNoPackageException extends
211
            InstallPackageServiceException {
212

    
213
        private static final long serialVersionUID = -2292735515704746966L;
214

    
215
        private static final String message = "Package does not exist";
216

    
217
        private static final String KEY = "_package__does_not_exist";
218

    
219
        public InstallerNoPackageException() {
220
            super(message, KEY, serialVersionUID);
221
        }
222

    
223
    }
224

    
225
    public class InstallerProviderCreationException extends
226
            InstallPackageServiceException {
227

    
228
        private static final long serialVersionUID = -7985786807492393584L;
229

    
230
        private static final String message = "Error creating the provider";
231

    
232
        private static final String KEY = "_Error_creating_the_provider";
233

    
234
        public InstallerProviderCreationException(ServiceException e) {
235
            super(message, e, KEY, serialVersionUID);
236
        }
237

    
238
    }
239

    
240
    public void installPackage(File applicationDirectory,
241
            PackageInfo packageInfo) throws InstallPackageServiceException {
242
        if (!applicationDirectory.exists()) {
243
            LOG.warn("Can install package '" + packageInfo.getCode() + "', application folder '" + applicationDirectory.toString() + "' does not exits.");
244
            throw new InstallerApplicationDirectoryNotFoundException(
245
                    applicationDirectory);
246
        }
247
        if (!packageInfoFileMap.containsKey(packageInfo)) {
248
            LOG.warn("Can install package '" + packageInfo.getCode() + "', package not found.");
249
            throw new InstallerPackageNotFoundException();
250
        }
251

    
252
        InstallPackageProvider installerExecutionProvider = createProvider(packageInfo);
253

    
254
        // Get the package or package set file
255
        File file = packageInfoFileMap.get(packageInfo);
256
        if (file == null) {
257
            if (packageInfo.getDownloadURL() == null) {
258
                throw new InstallerPackageNotFoundException();
259
            }
260
            this.downloadPackage(packageInfo);
261
            file = packageInfoFileMap.get(packageInfo);
262
        }
263

    
264
        // Open and install the package or package set file
265
        try {
266

    
267
            InputStream packageStream;
268
            InputStream fis = new FileInputStream(file);
269
            InputStream bis = new BufferedInputStream(fis);
270
            if (isPackage(file)) {
271
                packageStream = bis;
272
            } else {
273
                if (!isPackageSet(file)) {
274
                    LOG.info("Trying to install a package file ({0}) "
275
                            + "without a known file extension. Will try "
276
                            + "to install it as a package set", file);
277
                }
278
                packageStream = installerProviderServices.searchPackage(bis,
279
                        zipEntriesMap.get(packageInfo));
280
            }
281

    
282
            try {
283
                installerExecutionProvider.install(applicationDirectory,
284
                        packageStream, packageInfo);
285
            } catch (InstallPackageServiceException e) {
286

    
287
                packageStream.close();
288
                if (bis != packageStream) {
289
                    bis.close();
290
                }
291
                fis.close();
292

    
293
                // if fails the installation, zip files need to be reopen
294
                // the package will be installed into the update folder for
295
                // installation after a gvSIG restart
296
                fis = new FileInputStream(file);
297
                bis = new BufferedInputStream(fis);
298
                if (isPackage(file)) {
299
                    packageStream = bis;
300
                } else {
301
                    if (!isPackageSet(file)) {
302
                        LOG.info("Trying to install a package file ({0}) "
303
                                + "without a known file extension. Will try "
304
                                + "to install it as a package set", file);
305
                    }
306
                    packageStream = installerProviderServices.searchPackage(
307
                            bis, zipEntriesMap.get(packageInfo));
308
                }
309
                installerExecutionProvider.installLater(applicationDirectory,
310
                        packageStream, packageInfo);
311
            }
312

    
313
            packageStream.close();
314
            if (bis != packageStream) {
315
                bis.close();
316
            }
317
            fis.close();
318

    
319
        } catch (FileNotFoundException e) {
320
            throw new InstallerFileNotFoundException(file);
321
        } catch (IOException e) {
322
            throw new InstallerIOException(file, e);
323
        }
324

    
325
    }
326

    
327
    public void installPackage(File applicationDirectory, String packageCode)
328
            throws InstallPackageServiceException {
329
        PackageInfo packageInfo = getPackageInfo(packageCode);
330
        if (packageInfo == null) {
331
            throw new InstallerNoPackageException();
332
        }
333
        installPackage(applicationDirectory, packageInfo);
334
    }
335

    
336
    private InstallPackageProvider createProvider(PackageInfo packageInfo)
337
            throws InstallPackageServiceException {
338
        InstallerProviderManager installerProviderManager = (InstallerProviderManager) ((DefaultInstallerManager) manager)
339
                .getProviderManager();
340

    
341
        try {
342
            return installerProviderManager.createExecutionProvider(packageInfo
343
                    .getType());
344
        } catch (ServiceException e) {
345
            throw new InstallerProviderCreationException(e);
346
        }
347
    }
348

    
349
    public PackageInfo getPackageInfo(int index) {
350
        if (index >= packageInfos.size()) {
351
            return null;
352
        }
353
        return packageInfos.get(index);
354
    }
355

    
356
    public PackageInfo getPackageInfo(String packageCode) {
357
        for (int i = 0; i < getPackageCount(); i++) {
358
            if (packageInfos.get(i).getCode().equals(packageCode)) {
359
                return packageInfos.get(i);
360
            }
361
        }
362
        return null;
363
    }
364

    
365
    @Override
366
    public void addBundle(File bundle, SimpleTaskStatus taskStatus) throws InstallPackageServiceException {
367

    
368
        if (!bundle.exists()) {
369
            throw new InstallPackageServiceException();
370
        }
371

    
372
        int packageInfoCount = packageInfos.size();
373

    
374
        FileInputStream fis;
375
        try {
376
            fis = new FileInputStream(bundle);
377
        } catch (FileNotFoundException e) {
378
            throw new InstallerBundleNotFoundException(bundle, e);
379
        }
380
        BufferedInputStream bis = new BufferedInputStream(fis);
381
        if (isPackage(bundle)) {
382
            installerProviderServices.readPackageInfo(bis, packageInfos,
383
                    zipEntriesMap, bundle.getName(), taskStatus);
384
        } else {
385
            if (!isPackageSet(bundle)) {
386
                LOG
387
                        .info(
388
                                "Trying to add a package file ({0}) without a known "
389
                                + "file extension. Will try to add it as a package set",
390
                                bundle);
391
            }
392
            installerProviderServices.readPackageSetInfo(fis, packageInfos,
393
                    zipEntriesMap, taskStatus);
394
        }
395
        try {
396
            bis.close();
397
            fis.close();
398
        } catch (IOException e) {
399
            LOG.info("Error closing the input streams of the package file: "
400
                    + bundle, e);
401
        }
402

    
403
        for (int i = packageInfoCount; i < packageInfos.size(); i++) {
404
            packageInfoFileMap.put(packageInfos.get(i), bundle);
405
        }
406
    }
407

    
408
    private boolean isPackageSet(File file) {
409
        return file.getName().endsWith(
410
                manager.getDefaultPackageSetFileExtension());
411
    }
412

    
413
    private boolean isPackage(File file) {
414
        return file.getName()
415
                .endsWith(manager.getDefaultPackageFileExtension());
416
    }
417

    
418
    @Override
419
    public void addBundle(URL bundleURL, SimpleTaskStatus taskStatus) throws InstallPackageServiceException {
420
        File bundle;
421
        String urlString = bundleURL.toString();
422
        if (urlString.endsWith(InstallerManager.PACKAGE_EXTENSION) || urlString.endsWith(InstallerManager.PACKAGE_INDEX_EXTENSION)) {
423
            manager.setDownloadBaseURL(bundleURL);
424
            bundle = downloadFile(bundleURL, PACKAGE_FILE_NAME);
425
            addBundle(bundle,taskStatus);
426
        } else {
427
            if (!urlString.endsWith("/")) {
428
                urlString += "/";
429
            }
430

    
431
            Version version = manager.getVersionEx();
432
            urlString += ("dists/"
433
                    + version.getMayor() + "." + version.getMinor() + "."
434
                    + version.getRevision() + "/" + PACKAGE_FILE_NAME);
435

    
436
            URL completeURL;
437
            try {
438
                completeURL = new URL(urlString);
439
            } catch (MalformedURLException e) {
440
                // TODO Auto-generated catch block
441
                e.printStackTrace();
442
                return;
443
            }
444

    
445
            manager.setDownloadBaseURL(completeURL);
446
            bundle = downloadFile(completeURL, PACKAGE_FILE_NAME);
447
            addBundle(bundle,taskStatus);
448
        }
449

    
450
    }
451

    
452
    private File downloadFile(URL bundleURL, String defaultFileName)
453
            throws InstallPackageServiceException {
454
        try {
455
            Download download = new Download();
456
            return download.downloadFile(bundleURL, defaultFileName);
457
        } catch (IOException e) {
458
            throw new InstallerFileDownloadException(bundleURL, e);
459
        }
460
    }
461

    
462
    @Override
463
    public void addBundlesFromDirectory(File directory, SimpleTaskStatus taskStatus)
464
            throws InstallPackageServiceException {
465
        if (!directory.isDirectory()) {
466
            throw new InstallerNoDirectoryException(directory);
467
        }
468
        List<File> files = new ArrayList<File>();
469

    
470
        listRecursively(directory, new FileFilter() {
471

    
472
            private String packageExt = manager
473
                    .getDefaultPackageFileExtension();
474
            private String packageSetExt = manager
475
                    .getDefaultPackageSetFileExtension();
476

    
477
            public boolean accept(File file) {
478
                String name = file.getName().toLowerCase();
479
                return file.isDirectory() || name.endsWith(packageExt)
480
                        || name.endsWith(packageSetExt);
481
            }
482
        }, files);
483
        for (int i = 0; i < files.size(); i++) {
484
            if (files.get(i).isFile()) {
485
                addBundle(files.get(i),taskStatus);
486
            }
487
        }
488
    }
489

    
490
    private void listRecursively(File fileOrDir, FileFilter filter,
491
            List<File> files) {
492
        files.add(fileOrDir);
493

    
494
        if (fileOrDir.isDirectory()) {
495

    
496
            File[] dirContents = fileOrDir.listFiles(filter);
497

    
498
            for (File f : dirContents) {
499
                listRecursively(f, filter, files); // Recursively list.
500
            }
501
        } else {
502
            files.add(fileOrDir);
503
        }
504
    }
505

    
506
    public int getPackageCount() {
507
        if (packageInfos == null) {
508
            return 0;
509
        }
510
        return packageInfos.size();
511
    }
512

    
513
    public Manager getManager() {
514
        return this.manager;
515
    }
516

    
517
    public void downloadPackage(PackageInfo packageInfo)
518
            throws InstallPackageServiceException {
519
        this.downloadPackage(packageInfo, null);
520
    }
521

    
522
    public void downloadPackage(PackageInfo packageInfo,
523
            SimpleTaskStatus taskStatus) throws InstallPackageServiceException {
524

    
525
        File file = packageInfoFileMap.get(packageInfo);
526
        if (file == null) {
527
            try {
528
                file = packageInfo.downloadFile(taskStatus);
529
            } catch (BaseException e) {
530
                throw new InstallPackageServiceException(e);
531
            }
532
            this.packageInfoFileMap.put(packageInfo, file);
533
        }
534
    }
535

    
536
    public List<String> getDefaultSelectedPackagesIDs() {
537
        return installerProviderServices.getDefaultSelectedPackagesIDs();
538
    }
539

    
540
    @Override
541
    public Properties getProperties() {
542
        return installerProviderServices.getProperties();
543
    }
544

    
545
    public List<String> getCategories() {
546
        Set<String> categories = new HashSet<String>();
547

    
548
        for (int i = 0; i < packageInfos.size(); i++) {
549
            PackageInfo pkginfo = packageInfos.get(i);
550
            List<String> pkgcategories = pkginfo.getCategories();
551
            categories.addAll(pkgcategories);
552
        }
553
        try {
554
            PackageInfo[] pkgs = manager.getInstalledPackages();
555
            for (int i = 0; i < pkgs.length; i++) {
556
                PackageInfo pkginfo = pkgs[i];
557
                List<String> pkgcategories = pkginfo.getCategories();
558
                categories.addAll(pkgcategories);
559
            }
560

    
561
        } catch (MakePluginPackageServiceException e) {
562
            // Ignore exceptions
563
        }
564
        ArrayList<String> l = new ArrayList<String>(categories);
565
        Collections.sort(l);
566
        return l;
567
    }
568

    
569
    public List<String> getTypes() {
570
        Set<String> types = new HashSet<String>();
571

    
572
        for (int i = 0; i < packageInfos.size(); i++) {
573
            PackageInfo pkginfo = packageInfos.get(i);
574
            types.add(pkginfo.getType());
575
        }
576
        try {
577
            PackageInfo[] pkgs = manager.getInstalledPackages();
578
            for (int i = 0; i < pkgs.length; i++) {
579
                PackageInfo pkginfo = pkgs[i];
580
                types.add(pkginfo.getType());
581
            }
582

    
583
        } catch (MakePluginPackageServiceException e) {
584
            // Ignore exceptions
585
        }
586
        List<String> l = new ArrayList<>(types);
587
        Collections.sort(l);
588
        return l;
589
    }
590

    
591
    @Override
592
    public boolean needInstallPackageProviders() {
593
        boolean need = false;
594
        String ss = this.getProperties().getProperty("installers");
595
        if (ss != null) {
596
            String[] installerNames = StringUtils.split(ss);
597
            for (String installerName : installerNames) {
598
                InstallerProviderInstallers installer = new InstallerProviderInstallers(this, installerName);
599
                if( !installer.isAlreadyRegistered() ) {
600
                    need = true;
601
                    break;
602
                }
603
            }
604
        }
605
        return need;
606
    }
607

    
608
    @Override
609
    public void installPackageProviders(SimpleTaskStatus taskStatus) {
610
        Properties props = this.getProperties();
611
        String ss = props.getProperty("installers");
612
        if (ss == null) {
613
            return;
614
        }
615

    
616
        try {
617
            String[] installerNames = StringUtils.split(ss);
618
            taskStatus.setRangeOfValues(0, installerNames.length);
619
            int count=0;
620
            for (String installerName : installerNames) {
621
                taskStatus.message(installerName);
622
                taskStatus.setCurValue(count++);
623
                InstallerProviderInstallers installer = new InstallerProviderInstallers(this, installerName);
624
                installer.install();
625
            }
626
            taskStatus.setCurValue(count++);
627
        } finally {
628
            taskStatus.terminate();
629
        }
630
    }
631

    
632
}