/**
* OrbisGIS is a java GIS application dedicated to research in GIScience.
* OrbisGIS is developed by the GIS group of the DECIDE team of the
* Lab-STICC CNRS laboratory, see <http://www.lab-sticc.fr/>.
*
* The GIS group of the DECIDE team is located at :
*
* Laboratoire Lab-STICC – CNRS UMR 6285
* Equipe DECIDE
* UNIVERSITÉ DE BRETAGNE-SUD
* Institut Universitaire de Technologie de Vannes
* 8, Rue Montaigne - BP 561 56017 Vannes Cedex
*
* OrbisGIS is distributed under GPL 3 license.
*
* Copyright (C) 2007-2014 CNRS (IRSTV FR CNRS 2488)
* Copyright (C) 2015-2017 CNRS (Lab-STICC UMR CNRS 6285)
*
* This file is part of OrbisGIS.
*
* OrbisGIS is free software: you can redistribute it and/or modify it under the
* terms of the GNU General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later
* version.
*
* OrbisGIS is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with
* OrbisGIS. If not, see <http://www.gnu.org/licenses/>.
*
* For more information, please consult: <http://www.orbisgis.org/>
* or contact directly:
* info_at_ orbisgis.org
*/
package org.orbisgis.omanager.ui;
import java.awt.Component;
import java.awt.event.ActionListener;
import java.beans.EventHandler;
import java.util.concurrent.ExecutorService;
import javax.swing.*;
import org.orbisgis.commons.progress.SwingWorkerPM;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceReference;
import org.osgi.service.obr.RepositoryAdmin;
import org.osgi.service.obr.Requirement;
import org.osgi.service.obr.Resolver;
import org.osgi.service.obr.Resource;
import org.xnap.commons.i18n.I18n;
import org.xnap.commons.i18n.I18nFactory;
/**
* Download plug-in process.
* @author Nicolas Fortin
*/
public class ActionDeploy extends ActionBundle {
private static final I18n I18N = I18nFactory.getI18n(ActionDeploy.class);
private boolean start;
private Resource resource;
private BundleContext bundleContext;
private Component frame;
private ExecutorService executorService;
public ActionDeploy(String label, String toolTipText, boolean start, Resource resource, BundleContext bundleContext,
Component frame, Icon icon, boolean warnUser, ExecutorService executorService) {
super(label, toolTipText, icon, frame, warnUser);
this.start = start;
this.resource = resource;
this.bundleContext = bundleContext;
this.frame = frame;
this.executorService = executorService;
setActionListener(EventHandler.create(ActionListener.class, this, "doWork"));
}
private void deployBundle(Resolver resolver) {
long bytes = getSize(resource);
StringBuilder resourcesNames = new StringBuilder();
// If the bundle has dependencies, store the dependency name, version and size
Resource[] resources = resolver.getRequiredResources();
StringBuilder dependencyStr = new StringBuilder();
if ((resources != null) && (resources.length > 0)) {
for (Resource dependency : resources) {
dependencyStr.append(dependency.getPresentationName());
dependencyStr.append(" (");
dependencyStr.append(dependency.getVersion());
dependencyStr.append(")\n");
bytes += getSize(dependency);
}
}
// If the bundle has optional dependencies, store the dependency name, version and size
resources = resolver.getOptionalResources();
if ((resources != null) && (resources.length > 0)) {
for (Resource dependency : resources) {
bytes += getSize(dependency);
dependencyStr.append("Optional, ");
dependencyStr.append(dependency.getPresentationName());
dependencyStr.append(" (");
dependencyStr.append(dependency.getVersion());
dependencyStr.append(")\n");
}
}
// If there is hidden dependency (needed & optional)
// Ask user for validating additional download
boolean deployBundle = true;
if(dependencyStr.length() != 0) {
if (dependencyStr.length() > 0) {
resourcesNames.insert(0, ") ?\n");
resourcesNames.insert(0, BundleItem.getHumanReadableBytes(bytes));
resourcesNames.insert(0, "Do you want to download the following dependencies (Size : ");
}
if (DependencyMessageDialog.showModal(SwingUtilities.getWindowAncestor(frame),
I18N.tr("Dependencies downloading"), resourcesNames.toString(), dependencyStr.toString())
.equals(DependencyMessageDialog.CHOICE.CANCEL)) {
deployBundle = false;
}
}
if(deployBundle){
DeployBundleSwingWorker worker = new DeployBundleSwingWorker(resolver);
if(executorService != null){
executorService.execute(worker);
}
else{
worker.execute();
}
}
}
/**
* Called by user on action launch.
*/
public void doWork() {
ServiceReference<RepositoryAdmin> repositoryAdminServiceReference = bundleContext.getServiceReference(RepositoryAdmin.class);
if(repositoryAdminServiceReference==null) {
LOGGER.error(I18N.tr("OSGi repository service is not available"));
return;
}
RepositoryAdmin repositoryAdmin = bundleContext.getService(repositoryAdminServiceReference);
if(repositoryAdmin==null) {
LOGGER.error(I18N.tr("OSGi repository service is not available"));
return;
}
try {
// Specify the bundle reference to the dependency resolver
// Resolver class is able to fetch cached repositories and
// fetch dependencies for one or more bundles.
Resolver resolver = repositoryAdmin.resolver();
resolver.add(resource);
if ((resolver.getAddedResources() != null) &&
(resolver.getAddedResources().length > 0)) {
// Find dependencies
if (resolver.resolve()) {
// OSGi Bundle Repository is able to deploy this bundle
deployBundle(resolver);
} else {
// Some dependency is missing
// OSGi Bundle Repository is not able to deploy this bundle
// Log missing packages
Requirement[] requirements = resolver.getUnsatisfiedRequirements();
if ((requirements != null) && (requirements.length > 0)) {
StringBuilder sb = new StringBuilder();
sb.append(I18N.trn("Unsatisfied requirement :\n","Unsatisfied requirements :\n",requirements.length+1));
for (Requirement requirement : requirements) {
sb.append("\t");
sb.append(requirement.getFilter());
sb.append("\n");
for (Resource resource : resolver.getResources(requirement)) {
sb.append("\t");
sb.append(resource.getPresentationName());
sb.append(" (");
sb.append(resource.getVersion());
sb.append(")\n");
}
}
LOGGER.error(sb.toString());
} else {
LOGGER.error(I18N.tr("Could not resolve plugin dependencies for an unknown reason"));
}
}
}
} catch(Exception ex) {
LOGGER.error(ex.getLocalizedMessage(),ex);
} finally {
bundleContext.ungetService(repositoryAdminServiceReference);
}
}
private long getSize(Resource resource) {
Object depSize = resource.getProperties().get(Resource.SIZE);
if(depSize instanceof Long) {
return(Long) depSize;
} else {
return 0L;
}
}
private class DeployBundleSwingWorker extends SwingWorkerPM {
private Resolver resolver;
public DeployBundleSwingWorker(Resolver resolver){
this.resolver = resolver;
}
@Override
protected Object doInBackground() throws Exception {
setTaskName(I18N.tr("Downloading and installing dependencies"));
try {
// Download the bundle and dependencies
resolver.deploy(start);
} catch (IllegalStateException ex) {
LOGGER.error(ex.getLocalizedMessage(),ex);
}
return null;
}
}
}