Skip to main content
aboutsummaryrefslogtreecommitdiffstats
blob: ac0a446702b4ee94d21bc6030d3689f63dbe4aa9 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
/*******************************************************************************
 * Copyright (c) 2005, 2012 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.internal.container.Capabilities;
import org.eclipse.osgi.internal.loader.BundleLoader;
import org.osgi.framework.Bundle;
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.BundleWire;
import org.osgi.framework.wiring.BundleWiring;
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 -> {
					try {
						return b.loadClass(name);
					} catch (ClassNotFoundException e) {
						return null;
					}
				}).orElseGet(null);
	}

	@Override
	public URL loadResource(String name) {
		return getExportingBundles(BundleLoader.getResourcePackageName(name)) //
				.stream().findFirst().map(b -> {
					return b.getResource(name);
				}).orElseGet(null);
	}

	@Override
	public Enumeration<URL> loadResources(String name) {
		Enumeration<URL> results = null;
		Collection<Bundle> exporters = getExportingBundles(name);
		for (Bundle exporter : exporters) {
			try {
				results = BundleLoader.compoundEnumerations(results, exporter.getResources(name));
			}catch (IOException e) {
				//ignore IO problems and try next package
			}
		}
		return results;
	}

	private Collection<Bundle> getExportingBundles(String pkgName) {
		Collection<Bundle> result = new ArrayList<>();
		String filter = "(" + PackageNamespace.PACKAGE_NAMESPACE + "=" + pkgName + ")"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
		Map<String, String> directives = Collections
				.<String, String>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) {
			if ((pkg.getRevision().getTypes() & BundleRevision.TYPE_FRAGMENT) != 0) {
				// use the hosts
				BundleWiring wiring = pkg.getRevision().getWiring();
				for (BundleWire hostWire : wiring.getRequiredWires(HostNamespace.HOST_NAMESPACE)) {
					result.add(hostWire.getProvider().getBundle());
				}
			} else {
				result.add(pkg.getRevision().getBundle());
			}
		}
		return result;
	}
}

Back to the top