View Javadoc
1   package com.atlassian.plugin.osgi.factory.transform.model;
2   
3   import com.atlassian.plugin.osgi.util.OsgiHeaderUtil;
4   import com.google.common.collect.ImmutableMap;
5   
6   import java.util.LinkedHashMap;
7   import java.util.Map;
8   
9   import static com.google.common.collect.Maps.transformValues;
10  
11  /**
12   * Encapsulates the package exports from the system bundle
13   *
14   * @since 2.2.0
15   */
16  public class SystemExports {
17      private final Map<String, Map<String, String>> exports;
18  
19      public static final SystemExports NONE = new SystemExports("");
20  
21      /**
22       * Constructs an instance by parsing the exports line from the manifest
23       *
24       * @param exportsLine The Export-Package header value
25       */
26      public SystemExports(String exportsLine) {
27          if (exportsLine == null) {
28              exportsLine = "";
29          }
30  
31          this.exports = internAttributeKeys(OsgiHeaderUtil.parseHeader(exportsLine));
32      }
33  
34      /**
35       * OSGi manifest header keys come from a very small set of possible strings, and are ripe for interning. The other
36       * strings in this map are less suitable for interning, and so are left alone.
37       */
38      private static Map<String, Map<String, String>> internAttributeKeys(final Map<String, Map<String, String>> map) {
39          return transformValues(map, SystemExports::internKeys);
40      }
41  
42      private static Map<String, String> internKeys(final Map<String, String> innerMap) {
43          // Guava doesn't offer a "transformKeys" method, so we do it the old-fashioned way
44          final ImmutableMap.Builder<String, String> builder = ImmutableMap.builder();
45          for (Map.Entry<String, String> entry : innerMap.entrySet()) {
46              builder.put(
47                      entry.getKey().intern(),  // this here's the manifest header key
48                      entry.getValue()
49              );
50          }
51  
52          return builder.build();
53      }
54  
55      /**
56       * Constructs a package export, taking into account any attributes on the system export, including the version.
57       * The version is handled special, in that is added as an exact match, i.e. [1.0,1.0].
58       *
59       * @param pkg The java package
60       * @return The full export line to use for a host component import
61       */
62      public String getFullExport(String pkg) {
63          if (exports.containsKey(pkg)) {
64              Map<String, String> attrs = new LinkedHashMap<>(exports.get(pkg));
65              if (attrs.containsKey("version")) {
66                  final String version = attrs.get("version");
67                  attrs.put("version", "[" + version + "," + version + "]");
68              }
69              return OsgiHeaderUtil.buildHeader(pkg, attrs);
70          }
71          return pkg;
72      }
73  
74      /**
75       * @param pkg The package to check
76       * @return True if the package is being exported, false otherwise
77       */
78      public boolean isExported(String pkg) {
79          return exports.containsKey(pkg);
80      }
81  }