blob: a177424da6fdfbf88ebe88929eb79d3295a997c0 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2008, 2009 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
* Wojciech Galanciak <wojciech.galanciak@gmail.com> - bug 282804
*******************************************************************************/
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.MessageHelper;
import org.eclipse.pde.internal.runtime.PDERuntimePlugin;
import org.osgi.framework.*;
import org.osgi.service.packageadmin.PackageAdmin;
public class LocalRegistryBackend implements IRegistryEventListener, BundleListener, ServiceListener, RegistryBackend {
private BackendChangeListener listener;
public void setRegistryListener(BackendChangeListener listener) {
this.listener = listener;
}
/* (non-Javadoc)
* @see org.eclipse.pde.internal.runtime.registry.model.local.RegistryBackend#connect()
*/
public boolean connect(IProgressMonitor monitor) {
if (monitor.isCanceled())
return false;
PDERuntimePlugin.getDefault().getBundleContext().addBundleListener(this);
Platform.getExtensionRegistry().addListener(this);
PDERuntimePlugin.getDefault().getBundleContext().addServiceListener(this);
return true;
}
/* (non-Javadoc)
* @see org.eclipse.pde.internal.runtime.registry.model.local.RegistryBackend#disconnect()
*/
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));
}
/* (non-Javadoc)
* @see org.eclipse.pde.internal.runtime.registry.model.local.RegistryBackend#start(org.osgi.framework.Bundle)
*/
public void start(long id) {
try {
PDERuntimePlugin.getDefault().getBundleContext().getBundle(id).start();
} catch (BundleException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
/* (non-Javadoc)
* @see org.eclipse.pde.internal.runtime.registry.model.local.RegistryBackend#stop(org.osgi.framework.Bundle)
*/
public void stop(long id) {
try {
PDERuntimePlugin.getDefault().getBundleContext().getBundle(id).stop();
} catch (BundleException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
/* (non-Javadoc)
* @see org.eclipse.pde.internal.runtime.registry.model.local.RegistryBackend#diagnose(org.osgi.framework.Bundle)
*/
public String[] 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);
String[] problems = new String[unsatisfied.length + resolverErrors.length];
for (int i = 0; i < resolverErrors.length; i++) {
problems[i] = resolverErrors[i].toString();
}
int j = 0;
for (int i = resolverErrors.length; i < unsatisfied.length + resolverErrors.length; i++) {
problems[i] = MessageHelper.getResolutionFailureMessage(unsatisfied[j]);
j++;
}
return problems;
}
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);
}
}
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);
}
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]);
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().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;
}
private ServiceRegistration createServiceReferenceAdapter(ServiceReference ref) {
ServiceRegistration service = new ServiceRegistration();
service.setId(((Long) ref.getProperty(org.osgi.framework.Constants.SERVICE_ID)).longValue());
service.setBundle(ref.getBundle().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));
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;
}
if (bundleEntry == null)
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;
}
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);
}
}
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;
}
public void added(IExtension[] extensions) {
listener.addExtensions(createExtensionAdapters(extensions));
}
public void removed(IExtension[] extensions) {
listener.removeExtensions(createExtensionAdapters(extensions));
}
public void added(IExtensionPoint[] extensionPoints) {
listener.addExtensionPoints(createExtensionPointAdapters(extensionPoints));
}
public void removed(IExtensionPoint[] extensionPoints) {
listener.removeExtensionPoints(createExtensionPointAdapters(extensionPoints));
}
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});
}
public void setBackendChangeListener(BackendChangeListener listener) {
// TODO Auto-generated method stub
}
}