You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@felix.apache.org by pa...@apache.org on 2018/04/13 21:13:17 UTC
svn commit: r1829104 [1/4] - in /felix/trunk/osgi-r7/framework/src/main:
java/org/apache/felix/framework/ java/org/apache/felix/framework/util/
resources/
Author: pauls
Date: Fri Apr 13 21:13:16 2018
New Revision: 1829104
URL: http://svn.apache.org/viewvc?rev=1829104&view=rev
Log:
FELIX-5800: calculate system package exports at runtime on jpms, optionally with uses constraints, and cleanup the existing default definitions.
Added:
felix/trunk/osgi-r7/framework/src/main/java/org/apache/felix/framework/util/ClassFileVisitor.java
felix/trunk/osgi-r7/framework/src/main/java/org/apache/felix/framework/util/ClassParser.java
Modified:
felix/trunk/osgi-r7/framework/src/main/java/org/apache/felix/framework/ExtensionManager.java
felix/trunk/osgi-r7/framework/src/main/java/org/apache/felix/framework/Felix.java
felix/trunk/osgi-r7/framework/src/main/java/org/apache/felix/framework/util/FelixConstants.java
felix/trunk/osgi-r7/framework/src/main/java/org/apache/felix/framework/util/Util.java
felix/trunk/osgi-r7/framework/src/main/resources/default.properties
Modified: felix/trunk/osgi-r7/framework/src/main/java/org/apache/felix/framework/ExtensionManager.java
URL: http://svn.apache.org/viewvc/felix/trunk/osgi-r7/framework/src/main/java/org/apache/felix/framework/ExtensionManager.java?rev=1829104&r1=1829103&r2=1829104&view=diff
==============================================================================
--- felix/trunk/osgi-r7/framework/src/main/java/org/apache/felix/framework/ExtensionManager.java (original)
+++ felix/trunk/osgi-r7/framework/src/main/java/org/apache/felix/framework/ExtensionManager.java Fri Apr 13 21:13:16 2018
@@ -22,6 +22,7 @@ import org.apache.felix.framework.cache.
import org.apache.felix.framework.cache.DirectoryContent;
import org.apache.felix.framework.cache.JarContent;
import org.apache.felix.framework.ext.ClassPathExtenderFactory;
+import org.apache.felix.framework.util.ClassParser;
import org.apache.felix.framework.util.FelixConstants;
import org.apache.felix.framework.util.ImmutableList;
import org.apache.felix.framework.util.ImmutableMap;
@@ -33,6 +34,7 @@ import org.apache.felix.framework.util.m
import org.apache.felix.framework.wiring.BundleCapabilityImpl;
import org.apache.felix.framework.wiring.BundleRequirementImpl;
import org.apache.felix.framework.wiring.BundleWireImpl;
+import org.codehaus.mojo.animal_sniffer.IgnoreJRERequirement;
import org.osgi.framework.AdminPermission;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleActivator;
@@ -50,13 +52,20 @@ import org.osgi.framework.wiring.BundleW
import org.osgi.framework.wiring.BundleWiring;
import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.net.URI;
import java.net.URL;
import java.security.AccessController;
import java.security.AllPermission;
import java.security.PrivilegedExceptionAction;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
@@ -70,6 +79,10 @@ import java.util.NoSuchElementException;
import java.util.Properties;
import java.util.ServiceLoader;
import java.util.Set;
+import java.util.SortedMap;
+import java.util.SortedSet;
+import java.util.TreeMap;
+import java.util.TreeSet;
import java.util.concurrent.CopyOnWriteArrayList;
/**
@@ -146,12 +159,8 @@ class ExtensionManager implements Conten
}
private final Logger m_logger;
- private final Map m_configMap;
- private final Map m_headerMap = new StringMap();
- private final Map m_originalHeaderMap = new StringMap();
- private final BundleRevisionImpl m_systemBundleRevision;
- private volatile List<BundleCapability> m_capabilities = Collections.EMPTY_LIST;
- private volatile Set<String> m_exportNames = Collections.EMPTY_SET;
+ private volatile ExtensionManagerRevision m_systemBundleRevision;
+
private final List<ExtensionTuple> m_extensionTuples = Collections.synchronizedList(new ArrayList<ExtensionTuple>());
private final List<BundleRevisionImpl> m_resolvedExtensions = new CopyOnWriteArrayList<BundleRevisionImpl>();
@@ -180,96 +189,23 @@ class ExtensionManager implements Conten
* instance.
*
* @param logger the logger to use.
- * @param configMap the configuration to read properties from.
- * @param felix the framework.
*/
ExtensionManager(Logger logger, Map configMap, Felix felix)
{
m_logger = logger;
- m_configMap = configMap;
- m_systemBundleRevision = new ExtensionManagerRevision(felix);
-// TODO: FRAMEWORK - Not all of this stuff really belongs here, probably only exports.
- // Populate system bundle header map.
- m_headerMap.put(FelixConstants.BUNDLE_VERSION,
- m_configMap.get(FelixConstants.FELIX_VERSION_PROPERTY));
- m_headerMap.put(FelixConstants.BUNDLE_SYMBOLICNAME,
- FelixConstants.SYSTEM_BUNDLE_SYMBOLICNAME);
- m_headerMap.put(FelixConstants.BUNDLE_NAME, "System Bundle");
- m_headerMap.put(FelixConstants.BUNDLE_DESCRIPTION,
- "This bundle is system specific; it implements various system services.");
- m_headerMap.put(FelixConstants.EXPORT_SERVICE,
- "org.osgi.service.packageadmin.PackageAdmin," +
- "org.osgi.service.startlevel.StartLevel," +
- "org.osgi.service.url.URLHandlers");
-
- Properties configProps = Util.toProperties(m_configMap);
- // The system bundle exports framework packages as well as
- // arbitrary user-defined packages from the system class path.
- // We must construct the system bundle's export metadata.
- // Get configuration property that specifies which class path
- // packages should be exported by the system bundle.
- String syspkgs =
- "true".equalsIgnoreCase(configProps.getProperty(FelixConstants.USE_PROPERTY_SUBSTITUTION_IN_SYSTEMPACKAGES)) ?
- Util.getPropertyWithSubs(configProps, FelixConstants.FRAMEWORK_SYSTEMPACKAGES) :
- configProps.getProperty(FelixConstants.FRAMEWORK_SYSTEMPACKAGES);
-
- syspkgs = (syspkgs == null) ? "" : syspkgs;
-
- // If any extra packages are specified, then append them.
- String pkgextra =
- "true".equalsIgnoreCase(configProps.getProperty(FelixConstants.USE_PROPERTY_SUBSTITUTION_IN_SYSTEMPACKAGES)) ?
- Util.getPropertyWithSubs(configProps, FelixConstants.FRAMEWORK_SYSTEMPACKAGES_EXTRA) :
- configProps.getProperty(FelixConstants.FRAMEWORK_SYSTEMPACKAGES_EXTRA);
-
- syspkgs = ((pkgextra == null) || (pkgextra.trim().length() == 0))
- ? syspkgs : syspkgs + (pkgextra.trim().startsWith(",") ? pkgextra : "," + pkgextra);
-
- m_headerMap.put(FelixConstants.BUNDLE_MANIFESTVERSION, "2");
- m_headerMap.put(FelixConstants.EXPORT_PACKAGE, syspkgs);
-
- // The system bundle alsp provides framework generic capabilities
- // as well as arbitrary user-defined generic capabilities. We must
- // construct the system bundle's capabilitie metadata. Get the
- // configuration property that specifies which capabilities should
- // be provided by the system bundle.
- String syscaps = Util.getPropertyWithSubs(configProps, Constants.FRAMEWORK_SYSTEMCAPABILITIES);
-
- syscaps = (syscaps == null) ? "" : syscaps;
-
- // If any extra capabilities are specified, then append them.
- String capextra = Util.getPropertyWithSubs(configProps, Constants.FRAMEWORK_SYSTEMCAPABILITIES_EXTRA);
- syscaps = ((capextra == null) || (capextra.trim().length() == 0))
- ? syscaps : syscaps + (capextra.trim().startsWith(",") ? capextra : "," + capextra);
- m_headerMap.put(FelixConstants.PROVIDE_CAPABILITY, syscaps);
- m_originalHeaderMap.putAll(m_headerMap);
- try
- {
- ManifestParser mp = new ManifestParser(
- m_logger, m_configMap, m_systemBundleRevision, m_headerMap);
- List<BundleCapability> caps = ManifestParser.aliasSymbolicName(mp.getCapabilities(), m_systemBundleRevision);
- caps.add(buildNativeCapabilites());
- appendCapabilities(caps);
- }
- catch (Exception ex)
- {
- m_capabilities = Collections.EMPTY_LIST;
- m_logger.log(
- Logger.LOG_ERROR,
- "Error parsing system bundle export statement: "
- + syspkgs, ex);
- }
- }
-
- protected BundleCapability buildNativeCapabilites() {
- String osArchitecture = (String)m_configMap.get(FelixConstants.FRAMEWORK_PROCESSOR);
- String osName = (String)m_configMap.get(FelixConstants.FRAMEWORK_OS_NAME);
- String osVersion = (String)m_configMap.get(FelixConstants.FRAMEWORK_OS_VERSION);
- String userLang = (String)m_configMap.get(FelixConstants.FRAMEWORK_LANGUAGE);
+ m_systemBundleRevision = new ExtensionManagerRevision(configMap, felix);
+ }
+
+ protected BundleCapability buildNativeCapabilites(BundleRevisionImpl revision, Map configMap) {
+ String osArchitecture = (String) configMap.get(FelixConstants.FRAMEWORK_PROCESSOR);
+ String osName = (String) configMap.get(FelixConstants.FRAMEWORK_OS_NAME);
+ String osVersion = (String) configMap.get(FelixConstants.FRAMEWORK_OS_VERSION);
+ String userLang = (String) configMap.get(FelixConstants.FRAMEWORK_LANGUAGE);
Map<String, Object> attributes = new HashMap<String, Object>();
-
+
//Add all startup properties so we can match selection-filters
- attributes.putAll(m_configMap);
+ attributes.putAll(configMap);
if( osArchitecture != null )
{
@@ -291,7 +227,134 @@ class ExtensionManager implements Conten
attributes.put(NativeNamespace.CAPABILITY_LANGUAGE_ATTRIBUTE, userLang);
}
- return new BundleCapabilityImpl(getRevision(), NativeNamespace.NATIVE_NAMESPACE, Collections.<String, String> emptyMap(), attributes);
+ return new BundleCapabilityImpl(revision, NativeNamespace.NATIVE_NAMESPACE, Collections.<String, String> emptyMap(), attributes);
+ }
+
+ @IgnoreJRERequirement
+ void updateRevision(Felix felix, Map configMap)
+ {
+ Map config = new HashMap(configMap);
+ Properties defaultProperties = Util.loadDefaultProperties(m_logger);
+
+ Util.initializeJPMSEE(felix._getProperty("java.specification.version"), defaultProperties, m_logger);
+
+ String sysprops = felix._getProperty(Constants.FRAMEWORK_SYSTEMPACKAGES);
+
+ final Map<String, Set<String>> exports = Util.initializeJPMS(defaultProperties);
+
+ if (exports != null && (sysprops == null || "true".equalsIgnoreCase(felix._getProperty(FelixConstants.USE_PROPERTY_SUBSTITUTION_IN_SYSTEMPACKAGES))))
+ {
+ java.nio.file.FileSystem fs = java.nio.file.FileSystems.getFileSystem(URI.create("jrt:/"));
+ final ClassParser classParser = new ClassParser();
+ final Set<String> imports = new HashSet<String>();
+ for (Set<String> moduleImport : exports.values())
+ {
+ for (String pkg : moduleImport)
+ {
+ if (!pkg.startsWith("java."))
+ {
+ imports.add(pkg);
+ }
+ }
+ }
+ for (final String moduleKey : exports.keySet())
+ {
+ int idx = moduleKey.indexOf("@");
+ String module = idx == -1 ? moduleKey : moduleKey.substring(0, idx);
+ if (felix._getProperty(module) == null && !exports.get(moduleKey).isEmpty() && defaultProperties.getProperty(module) == null)
+ {
+ final SortedMap<String, SortedSet<String>> referred = new TreeMap<String, SortedSet<String>>();
+ if ("true".equalsIgnoreCase(felix._getProperty(FelixConstants.CALCULATE_SYSTEMPACKAGES_USES)))
+ {
+ try
+ {
+ Properties cachedProps = new Properties();
+ File modulesDir = felix.getDataFile(felix, "modules");
+ modulesDir.mkdirs();
+ File cached = new File(modulesDir, moduleKey + ".properties");
+ if (cached.isFile())
+ {
+ FileInputStream input = new FileInputStream(cached);
+ cachedProps.load(new InputStreamReader(input, "UTF-8"));
+ input.close();
+ for (Enumeration<?> keys = cachedProps.propertyNames(); keys.hasMoreElements();)
+ {
+ String pkg = (String) keys.nextElement();
+ referred.put(pkg, new TreeSet<String>(Arrays.asList(cachedProps.getProperty(pkg).split(","))));
+ }
+ }
+ else
+ {
+ java.nio.file.Path path = fs.getPath("modules", module.substring("felix.jpms.".length()));
+ java.nio.file.Files.walkFileTree(path, (java.nio.file.FileVisitor) Felix.class.getClassLoader().loadClass("org.apache.felix.framework.util.ClassFileVisitor")
+ .getConstructor(Set.class, Set.class, ClassParser.class, SortedMap.class).newInstance(imports, exports.get(moduleKey), classParser, referred));
+ for (String pkg : referred.keySet())
+ {
+ SortedSet<String> uses = referred.get(pkg);
+ if (uses != null && !uses.isEmpty())
+ {
+ cachedProps.setProperty(pkg, String.join(",", uses));
+ }
+ }
+ OutputStream output = new FileOutputStream(cached);
+ cachedProps.store(new OutputStreamWriter(output, "UTF-8"), null);
+ output.close();
+ }
+ }
+ catch (Throwable e)
+ {
+ m_logger.log(Logger.LOG_WARNING, "Exception calculating JPMS module exports", e);
+ }
+ }
+
+ String pkgs = "";
+
+ for (String pkg : exports.get(moduleKey))
+ {
+ pkgs += "," + pkg;
+ SortedSet<String> uses = referred.get(pkg);
+ if (uses != null && !uses.isEmpty())
+ {
+ pkgs += ";uses:=\"";
+ String sep = "";
+ for (String u : uses)
+ {
+ pkgs += sep + u;
+ sep = ",";
+ }
+ pkgs += "\"";
+ }
+ pkgs += ";version=\"" + defaultProperties.getProperty("felix.detect.java.version") + "\"";
+ }
+ defaultProperties.put(module, pkgs);
+ }
+ }
+ }
+ if(sysprops != null && "true".equalsIgnoreCase(felix._getProperty(FelixConstants.USE_PROPERTY_SUBSTITUTION_IN_SYSTEMPACKAGES)) )
+ {
+ defaultProperties.put(Constants.FRAMEWORK_SYSTEMPACKAGES, sysprops);
+ config.put(Constants.FRAMEWORK_SYSTEMPACKAGES, Util.getPropertyWithSubs(defaultProperties, Constants.FRAMEWORK_SYSTEMPACKAGES));
+ }
+ else if (sysprops == null)
+ {
+ config.put(Constants.FRAMEWORK_SYSTEMPACKAGES, Util.getPropertyWithSubs(defaultProperties, Constants.FRAMEWORK_SYSTEMPACKAGES));
+ }
+
+ String syscaps = felix._getProperty(Constants.FRAMEWORK_SYSTEMCAPABILITIES);
+ if(syscaps == null)
+ {
+ config.put(Constants.FRAMEWORK_SYSTEMCAPABILITIES, Util.getPropertyWithSubs(defaultProperties, Constants.FRAMEWORK_SYSTEMCAPABILITIES));
+ }
+
+ for (Map.Entry entry : defaultProperties.entrySet())
+ {
+ if (!config.containsKey(entry.getKey()))
+ {
+ config.put(entry.getKey(), entry.getValue());
+ }
+ }
+
+ m_systemBundleRevision.update(config);
}
public BundleRevisionImpl getRevision()
@@ -381,30 +444,6 @@ class ExtensionManager implements Conten
m_unresolvedExtensions.add(bri);
}
- public synchronized void removeExtensionBundles()
- {
- m_resolvedExtensions.clear();
- m_unresolvedExtensions.clear();
- m_failedExtensions.clear();
- m_headerMap.clear();
- m_headerMap.putAll(m_originalHeaderMap);
- try
- {
- ManifestParser mp = new ManifestParser(
- m_logger, m_configMap, m_systemBundleRevision, m_headerMap);
- List<BundleCapability> caps = ManifestParser.aliasSymbolicName(mp.getCapabilities(), m_systemBundleRevision);
- caps.add(buildNativeCapabilites());
- appendCapabilities(caps);
- }
- catch (Exception ex)
- {
- m_capabilities = Collections.EMPTY_LIST;
- m_logger.log(
- Logger.LOG_ERROR,
- "Error parsing system bundle export statement", ex);
- }
- }
-
public synchronized List<Bundle> resolveExtensionBundles(Felix felix)
{
if (m_unresolvedExtensions.isEmpty())
@@ -459,11 +498,11 @@ class ExtensionManager implements Conten
BundleWire wire = new BundleWireImpl(revision,
revision.getDeclaredRequirements(BundleRevision.HOST_NAMESPACE).get(0),
- m_systemBundleRevision, getCapabilities(BundleRevision.HOST_NAMESPACE).get(0));
+ m_systemBundleRevision, m_systemBundleRevision.getWiring().getCapabilities(BundleRevision.HOST_NAMESPACE).get(0));
try
{
- revision.resolve(new BundleWiringImpl(m_logger, m_configMap, null, revision, null,
+ revision.resolve(new BundleWiringImpl(m_logger, m_systemBundleRevision.m_configMap, null, revision, null,
Collections.singletonList(wire), Collections.EMPTY_MAP, Collections.EMPTY_MAP));
}
catch (Exception ex)
@@ -474,7 +513,7 @@ class ExtensionManager implements Conten
felix.getDependencies().addDependent(wire);
- appendCapabilities(entry.getKey().getDeclaredExtensionCapabilities(null));
+ m_systemBundleRevision.appendCapabilities(entry.getKey().getDeclaredExtensionCapabilities(null));
for (BundleWire w : entry.getValue())
{
if (!w.getRequirement().getNamespace().equals(BundleRevision.HOST_NAMESPACE) &&
@@ -642,6 +681,13 @@ class ExtensionManager implements Conten
m_extensionTuples.clear();
}
+ public synchronized void removeExtensionBundles()
+ {
+ m_resolvedExtensions.clear();
+ m_unresolvedExtensions.clear();
+ m_failedExtensions.clear();
+ }
+
private Map<BundleRevisionImpl, List<BundleWire>> findResolvableExtensions(List<BundleRevisionImpl> extensions, List<BundleRevisionImpl> alt)
{
// The idea is to loop through the extensions and try to resolve all unresolved extension. If we can't resolve
@@ -659,7 +705,7 @@ class ExtensionManager implements Conten
outer: for (BundleRequirement req : bri.getDeclaredRequirements(null))
{
// first see if we can resolve from the system bundle
- for (BundleCapability cap : getCapabilities(req.getNamespace()))
+ for (BundleCapability cap : m_systemBundleRevision.getWiring().getCapabilities(req.getNamespace()))
{
if (req.matches(cap))
{
@@ -756,83 +802,6 @@ class ExtensionManager implements Conten
return wires;
}
- private List<BundleCapability> getCapabilities(String namespace)
- {
- List<BundleCapability> caps = m_capabilities;
- List<BundleCapability> result = caps;
- if (namespace != null)
- {
- result = new ArrayList<BundleCapability>();
- for (BundleCapability cap : caps)
- {
- if (cap.getNamespace().equals(namespace))
- {
- result.add(cap);
- }
- }
- }
- return result;
- }
-
- private void appendCapabilities(List<BundleCapability> caps)
- {
- List<BundleCapability> newCaps = new ArrayList<BundleCapability>(m_capabilities.size() + caps.size());
- newCaps.addAll(m_capabilities);
- newCaps.addAll(caps);
- m_capabilities = ImmutableList.newInstance(newCaps);
- m_headerMap.put(Constants.EXPORT_PACKAGE, convertCapabilitiesToHeaders(newCaps));
- }
-
- private String convertCapabilitiesToHeaders(List<BundleCapability> caps)
- {
- StringBuffer exportSB = new StringBuffer("");
- Set<String> exportNames = new HashSet<String>();
-
- for (BundleCapability cap : caps)
- {
- if (cap.getNamespace().equals(BundleRevision.PACKAGE_NAMESPACE))
- {
- // Add a comma separate if there is an existing package.
- if (exportSB.length() > 0)
- {
- exportSB.append(", ");
- }
-
- // Append exported package information.
- exportSB.append(cap.getAttributes().get(BundleRevision.PACKAGE_NAMESPACE));
- for (Entry<String, String> entry : cap.getDirectives().entrySet())
- {
- exportSB.append("; ");
- exportSB.append(entry.getKey());
- exportSB.append(":=\"");
- exportSB.append(entry.getValue());
- exportSB.append("\"");
- }
- for (Entry<String, Object> entry : cap.getAttributes().entrySet())
- {
- if (!entry.getKey().equals(BundleRevision.PACKAGE_NAMESPACE)
- && !entry.getKey().equals(Constants.BUNDLE_SYMBOLICNAME_ATTRIBUTE)
- && !entry.getKey().equals(Constants.BUNDLE_VERSION_ATTRIBUTE))
- {
- exportSB.append("; ");
- exportSB.append(entry.getKey());
- exportSB.append("=\"");
- exportSB.append(entry.getValue());
- exportSB.append("\"");
- }
- }
-
- // Remember exported packages.
- exportNames.add(
- (String) cap.getAttributes().get(BundleRevision.PACKAGE_NAMESPACE));
- }
- }
-
- m_exportNames = exportNames;
-
- return exportSB.toString();
- }
-
public void close()
{
// Do nothing on close, since we have nothing open.
@@ -889,14 +858,173 @@ class ExtensionManager implements Conten
class ExtensionManagerRevision extends BundleRevisionImpl
{
- private final Version m_version;
+ private volatile Map m_configMap;
+ private final Map m_headerMap = new StringMap();
+ private volatile List<BundleCapability> m_capabilities = Collections.EMPTY_LIST;
+ private volatile Set<String> m_exportNames = Collections.EMPTY_SET;
+ private volatile Version m_version;
private volatile BundleWiring m_wiring;
- ExtensionManagerRevision(Felix felix)
+ ExtensionManagerRevision(Map configMap, Felix felix)
{
super(felix, "0");
- m_version = new Version((String)
+
+ m_configMap = configMap;
+
+// TODO: FRAMEWORK - Not all of this stuff really belongs here
+ // Populate system bundle header map.
+ m_headerMap.put(FelixConstants.BUNDLE_VERSION,
m_configMap.get(FelixConstants.FELIX_VERSION_PROPERTY));
+ m_headerMap.put(FelixConstants.BUNDLE_SYMBOLICNAME,
+ FelixConstants.SYSTEM_BUNDLE_SYMBOLICNAME);
+ m_headerMap.put(FelixConstants.BUNDLE_NAME, "System Bundle");
+ m_headerMap.put(FelixConstants.BUNDLE_DESCRIPTION,
+ "This bundle is system specific; it implements various system services.");
+ m_headerMap.put(FelixConstants.EXPORT_SERVICE,
+ "org.osgi.service.packageadmin.PackageAdmin," +
+ "org.osgi.service.startlevel.StartLevel," +
+ "org.osgi.service.url.URLHandlers");
+
+
+ m_headerMap.put(FelixConstants.BUNDLE_MANIFESTVERSION, "2");
+
+
+ m_version = new Version((String) m_configMap.get(FelixConstants.FELIX_VERSION_PROPERTY));
+
+ try
+ {
+ ManifestParser mp = new ManifestParser(
+ m_logger, m_configMap, this, m_headerMap);
+ List<BundleCapability> caps = ManifestParser.aliasSymbolicName(mp.getCapabilities(), this);
+ caps.add(buildNativeCapabilites(this, m_configMap));
+ appendCapabilities(caps);
+ }
+ catch (Exception ex)
+ {
+ m_capabilities = Collections.EMPTY_LIST;
+ m_logger.log(
+ Logger.LOG_ERROR,
+ "Error parsing system bundle statement", ex);
+ }
+ }
+
+ private void update(Map configMap)
+ {
+ Properties configProps = Util.toProperties(configMap);
+ // The system bundle exports framework packages as well as
+ // arbitrary user-defined packages from the system class path.
+ // We must construct the system bundle's export metadata.
+ // Get configuration property that specifies which class path
+ // packages should be exported by the system bundle.
+ String syspkgs =
+ "true".equalsIgnoreCase(configProps.getProperty(FelixConstants.USE_PROPERTY_SUBSTITUTION_IN_SYSTEMPACKAGES)) ?
+ Util.getPropertyWithSubs(configProps, FelixConstants.FRAMEWORK_SYSTEMPACKAGES) :
+ configProps.getProperty(FelixConstants.FRAMEWORK_SYSTEMPACKAGES);
+
+ syspkgs = (syspkgs == null) ? "" : syspkgs;
+
+ // If any extra packages are specified, then append them.
+ String pkgextra =
+ "true".equalsIgnoreCase(configProps.getProperty(FelixConstants.USE_PROPERTY_SUBSTITUTION_IN_SYSTEMPACKAGES)) ?
+ Util.getPropertyWithSubs(configProps, FelixConstants.FRAMEWORK_SYSTEMPACKAGES_EXTRA) :
+ configProps.getProperty(FelixConstants.FRAMEWORK_SYSTEMPACKAGES_EXTRA);
+
+ syspkgs = ((pkgextra == null) || (pkgextra.trim().length() == 0))
+ ? syspkgs : syspkgs + (pkgextra.trim().startsWith(",") ? pkgextra : "," + pkgextra);
+
+ m_headerMap.put(FelixConstants.EXPORT_PACKAGE, syspkgs);
+
+ // The system bundle alsp provides framework generic capabilities
+ // as well as arbitrary user-defined generic capabilities. We must
+ // construct the system bundle's capabilitie metadata. Get the
+ // configuration property that specifies which capabilities should
+ // be provided by the system bundle.
+ String syscaps = Util.getPropertyWithSubs(configProps, Constants.FRAMEWORK_SYSTEMCAPABILITIES);
+
+ syscaps = (syscaps == null) ? "" : syscaps;
+
+ // If any extra capabilities are specified, then append them.
+ String capextra = Util.getPropertyWithSubs(configProps, Constants.FRAMEWORK_SYSTEMCAPABILITIES_EXTRA);
+ syscaps = ((capextra == null) || (capextra.trim().length() == 0))
+ ? syscaps : syscaps + (capextra.trim().startsWith(",") ? capextra : "," + capextra);
+
+ m_headerMap.put(FelixConstants.PROVIDE_CAPABILITY, syscaps);
+
+ try
+ {
+ ManifestParser mp = new ManifestParser(
+ m_logger, m_configMap, this, m_headerMap);
+ List<BundleCapability> caps = ManifestParser.aliasSymbolicName(mp.getCapabilities(), this);
+ caps.add(buildNativeCapabilites(this, m_configMap));
+ m_capabilities = Collections.EMPTY_LIST;
+ appendCapabilities(caps);
+ }
+ catch (Exception ex)
+ {
+ m_capabilities = Collections.EMPTY_LIST;
+ m_logger.log(
+ Logger.LOG_ERROR,
+ "Error parsing system bundle statement.", ex);
+ }
+ }
+
+ private void appendCapabilities(List<BundleCapability> caps)
+ {
+ List<BundleCapability> newCaps = new ArrayList<BundleCapability>(m_capabilities.size() + caps.size());
+ newCaps.addAll(m_capabilities);
+ newCaps.addAll(caps);
+ m_capabilities = ImmutableList.newInstance(newCaps);
+ m_headerMap.put(Constants.EXPORT_PACKAGE, convertCapabilitiesToHeaders(newCaps));
+ }
+
+ private String convertCapabilitiesToHeaders(List<BundleCapability> caps)
+ {
+ StringBuffer exportSB = new StringBuffer("");
+ Set<String> exportNames = new HashSet<String>();
+
+ for (BundleCapability cap : caps)
+ {
+ if (cap.getNamespace().equals(BundleRevision.PACKAGE_NAMESPACE))
+ {
+ // Add a comma separate if there is an existing package.
+ if (exportSB.length() > 0)
+ {
+ exportSB.append(", ");
+ }
+
+ // Append exported package information.
+ exportSB.append(cap.getAttributes().get(BundleRevision.PACKAGE_NAMESPACE));
+ for (Entry<String, String> entry : cap.getDirectives().entrySet())
+ {
+ exportSB.append("; ");
+ exportSB.append(entry.getKey());
+ exportSB.append(":=\"");
+ exportSB.append(entry.getValue());
+ exportSB.append("\"");
+ }
+ for (Entry<String, Object> entry : cap.getAttributes().entrySet())
+ {
+ if (!entry.getKey().equals(BundleRevision.PACKAGE_NAMESPACE)
+ && !entry.getKey().equals(Constants.BUNDLE_SYMBOLICNAME_ATTRIBUTE)
+ && !entry.getKey().equals(Constants.BUNDLE_VERSION_ATTRIBUTE))
+ {
+ exportSB.append("; ");
+ exportSB.append(entry.getKey());
+ exportSB.append("=\"");
+ exportSB.append(entry.getValue());
+ exportSB.append("\"");
+ }
+ }
+
+ // Remember exported packages.
+ exportNames.add(
+ (String) cap.getAttributes().get(BundleRevision.PACKAGE_NAMESPACE));
+ }
+ }
+
+ m_exportNames = exportNames;
+
+ return exportSB.toString();
}
@Override
@@ -908,7 +1036,24 @@ class ExtensionManager implements Conten
@Override
public List<BundleCapability> getDeclaredCapabilities(String namespace)
{
- return ExtensionManager.this.getCapabilities(namespace);
+ List<BundleCapability> caps = m_capabilities;
+ List<BundleCapability> result;
+ if (namespace != null)
+ {
+ result = new ArrayList<BundleCapability>();
+ for (BundleCapability cap : caps)
+ {
+ if (cap.getNamespace().equals(namespace))
+ {
+ result.add(cap);
+ }
+ }
+ }
+ else
+ {
+ result = new ArrayList<BundleCapability>(m_capabilities);
+ }
+ return result;
}
@Override
@@ -1000,7 +1145,7 @@ class ExtensionManager implements Conten
@Override
public List<BundleCapability> getCapabilities(String namespace)
{
- return ExtensionManager.this.getCapabilities(namespace);
+ return m_systemBundleRevision.getDeclaredCapabilities(namespace);
}
@Override
@@ -1040,7 +1185,7 @@ class ExtensionManager implements Conten
}
if (clazz == null)
{
- if (!m_exportNames.contains(Util.getClassPackage(name)))
+ if (!m_systemBundleRevision.m_exportNames.contains(Util.getClassPackage(name)))
{
throw new ClassNotFoundException(name);
}
Modified: felix/trunk/osgi-r7/framework/src/main/java/org/apache/felix/framework/Felix.java
URL: http://svn.apache.org/viewvc/felix/trunk/osgi-r7/framework/src/main/java/org/apache/felix/framework/Felix.java?rev=1829104&r1=1829103&r2=1829104&view=diff
==============================================================================
--- felix/trunk/osgi-r7/framework/src/main/java/org/apache/felix/framework/Felix.java (original)
+++ felix/trunk/osgi-r7/framework/src/main/java/org/apache/felix/framework/Felix.java Fri Apr 13 21:13:16 2018
@@ -437,6 +437,7 @@ public class Felix extends BundleImpl im
// Create the extension manager, which we will use as the
// revision for the system bundle.
m_extensionManager = new ExtensionManager(m_logger, m_configMap, this);
+
try
{
addRevision(m_extensionManager.getRevision());
@@ -445,7 +446,7 @@ public class Felix extends BundleImpl im
{
// This should not throw an exception, but if so, lets convert it to
// a runtime exception.
- throw new RuntimeException(ex.getMessage());
+ throw new RuntimeException("Exception creating system bundle revision", ex);
}
// Create event dispatcher.
@@ -735,6 +736,25 @@ public class Felix extends BundleImpl im
maps[IDENTIFIER_MAP_IDX].put(new Long(0), this);
m_installedBundles = maps;
+
+ try
+ {
+ getResolver().removeRevision(m_extensionManager.getRevision());
+ m_extensionManager.removeExtensionBundles();
+ m_extensionManager.updateRevision(this, m_configMap);
+ if (!m_configMutableMap.containsKey(Constants.FRAMEWORK_SYSTEMPACKAGES))
+ {
+ m_configMutableMap.put(Constants.FRAMEWORK_SYSTEMPACKAGES, m_extensionManager.getRevision().getHeaders().get(Constants.EXPORT_PACKAGE));
+ }
+ getResolver().addRevision(m_extensionManager.getRevision());
+ }
+ catch (Exception ex)
+ {
+ // This should not throw an exception, but if so, lets convert it to
+ // a runtime exception.
+ throw new BundleException("Exception creating system bundle revision", ex);
+ }
+
// Manually resolve the system bundle, which will cause its
// state to be set to RESOLVED.
try
@@ -4848,41 +4868,16 @@ public class Felix extends BundleImpl im
Properties defaultProperties = Util.loadDefaultProperties(m_logger);
- Util.initializeJPMS(defaultProperties);
-
Util.initializeJPMSEE(_getProperty("java.specification.version"), defaultProperties, m_logger);
// Set supported execution environments to default value,
// if not explicitly configured.
loadFromDefaultIfNotDefined(defaultProperties, Constants.FRAMEWORK_EXECUTIONENVIRONMENT);
- String sysprops = _getProperty(Constants.FRAMEWORK_SYSTEMPACKAGES);
- if(sysprops != null && "true".equalsIgnoreCase(_getProperty(FelixConstants.USE_PROPERTY_SUBSTITUTION_IN_SYSTEMPACKAGES)) )
- {
- defaultProperties.put(Constants.FRAMEWORK_SYSTEMPACKAGES, sysprops);
- m_configMutableMap.put(Constants.FRAMEWORK_SYSTEMPACKAGES, Util.getPropertyWithSubs(defaultProperties, Constants.FRAMEWORK_SYSTEMPACKAGES));
- }
- else if (sysprops == null)
- {
- m_configMutableMap.put(Constants.FRAMEWORK_SYSTEMPACKAGES, Util.getPropertyWithSubs(defaultProperties, Constants.FRAMEWORK_SYSTEMPACKAGES));
- }
-
- String syscaps = _getProperty(Constants.FRAMEWORK_SYSTEMCAPABILITIES);
- if(syscaps == null)
- {
- m_configMutableMap.put(Constants.FRAMEWORK_SYSTEMCAPABILITIES, Util.getPropertyWithSubs(defaultProperties, Constants.FRAMEWORK_SYSTEMCAPABILITIES));
- }
-
- loadFromDefaultIfNotDefined(defaultProperties, "ee-jpms");
- loadFromDefaultIfNotDefined(defaultProperties, "eecap-jpms");
- loadFromDefaultIfNotDefined(defaultProperties, "felix.detect.java.version");
-
// Set supported native capabilities to default value,
// if not explicitly configured.
loadPrefixFromDefaultIfNotDefined(m_configMutableMap, defaultProperties, FelixConstants.NATIVE_OS_NAME_ALIAS_PREFIX);
loadPrefixFromDefaultIfNotDefined(m_configMutableMap, defaultProperties, FelixConstants.NATIVE_PROC_NAME_ALIAS_PREFIX);
- loadPrefixFromDefaultIfNotDefined(m_configMutableMap, defaultProperties, "felix.detect.jpms.");
- loadPrefixFromDefaultIfNotDefined(m_configMutableMap, defaultProperties, "felix.jpms.");
}
private void loadFromDefaultIfNotDefined(Properties defaultProperties, String propertyName)
@@ -5226,7 +5221,6 @@ public class Felix extends BundleImpl im
m_securityManager = null;
}
- m_extensionManager.removeExtensionBundles();
m_dependencies.removeDependents(adapt(BundleRevision.class));
// Dispose of the bundle cache.
Added: felix/trunk/osgi-r7/framework/src/main/java/org/apache/felix/framework/util/ClassFileVisitor.java
URL: http://svn.apache.org/viewvc/felix/trunk/osgi-r7/framework/src/main/java/org/apache/felix/framework/util/ClassFileVisitor.java?rev=1829104&view=auto
==============================================================================
--- felix/trunk/osgi-r7/framework/src/main/java/org/apache/felix/framework/util/ClassFileVisitor.java (added)
+++ felix/trunk/osgi-r7/framework/src/main/java/org/apache/felix/framework/util/ClassFileVisitor.java Fri Apr 13 21:13:16 2018
@@ -0,0 +1,85 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.framework.util;
+
+import org.codehaus.mojo.animal_sniffer.IgnoreJRERequirement;
+
+import java.io.IOException;
+import java.util.Set;
+import java.util.SortedMap;
+import java.util.SortedSet;
+import java.util.TreeSet;
+
+@IgnoreJRERequirement
+public class ClassFileVisitor extends java.nio.file.SimpleFileVisitor<java.nio.file.Path>
+{
+ private final Set<String> m_imports;
+ private final Set<String> m_exports;
+ private final ClassParser m_classParser;
+ private final SortedMap<String, SortedSet<String>> m_result;
+
+ public ClassFileVisitor(Set<String> imports, Set<String> exports, ClassParser classParser, SortedMap<String, SortedSet<String>> result)
+ {
+ m_imports = imports;
+ m_exports = exports;
+ m_classParser = classParser;
+ m_result = result;
+ }
+
+ @Override
+ public java.nio.file.FileVisitResult visitFile(java.nio.file.Path file, java.nio.file.attribute.BasicFileAttributes attrs) throws IOException
+ {
+ if (file.getNameCount() > 3)
+ {
+ String name = file.subpath(2, file.getNameCount() - 1).toString().replace("/", ".");
+ if (m_exports.contains(name) && file.toString().endsWith(".class"))
+ {
+ SortedSet<String> strings = m_result.get(name);
+
+ if (!name.startsWith("java."))
+ {
+ try
+ {
+ Set<String> refs = m_classParser.parseClassFileUses(file.toString(), java.nio.file.Files.newInputStream(file));
+ refs.retainAll(m_imports);
+ refs.remove(name);
+ if (strings == null)
+ {
+ strings = new TreeSet<String>(refs);
+ m_result.put(name, strings);
+ }
+ else
+ {
+ strings.addAll(refs);
+ }
+ }
+ catch (Exception ex)
+ {
+ ex.printStackTrace();
+ }
+ }
+ else if (strings == null)
+ {
+ m_result.put(name, new TreeSet<String>());
+ }
+ }
+ }
+ return java.nio.file.FileVisitResult.CONTINUE;
+ }
+}
\ No newline at end of file