File: export_package.md

package info (click to toggle)
bnd 5.0.1-3
  • links: PTS, VCS
  • area: main
  • in suites: bookworm, bullseye
  • size: 44,092 kB
  • sloc: java: 249,039; xml: 90,727; sh: 655; perl: 153; makefile: 95; python: 47; javascript: 9
file content (149 lines) | stat: -rw-r--r-- 5,983 bytes parent folder | download | duplicates (3)
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
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
---
layout: default
class: Header
title: Export-Package  ::= export ( ',' export)* 
summary: The Export-Package header contains a declaration of exported packages
---
The bnd definition allows the specification to be done using ''patterns'', a modified regular expression. All patterns in the definition are matched against every package on the [ class path][#CLASSPATH ]. If the pattern is a negating pattern (starts with !) and it is matched, then the package is completely excluded. Normal patterns cause the package to be included in the resulting bundle. Patterns can include both directives and attributes, these items will be copied to the output. The list is ordered, earlier patterns take effect before later patterns. The following examples copies everything on the class path except for packages starting with `com`. The default for Export-Package is "*", which can result in quite large bundles. If the source packages have an associated version (from their manifest of packageinfo file), then this version is automatically added to the clauses.

  Export-Package= !com.*, *

Exports are automatically imported. This features can be disabled with a special directive on the export instruction: `-noimport:=true`. For example:
  
  Export-Package= com.acme.impl.*;-noimport:=true, *

Bnd will automatically calculate the `uses:` directive. This directive is used by the OSGi framework to create a consistent class space for a bundle. The Export-Package statement allows this directive to be overridden on a package basis by specifying the directive in an Export-Package instruction. 

  Export-package = com.acme.impl.*;uses="my.special.import"

However, in certain cases it is necessary to augment the uses clause. It is therefore possible to use the special name `<<USES>>` in the clause. Bnd will replace this special name with the calculated uses set. Bnd will remove any extraneous commas when the `<<USES>>` is empty.

  Export-package = com.acme.impl.*;uses:="my.special.import,<<USES>>"

Directives that are not part of the OSGi specification will give a warning unless they are prefixed with a 'x-'.


			//
			// EXPORTS
			//
			{
				Set<Instruction> unused = Create.set();

				Instructions filter = new Instructions(getExportPackage());
				filter.append(getExportContents());

				exports = filter(filter, contained, unused);

				if (!unused.isEmpty()) {
					warning("Unused " + Constants.EXPORT_PACKAGE + " instructions: %s ", unused);
				}

				// See what information we can find to augment the
				// exports. I.e. look on the classpath
				augmentExports(exports);
			}

		/**
	 * Check if the given resource is in scope of this bundle. That is, it
	 * checks if the Include-Resource includes this resource or if it is a class
	 * file it is on the class path and the Export-Package or Private-Package
	 * include this resource.
	 *
	 * @param f
	 * @return
	 */
	public boolean isInScope(Collection<File> resources) throws Exception {
		Parameters clauses = parseHeader(getProperty(Constants.EXPORT_PACKAGE));
		clauses.putAll(parseHeader(getProperty(Constants.PRIVATE_PACKAGE)));
		clauses.putAll(parseHeader(getProperty(Constants.PRIVATEPACKAGE)));
		if (isTrue(getProperty(Constants.UNDERTEST))) {
			clauses.putAll(parseHeader(getProperty(Constants.TESTPACKAGES, "test;presence:=optional")));
		}

		Collection<String> ir = getIncludedResourcePrefixes();

		Instructions instructions = new Instructions(clauses);

		for (File r : resources) {
			String cpEntry = getClasspathEntrySuffix(r);

			if (cpEntry != null) {

				if (cpEntry.equals("")) // Meaning we actually have a CPE
					return true;

				String pack = Descriptors.getPackage(cpEntry);
				Instruction i = matches(instructions, pack, null, r.getName());
				if (i != null)
					return !i.isNegated();
			}

			// Check if this resource starts with one of the I-C header
			// paths.
			String path = r.getAbsolutePath();
			for (String p : ir) {
				if (path.startsWith(p))
					return true;
			}
		}
		return false;
	}
	
		/**
	 * Verify that the exports only use versions.
	 */
	private void verifyExports() {
		if (isStrict()) {
			Parameters map = parseHeader(manifest.getMainAttributes().getValue(Constants.EXPORT_PACKAGE));
			Set<String> noexports = new HashSet<String>();

			for (Entry<String,Attrs> e : map.entrySet()) {

				String version = e.getValue().get(Constants.VERSION_ATTRIBUTE);
				if (version == null) {
					noexports.add(e.getKey());
				} else {
					if (!VERSION.matcher(version).matches()) {
						Location location;
						if (VERSIONRANGE.matcher(version).matches()) {
							location = error(
									"Export Package %s version is a range: %s; Exports do not allow for ranges.",
									e.getKey(), version).location();
						} else {
							location = error("Export Package %s version has invalid syntax: %s", e.getKey(), version)
									.location();
						}
						location.header = Constants.EXPORT_PACKAGE;
						location.context = e.getKey();
					}
				}

				if (e.getValue().containsKey(Constants.SPECIFICATION_VERSION)) {
					Location location = error(
							"Export Package %s uses deprecated specification-version instead of version", e.getKey())
							.location();
					location.header = Constants.EXPORT_PACKAGE;
					location.context = e.getKey();
				}

				String mandatory = e.getValue().get(Constants.MANDATORY_DIRECTIVE);
				if (mandatory != null) {
					Set<String> missing = new HashSet<String>(split(mandatory));
					missing.removeAll(e.getValue().keySet());
					if (!missing.isEmpty()) {
						Location location = error("Export Package %s misses mandatory attribute: %s", e.getKey(),
								missing).location();
						location.header = Constants.EXPORT_PACKAGE;
						location.context = e.getKey();
					}
				}
			}

			if (!noexports.isEmpty()) {
				Location location = error("Export Package clauses without version range: %s", noexports).location();
				location.header = Constants.EXPORT_PACKAGE;
			}
		}
	}