/*
* This program is free software; you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License, version 2.1 as published by the Free Software
* Foundation.
*
* You should have received a copy of the GNU Lesser General Public License along with this
* program; if not, you can obtain a copy at http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html
* or from the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* This program 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 Lesser General Public License for more details.
*
* Copyright (c) 2015 Pentaho Corporation. All rights reserved.
*/
package org.pentaho.marketplace.domain.services;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.karaf.features.Feature;
import org.apache.karaf.features.FeaturesService;
import org.apache.karaf.kar.KarService;
import org.apache.commons.io.FileUtils;
import org.osgi.service.cm.Configuration;
import org.osgi.service.cm.ConfigurationAdmin;
import org.pentaho.marketplace.domain.model.entities.interfaces.IDomainStatusMessage;
import org.pentaho.marketplace.domain.model.entities.interfaces.IPlugin;
import org.pentaho.marketplace.domain.model.entities.interfaces.IPluginVersion;
import org.pentaho.marketplace.domain.model.entities.interfaces.IVersionData;
import org.pentaho.marketplace.domain.model.factories.interfaces.IDomainStatusMessageFactory;
import org.pentaho.marketplace.domain.model.factories.interfaces.IPluginVersionFactory;
import org.pentaho.marketplace.domain.model.factories.interfaces.IVersionDataFactory;
import org.pentaho.marketplace.domain.services.interfaces.IPluginProvider;
import org.pentaho.marketplace.domain.services.interfaces.IPluginService;
import org.pentaho.marketplace.domain.services.interfaces.IRemotePluginProvider;
import org.pentaho.telemetry.ITelemetryService;
import org.pentaho.telemetry.TelemetryEvent;
import java.io.File;
import java.io.IOException;
import java.net.URI;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Dictionary;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
public abstract class BasePluginService implements IPluginService {
//region Inner Definitions
protected static class MarketplaceSecurityException extends Exception {
private static final long serialVersionUID = -1852471739131561628L;
}
//endregion
//region Constants
// Error messages codes should begin with ERROR
protected static final String UNAUTHORIZED_ACCESS_MESSAGE = "Unauthorized Access.";
protected static final String UNAUTHORIZED_ACCESS_ERROR_CODE = "ERROR_0002_UNAUTHORIZED_ACCESS";
protected static final String NO_PLUGIN_ERROR_CODE = "ERROR_0001_NO_PLUGIN";
protected static final String FAIL_ERROR_CODE = "ERROR_0003_FAIL";
protected static final String PLUGIN_INSTALLED_CODE = "PLUGIN_INSTALLED";
protected static final String PLUGIN_UNINSTALLED_CODE = "PLUGIN_UNINSTALLED";
protected static final String KARAF_FEATURES_CONFIG_PID = "org.apache.karaf.features";
protected static final String KARAF_FEATURES_BOOT_PROPERTY_ID = "featuresBoot";
protected static final String PENTAHO_FEATURES_CONFIG_PID = "org.pentaho.features";
protected static final String PENTAHO_RUNTIME_FEATURES_PROPERTY_ID = "runtimeFeatures";
//endregion
//region Properties
//region logger
protected Log getLogger() {
return this.logger;
}
protected Log logger = LogFactory.getLog( this.getClass() );
//endregion
//region metadataPluginsProvider
public IPluginProvider getMetadataPluginsProvider() {
return this.metadataPluginsProvider;
}
protected BasePluginService setMetadataPluginsProvider( IPluginProvider provider ) {
this.metadataPluginsProvider = provider;
return this;
}
private IPluginProvider metadataPluginsProvider;
//endregion
//region versionDataFactory
public IVersionDataFactory getVersionDataFactory() {
return this.versionDataFactory;
}
protected void setVersionDataFactory(
IVersionDataFactory versionDataFactory ) {
this.versionDataFactory = versionDataFactory;
}
private IVersionDataFactory versionDataFactory;
//endregion
//region pluginVersionFactory
public IPluginVersionFactory getPluginVersionFactory() {
return pluginVersionFactory;
}
protected void setPluginVersionFactory( IPluginVersionFactory pluginVersionFactory ) {
this.pluginVersionFactory = pluginVersionFactory;
}
private IPluginVersionFactory pluginVersionFactory;
//endregion
//region karService
public KarService getKarService() {
return this.karService;
}
protected void setKarService( KarService karService ) {
this.karService = karService;
}
private KarService karService;
//endregion karService
//region featureService
public FeaturesService getFeaturesService() {
return this.featuresService;
}
protected void setFeaturesService( FeaturesService featuresService ) {
this.featuresService = featuresService;
}
private FeaturesService featuresService;
//endregion
//region telemetryService
public ITelemetryService getTelemetryService() {
return this.telemetryService;
}
protected void setTelemetryService( ITelemetryService telemetryService ) {
this.telemetryService = telemetryService;
}
private ITelemetryService telemetryService;
//endregion
//region getDomainStatusMessageFactory
public IDomainStatusMessageFactory getDomainStatusMessageFactory() {
return this.domainStatusMessageFactory;
}
protected BasePluginService setDomainStatusMessageFactory( IDomainStatusMessageFactory domainStatusMessageFactory ) {
this.domainStatusMessageFactory = domainStatusMessageFactory;
return this;
}
private IDomainStatusMessageFactory domainStatusMessageFactory;
//endregion
//region serverVersion
protected String getServerVersion() {
return this.serverVersion;
}
protected BasePluginService setServerVersion( String serverVersion ) {
this.serverVersion = serverVersion;
return this;
}
private String serverVersion;
//endregion
protected ConfigurationAdmin getConfigurationAdmin() {
return this.configurationAdmin;
}
protected BasePluginService setConfigurationAdmin( ConfigurationAdmin configurationAdmin ) {
this.configurationAdmin = configurationAdmin;
return this;
}
private ConfigurationAdmin configurationAdmin;
//endregion
//region Constructors
protected BasePluginService( IRemotePluginProvider metadataPluginsProvider,
IVersionDataFactory versionDataFactory,
IPluginVersionFactory pluginVersionFactory,
KarService karService,
FeaturesService featuresService,
ConfigurationAdmin configurationAdmin,
ITelemetryService telemetryService,
IDomainStatusMessageFactory domainStatusMessageFactory
) {
//initialize dependencies
this.setMetadataPluginsProvider( metadataPluginsProvider );
this.setVersionDataFactory( versionDataFactory );
this.setPluginVersionFactory( pluginVersionFactory );
this.setKarService( karService );
this.setFeaturesService( featuresService );
this.setConfigurationAdmin( configurationAdmin );
this.setTelemetryService( telemetryService );
this.setDomainStatusMessageFactory( domainStatusMessageFactory );
}
//endregion
//region Methods
private boolean withinParentVersion( IPluginVersion pv ) {
// need to compare plugin version min and max parent with system version.
// replace the version of the xml url path with the current release version:
String v = this.getServerVersion();
IVersionData pvMax = this.getVersionDataFactory().create( pv.getMaxParentVersion() );
IVersionData pvMin = this.getVersionDataFactory().create( pv.getMinParentVersion() );
IVersionData version = this.getVersionDataFactory().create( v );
return version.within( pvMin, pvMax );
}
private Collection<IPluginVersion> getCompatibleVersionsWithParent( Iterable<IPluginVersion> versions ) {
Collection<IPluginVersion> compatibleVersions = new ArrayList<>();
for ( IPluginVersion version : versions ) {
if ( withinParentVersion( version ) ) {
compatibleVersions.add( version );
}
}
return compatibleVersions;
}
/**
* Filters out plugins without a compatible version to server. Removes non compatible versions for the plugins which
* pass the filter.
*/
private Map<String, IPlugin> removeNonCompatibleVersions( Iterable<IPlugin> plugins ) {
Map<String, IPlugin> pluginsWithCompatibleVersions = new HashMap<>();
for ( IPlugin plugin : plugins ) {
// filter out plugin versions that are not compatible with parent version
Collection<IPluginVersion> compatibleVersions = this.getCompatibleVersionsWithParent( plugin.getVersions() );
// only include plugins that have versions within this release
if ( compatibleVersions.size() > 0 ) {
// change available version to only compatible ones
plugin.setVersions( compatibleVersions );
pluginsWithCompatibleVersions.put( plugin.getId(), plugin );
}
}
return pluginsWithCompatibleVersions;
}
private boolean isPluginIdValid( String pluginId ) {
return pluginId != null
&& pluginId.length() > 0
// this checks to make sure the plugin metadata isn't attempting to overwrite a folder on the system.
// TODO: Test a .. encoded in UTF8, etc to see if there is a way to thwart this check
&& pluginId.indexOf( "." ) < 0;
}
public IPlugin getPlugin( String id ) {
return this.getPlugins().get( id );
}
// TODO: only allows one version per branch
public IPluginVersion getPluginVersion( IPlugin plugin, String versionBranch ) {
if ( versionBranch != null && versionBranch.length() > 0 ) {
return plugin.getVersionByBranch( versionBranch );
}
return null;
}
/**
* Filters plugins by plugin id
*/
private Map<String, IPlugin> filterPlugins( Map<String, IPlugin> plugins, Collection<String> pluginIds ) {
if ( pluginIds.size() < 1 ) {
return Collections.emptyMap();
}
Map<String, IPlugin> filteredPlugins = new HashMap<>();
for ( String pluginId : pluginIds ) {
IPlugin plugin = plugins.get( pluginId );
if ( plugin != null ) {
filteredPlugins.put( pluginId, plugin );
}
}
return filteredPlugins;
}
/**
* Sets plugins as installed as well as the installed version
*
* @param plugins the plugins to be marked as installed
*/
private void setPluginsAsInstalled( Collection<IPlugin> plugins ) {
for ( IPlugin plugin : plugins ) {
plugin.setInstalled( true );
IPluginVersion installedVersion = getInstalledPluginVersion( plugin );
if ( installedVersion != null ) {
plugin.setInstalledBranch( installedVersion.getBranch() );
plugin.setInstalledVersion( installedVersion.getVersion() );
plugin.setInstalledBuildId( installedVersion.getBuildId() );
}
}
}
private void publishTelemetryEvent( TelemetryEvent.Type eventType, IPlugin plugin, IPluginVersion version ) {
try {
ITelemetryService telemetryService = this.getTelemetryService();
TelemetryEvent event = telemetryService.createEvent( eventType );
event.getExtraInfo().put( "installedPlugin", plugin.getId() );
event.getExtraInfo().put( "installedBranch", version.getBranch() );
event.getExtraInfo().put( "installedVersion", version.getVersion() );
telemetryService.publishEvent( event );
} catch ( NoClassDefFoundError e ) {
this.getLogger().debug( "Failed to find class definitions. Most likely reason is reinstalling marketplace.", e );
}
}
private IDomainStatusMessage upgradePluginAux( String pluginId, String versionBranch ) {
if ( !hasMarketplacePermission() ) {
return this.getDomainStatusMessageFactory()
.create( UNAUTHORIZED_ACCESS_ERROR_CODE, UNAUTHORIZED_ACCESS_MESSAGE );
}
if ( !isPluginIdValid( pluginId ) ) {
return this.getDomainStatusMessageFactory()
.create( NO_PLUGIN_ERROR_CODE, "Invalid plugin id" );
}
IPlugin plugin = this.getPlugin( pluginId );
if ( plugin == null ) {
return this.getDomainStatusMessageFactory()
.create( NO_PLUGIN_ERROR_CODE, "Plugin not found" );
}
IPluginVersion pluginVersionToInstall = plugin.getVersionByBranch( versionBranch );
if ( pluginVersionToInstall == null ) {
return this.getDomainStatusMessageFactory()
.create( NO_PLUGIN_ERROR_CODE, "Plugin version for branch " + versionBranch + " not found" );
}
// Perhaps we are reinstalling the marketplace.
// Create telemetry event and messages before closing class loader just in case.
ITelemetryService telemetryService = this.getTelemetryService();
TelemetryEvent event = telemetryService.createEvent( TelemetryEvent.Type.UPGRADE );
event.getExtraInfo().put( "installedPlugin", plugin.getId() );
event.getExtraInfo().put( "installedVersion", pluginVersionToInstall.getVersion() );
event.getExtraInfo().put( "installedBranch", versionBranch );
IDomainStatusMessage successMessage =
this.domainStatusMessageFactory.create( PLUGIN_INSTALLED_CODE, plugin.getName()
+ " was successfully Upgraded. Please restart. \n" + plugin.getInstallationNotes() );
IDomainStatusMessage upgradeInstallFailureMessage = this.domainStatusMessageFactory
.create(FAIL_ERROR_CODE, "Failed to install on plugin upgrade, see log for details.");
IDomainStatusMessage upgradeUninstallFailureMessage = this.domainStatusMessageFactory
.create(FAIL_ERROR_CODE, "Failed to uninstall on plugin upgrade, see log for details.");
// it's an upgrade, uninstall old version first
if ( !this.executeUninstall(plugin) ) {
return upgradeUninstallFailureMessage;
}
// install new version
if ( !this.executeInstall( plugin, pluginVersionToInstall ) ) {
return upgradeInstallFailureMessage;
}
try {
telemetryService.publishEvent( event );
} catch ( NoClassDefFoundError e ) {
this.getLogger().debug( "Failed to find class definitions. Most likely reason is reinstalling marketplace.", e );
}
return successMessage;
}
private IDomainStatusMessage installPluginAux( String pluginId, String versionBranch )
throws MarketplaceSecurityException {
if ( !hasMarketplacePermission() ) {
throw new MarketplaceSecurityException();
}
if ( !isPluginIdValid( pluginId ) ) {
return this.domainStatusMessageFactory.create( NO_PLUGIN_ERROR_CODE, "Invalid Plugin Id." );
}
IPlugin toInstall = this.getPlugin( pluginId );
if ( toInstall == null ) {
return this.domainStatusMessageFactory.create( NO_PLUGIN_ERROR_CODE, "Plugin Not Found" );
}
IPluginVersion versionToInstall = null;
if ( versionBranch != null && versionBranch.length() > 0 ) {
versionToInstall = toInstall.getVersionByBranch( versionBranch );
if ( versionToInstall == null ) {
return this.domainStatusMessageFactory.create( NO_PLUGIN_ERROR_CODE, "Plugin version not found" );
}
} else {
return this.domainStatusMessageFactory
.create( FAIL_ERROR_CODE, "Version " + versionBranch + " not found for plugin " + pluginId
+ ", see log for details." );
}
// Perhaps we are reinstalling the marketplace.
// Create telemetry event and messages before closing class loader just in case.
ITelemetryService telemetryService = this.getTelemetryService();
TelemetryEvent event = telemetryService.createEvent( TelemetryEvent.Type.INSTALLATION );
event.getExtraInfo().put( "installedPlugin", toInstall.getId() );
event.getExtraInfo().put( "installedVersion", versionToInstall.getVersion() );
event.getExtraInfo().put( "installedBranch", versionBranch );
IDomainStatusMessage successMessage =
this.domainStatusMessageFactory.create( PLUGIN_INSTALLED_CODE, toInstall.getName()
+ " was successfully installed. Please restart your BI Server. \n" + toInstall.getInstallationNotes() );
IDomainStatusMessage failureMessage = this.domainStatusMessageFactory
.create( FAIL_ERROR_CODE, "Failed to execute install, see log for details." );
if ( !this.executeInstall( toInstall, versionToInstall ) ) {
return failureMessage;
}
try {
telemetryService.publishEvent( event );
} catch ( NoClassDefFoundError e ) {
this.getLogger().debug( "Failed to find class definitions. Most likely reason is reinstalling marketplace.", e );
}
return successMessage;
}
private IDomainStatusMessage uninstallPluginAux( String pluginId ) throws MarketplaceSecurityException {
if ( !hasMarketplacePermission() ) {
throw new MarketplaceSecurityException();
}
IPlugin toUninstall = this.getPlugin( pluginId );
if ( toUninstall == null ) {
return this.domainStatusMessageFactory.create( NO_PLUGIN_ERROR_CODE, "Plugin Not Found" );
}
// Perhaps we are uninstalling the marketplace.
// Create telemetry event and messages before closing class loader just in case.
ITelemetryService telemetryService = this.getTelemetryService();
TelemetryEvent event = telemetryService.createEvent( TelemetryEvent.Type.INSTALLATION );
event.getExtraInfo().put( "uninstalledPlugin", toUninstall.getId() );
event.getExtraInfo().put( "uninstalledPluginVersion", toUninstall.getInstalledVersion() );
event.getExtraInfo().put( "uninstalledPluginBranch", toUninstall.getInstalledBranch() );
IDomainStatusMessage successMessage =
this.domainStatusMessageFactory.create( PLUGIN_UNINSTALLED_CODE, toUninstall.getName()
+ " was successfully uninstalled. Please restart your BI Server." );
IDomainStatusMessage failureMessage = this.domainStatusMessageFactory
.create( FAIL_ERROR_CODE, "Failed to execute uninstall, see log for details." );
if ( !this.executeUninstall( toUninstall ) ) {
return failureMessage;
}
try {
telemetryService.publishEvent( event );
} catch ( NoClassDefFoundError e ) {
this.getLogger().debug( "Failed to find class definitions. Most likely reason is uninstalling marketplace.", e );
}
return successMessage;
}
//endregion
//region IPluginService implementation
@Override public Map<String, IPlugin> getPlugins() {
Map<String, IPlugin> marketplacePlugins = this.getMetadataPluginsProvider().getPlugins();
Map<String, IPlugin> compatiblePlugins = this.removeNonCompatibleVersions( marketplacePlugins.values() );
Collection<String> installedPluginIds = getInstalledPluginIds();
Map<String, IPlugin> installedPlugins = this.filterPlugins( compatiblePlugins, installedPluginIds );
this.setPluginsAsInstalled( installedPlugins.values() );
return compatiblePlugins;
}
@Override
public IDomainStatusMessage installPlugin( String pluginId, String versionBranch ) {
try {
IPlugin plugin = this.getPlugin( pluginId );
if ( plugin != null && plugin.isInstalled() ) {
return this.upgradePluginAux( pluginId, versionBranch );
} else {
return this.installPluginAux( pluginId, versionBranch );
}
} catch ( MarketplaceSecurityException e ) {
this.getLogger().debug( e.getMessage(), e );
return this.domainStatusMessageFactory.create( UNAUTHORIZED_ACCESS_ERROR_CODE, UNAUTHORIZED_ACCESS_MESSAGE );
}
}
@Override
public IDomainStatusMessage uninstallPlugin( String pluginId ) {
try {
return uninstallPluginAux( pluginId );
} catch ( MarketplaceSecurityException e ) {
this.getLogger().debug( e.getMessage(), e );
return this.domainStatusMessageFactory.create( UNAUTHORIZED_ACCESS_ERROR_CODE, UNAUTHORIZED_ACCESS_MESSAGE );
}
}
//endregion
protected boolean executeOsgiInstallViaKarService( IPlugin plugin, IPluginVersion versionToInstall ) {
if ( versionToInstall.isOsgi() ) {
this.getLogger().debug( "## Install Osgi Plugin ##" );
try {
URI uri = new URL( versionToInstall.getDownloadUrl() ).toURI();
this.getKarService().install( uri );
// TODO: check if it was successful or not
return true;
} catch ( Exception e ) {
this.getLogger().warn( "Failed to install OSGi plugin.", e );
return false;
}
}
return false;
}
private String getKarafDeployFolder() {
//TODO: hardcoded deploy folder. Check for better alternative
return System.getProperty( "karaf.base" ) + File.separator + "deploy";
}
protected boolean executeOsgiInstall( IPlugin plugin, IPluginVersion versionToInstall ) {
if ( versionToInstall.isOsgi() ) {
this.getLogger().debug( "Installing Osgi Plugin " + plugin.getId() );
try {
String deployFolderName = this.getKarafDeployFolder();
String downloadUrl = versionToInstall.getDownloadUrl();
//String karName = FilenameUtils.getName( downloadUrl );
File dlKarFile = new File( deployFolderName + File.separator + plugin.getId() + ".kar" );
FileUtils.copyURLToFile( new URL( downloadUrl ), dlKarFile );
// TODO: check if it was successful or not
return true;
} catch ( Exception e ) {
this.getLogger().warn( "Failed to install OSGi plugin " + plugin.getId(), e );
return false;
}
}
return false;
}
protected boolean executeOsgiUninstallViaKarService( IPlugin plugin ) {
this.getLogger().debug( "Uninstalling Osgi Plugin " + plugin.getId() );
try {
this.getKarService().uninstall( plugin.getId() );
// TODO: check if it was successful or not
return true;
} catch ( Exception e ) {
this.getLogger().warn( "Failed to uninstall OSGi plugin " + plugin.getId(), e );
return false;
}
}
protected boolean executeOsgiUninstall( IPlugin plugin ) {
String pluginId = plugin.getId();
this.removeFeatureFromKarafBoot( pluginId );
try {
this.getFeaturesService().uninstallFeature( pluginId );
} catch ( Exception e ) {
this.getLogger().debug( "No installed feature found with name " + pluginId + " when uninstalling OSGI plugin." );
}
// remove KAR file from deploy folder if it exists
String deployFolder = this.getKarafDeployFolder();
File karFile = new File( deployFolder + File.separator + pluginId + ".kar" );
if( karFile.exists() && karFile.isFile() ) {
return FileUtils.deleteQuietly( karFile );
}
return true;
}
private void removeFeatureFromKarafBoot( String featureName ) {
this.removeFeatureFromKarafBoot( featureName, KARAF_FEATURES_CONFIG_PID, KARAF_FEATURES_BOOT_PROPERTY_ID );
this.removeFeatureFromKarafBoot( featureName, PENTAHO_FEATURES_CONFIG_PID, PENTAHO_RUNTIME_FEATURES_PROPERTY_ID );
}
private void removeFeatureFromKarafBoot( String featureName, String configurationPid, String propertyId ) {
ConfigurationAdmin configurationAdmin = this.getConfigurationAdmin();
Log logger = this.getLogger();
try {
Configuration configuration = configurationAdmin.getConfiguration( configurationPid );
Dictionary<String, Object> properties = configuration.getProperties();
if( properties == null ) {
logger.debug( "Configuration " + configurationPid + " has no properties." );
return;
}
String propertyValue = (String) properties.get( propertyId );
if( propertyValue == null ) {
logger.debug( "Property " + propertyId + " not set in configuration " + configurationPid + "." );
return;
}
String newPropertyValue = propertyValue.replaceFirst("," + featureName, "");
if( !propertyValue.equals( newPropertyValue ) ) {
properties.put( propertyId, newPropertyValue );
configuration.update( properties );
}
} catch ( IOException e ) {
logger.debug( "Unable to access configuration " + configurationPid + "." );
}
}
private IPluginVersion getInstalledOsgiPluginVersion( IPlugin plugin ) {
this.getLogger().debug( "Infer Version from installed Osgi Plugin" );
// search installed features for plugin id
IPluginVersion installedOsgiPluginVersion = this.getInstalledOsgiPluginVersionFromFeatures( plugin );
if( installedOsgiPluginVersion == null ) {
// If no feature with the plugin id is found, check installed KARs
installedOsgiPluginVersion = this.getInstalledOsgiPluginVersionFromKars( plugin );
}
return installedOsgiPluginVersion;
}
private IPluginVersion getInstalledOsgiPluginVersionFromKars( IPlugin plugin ) {
try {
if ( this.getKarService().list().contains( plugin.getId() ) ) {
IPluginVersion installedPluginVersion = this.getPluginVersionFactory().create();
installedPluginVersion.setIsOsgi( true );
// TODO: add branch / version / buildId information that currently is not available
return installedPluginVersion;
}
} catch ( Exception e ) {
return null;
}
return null;
}
private IPluginVersion getInstalledOsgiPluginVersionFromFeatures( IPlugin plugin ) {
this.getLogger().debug( "## Infer Version from Karaf features ##" );
try {
String pluginId = plugin.getId();
Feature feature = this.getFeaturesService().getFeature( pluginId );
if ( feature != null ) {
IPluginVersion installedPluginVersion = this.getPluginVersionFactory().create();
installedPluginVersion.setIsOsgi( true );
// installedPluginVersion.setName( feature.getName() );
installedPluginVersion.setVersion( feature.getVersion() );
installedPluginVersion.setBranch( null );
installedPluginVersion.setBuildId( null );
return installedPluginVersion;
}
} catch ( Exception e ) {
this.getLogger().warn( "Failed to infer version of installed OSGi plugin from features.", e );
return null;
}
return null;
}
private IPluginVersion getInstalledPluginVersion( IPlugin plugin ) {
IPluginVersion osgiPluginVersion = this.getInstalledOsgiPluginVersion( plugin );
if( osgiPluginVersion != null ) {
return osgiPluginVersion;
} else {
return this.getInstalledNonOsgiPluginVersion( plugin );
}
}
private Collection<String> getInstalledOsgiPluginIds() {
Collection<String> potentialOsgiPluginIds = new HashSet<>();
try {
for( String installedKar : this.getKarService().list() ) {
potentialOsgiPluginIds.add( installedKar );
}
} catch ( Exception e ) { }
for( Feature feature : this.getFeaturesService().listInstalledFeatures() ) {
potentialOsgiPluginIds.add( feature.getName() );
}
return potentialOsgiPluginIds;
}
private Collection<String> getInstalledPluginIds() {
Collection<String> installedPluginIds = this.getInstalledOsgiPluginIds();
installedPluginIds.addAll( this.getInstalledNonOsgiPluginIds() );
return installedPluginIds;
}
private boolean executeInstall( IPlugin plugin, IPluginVersion version ) {
if ( version.isOsgi() ) {
return this.executeOsgiInstall( plugin, version );
} else {
// before install, close class loader in case it's a reinstall
this.unloadPlugin( plugin );
return this.executeNonOsgiInstall( plugin, version );
}
}
private boolean executeUninstall( IPlugin plugin ) {
IPluginVersion version = this.getInstalledPluginVersion( plugin );
if ( version == null ) {
this.getLogger().debug( "Did not find plugin version for installed plugin: " + plugin.getId() );
return false;
}
if ( version.isOsgi() ) {
return this.executeOsgiUninstall( plugin );
} else {
// before install, close class loader in case it's a reinstall
this.unloadPlugin( plugin );
return this.executeNonOsgiUninstall( plugin );
}
}
protected abstract boolean hasMarketplacePermission();
protected abstract void unloadPlugin( IPlugin pluginId );
protected abstract boolean executeNonOsgiInstall( IPlugin plugin, IPluginVersion version );
protected abstract boolean executeNonOsgiUninstall( IPlugin plugin );
protected abstract IPluginVersion getInstalledNonOsgiPluginVersion( IPlugin plugin );
protected abstract Collection<String> getInstalledNonOsgiPluginIds();
}