blob: 16bab2eae771821e7f766dbf90a56336210a8b7e [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2005, 2021 IBM Corporation and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.osgi.internal.loader.buddy;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Enumeration;
import java.util.Map;
import org.eclipse.osgi.container.ModuleContainer;
import org.eclipse.osgi.container.ModuleWire;
import org.eclipse.osgi.container.ModuleWiring;
import org.eclipse.osgi.internal.container.Capabilities;
import org.eclipse.osgi.internal.loader.BundleLoader;
import org.osgi.framework.namespace.HostNamespace;
import org.osgi.framework.namespace.PackageNamespace;
import org.osgi.framework.wiring.BundleCapability;
import org.osgi.framework.wiring.BundleRevision;
import org.osgi.framework.wiring.FrameworkWiring;
import org.osgi.resource.Namespace;
/**
* Global policy is an implementation of a buddy policy. It is responsible
* for looking up a class within the global set of exported classes. If multiple
* version of the same package are exported in the system, the exported package
* with the highest version will be returned.
*/
public class GlobalPolicy implements IBuddyPolicy {
private FrameworkWiring frameworkWiring;
public GlobalPolicy(FrameworkWiring frameworkWiring) {
this.frameworkWiring = frameworkWiring;
}
@Override
public Class<?> loadClass(String name) {
return getExportingBundles(BundleLoader.getPackageName(name)) //
.stream().findFirst().map(b -> b.findClassNoParentNoException(name)).orElse(null);
}
@Override
public URL loadResource(String name) {
return getExportingBundles(BundleLoader.getResourcePackageName(name)) //
.stream().findFirst().map(b -> b.findResource(name)).orElse(null);
}
@Override
public Enumeration<URL> loadResources(String name) {
Enumeration<URL> results = null;
Collection<BundleLoader> exporters = getExportingBundles(name);
for (BundleLoader exporter : exporters) {
try {
results = BundleLoader.compoundEnumerations(results, exporter.findResources(name));
}catch (IOException e) {
//ignore IO problems and try next package
}
}
return results;
}
private Collection<BundleLoader> getExportingBundles(String pkgName) {
Collection<BundleLoader> result = new ArrayList<>();
String filter = "(" + PackageNamespace.PACKAGE_NAMESPACE + "=" + pkgName + ")"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
Map<String, String> directives = Collections.singletonMap(Namespace.REQUIREMENT_FILTER_DIRECTIVE, filter);
Map<String, Boolean> attributes = Collections.singletonMap(Capabilities.SYNTHETIC_REQUIREMENT, Boolean.TRUE);
Collection<BundleCapability> packages = frameworkWiring.findProviders(
ModuleContainer.createRequirement(PackageNamespace.PACKAGE_NAMESPACE, directives, attributes));
for (BundleCapability pkg : packages) {
ModuleWiring wiring = (ModuleWiring) pkg.getRevision().getWiring();
if (wiring != null) {
if ((pkg.getRevision().getTypes() & BundleRevision.TYPE_FRAGMENT) != 0) {
// use the hosts
if (wiring != null) {
for (ModuleWire hostWire : wiring.getRequiredModuleWires(HostNamespace.HOST_NAMESPACE)) {
result.add((BundleLoader) hostWire.getProviderWiring().getModuleLoader());
}
}
} else {
result.add((BundleLoader) wiring.getModuleLoader());
}
}
}
return result;
}
}