blob: 75234831dfe8f949d9a436ff1385f7738f89e973 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2008, 2015 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
* Wolfgang Schell <ws@jetztgrad.net> - bug 259348
* Arnaud Mergey <a_mergey@yahoo.fr>
*******************************************************************************/
package org.eclipse.pde.internal.runtime.registry.model;
import java.io.IOException;
import java.net.URL;
import java.util.Arrays;
import org.eclipse.core.runtime.*;
import org.eclipse.osgi.service.resolver.*;
import org.eclipse.osgi.util.ManifestElement;
import org.eclipse.pde.internal.runtime.*;
import org.osgi.framework.*;
import org.osgi.service.packageadmin.PackageAdmin;
public class LocalRegistryBackend
implements IRegistryEventListener, BundleListener, ServiceListener, RegistryBackend
{
private BackendChangeListener listener;
@Override
public void setRegistryListener( BackendChangeListener listener ) {
this.listener = listener;
}
@Override
public void connect( IProgressMonitor monitor ) {
if( monitor.isCanceled() )
return;
PDERuntimePlugin.getDefault().getBundleContext().addBundleListener( this );
Platform.getExtensionRegistry().addListener( this );
PDERuntimePlugin.getDefault().getBundleContext().addServiceListener( this );
}
@Override
public void disconnect() {
Platform.getExtensionRegistry().removeListener( this );
PDERuntimePlugin.getDefault().getBundleContext().removeBundleListener( this );
PDERuntimePlugin.getDefault().getBundleContext().removeServiceListener( this );
}
protected static boolean isRegisteredService( org.osgi.framework.Bundle bundle,
ServiceReference ref )
{
return bundle.equals( ref.getBundle() );
}
protected static boolean isServiceInUse( org.osgi.framework.Bundle bundle,
ServiceReference ref )
{
org.osgi.framework.Bundle[] usingBundles = ref.getUsingBundles();
return( usingBundles != null && Arrays.asList( usingBundles ).contains( bundle ) );
}
@Override
public void start( long id ) throws BundleException {
PDERuntimePlugin.getDefault().getBundleContext().getBundle( id ).start();
}
@Override
public void stop( long id ) throws BundleException {
PDERuntimePlugin.getDefault().getBundleContext().getBundle( id ).stop();
}
@Override
public MultiStatus diagnose( long id ) {
PlatformAdmin plaformAdmin = PDERuntimePlugin.getDefault().getPlatformAdmin();
State state = plaformAdmin.getState( false );
BundleDescription desc = state.getBundle( id );
PlatformAdmin platformAdmin = PDERuntimePlugin.getDefault().getPlatformAdmin();
VersionConstraint[] unsatisfied = platformAdmin.getStateHelper()
.getUnsatisfiedConstraints( desc );
ResolverError[] resolverErrors = platformAdmin.getState( false ).getResolverErrors( desc );
MultiStatus problems = new MultiStatus( PDERuntimePlugin.ID,
IStatus.INFO,
PDERuntimeMessages.get().RegistryView_found_problems,
null );
for( int i = 0; i < resolverErrors.length; i++ ) {
if( ( resolverErrors[ i ].getType()
& ( ResolverError.MISSING_FRAGMENT_HOST
| ResolverError.MISSING_GENERIC_CAPABILITY
| ResolverError.MISSING_IMPORT_PACKAGE
| ResolverError.MISSING_REQUIRE_BUNDLE ) ) != 0 )
continue;
IStatus status = new Status( IStatus.WARNING,
PDERuntimePlugin.ID,
resolverErrors[ i ].toString() );
problems.add( status );
}
for( int i = 0; i < unsatisfied.length; i++ ) {
IStatus status = new Status( IStatus.WARNING,
PDERuntimePlugin.ID,
MessageHelper.getResolutionFailureMessage( unsatisfied[ i ] ) );
problems.add( status );
}
return problems;
}
@Override
public void initializeBundles( IProgressMonitor monitor ) {
if( monitor.isCanceled() )
return;
org.osgi.framework.Bundle[] newBundles = PDERuntimePlugin.getDefault()
.getBundleContext()
.getBundles();
for( int i = 0; i < newBundles.length; i++ ) {
if( monitor.isCanceled() )
return;
Bundle ba = createBundleAdapter( newBundles[ i ] );
listener.addBundle( ba );
}
}
@Override
public void initializeExtensionPoints( IProgressMonitor monitor ) {
if( monitor.isCanceled() )
return;
IExtensionPoint[] extPoints = Platform.getExtensionRegistry().getExtensionPoints();
ExtensionPoint[] extPts = new ExtensionPoint[ extPoints.length ];
for( int i = 0; i < extPoints.length; i++ ) {
if( monitor.isCanceled() )
return;
extPts[ i ] = createExtensionPointAdapter( extPoints[ i ] );
}
listener.addExtensionPoints( extPts );
}
@Override
public void initializeServices( IProgressMonitor monitor ) {
if( monitor.isCanceled() )
return;
ServiceReference[] references = null;
try {
references = PDERuntimePlugin.getDefault().getBundleContext().getAllServiceReferences( null,
null );
} catch( InvalidSyntaxException e ) { // nothing
}
if( references == null ) {
return;
}
for( int i = 0; i < references.length; i++ ) {
if( monitor.isCanceled() )
return;
ServiceRegistration service = createServiceReferenceAdapter( references[ i ] );
// The list of registered services is volatile, avoid adding unregistered services to the
// listener
if( service.getBundle() != null ) {
listener.addService( service );
}
}
}
private Bundle createBundleAdapter( org.osgi.framework.Bundle bundle ) {
Bundle adapter = new Bundle();
adapter.setSymbolicName( bundle.getSymbolicName() );
adapter.setVersion( ( String )bundle.getHeaders()
.get( org.osgi.framework.Constants.BUNDLE_VERSION ) );
adapter.setState( bundle.getState() );
adapter.setId( bundle.getBundleId() );
adapter.setEnabled( getIsEnabled( bundle ) );
adapter.setLocation( createLocation( bundle ) );
String fragmentHost = ( String )bundle.getHeaders().get( Constants.FRAGMENT_HOST );
if( fragmentHost != null ) {
ManifestElement[] header;
try {
header = ManifestElement.parseHeader( Constants.FRAGMENT_HOST, fragmentHost );
if( header.length > 0 ) {
ManifestElement host = header[ 0 ];
adapter.setFragmentHost( host.getValue() );
String version = host.getAttribute( Constants.BUNDLE_VERSION_ATTRIBUTE );
if( version != null ) {
adapter.setFragmentHostVersion( version );
}
}
} catch( BundleException e ) {
PDERuntimePlugin.log( e );
}
}
BundlePrerequisite[] imports = ( BundlePrerequisite[] )getManifestHeaderArray( bundle,
Constants.REQUIRE_BUNDLE );
if( imports != null )
adapter.setImports( imports );
BundleLibrary[] libraries = ( BundleLibrary[] )getManifestHeaderArray( bundle,
Constants.BUNDLE_CLASSPATH );
if( libraries != null )
adapter.setLibraries( libraries );
BundlePrerequisite[] importPackages = ( BundlePrerequisite[] )getManifestHeaderArray( bundle,
Constants.IMPORT_PACKAGE );
if( importPackages != null )
adapter.setImportedPackages( importPackages );
BundlePrerequisite[] exportPackages = ( BundlePrerequisite[] )getManifestHeaderArray( bundle,
Constants.EXPORT_PACKAGE );
if( exportPackages != null )
adapter.setExportedPackages( exportPackages );
return adapter;
}
private Extension createExtensionAdapter( IExtension extension ) {
Extension adapter = new Extension();
adapter.setNamespaceIdentifier( extension.getNamespaceIdentifier() );
adapter.setLabel( extension.getLabel() );
adapter.setExtensionPointUniqueIdentifier( extension.getExtensionPointUniqueIdentifier() );
adapter.setContributor( getBundleId( extension.getContributor().getName() ) );
IConfigurationElement[] elements = extension.getConfigurationElements();
if( elements.length > 0 ) {
ConfigurationElement[] configurationElements = new ConfigurationElement[ elements.length ];
for( int i = 0; i < elements.length; i++ ) {
configurationElements[ i ] = createConfigurationElement( elements[ i ] );
}
adapter.setConfigurationElements( configurationElements );
}
return adapter;
}
private ConfigurationElement createConfigurationElement( IConfigurationElement config ) {
ConfigurationElement element = new ConfigurationElement();
element.setName( createName( config ) );
Attribute[] attributes = createConfigurationElementAttributes( config );
if( attributes != null )
element.setElements( attributes );
return element;
}
private static Long getBundleId( String name ) {
BundleDescription descr = PDERuntimePlugin.getDefault()
.getPlatformAdmin()
.getState( false )
.getBundle( name, null );
return descr == null
? null
: new Long( descr.getBundleId() );
}
private ExtensionPoint createExtensionPointAdapter( IExtensionPoint extensionPoint ) {
ExtensionPoint adapter = new ExtensionPoint();
adapter.setLabel( extensionPoint.getLabel() );
adapter.setUniqueIdentifier( extensionPoint.getUniqueIdentifier() );
adapter.setNamespaceIdentifier( extensionPoint.getNamespaceIdentifier() );
adapter.setContributor( getBundleId( extensionPoint.getContributor().getName() ) );
Extension[] extensions = createExtensionAdapters( extensionPoint.getExtensions() );
adapter.getExtensions().addAll( Arrays.asList( extensions ) );
return adapter;
}
/**
* Returns a new {@link ServiceRegistration} for the given service reference. If the service being
* referenced is unregistered, the returned service registration will not have a bundle set.
*
* @param ref the service reference to get the registration for
* @return a new service registration containing information from the service reference
*/
private ServiceRegistration createServiceReferenceAdapter( ServiceReference ref ) {
ServiceRegistration service = new ServiceRegistration();
service
.setId( ( ( Long )ref.getProperty( org.osgi.framework.Constants.SERVICE_ID ) ).longValue() );
org.osgi.framework.Bundle bundle = ref.getBundle();
if( bundle != null ) {
service.setBundle( bundle.getSymbolicName() );
}
org.osgi.framework.Bundle[] usingBundles = ref.getUsingBundles();
long[] usingBundlesIds = null;
if( usingBundles != null ) {
usingBundlesIds = new long[ usingBundles.length ];
for( int i = 0; i < usingBundles.length; i++ ) {
usingBundlesIds[ i ] = usingBundles[ i ].getBundleId();
}
}
if( usingBundlesIds != null )
service.setUsingBundles( usingBundlesIds );
String[] classes = ( String[] )ref.getProperty( org.osgi.framework.Constants.OBJECTCLASS );
String[] propertyKeys = ref.getPropertyKeys();
Property[] properties = null;
if( propertyKeys != null ) {
properties = new Property[ propertyKeys.length ];
for( int p = 0; p < propertyKeys.length; p++ ) {
String key = propertyKeys[ p ];
Object value = ref.getProperty( key );
properties[ p ] = new Property( key, ServiceRegistration.toString( value ) );
}
}
if( classes != null ) {
Arrays.sort( classes );
service.setName( new ServiceName( classes, ref ) );
service.setProperties( properties );
}
return service;
}
private static boolean getIsEnabled( org.osgi.framework.Bundle bundle ) {
PlatformAdmin plaformAdmin = PDERuntimePlugin.getDefault().getPlatformAdmin();
State state = plaformAdmin.getState( false );
BundleDescription description = state.getBundle( bundle.getBundleId() );
return ( state.getDisabledInfos( description ) ).length == 0;
}
private static String createLocation( org.osgi.framework.Bundle bundle ) {
URL bundleEntry = null;
try {
bundleEntry = bundle.getEntry( "/" ); //$NON-NLS-1$
} catch( IllegalStateException e ) {
return null;
}
try {
bundleEntry = FileLocator.resolve( bundleEntry );
} catch( IOException e ) { // do nothing
}
IPath path = new Path( bundleEntry.getFile() );
String pathString = path.removeTrailingSeparator().toOSString();
if( pathString.startsWith( "file:" ) ) //$NON-NLS-1$
pathString = pathString.substring( 5 );
if( pathString.endsWith( "!" ) ) //$NON-NLS-1$
pathString = pathString.substring( 0, pathString.length() - 1 );
return pathString;
}
private Object[] getManifestHeaderArray( org.osgi.framework.Bundle bundle, String headerKey ) {
String libraries = ( String )bundle.getHeaders().get( headerKey );
try {
ManifestElement[] elements = ManifestElement.parseHeader( headerKey, libraries );
if( elements == null )
return null;
if( headerKey.equals( Constants.BUNDLE_CLASSPATH ) ) {
BundleLibrary[] array = new BundleLibrary[ elements.length ];
for( int i = 0; i < elements.length; i++ ) {
BundleLibrary library = new BundleLibrary();
library.setLibrary( elements[ i ].getValue() );
array[ i ] = library;
}
return array;
} else if( headerKey.equals( Constants.REQUIRE_BUNDLE )
|| headerKey.equals( Constants.IMPORT_PACKAGE )
|| headerKey.equals( Constants.EXPORT_PACKAGE ) )
{
BundlePrerequisite[] array = new BundlePrerequisite[ elements.length ];
for( int i = 0; i < elements.length; i++ ) {
ManifestElement element = elements[ i ];
BundlePrerequisite prereq = new BundlePrerequisite();
prereq.setName( element.getValue() );
if( headerKey.equals( Constants.REQUIRE_BUNDLE ) ) {
prereq.setVersion( element.getAttribute( Constants.BUNDLE_VERSION_ATTRIBUTE ) );
String visibility = element.getDirective( Constants.VISIBILITY_DIRECTIVE );
prereq.setExported( Constants.VISIBILITY_REEXPORT.equals( visibility ) );
} else {
prereq.setVersion( element.getAttribute( Constants.VERSION_ATTRIBUTE ) );
prereq.setPackage( true );
}
array[ i ] = prereq;
}
return array;
}
} catch( BundleException e ) { // do nothing
}
return null;
}
private Attribute[] createConfigurationElementAttributes( IConfigurationElement config ) {
String[] atts = config.getAttributeNames();
Attribute[] catts = new Attribute[ atts.length ];
for( int i = 0; i < atts.length; i++ )
catts[ i ] = new Attribute( atts[ i ], config.getAttribute( atts[ i ] ) );
IConfigurationElement[] children = config.getChildren();
Attribute[] result = new Attribute[ children.length + catts.length ];
for( int i = 0; i < children.length; i++ ) {
IConfigurationElement child = children[ i ];
result[ i ] = createConfigurationElement( child );
}
for( int i = 0; i < catts.length; i++ ) {
result[ children.length + i ] = catts[ i ];
}
return result;
}
private static String createName( IConfigurationElement config ) {
String label = config.getAttribute( "label" ); //$NON-NLS-1$
if( label == null )
label = config.getName();
if( label == null )
label = config.getAttribute( "name" ); //$NON-NLS-1$
if( label == null && config.getAttribute( "id" ) != null ) { //$NON-NLS-1$
String[] labelSplit = config.getAttribute( "id" ).split( "\\." ); //$NON-NLS-1$ //$NON-NLS-2$
label = labelSplit.length == 0
? null
: labelSplit[ labelSplit.length - 1 ];
}
return label;
}
private Extension[] createExtensionAdapters( IExtension[] extensions ) {
Extension[] extensionAdapters = new Extension[ extensions.length ];
for( int i = 0; i < extensions.length; i++ ) {
extensionAdapters[ i ] = createExtensionAdapter( extensions[ i ] );
}
return extensionAdapters;
}
@Override
public void bundleChanged( BundleEvent event ) {
Bundle adapter = createBundleAdapter( event.getBundle() );
switch( event.getType() ) {
case BundleEvent.INSTALLED:
listener.addBundle( adapter );
break;
case BundleEvent.UNINSTALLED:
listener.removeBundle( adapter );
break;
case BundleEvent.UPDATED:
listener.updateBundle( adapter, ModelChangeDelta.UPDATED );
break;
case BundleEvent.RESOLVED:
listener.updateBundle( adapter, ModelChangeDelta.RESOLVED );
break;
case BundleEvent.UNRESOLVED:
listener.updateBundle( adapter, ModelChangeDelta.UNRESOLVED );
break;
case BundleEvent.STARTING:
listener.updateBundle( adapter, ModelChangeDelta.STARTING );
break;
case BundleEvent.STARTED:
listener.updateBundle( adapter, ModelChangeDelta.STARTED );
break;
case BundleEvent.STOPPING:
listener.updateBundle( adapter, ModelChangeDelta.STOPPING );
break;
case BundleEvent.STOPPED:
listener.updateBundle( adapter, ModelChangeDelta.STOPPED );
break;
default:
listener.updateBundle( adapter, ModelChangeDelta.UPDATED );
}
}
@Override
public void serviceChanged( ServiceEvent event ) {
ServiceReference ref = event.getServiceReference();
ServiceRegistration adapter = createServiceReferenceAdapter( ref );
switch( event.getType() ) {
case ServiceEvent.REGISTERED:
listener.addService( adapter );
break;
case ServiceEvent.UNREGISTERING:
listener.removeService( adapter );
break;
case ServiceEvent.MODIFIED:
default:
listener.updateService( adapter );
break;
}
}
private ExtensionPoint[] createExtensionPointAdapters( IExtensionPoint[] extensionPoints ) {
ExtensionPoint[] result = new ExtensionPoint[ extensionPoints.length ];
for( int i = 0; i < extensionPoints.length; i++ ) {
result[ i ] = createExtensionPointAdapter( extensionPoints[ i ] );
}
return result;
}
@Override
public void added( IExtension[] extensions ) {
listener.addExtensions( createExtensionAdapters( extensions ) );
}
@Override
public void removed( IExtension[] extensions ) {
listener.removeExtensions( createExtensionAdapters( extensions ) );
}
@Override
public void added( IExtensionPoint[] extensionPoints ) {
listener.addExtensionPoints( createExtensionPointAdapters( extensionPoints ) );
}
@Override
public void removed( IExtensionPoint[] extensionPoints ) {
listener.removeExtensionPoints( createExtensionPointAdapters( extensionPoints ) );
}
@Override
public void setEnabled( long id, boolean enabled ) {
State state = PDERuntimePlugin.getDefault().getState();
BundleDescription desc = state.getBundle( id );
if( enabled ) {
DisabledInfo[] infos = state.getDisabledInfos( desc );
for( int i = 0; i < infos.length; i++ ) {
PlatformAdmin platformAdmin = PDERuntimePlugin.getDefault().getPlatformAdmin();
platformAdmin.removeDisabledInfo( infos[ i ] );
}
} else {
DisabledInfo info = new DisabledInfo( "org.eclipse.pde.ui", "Disabled via PDE", desc ); //$NON-NLS-1$ //$NON-NLS-2$
PlatformAdmin platformAdmin = PDERuntimePlugin.getDefault().getPlatformAdmin();
platformAdmin.addDisabledInfo( info );
}
org.osgi.framework.Bundle b = PDERuntimePlugin.getDefault().getBundleContext().getBundle( id );
PackageAdmin packageAdmin = PDERuntimePlugin.getDefault().getPackageAdmin();
packageAdmin.refreshPackages( new org.osgi.framework.Bundle[] {
b
} );
}
}