Merge branch osgiR8 into master
diff --git a/bundles/org.eclipse.osgi.compatibility.state/.classpath b/bundles/org.eclipse.osgi.compatibility.state/.classpath
index 098194c..eca7bdb 100644
--- a/bundles/org.eclipse.osgi.compatibility.state/.classpath
+++ b/bundles/org.eclipse.osgi.compatibility.state/.classpath
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <classpath>
-	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.7"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"/>
 	<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
 	<classpathentry kind="src" path="src"/>
 	<classpathentry kind="output" path="bin"/>
diff --git a/bundles/org.eclipse.osgi.compatibility.state/.settings/org.eclipse.jdt.core.prefs b/bundles/org.eclipse.osgi.compatibility.state/.settings/org.eclipse.jdt.core.prefs
index 4b36b50..d36025c 100644
--- a/bundles/org.eclipse.osgi.compatibility.state/.settings/org.eclipse.jdt.core.prefs
+++ b/bundles/org.eclipse.osgi.compatibility.state/.settings/org.eclipse.jdt.core.prefs
@@ -16,9 +16,9 @@
 org.eclipse.jdt.core.compiler.annotation.nullable.secondary=
 org.eclipse.jdt.core.compiler.annotation.nullanalysis=disabled
 org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
-org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
 org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
-org.eclipse.jdt.core.compiler.compliance=1.7
+org.eclipse.jdt.core.compiler.compliance=1.8
 org.eclipse.jdt.core.compiler.debug.lineNumber=generate
 org.eclipse.jdt.core.compiler.debug.localVariable=generate
 org.eclipse.jdt.core.compiler.debug.sourceFile=generate
@@ -124,23 +124,27 @@
 org.eclipse.jdt.core.compiler.problem.unusedTypeParameter=ignore
 org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning
 org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=error
-org.eclipse.jdt.core.compiler.source=1.7
+org.eclipse.jdt.core.compiler.source=1.8
 org.eclipse.jdt.core.formatter.align_type_members_on_columns=false
+org.eclipse.jdt.core.formatter.alignment_for_additive_operator=16
 org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16
 org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=16
 org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call=16
 org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation=16
 org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression=16
 org.eclipse.jdt.core.formatter.alignment_for_assignment=0
-org.eclipse.jdt.core.formatter.alignment_for_binary_expression=16
+org.eclipse.jdt.core.formatter.alignment_for_bitwise_operator=16
 org.eclipse.jdt.core.formatter.alignment_for_compact_if=16
 org.eclipse.jdt.core.formatter.alignment_for_conditional_expression=80
 org.eclipse.jdt.core.formatter.alignment_for_enum_constants=0
 org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer=16
+org.eclipse.jdt.core.formatter.alignment_for_logical_operator=16
 org.eclipse.jdt.core.formatter.alignment_for_multiple_fields=16
+org.eclipse.jdt.core.formatter.alignment_for_multiplicative_operator=16
 org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration=16
 org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration=16
 org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation=16
+org.eclipse.jdt.core.formatter.alignment_for_string_concatenation=16
 org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration=16
 org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration=16
 org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration=16
@@ -210,11 +214,12 @@
 org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration=insert
 org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body=insert
 org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_after_additive_operator=insert
 org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter=insert
 org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator=insert
 org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation=do not insert
 org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration=do not insert
-org.eclipse.jdt.core.formatter.insert_space_after_binary_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_after_bitwise_operator=insert
 org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments=insert
 org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters=insert
 org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block=insert
@@ -244,6 +249,8 @@
 org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments=insert
 org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters=insert
 org.eclipse.jdt.core.formatter.insert_space_after_ellipsis=insert
+org.eclipse.jdt.core.formatter.insert_space_after_logical_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_after_multiplicative_operator=insert
 org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference=do not insert
 org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments=do not insert
 org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters=do not insert
@@ -267,12 +274,16 @@
 org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator=do not insert
 org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional=insert
 org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_relational_operator=insert
 org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_after_shift_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_after_string_concatenation=insert
 org.eclipse.jdt.core.formatter.insert_space_after_unary_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_additive_operator=insert
 org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter=insert
 org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator=insert
 org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration=insert
-org.eclipse.jdt.core.formatter.insert_space_before_binary_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_before_bitwise_operator=insert
 org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference=do not insert
 org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments=do not insert
 org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters=do not insert
@@ -318,6 +329,8 @@
 org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments=do not insert
 org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters=do not insert
 org.eclipse.jdt.core.formatter.insert_space_before_ellipsis=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_logical_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_before_multiplicative_operator=insert
 org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference=do not insert
 org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments=do not insert
 org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters=do not insert
@@ -353,8 +366,11 @@
 org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator=do not insert
 org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional=insert
 org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_relational_operator=insert
 org.eclipse.jdt.core.formatter.insert_space_before_semicolon=do not insert
 org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_shift_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_before_string_concatenation=insert
 org.eclipse.jdt.core.formatter.insert_space_before_unary_operator=do not insert
 org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference=do not insert
 org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer=do not insert
@@ -377,6 +393,10 @@
 org.eclipse.jdt.core.formatter.tabulation.char=tab
 org.eclipse.jdt.core.formatter.tabulation.size=4
 org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations=false
-org.eclipse.jdt.core.formatter.wrap_before_binary_operator=true
+org.eclipse.jdt.core.formatter.wrap_before_additive_operator=true
+org.eclipse.jdt.core.formatter.wrap_before_bitwise_operator=true
+org.eclipse.jdt.core.formatter.wrap_before_logical_operator=true
+org.eclipse.jdt.core.formatter.wrap_before_multiplicative_operator=true
+org.eclipse.jdt.core.formatter.wrap_before_string_concatenation=true
 org.eclipse.jdt.core.incompatibleJDKLevel=ignore
 org.eclipse.jdt.core.incompleteClasspath=error
diff --git a/bundles/org.eclipse.osgi.compatibility.state/META-INF/MANIFEST.MF b/bundles/org.eclipse.osgi.compatibility.state/META-INF/MANIFEST.MF
index 7f51a90..6153f31 100644
--- a/bundles/org.eclipse.osgi.compatibility.state/META-INF/MANIFEST.MF
+++ b/bundles/org.eclipse.osgi.compatibility.state/META-INF/MANIFEST.MF
@@ -2,9 +2,9 @@
 Bundle-ManifestVersion: 2
 Bundle-Name: %Bundle-Name
 Bundle-SymbolicName: org.eclipse.osgi.compatibility.state
-Bundle-Version: 1.1.800.qualifier
+Bundle-Version: 1.2.0.qualifier
 ExtensionBundle-Activator: org.eclipse.osgi.compatibility.state.Activator
 Fragment-Host: org.eclipse.osgi;bundle-version="3.12.0"
-Bundle-RequiredExecutionEnvironment: JavaSE-1.7
+Bundle-RequiredExecutionEnvironment: JavaSE-1.8
 Bundle-Vendor: %Bundle-Vendor
 Automatic-Module-Name: org.eclipse.osgi.compatibility.state
diff --git a/bundles/org.eclipse.osgi.compatibility.state/pom.xml b/bundles/org.eclipse.osgi.compatibility.state/pom.xml
index a0276f1..cb3b877 100644
--- a/bundles/org.eclipse.osgi.compatibility.state/pom.xml
+++ b/bundles/org.eclipse.osgi.compatibility.state/pom.xml
@@ -19,6 +19,6 @@
   </parent>
   <groupId>org.eclipse.osgi</groupId>
   <artifactId>org.eclipse.osgi.compatibility.state</artifactId>
-  <version>1.1.800-SNAPSHOT</version>
+  <version>1.2.0-SNAPSHOT</version>
   <packaging>eclipse-plugin</packaging>
 </project>
diff --git a/bundles/org.eclipse.osgi.services/.settings/.api_filters b/bundles/org.eclipse.osgi.services/.settings/.api_filters
index 628261d..1f4a3ae 100644
--- a/bundles/org.eclipse.osgi.services/.settings/.api_filters
+++ b/bundles/org.eclipse.osgi.services/.settings/.api_filters
@@ -1,497 +1,10 @@
 <?xml version="1.0" encoding="UTF-8" standalone="no"?>
 <component id="org.eclipse.osgi.services" version="2">
     <resource path="META-INF/MANIFEST.MF">
-        <filter comment="Ignore OSGI API" id="923795461">
+        <filter comment="Semantics of log package changed and package version increased." id="926941240">
             <message_arguments>
+                <message_argument value="3.9.0"/>
                 <message_argument value="3.8.0"/>
-                <message_argument value="3.7.100"/>
-            </message_arguments>
-        </filter>
-    </resource>
-    <resource path="src/org/osgi/service/cm/Configuration.java" type="org.osgi.service.cm.Configuration">
-        <filter comment="Ignore OSGi API" id="403804204">
-            <message_arguments>
-                <message_argument value="org.osgi.service.cm.Configuration"/>
-                <message_argument value="addAttributes(Configuration.ConfigurationAttribute[])"/>
-            </message_arguments>
-        </filter>
-        <filter comment="Ignore OSGi API" id="403804204">
-            <message_arguments>
-                <message_argument value="org.osgi.service.cm.Configuration"/>
-                <message_argument value="getAttributes()"/>
-            </message_arguments>
-        </filter>
-        <filter comment="Ignore OSGi API" id="403804204">
-            <message_arguments>
-                <message_argument value="org.osgi.service.cm.Configuration"/>
-                <message_argument value="getProcessedProperties(ServiceReference&lt;?&gt;)"/>
-            </message_arguments>
-        </filter>
-        <filter comment="Ignore OSGi API" id="403804204">
-            <message_arguments>
-                <message_argument value="org.osgi.service.cm.Configuration"/>
-                <message_argument value="removeAttributes(Configuration.ConfigurationAttribute[])"/>
-            </message_arguments>
-        </filter>
-        <filter comment="Ignore OSGi API" id="403804204">
-            <message_arguments>
-                <message_argument value="org.osgi.service.cm.Configuration"/>
-                <message_argument value="updateIfDifferent(Dictionary&lt;String,?&gt;)"/>
-            </message_arguments>
-        </filter>
-        <filter comment="Ignore OSGi API" id="1209008130">
-            <message_arguments>
-                <message_argument value="1.6"/>
-                <message_argument value="3.8"/>
-                <message_argument value="addAttributes(Configuration.ConfigurationAttribute[])"/>
-            </message_arguments>
-        </filter>
-        <filter comment="Ignore OSGi API" id="1209008130">
-            <message_arguments>
-                <message_argument value="1.6"/>
-                <message_argument value="3.8"/>
-                <message_argument value="getAttributes()"/>
-            </message_arguments>
-        </filter>
-        <filter comment="Ignore OSGi API" id="1209008130">
-            <message_arguments>
-                <message_argument value="1.6"/>
-                <message_argument value="3.8"/>
-                <message_argument value="getProcessedProperties(ServiceReference&lt;?&gt;)"/>
-            </message_arguments>
-        </filter>
-        <filter comment="Ignore OSGi API" id="1209008130">
-            <message_arguments>
-                <message_argument value="1.6"/>
-                <message_argument value="3.8"/>
-                <message_argument value="removeAttributes(Configuration.ConfigurationAttribute[])"/>
-            </message_arguments>
-        </filter>
-        <filter comment="Ignore OSGi API" id="1209008130">
-            <message_arguments>
-                <message_argument value="1.6"/>
-                <message_argument value="3.8"/>
-                <message_argument value="updateIfDifferent(Dictionary&lt;String,?&gt;)"/>
-            </message_arguments>
-        </filter>
-    </resource>
-    <resource path="src/org/osgi/service/cm/Configuration.java" type="org.osgi.service.cm.Configuration$ConfigurationAttribute">
-        <filter comment="Ignore OSGi API" id="1209008130">
-            <message_arguments>
-                <message_argument value="1.6"/>
-                <message_argument value="3.8"/>
-                <message_argument value="ConfigurationAttribute"/>
-            </message_arguments>
-        </filter>
-    </resource>
-    <resource path="src/org/osgi/service/cm/ConfigurationAdmin.java" type="org.osgi.service.cm.ConfigurationAdmin">
-        <filter comment="Ignore OSGi API" id="403804204">
-            <message_arguments>
-                <message_argument value="org.osgi.service.cm.ConfigurationAdmin"/>
-                <message_argument value="getFactoryConfiguration(String, String)"/>
-            </message_arguments>
-        </filter>
-        <filter comment="Ignore OSGi API" id="403804204">
-            <message_arguments>
-                <message_argument value="org.osgi.service.cm.ConfigurationAdmin"/>
-                <message_argument value="getFactoryConfiguration(String, String, String)"/>
-            </message_arguments>
-        </filter>
-        <filter comment="Ignore OSGi API" id="1209008130">
-            <message_arguments>
-                <message_argument value="1.6"/>
-                <message_argument value="3.8"/>
-                <message_argument value="getFactoryConfiguration(String, String)"/>
-            </message_arguments>
-        </filter>
-        <filter comment="Ignore OSGi API" id="1209008130">
-            <message_arguments>
-                <message_argument value="1.6"/>
-                <message_argument value="3.8"/>
-                <message_argument value="getFactoryConfiguration(String, String, String)"/>
-            </message_arguments>
-        </filter>
-    </resource>
-    <resource path="src/org/osgi/service/cm/ConfigurationConstants.java" type="org.osgi.service.cm.ConfigurationConstants">
-        <filter comment="Ignore OSGi API" id="1110441988">
-            <message_arguments>
-                <message_argument value="org.osgi.service.cm.ConfigurationConstants"/>
-            </message_arguments>
-        </filter>
-    </resource>
-    <resource path="src/org/osgi/service/cm/ConfigurationPermission.java" type="org.osgi.service.cm.ConfigurationPermission">
-        <filter comment="Ignore OSGi API" id="1141899266">
-            <message_arguments>
-                <message_argument value="1.6"/>
-                <message_argument value="3.8"/>
-                <message_argument value="ATTRIBUTE"/>
-            </message_arguments>
-        </filter>
-    </resource>
-    <resource path="src/org/osgi/service/cm/ReadOnlyConfigurationException.java" type="org.osgi.service.cm.ReadOnlyConfigurationException">
-        <filter comment="Ignore OSGi API" id="1108344834">
-            <message_arguments>
-                <message_argument value="1.6"/>
-                <message_argument value="3.8"/>
-                <message_argument value="org.osgi.service.cm.ReadOnlyConfigurationException"/>
-            </message_arguments>
-        </filter>
-    </resource>
-    <resource path="src/org/osgi/service/component/ComponentConstants.java" type="org.osgi.service.component.ComponentConstants">
-        <filter comment="Ignore OSGI API" id="403767336">
-            <message_arguments>
-                <message_argument value="org.osgi.service.component.ComponentConstants"/>
-                <message_argument value="COMPONENT_SPECIFICATION_VERSION"/>
-            </message_arguments>
-        </filter>
-        <filter comment="Ignore OSGI API" id="1209008130">
-            <message_arguments>
-                <message_argument value="1.4"/>
-                <message_argument value="3.8"/>
-                <message_argument value="COMPONENT_SPECIFICATION_VERSION"/>
-            </message_arguments>
-        </filter>
-    </resource>
-    <resource path="src/org/osgi/service/component/runtime/dto/ComponentConfigurationDTO.java" type="org.osgi.service.component.runtime.dto.ComponentConfigurationDTO">
-        <filter comment="Ignore OSGI API" id="336658481">
-            <message_arguments>
-                <message_argument value="org.osgi.service.component.runtime.dto.ComponentConfigurationDTO"/>
-                <message_argument value="FAILED_ACTIVATION"/>
-            </message_arguments>
-        </filter>
-        <filter comment="Ignore OSGI API" id="336658481">
-            <message_arguments>
-                <message_argument value="org.osgi.service.component.runtime.dto.ComponentConfigurationDTO"/>
-                <message_argument value="failure"/>
-            </message_arguments>
-        </filter>
-        <filter comment="Ignore OSGI API" id="336658481">
-            <message_arguments>
-                <message_argument value="org.osgi.service.component.runtime.dto.ComponentConfigurationDTO"/>
-                <message_argument value="service"/>
-            </message_arguments>
-        </filter>
-        <filter comment="Ignore OSGI API" id="1141899266">
-            <message_arguments>
-                <message_argument value="1.4"/>
-                <message_argument value="3.8"/>
-                <message_argument value="FAILED_ACTIVATION"/>
-            </message_arguments>
-        </filter>
-        <filter comment="Ignore OSGI API" id="1141899266">
-            <message_arguments>
-                <message_argument value="1.4"/>
-                <message_argument value="3.8"/>
-                <message_argument value="failure"/>
-            </message_arguments>
-        </filter>
-        <filter comment="Ignore OSGI API" id="1141899266">
-            <message_arguments>
-                <message_argument value="1.4"/>
-                <message_argument value="3.8"/>
-                <message_argument value="service"/>
-            </message_arguments>
-        </filter>
-    </resource>
-    <resource path="src/org/osgi/service/component/runtime/dto/ComponentDescriptionDTO.java" type="org.osgi.service.component.runtime.dto.ComponentDescriptionDTO">
-        <filter comment="Ignore OSGI API" id="336658481">
-            <message_arguments>
-                <message_argument value="org.osgi.service.component.runtime.dto.ComponentDescriptionDTO"/>
-                <message_argument value="activationFields"/>
-            </message_arguments>
-        </filter>
-        <filter comment="Ignore OSGI API" id="336658481">
-            <message_arguments>
-                <message_argument value="org.osgi.service.component.runtime.dto.ComponentDescriptionDTO"/>
-                <message_argument value="factoryProperties"/>
-            </message_arguments>
-        </filter>
-        <filter comment="Ignore OSGI API" id="336658481">
-            <message_arguments>
-                <message_argument value="org.osgi.service.component.runtime.dto.ComponentDescriptionDTO"/>
-                <message_argument value="init"/>
-            </message_arguments>
-        </filter>
-        <filter comment="Ignore OSGI API" id="1141899266">
-            <message_arguments>
-                <message_argument value="1.4"/>
-                <message_argument value="3.8"/>
-                <message_argument value="activationFields"/>
-            </message_arguments>
-        </filter>
-        <filter comment="Ignore OSGI API" id="1141899266">
-            <message_arguments>
-                <message_argument value="1.4"/>
-                <message_argument value="3.8"/>
-                <message_argument value="factoryProperties"/>
-            </message_arguments>
-        </filter>
-        <filter comment="Ignore OSGI API" id="1141899266">
-            <message_arguments>
-                <message_argument value="1.4"/>
-                <message_argument value="3.8"/>
-                <message_argument value="init"/>
-            </message_arguments>
-        </filter>
-    </resource>
-    <resource path="src/org/osgi/service/component/runtime/dto/ReferenceDTO.java" type="org.osgi.service.component.runtime.dto.ReferenceDTO">
-        <filter comment="Ignore OSGI API" id="336658481">
-            <message_arguments>
-                <message_argument value="org.osgi.service.component.runtime.dto.ReferenceDTO"/>
-                <message_argument value="collectionType"/>
-            </message_arguments>
-        </filter>
-        <filter comment="Ignore OSGI API" id="336658481">
-            <message_arguments>
-                <message_argument value="org.osgi.service.component.runtime.dto.ReferenceDTO"/>
-                <message_argument value="parameter"/>
-            </message_arguments>
-        </filter>
-        <filter comment="Ignore OSGI API" id="1141899266">
-            <message_arguments>
-                <message_argument value="1.4"/>
-                <message_argument value="3.8"/>
-                <message_argument value="collectionType"/>
-            </message_arguments>
-        </filter>
-        <filter comment="Ignore OSGI API" id="1141899266">
-            <message_arguments>
-                <message_argument value="1.4"/>
-                <message_argument value="3.8"/>
-                <message_argument value="parameter"/>
-            </message_arguments>
-        </filter>
-    </resource>
-    <resource path="src/org/osgi/service/http/context/ServletContextHelper.java" type="org.osgi.service.http.context.ServletContextHelper">
-        <filter comment="Ignore OSGi API" id="1141899266">
-            <message_arguments>
-                <message_argument value="1.1"/>
-                <message_argument value="3.8"/>
-                <message_argument value="finishSecurity(HttpServletRequest, HttpServletResponse)"/>
-            </message_arguments>
-        </filter>
-    </resource>
-    <resource path="src/org/osgi/service/http/runtime/dto/DTOConstants.java" type="org.osgi.service.http.runtime.dto.DTOConstants">
-        <filter comment="Ignore OSGi API" id="1141899266">
-            <message_arguments>
-                <message_argument value="1.1"/>
-                <message_argument value="3.8"/>
-                <message_argument value="FAILURE_REASON_SERVLET_READ_FROM_DEFAULT_DENIED"/>
-            </message_arguments>
-        </filter>
-        <filter comment="Ignore OSGi API" id="1141899266">
-            <message_arguments>
-                <message_argument value="1.1"/>
-                <message_argument value="3.8"/>
-                <message_argument value="FAILURE_REASON_SERVLET_WRITE_TO_LOCATION_DENIED"/>
-            </message_arguments>
-        </filter>
-        <filter comment="Ignore OSGi API" id="1141899266">
-            <message_arguments>
-                <message_argument value="1.1"/>
-                <message_argument value="3.8"/>
-                <message_argument value="FAILURE_REASON_WHITEBOARD_WRITE_TO_DEFAULT_DENIED"/>
-            </message_arguments>
-        </filter>
-        <filter comment="Ignore OSGi API" id="1141899266">
-            <message_arguments>
-                <message_argument value="1.1"/>
-                <message_argument value="3.8"/>
-                <message_argument value="FAILURE_REASON_WHITEBOARD_WRITE_TO_LOCATION_DENIED"/>
-            </message_arguments>
-        </filter>
-    </resource>
-    <resource path="src/org/osgi/service/http/runtime/dto/FailedPreprocessorDTO.java" type="org.osgi.service.http.runtime.dto.FailedPreprocessorDTO">
-        <filter comment="Ignore OSGi API" id="1108344834">
-            <message_arguments>
-                <message_argument value="1.1"/>
-                <message_argument value="3.8"/>
-                <message_argument value="org.osgi.service.http.runtime.dto.FailedPreprocessorDTO"/>
-            </message_arguments>
-        </filter>
-    </resource>
-    <resource path="src/org/osgi/service/http/runtime/dto/PreprocessorDTO.java" type="org.osgi.service.http.runtime.dto.PreprocessorDTO">
-        <filter comment="Ignore OSGi API" id="1108344834">
-            <message_arguments>
-                <message_argument value="1.1"/>
-                <message_argument value="3.8"/>
-                <message_argument value="org.osgi.service.http.runtime.dto.PreprocessorDTO"/>
-            </message_arguments>
-        </filter>
-    </resource>
-    <resource path="src/org/osgi/service/http/runtime/dto/RuntimeDTO.java" type="org.osgi.service.http.runtime.dto.RuntimeDTO">
-        <filter comment="Ignore OSGi API" id="336658481">
-            <message_arguments>
-                <message_argument value="org.osgi.service.http.runtime.dto.RuntimeDTO"/>
-                <message_argument value="failedPreprocessorDTOs"/>
-            </message_arguments>
-        </filter>
-        <filter comment="Ignore OSGi API" id="336658481">
-            <message_arguments>
-                <message_argument value="org.osgi.service.http.runtime.dto.RuntimeDTO"/>
-                <message_argument value="preprocessorDTOs"/>
-            </message_arguments>
-        </filter>
-        <filter comment="Ignore OSGi API" id="1141899266">
-            <message_arguments>
-                <message_argument value="1.1"/>
-                <message_argument value="3.8"/>
-                <message_argument value="failedPreprocessorDTOs"/>
-            </message_arguments>
-        </filter>
-        <filter comment="Ignore OSGi API" id="1141899266">
-            <message_arguments>
-                <message_argument value="1.1"/>
-                <message_argument value="3.8"/>
-                <message_argument value="preprocessorDTOs"/>
-            </message_arguments>
-        </filter>
-    </resource>
-    <resource path="src/org/osgi/service/http/runtime/dto/ServletDTO.java" type="org.osgi.service.http.runtime.dto.ServletDTO">
-        <filter comment="Ignore OSGi API" id="336658481">
-            <message_arguments>
-                <message_argument value="org.osgi.service.http.runtime.dto.ServletDTO"/>
-                <message_argument value="multipartEnabled"/>
-            </message_arguments>
-        </filter>
-        <filter comment="Ignore OSGi API" id="336658481">
-            <message_arguments>
-                <message_argument value="org.osgi.service.http.runtime.dto.ServletDTO"/>
-                <message_argument value="multipartFileSizeThreshold"/>
-            </message_arguments>
-        </filter>
-        <filter comment="Ignore OSGi API" id="336658481">
-            <message_arguments>
-                <message_argument value="org.osgi.service.http.runtime.dto.ServletDTO"/>
-                <message_argument value="multipartLocation"/>
-            </message_arguments>
-        </filter>
-        <filter comment="Ignore OSGi API" id="336658481">
-            <message_arguments>
-                <message_argument value="org.osgi.service.http.runtime.dto.ServletDTO"/>
-                <message_argument value="multipartMaxFileSize"/>
-            </message_arguments>
-        </filter>
-        <filter comment="Ignore OSGi API" id="336658481">
-            <message_arguments>
-                <message_argument value="org.osgi.service.http.runtime.dto.ServletDTO"/>
-                <message_argument value="multipartMaxRequestSize"/>
-            </message_arguments>
-        </filter>
-        <filter comment="Ignore OSGi API" id="1141899266">
-            <message_arguments>
-                <message_argument value="1.1"/>
-                <message_argument value="3.8"/>
-                <message_argument value="multipartEnabled"/>
-            </message_arguments>
-        </filter>
-        <filter comment="Ignore OSGi API" id="1141899266">
-            <message_arguments>
-                <message_argument value="1.1"/>
-                <message_argument value="3.8"/>
-                <message_argument value="multipartFileSizeThreshold"/>
-            </message_arguments>
-        </filter>
-        <filter comment="Ignore OSGi API" id="1141899266">
-            <message_arguments>
-                <message_argument value="1.1"/>
-                <message_argument value="3.8"/>
-                <message_argument value="multipartLocation"/>
-            </message_arguments>
-        </filter>
-        <filter comment="Ignore OSGi API" id="1141899266">
-            <message_arguments>
-                <message_argument value="1.1"/>
-                <message_argument value="3.8"/>
-                <message_argument value="multipartMaxFileSize"/>
-            </message_arguments>
-        </filter>
-        <filter comment="Ignore OSGi API" id="1141899266">
-            <message_arguments>
-                <message_argument value="1.1"/>
-                <message_argument value="3.8"/>
-                <message_argument value="multipartMaxRequestSize"/>
-            </message_arguments>
-        </filter>
-    </resource>
-    <resource path="src/org/osgi/service/http/whiteboard/HttpWhiteboardConstants.java" type="org.osgi.service.http.whiteboard.HttpWhiteboardConstants">
-        <filter comment="Ignore OSGi API" id="1141899266">
-            <message_arguments>
-                <message_argument value="1.1"/>
-                <message_argument value="3.8"/>
-                <message_argument value="HTTP_SERVICE_CONTEXT_FILTER"/>
-            </message_arguments>
-        </filter>
-        <filter comment="Ignore OSGi API" id="1141899266">
-            <message_arguments>
-                <message_argument value="1.1"/>
-                <message_argument value="3.8"/>
-                <message_argument value="HTTP_SERVICE_CONTEXT_PROPERTY"/>
-            </message_arguments>
-        </filter>
-        <filter comment="Ignore OSGi API" id="1141899266">
-            <message_arguments>
-                <message_argument value="1.1"/>
-                <message_argument value="3.8"/>
-                <message_argument value="HTTP_WHITEBOARD_IMPLEMENTATION"/>
-            </message_arguments>
-        </filter>
-        <filter comment="Ignore OSGi API" id="1141899266">
-            <message_arguments>
-                <message_argument value="1.1"/>
-                <message_argument value="3.8"/>
-                <message_argument value="HTTP_WHITEBOARD_PREPROCESSOR_INIT_PARAM_PREFIX"/>
-            </message_arguments>
-        </filter>
-        <filter comment="Ignore OSGi API" id="1141899266">
-            <message_arguments>
-                <message_argument value="1.1"/>
-                <message_argument value="3.8"/>
-                <message_argument value="HTTP_WHITEBOARD_SERVLET_MULTIPART_ENABLED"/>
-            </message_arguments>
-        </filter>
-        <filter comment="Ignore OSGi API" id="1141899266">
-            <message_arguments>
-                <message_argument value="1.1"/>
-                <message_argument value="3.8"/>
-                <message_argument value="HTTP_WHITEBOARD_SERVLET_MULTIPART_FILESIZETHRESHOLD"/>
-            </message_arguments>
-        </filter>
-        <filter comment="Ignore OSGi API" id="1141899266">
-            <message_arguments>
-                <message_argument value="1.1"/>
-                <message_argument value="3.8"/>
-                <message_argument value="HTTP_WHITEBOARD_SERVLET_MULTIPART_LOCATION"/>
-            </message_arguments>
-        </filter>
-        <filter comment="Ignore OSGi API" id="1141899266">
-            <message_arguments>
-                <message_argument value="1.1"/>
-                <message_argument value="3.8"/>
-                <message_argument value="HTTP_WHITEBOARD_SERVLET_MULTIPART_MAXFILESIZE"/>
-            </message_arguments>
-        </filter>
-        <filter comment="Ignore OSGi API" id="1141899266">
-            <message_arguments>
-                <message_argument value="1.1"/>
-                <message_argument value="3.8"/>
-                <message_argument value="HTTP_WHITEBOARD_SERVLET_MULTIPART_MAXREQUESTSIZE"/>
-            </message_arguments>
-        </filter>
-        <filter comment="Ignore OSGi API" id="1141899266">
-            <message_arguments>
-                <message_argument value="1.1"/>
-                <message_argument value="3.8"/>
-                <message_argument value="HTTP_WHITEBOARD_SPECIFICATION_VERSION"/>
-            </message_arguments>
-        </filter>
-    </resource>
-    <resource path="src/org/osgi/service/http/whiteboard/Preprocessor.java" type="org.osgi.service.http.whiteboard.Preprocessor">
-        <filter comment="Ignore OSGi API" id="1108344834">
-            <message_arguments>
-                <message_argument value="1.1"/>
-                <message_argument value="3.8"/>
-                <message_argument value="org.osgi.service.http.whiteboard.Preprocessor"/>
             </message_arguments>
         </filter>
     </resource>
diff --git a/bundles/org.eclipse.osgi.services/.settings/org.eclipse.jdt.core.prefs b/bundles/org.eclipse.osgi.services/.settings/org.eclipse.jdt.core.prefs
index 0b08c18..c352a71 100644
--- a/bundles/org.eclipse.osgi.services/.settings/org.eclipse.jdt.core.prefs
+++ b/bundles/org.eclipse.osgi.services/.settings/org.eclipse.jdt.core.prefs
@@ -9,8 +9,11 @@
 org.eclipse.jdt.core.compiler.annotation.inheritNullAnnotations=disabled
 org.eclipse.jdt.core.compiler.annotation.missingNonNullByDefaultAnnotation=ignore
 org.eclipse.jdt.core.compiler.annotation.nonnull=org.eclipse.jdt.annotation.NonNull
+org.eclipse.jdt.core.compiler.annotation.nonnull.secondary=
 org.eclipse.jdt.core.compiler.annotation.nonnullbydefault=org.eclipse.jdt.annotation.NonNullByDefault
+org.eclipse.jdt.core.compiler.annotation.nonnullbydefault.secondary=
 org.eclipse.jdt.core.compiler.annotation.nullable=org.eclipse.jdt.annotation.Nullable
+org.eclipse.jdt.core.compiler.annotation.nullable.secondary=
 org.eclipse.jdt.core.compiler.annotation.nullanalysis=disabled
 org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
 org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7
@@ -21,6 +24,8 @@
 org.eclipse.jdt.core.compiler.debug.sourceFile=generate
 org.eclipse.jdt.core.compiler.doc.comment.support=enabled
 org.eclipse.jdt.core.compiler.maxProblemPerUnit=1000
+org.eclipse.jdt.core.compiler.problem.APILeak=warning
+org.eclipse.jdt.core.compiler.problem.annotatedTypeArgumentToUnannotated=info
 org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning
 org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
 org.eclipse.jdt.core.compiler.problem.autoboxing=ignore
@@ -66,12 +71,14 @@
 org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning
 org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=ignore
 org.eclipse.jdt.core.compiler.problem.nonnullParameterAnnotationDropped=warning
+org.eclipse.jdt.core.compiler.problem.nonnullTypeVariableFromLegacyInvocation=warning
 org.eclipse.jdt.core.compiler.problem.nullAnnotationInferenceConflict=error
 org.eclipse.jdt.core.compiler.problem.nullReference=warning
 org.eclipse.jdt.core.compiler.problem.nullSpecViolation=error
 org.eclipse.jdt.core.compiler.problem.nullUncheckedConversion=warning
 org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning
 org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore
+org.eclipse.jdt.core.compiler.problem.pessimisticNullAnalysisForFreeTypeVariables=warning
 org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=warning
 org.eclipse.jdt.core.compiler.problem.potentialNullReference=ignore
 org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=ignore
@@ -86,21 +93,28 @@
 org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning
 org.eclipse.jdt.core.compiler.problem.suppressOptionalErrors=disabled
 org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled
+org.eclipse.jdt.core.compiler.problem.suppressWarningsNotFullyAnalysed=info
 org.eclipse.jdt.core.compiler.problem.syntacticNullAnalysisForFields=disabled
 org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=warning
+org.eclipse.jdt.core.compiler.problem.terminalDeprecation=warning
 org.eclipse.jdt.core.compiler.problem.typeParameterHiding=warning
 org.eclipse.jdt.core.compiler.problem.unavoidableGenericTypeProblems=disabled
 org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning
 org.eclipse.jdt.core.compiler.problem.unclosedCloseable=warning
 org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=warning
 org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning
+org.eclipse.jdt.core.compiler.problem.unlikelyCollectionMethodArgumentType=warning
+org.eclipse.jdt.core.compiler.problem.unlikelyCollectionMethodArgumentTypeStrict=disabled
+org.eclipse.jdt.core.compiler.problem.unlikelyEqualsArgumentType=info
 org.eclipse.jdt.core.compiler.problem.unnecessaryElse=warning
 org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=warning
 org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore
+org.eclipse.jdt.core.compiler.problem.unstableAutoModuleName=warning
 org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=warning
 org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=enabled
 org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=enabled
 org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=enabled
+org.eclipse.jdt.core.compiler.problem.unusedExceptionParameter=ignore
 org.eclipse.jdt.core.compiler.problem.unusedImport=error
 org.eclipse.jdt.core.compiler.problem.unusedLabel=warning
 org.eclipse.jdt.core.compiler.problem.unusedLocal=warning
diff --git a/bundles/org.eclipse.osgi.services/.settings/org.eclipse.pde.api.tools.prefs b/bundles/org.eclipse.osgi.services/.settings/org.eclipse.pde.api.tools.prefs
index e2758b7..fa3737c 100644
--- a/bundles/org.eclipse.osgi.services/.settings/org.eclipse.pde.api.tools.prefs
+++ b/bundles/org.eclipse.osgi.services/.settings/org.eclipse.pde.api.tools.prefs
@@ -94,7 +94,7 @@
 eclipse.preferences.version=1
 incompatible_api_component_version=Error
 incompatible_api_component_version_report_major_without_breaking_change=Warning
-incompatible_api_component_version_report_minor_without_api_change=Warning
+incompatible_api_component_version_report_minor_without_api_change=Error
 invalid_since_tag_version=Error
 malformed_since_tag=Error
 missing_since_tag=Error
diff --git a/bundles/org.eclipse.osgi.services/META-INF/MANIFEST.MF b/bundles/org.eclipse.osgi.services/META-INF/MANIFEST.MF
index 5129383..79ba75f 100644
--- a/bundles/org.eclipse.osgi.services/META-INF/MANIFEST.MF
+++ b/bundles/org.eclipse.osgi.services/META-INF/MANIFEST.MF
@@ -2,7 +2,7 @@
 Bundle-ManifestVersion: 2
 Bundle-Name: %osgiServices
 Bundle-SymbolicName: org.eclipse.osgi.services
-Bundle-Version: 3.8.0.qualifier
+Bundle-Version: 3.9.0.qualifier
 Bundle-Description: %osgiServicesDes
 Bundle-Localization: plugin
 Bundle-Vendor: %eclipse.org
@@ -20,7 +20,7 @@
  org.osgi.service.http.runtime;version="1.1";uses:="org.osgi.service.http.runtime.dto",
  org.osgi.service.http.runtime.dto;version="1.1";uses:="org.osgi.dto,org.osgi.framework.dto",
  org.osgi.service.http.whiteboard;version="1.1",
- org.osgi.service.log;version="1.4";uses:="org.osgi.framework",
+ org.osgi.service.log;version="1.5";uses:="org.osgi.framework",
  org.osgi.service.metatype;version="1.4";uses:="org.osgi.framework",
  org.osgi.service.provisioning;version="1.2",
  org.osgi.service.upnp;version="1.2",
@@ -43,7 +43,7 @@
  org.osgi.service.http.runtime;version="[1.1,1.2)",
  org.osgi.service.http.runtime.dto;version="[1.1,1.2)",
  org.osgi.service.http.whiteboard;version="[1.1,1.2)",
- org.osgi.service.log;version="[1.4,1.5)",
+ org.osgi.service.log;version="[1.5,1.6)",
  org.osgi.service.metatype;version="[1.4,1.5)",
  org.osgi.service.provisioning;version="[1.2,1.3)",
  org.osgi.service.upnp;version="[1.2,1.3)",
diff --git a/bundles/org.eclipse.osgi.services/pom.xml b/bundles/org.eclipse.osgi.services/pom.xml
index 63eaa42..c757ef1 100644
--- a/bundles/org.eclipse.osgi.services/pom.xml
+++ b/bundles/org.eclipse.osgi.services/pom.xml
@@ -19,7 +19,7 @@
   </parent>
   <groupId>org.eclipse.osgi</groupId>
   <artifactId>org.eclipse.osgi.services</artifactId>
-  <version>3.8.0-SNAPSHOT</version>
+  <version>3.9.0-SNAPSHOT</version>
   <packaging>eclipse-plugin</packaging>
   <build>
     <plugins>
diff --git a/bundles/org.eclipse.osgi.services/src/org/osgi/service/log/LogService.java b/bundles/org.eclipse.osgi.services/src/org/osgi/service/log/LogService.java
index 55d1069..b5b08d7 100644
--- a/bundles/org.eclipse.osgi.services/src/org/osgi/service/log/LogService.java
+++ b/bundles/org.eclipse.osgi.services/src/org/osgi/service/log/LogService.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) OSGi Alliance (2000, 2016). All Rights Reserved.
+ * Copyright (c) OSGi Alliance (2000, 2020). All Rights Reserved.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -75,9 +75,11 @@
 	 * The {@code ServiceReference} field and the {@code Throwable} field of the
 	 * {@code LogEntry} object will be set to {@code null}.
 	 * <p>
-	 * This method will log to the {@link Logger} named {@code "LogService"} for
-	 * the bundle. The specified level is mapped to a {@link LogLevel} as
-	 * follows:
+	 * This method will log to the bundle's {@link Logger} named
+	 * {@code "LogService.<bsn>"} where {@code <bsn>} is the Bundle Symbolic
+	 * Name of the bundle.
+	 * <p>
+	 * The specified level is mapped to a {@link LogLevel} as follows:
 	 * <ul>
 	 * <li>{@link #LOG_ERROR} - {@link LogLevel#ERROR}</li>
 	 * <li>{@link #LOG_WARNING} - {@link LogLevel#WARN}</li>
@@ -105,9 +107,11 @@
 	 * The {@code ServiceReference} field of the {@code LogEntry} object will be
 	 * set to {@code null}.
 	 * <p>
-	 * This method will log to the {@link Logger} named {@code "LogService"} for
-	 * the bundle. The specified level is mapped to a {@link LogLevel} as
-	 * follows:
+	 * This method will log to the bundle's {@link Logger} named
+	 * {@code "LogService.<bsn>"} where {@code <bsn>} is the Bundle Symbolic
+	 * Name of the bundle.
+	 * <p>
+	 * The specified level is mapped to a {@link LogLevel} as follows:
 	 * <ul>
 	 * <li>{@link #LOG_ERROR} - {@link LogLevel#ERROR}</li>
 	 * <li>{@link #LOG_WARNING} - {@link LogLevel#WARN}</li>
@@ -138,9 +142,11 @@
 	 * The {@code Throwable} field of the {@code LogEntry} will be set to
 	 * {@code null}.
 	 * <p>
-	 * This method will log to the {@link Logger} named {@code "LogService"} for
-	 * the bundle. The specified level is mapped to a {@link LogLevel} as
-	 * follows:
+	 * This method will log to the bundle's {@link Logger} named
+	 * {@code "LogService.<bsn>"} where {@code <bsn>} is the Bundle Symbolic
+	 * Name of the bundle.
+	 * <p>
+	 * The specified level is mapped to a {@link LogLevel} as follows:
 	 * <ul>
 	 * <li>{@link #LOG_ERROR} - {@link LogLevel#ERROR}</li>
 	 * <li>{@link #LOG_WARNING} - {@link LogLevel#WARN}</li>
@@ -168,9 +174,11 @@
 	 * Logs a message with an exception associated and a
 	 * {@code ServiceReference} object.
 	 * <p>
-	 * This method will log to the {@link Logger} named {@code "LogService"} for
-	 * the bundle. The specified level is mapped to a {@link LogLevel} as
-	 * follows:
+	 * This method will log to the bundle's {@link Logger} named
+	 * {@code "LogService.<bsn>"} where {@code <bsn>} is the Bundle Symbolic
+	 * Name of the bundle.
+	 * <p>
+	 * The specified level is mapped to a {@link LogLevel} as follows:
 	 * <ul>
 	 * <li>{@link #LOG_ERROR} - {@link LogLevel#ERROR}</li>
 	 * <li>{@link #LOG_WARNING} - {@link LogLevel#WARN}</li>
diff --git a/bundles/org.eclipse.osgi.services/src/org/osgi/service/log/package-info.java b/bundles/org.eclipse.osgi.services/src/org/osgi/service/log/package-info.java
index 81c287a..b053188 100644
--- a/bundles/org.eclipse.osgi.services/src/org/osgi/service/log/package-info.java
+++ b/bundles/org.eclipse.osgi.services/src/org/osgi/service/log/package-info.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) OSGi Alliance (2010, 2016). All Rights Reserved.
+ * Copyright (c) OSGi Alliance (2010, 2020). All Rights Reserved.
  * 
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -15,7 +15,7 @@
  */
 
 /**
- * Log Service Package Version 1.4.
+ * Log Service Package Version 1.5.
  * <p>
  * Bundles wishing to use this package must list the package in the
  * Import-Package header of the bundle's manifest. This package has two types of
@@ -24,15 +24,15 @@
  * <p>
  * Example import for consumers using the API in this package:
  * <p>
- * {@code  Import-Package: org.osgi.service.log; version="[1.4,2.0)"}
+ * {@code  Import-Package: org.osgi.service.log; version="[1.5,2.0)"}
  * <p>
  * Example import for providers implementing the API in this package:
  * <p>
- * {@code  Import-Package: org.osgi.service.log; version="[1.4,1.5)"}
+ * {@code  Import-Package: org.osgi.service.log; version="[1.5,1.6)"}
  * 
  * @author $Id$
  */
-@Version("1.4")
+@Version("1.5")
 package org.osgi.service.log;
 
 import org.osgi.annotation.versioning.Version;
diff --git a/bundles/org.eclipse.osgi.tests/.classpath b/bundles/org.eclipse.osgi.tests/.classpath
index cc89595..2d89fd7 100644
--- a/bundles/org.eclipse.osgi.tests/.classpath
+++ b/bundles/org.eclipse.osgi.tests/.classpath
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <classpath>
-	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.7"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"/>
 	<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
 	<classpathentry kind="src" path="src"/>
 	<classpathentry kind="src" output="bundle_tests/test" path="bundles_src/test"/>
@@ -112,6 +112,7 @@
 	<classpathentry kind="src" output="bundle_tests/geturl" path="bundles_src/geturl"/>
 	<classpathentry kind="src" output="bundle_tests/test.bug375784" path="bundles_src/test.bug375784"/>
 	<classpathentry kind="src" output="bundle_tests/storage.hooks.a" path="bundles_src/storage.hooks.a"/>
+	<classpathentry kind="src" output="bundle_tests/activator.hooks.a" path="bundles_src/activator.hooks.a"/>
 	<classpathentry kind="src" output="bundle_tests/test.bug412228" path="bundles_src/test.bug412228"/>
 	<classpathentry kind="src" output="bundle_tests/test.uninstall.start1" path="bundles_src/test.uninstall.start1"/>
 	<classpathentry kind="src" output="bundle_tests/test.uninstall.start2" path="bundles_src/test.uninstall.start2"/>
diff --git a/bundles/org.eclipse.osgi.tests/.settings/org.eclipse.jdt.core.prefs b/bundles/org.eclipse.osgi.tests/.settings/org.eclipse.jdt.core.prefs
index d607898..25c2151 100644
--- a/bundles/org.eclipse.osgi.tests/.settings/org.eclipse.jdt.core.prefs
+++ b/bundles/org.eclipse.osgi.tests/.settings/org.eclipse.jdt.core.prefs
@@ -17,9 +17,9 @@
 org.eclipse.jdt.core.compiler.annotation.nullanalysis=disabled
 org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
 org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate
-org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
 org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
-org.eclipse.jdt.core.compiler.compliance=1.7
+org.eclipse.jdt.core.compiler.compliance=1.8
 org.eclipse.jdt.core.compiler.debug.lineNumber=generate
 org.eclipse.jdt.core.compiler.debug.localVariable=generate
 org.eclipse.jdt.core.compiler.debug.sourceFile=generate
@@ -131,7 +131,7 @@
 org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning
 org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning
 org.eclipse.jdt.core.compiler.release=disabled
-org.eclipse.jdt.core.compiler.source=1.7
+org.eclipse.jdt.core.compiler.source=1.8
 org.eclipse.jdt.core.formatter.align_assignment_statements_on_columns=false
 org.eclipse.jdt.core.formatter.align_fields_grouping_blank_lines=2147483647
 org.eclipse.jdt.core.formatter.align_type_members_on_columns=false
diff --git a/bundles/org.eclipse.osgi.tests/META-INF/MANIFEST.MF b/bundles/org.eclipse.osgi.tests/META-INF/MANIFEST.MF
index f59d996..fb97223 100644
--- a/bundles/org.eclipse.osgi.tests/META-INF/MANIFEST.MF
+++ b/bundles/org.eclipse.osgi.tests/META-INF/MANIFEST.MF
@@ -2,7 +2,7 @@
 Bundle-ManifestVersion: 2
 Bundle-Name: Core OSGi Tests
 Bundle-SymbolicName: org.eclipse.osgi.tests;singleton:=true
-Bundle-Version: 3.15.400.qualifier
+Bundle-Version: 3.16.0.qualifier
 Bundle-Vendor: Eclipse.org
 Require-Bundle: 
  org.eclipse.core.runtime,
@@ -14,7 +14,7 @@
 Import-Package: org.osgi.service.event; resolution:="optional"
 Export-Package: org.eclipse.osgi.tests.bundles,
  org.eclipse.osgi.tests.appadmin
-Bundle-RequiredExecutionEnvironment: JavaSE-1.7
+Bundle-RequiredExecutionEnvironment: JavaSE-1.8
 DynamicImport-Package: ext.framework.b
 Eclipse-BundleShape: dir
 Automatic-Module-Name: org.eclipse.osgi.tests
diff --git a/bundles/org.eclipse.osgi.tests/build.properties b/bundles/org.eclipse.osgi.tests/build.properties
index 0054cac..91c0b2d 100644
--- a/bundles/org.eclipse.osgi.tests/build.properties
+++ b/bundles/org.eclipse.osgi.tests/build.properties
@@ -239,6 +239,8 @@
 manifest.bundle_tests/test.bug375784.jar = META-INF/MANIFEST.MF
 source.bundle_tests/storage.hooks.a.jar = bundles_src/storage.hooks.a/
 manifest.bundle_tests/storage.hooks.a.jar = META-INF/MANIFEST.MF
+source.bundle_tests/activator.hooks.a.jar = bundles_src/activator.hooks.a/
+manifest.bundle_tests/activator.hooks.a.jar = META-INF/MANIFEST.MF
 source.bundle_tests/test.bug412228.jar = bundles_src/test.bug412228/
 manifest.bundle_tests/test.bug412228.jar = META-INF/MANIFEST.MF
 source.bundle_tests/test.uninstall.start1.jar = bundles_src/test.uninstall.start1/
@@ -388,6 +390,7 @@
                      bundle_tests/geturl.jar,\
                      bundle_tests/test.bug375784.jar,\
                      bundle_tests/storage.hooks.a.jar,\
+                     bundle_tests/activator.hooks.a.jar,\
                      bundle_tests/test.plugins.a.jar,\
                      bundle_tests/test.plugins.b.jar,\
                      bundle_tests/test.plugins.c.jar,\
diff --git a/bundles/org.eclipse.osgi.tests/bundles_src/activator.hooks.a/META-INF/MANIFEST.MF b/bundles/org.eclipse.osgi.tests/bundles_src/activator.hooks.a/META-INF/MANIFEST.MF
new file mode 100644
index 0000000..9ced5b5
--- /dev/null
+++ b/bundles/org.eclipse.osgi.tests/bundles_src/activator.hooks.a/META-INF/MANIFEST.MF
@@ -0,0 +1,3 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-SymbolicName: activator.hooks.a
diff --git a/bundles/org.eclipse.osgi.tests/bundles_src/activator.hooks.a/org/eclipse/osgi/tests/hooks/framework/activator/a/TestHookConfigurator1.java b/bundles/org.eclipse.osgi.tests/bundles_src/activator.hooks.a/org/eclipse/osgi/tests/hooks/framework/activator/a/TestHookConfigurator1.java
new file mode 100644
index 0000000..1c1057f
--- /dev/null
+++ b/bundles/org.eclipse.osgi.tests/bundles_src/activator.hooks.a/org/eclipse/osgi/tests/hooks/framework/activator/a/TestHookConfigurator1.java
@@ -0,0 +1,51 @@
+/*******************************************************************************
+ * Copyright (c) 2013, 2017 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.tests.hooks.framework.activator.a;
+
+import java.util.List;
+import org.eclipse.osgi.internal.hookregistry.ActivatorHookFactory;
+import org.eclipse.osgi.internal.hookregistry.HookConfigurator;
+import org.eclipse.osgi.internal.hookregistry.HookRegistry;
+import org.osgi.framework.BundleActivator;
+import org.osgi.framework.BundleContext;
+
+public class TestHookConfigurator1 implements HookConfigurator {
+
+	public static volatile List<String> events;
+
+	public void addHooks(HookRegistry hookRegistry) {
+		hookRegistry.addActivatorHookFactory(new ActivatorHookFactory() {
+
+			@Override
+			public BundleActivator createActivator() {
+				return new BundleActivator() {
+					@Override
+					public void start(BundleContext context) throws Exception {
+						if (events != null) {
+							events.add("HOOK1 STARTED");
+						}
+					}
+
+					@Override
+					public void stop(BundleContext context) throws Exception {
+						if (events != null) {
+							events.add("HOOK1 STOPPED");
+						}
+					}
+				};
+			}
+		});
+	}
+
+}
diff --git a/bundles/org.eclipse.osgi.tests/bundles_src/activator.hooks.a/org/eclipse/osgi/tests/hooks/framework/activator/a/TestHookConfigurator2.java b/bundles/org.eclipse.osgi.tests/bundles_src/activator.hooks.a/org/eclipse/osgi/tests/hooks/framework/activator/a/TestHookConfigurator2.java
new file mode 100644
index 0000000..b9724a5
--- /dev/null
+++ b/bundles/org.eclipse.osgi.tests/bundles_src/activator.hooks.a/org/eclipse/osgi/tests/hooks/framework/activator/a/TestHookConfigurator2.java
@@ -0,0 +1,51 @@
+/*******************************************************************************
+ * Copyright (c) 2013, 2017 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.tests.hooks.framework.activator.a;
+
+import java.util.List;
+import org.eclipse.osgi.internal.hookregistry.ActivatorHookFactory;
+import org.eclipse.osgi.internal.hookregistry.HookConfigurator;
+import org.eclipse.osgi.internal.hookregistry.HookRegistry;
+import org.osgi.framework.BundleActivator;
+import org.osgi.framework.BundleContext;
+
+public class TestHookConfigurator2 implements HookConfigurator {
+	public static volatile List<String> events;
+
+	@Override
+	public void addHooks(HookRegistry hookRegistry) {
+		hookRegistry.addActivatorHookFactory(new ActivatorHookFactory() {
+
+			@Override
+			public BundleActivator createActivator() {
+				return new BundleActivator() {
+					@Override
+					public void start(BundleContext context) throws Exception {
+						if (events != null) {
+							events.add("HOOK2 STARTED");
+						}
+					}
+
+					@Override
+					public void stop(BundleContext context) throws Exception {
+						if (events != null) {
+							events.add("HOOK2 STOPPED");
+						}
+					}
+				};
+			}
+		});
+
+	}
+}
diff --git a/bundles/org.eclipse.osgi.tests/bundles_src/activator.hooks.a/org/eclipse/osgi/tests/hooks/framework/activator/a/TestHookConfigurator3.java b/bundles/org.eclipse.osgi.tests/bundles_src/activator.hooks.a/org/eclipse/osgi/tests/hooks/framework/activator/a/TestHookConfigurator3.java
new file mode 100644
index 0000000..85e2bfe
--- /dev/null
+++ b/bundles/org.eclipse.osgi.tests/bundles_src/activator.hooks.a/org/eclipse/osgi/tests/hooks/framework/activator/a/TestHookConfigurator3.java
@@ -0,0 +1,51 @@
+/*******************************************************************************
+ * Copyright (c) 2013, 2017 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.tests.hooks.framework.activator.a;
+
+import java.util.List;
+import org.eclipse.osgi.internal.hookregistry.ActivatorHookFactory;
+import org.eclipse.osgi.internal.hookregistry.HookConfigurator;
+import org.eclipse.osgi.internal.hookregistry.HookRegistry;
+import org.osgi.framework.BundleActivator;
+import org.osgi.framework.BundleContext;
+
+public class TestHookConfigurator3 implements HookConfigurator {
+	public static volatile List<String> events;
+
+	@Override
+	public void addHooks(HookRegistry hookRegistry) {
+		hookRegistry.addActivatorHookFactory(new ActivatorHookFactory() {
+
+			@Override
+			public BundleActivator createActivator() {
+				return new BundleActivator() {
+					@Override
+					public void start(BundleContext context) throws Exception {
+						if (events != null) {
+							events.add("HOOK3 STARTED");
+						}
+					}
+
+					@Override
+					public void stop(BundleContext context) throws Exception {
+						if (events != null) {
+							events.add("HOOK3 STOPPED");
+						}
+					}
+				};
+			}
+		});
+
+	}
+}
diff --git a/bundles/org.eclipse.osgi.tests/bundles_src/ext.framework.a.importer/ext/framework/a/importer/Activator.java b/bundles/org.eclipse.osgi.tests/bundles_src/ext.framework.a.importer/ext/framework/a/importer/Activator.java
index e85f335..367c27c 100644
--- a/bundles/org.eclipse.osgi.tests/bundles_src/ext.framework.a.importer/ext/framework/a/importer/Activator.java
+++ b/bundles/org.eclipse.osgi.tests/bundles_src/ext.framework.a.importer/ext/framework/a/importer/Activator.java
@@ -14,9 +14,12 @@
 package ext.framework.a.importer;
 
 import ext.framework.a.FrameworkExtTest;
-import java.io.*;
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
 import java.net.URL;
 import org.eclipse.osgi.tests.bundles.AbstractBundleTests;
+import org.eclipse.osgi.tests.bundles.ExtensionBundleTests;
 import org.osgi.framework.BundleActivator;
 import org.osgi.framework.BundleContext;
 
@@ -25,6 +28,7 @@
 	public void start(BundleContext context) throws Exception {
 		AbstractBundleTests.simpleResults.addEvent(new FrameworkExtTest().testIt("success")); //$NON-NLS-1$
 		AbstractBundleTests.simpleResults.addEvent(getURLContent(this.getClass().getResource("/ext/framework/a/fwkresource.txt"))); //$NON-NLS-1$
+		ExtensionBundleTests.events.add(context.getBundle().getSymbolicName() + " STARTED");
 	}
 
 	private String getURLContent(URL resource) throws IOException {
@@ -37,7 +41,7 @@
 	}
 
 	public void stop(BundleContext context) throws Exception {
-		// nothing
+		ExtensionBundleTests.events.add(context.getBundle().getSymbolicName() + " STOPPED");
 	}
 
 }
diff --git a/bundles/org.eclipse.osgi.tests/bundles_src/ext.framework.a.requires/ext/framework/a/requires/Activator.java b/bundles/org.eclipse.osgi.tests/bundles_src/ext.framework.a.requires/ext/framework/a/requires/Activator.java
index 09a88fd..7367f0a 100644
--- a/bundles/org.eclipse.osgi.tests/bundles_src/ext.framework.a.requires/ext/framework/a/requires/Activator.java
+++ b/bundles/org.eclipse.osgi.tests/bundles_src/ext.framework.a.requires/ext/framework/a/requires/Activator.java
@@ -14,9 +14,12 @@
 package ext.framework.a.requires;
 
 import ext.framework.a.FrameworkExtTest;
-import java.io.*;
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
 import java.net.URL;
 import org.eclipse.osgi.tests.bundles.AbstractBundleTests;
+import org.eclipse.osgi.tests.bundles.ExtensionBundleTests;
 import org.osgi.framework.BundleActivator;
 import org.osgi.framework.BundleContext;
 
@@ -25,6 +28,7 @@
 	public void start(BundleContext context) throws Exception {
 		AbstractBundleTests.simpleResults.addEvent(new FrameworkExtTest().testIt("success")); //$NON-NLS-1$
 		AbstractBundleTests.simpleResults.addEvent(getURLContent(this.getClass().getResource("/ext/framework/a/fwkresource.txt"))); //$NON-NLS-1$
+		ExtensionBundleTests.events.add(context.getBundle().getSymbolicName() + " STARTED");
 	}
 
 	private String getURLContent(URL resource) throws IOException {
@@ -37,7 +41,7 @@
 	}
 
 	public void stop(BundleContext context) throws Exception {
-		// nothing
+		ExtensionBundleTests.events.add(context.getBundle().getSymbolicName() + " STOPPED");
 	}
 
 }
diff --git a/bundles/org.eclipse.osgi.tests/bundles_src/storage.hooks.a/META-INF/services/org.eclipse.osgi.internal.hookregistry.FrameworkUtilHelper b/bundles/org.eclipse.osgi.tests/bundles_src/storage.hooks.a/META-INF/services/org.osgi.framework.connect.FrameworkUtilHelper
similarity index 98%
rename from bundles/org.eclipse.osgi.tests/bundles_src/storage.hooks.a/META-INF/services/org.eclipse.osgi.internal.hookregistry.FrameworkUtilHelper
rename to bundles/org.eclipse.osgi.tests/bundles_src/storage.hooks.a/META-INF/services/org.osgi.framework.connect.FrameworkUtilHelper
index a3365b5..875f91c 100644
--- a/bundles/org.eclipse.osgi.tests/bundles_src/storage.hooks.a/META-INF/services/org.eclipse.osgi.internal.hookregistry.FrameworkUtilHelper
+++ b/bundles/org.eclipse.osgi.tests/bundles_src/storage.hooks.a/META-INF/services/org.osgi.framework.connect.FrameworkUtilHelper
@@ -1 +1 @@
-org.eclipse.osgi.tests.hooks.framework.storage.a.TestHelper
\ No newline at end of file
+org.eclipse.osgi.tests.hooks.framework.storage.a.TestHelper
diff --git a/bundles/org.eclipse.osgi.tests/bundles_src/storage.hooks.a/org/eclipse/osgi/tests/hooks/framework/storage/a/TestHelper.java b/bundles/org.eclipse.osgi.tests/bundles_src/storage.hooks.a/org/eclipse/osgi/tests/hooks/framework/storage/a/TestHelper.java
index 35b949c..639865e 100644
--- a/bundles/org.eclipse.osgi.tests/bundles_src/storage.hooks.a/org/eclipse/osgi/tests/hooks/framework/storage/a/TestHelper.java
+++ b/bundles/org.eclipse.osgi.tests/bundles_src/storage.hooks.a/org/eclipse/osgi/tests/hooks/framework/storage/a/TestHelper.java
@@ -13,14 +13,19 @@
  *******************************************************************************/
 package org.eclipse.osgi.tests.hooks.framework.storage.a;
 
-import org.eclipse.osgi.internal.hookregistry.FrameworkUtilHelper;
+import java.util.Optional;
 import org.osgi.framework.Bundle;
+import org.osgi.framework.connect.FrameworkUtilHelper;
 
-public class TestHelper extends FrameworkUtilHelper {
-	volatile static Bundle testBundle = null;
+public class TestHelper implements FrameworkUtilHelper {
+	volatile static Bundle testBundle;
 
 	@Override
-	public Bundle getBundle(Class<?> classFromBundle) {
-		return testBundle;
+	public Optional<Bundle> getBundle(Class<?> classFromBundle) {
+		return Optional.ofNullable(testBundle);
+	}
+
+	public static void setBundle(Bundle testBundle) {
+		TestHelper.testBundle = testBundle;
 	}
 }
diff --git a/bundles/org.eclipse.osgi.tests/bundles_src/storage.hooks.a/org/eclipse/osgi/tests/hooks/framework/storage/a/TestHookConfigurator.java b/bundles/org.eclipse.osgi.tests/bundles_src/storage.hooks.a/org/eclipse/osgi/tests/hooks/framework/storage/a/TestHookConfigurator.java
index aa29bef..d25cb8a 100644
--- a/bundles/org.eclipse.osgi.tests/bundles_src/storage.hooks.a/org/eclipse/osgi/tests/hooks/framework/storage/a/TestHookConfigurator.java
+++ b/bundles/org.eclipse.osgi.tests/bundles_src/storage.hooks.a/org/eclipse/osgi/tests/hooks/framework/storage/a/TestHookConfigurator.java
@@ -184,15 +184,14 @@
 			@Override
 			public BundleActivator createActivator() {
 				return new BundleActivator() {
-
 					@Override
 					public void start(BundleContext context) throws Exception {
-						TestHelper.testBundle = context.getBundle(Constants.SYSTEM_BUNDLE_LOCATION);
+						TestHelper.setBundle(context.getBundle(Constants.SYSTEM_BUNDLE_LOCATION));
 					}
 
 					@Override
 					public void stop(BundleContext context) throws Exception {
-						// nothing
+						TestHelper.setBundle(null);
 					}
 				};
 			}
diff --git a/bundles/org.eclipse.osgi.tests/pom.xml b/bundles/org.eclipse.osgi.tests/pom.xml
index 1972767..09698e8 100644
--- a/bundles/org.eclipse.osgi.tests/pom.xml
+++ b/bundles/org.eclipse.osgi.tests/pom.xml
@@ -19,7 +19,7 @@
   </parent>
   <groupId>org.eclipse.osgi</groupId>
   <artifactId>org.eclipse.osgi.tests</artifactId>
-  <version>3.15.400-SNAPSHOT</version>
+  <version>3.16.0-SNAPSHOT</version>
   <packaging>eclipse-test-plugin</packaging>
 
   <properties>
diff --git a/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/bundles/AbstractBundleTests.java b/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/bundles/AbstractBundleTests.java
index 75b74e3..10a06ad 100644
--- a/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/bundles/AbstractBundleTests.java
+++ b/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/bundles/AbstractBundleTests.java
@@ -360,6 +360,23 @@
 		return waitForStop(equinox, uuid, quietly, timeout);
 	}
 
+	protected static boolean delete(File file) {
+		if (file.exists()) {
+			if (file.isDirectory()) {
+				String list[] = file.list();
+				if (list != null) {
+					int len = list.length;
+					for (int i = 0; i < len; i++) {
+						delete(new File(file, list[i]));
+					}
+				}
+			}
+
+			return file.delete();
+		}
+		return (true);
+	}
+
 	static public FrameworkEvent waitForStop(Framework equinox, String uuid, boolean quietly, long timeout) {
 		try {
 			FrameworkEvent stopEvent = equinox.waitForStop(timeout);
@@ -407,4 +424,4 @@
 			return "UNKNOWN:" + state;
 		}
 	}
-}
\ No newline at end of file
+}
diff --git a/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/bundles/BundleTests.java b/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/bundles/BundleTests.java
index e955a5c..9805426 100644
--- a/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/bundles/BundleTests.java
+++ b/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/bundles/BundleTests.java
@@ -19,6 +19,7 @@
 public class BundleTests {
 	public static Test suite() {
 		TestSuite suite = new TestSuite(BundleTests.class.getName());
+		suite.addTest(ConnectTests.suite());
 		suite.addTest(ExceptionMessageTest.suite());
 		suite.addTest(ImportJavaSEPackagesTests.suite());
 		suite.addTest(MultiReleaseJarTests.suite());
diff --git a/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/bundles/ConnectTests.java b/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/bundles/ConnectTests.java
new file mode 100644
index 0000000..c84ab16
--- /dev/null
+++ b/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/bundles/ConnectTests.java
@@ -0,0 +1,1035 @@
+/*******************************************************************************
+ * Copyright (c) 2019 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.tests.bundles;
+
+import static org.junit.Assert.assertNotEquals;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import java.net.URLConnection;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Dictionary;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Optional;
+import java.util.Queue;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentLinkedQueue;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.atomic.AtomicReference;
+import java.util.function.Consumer;
+import java.util.jar.Attributes;
+import java.util.jar.Manifest;
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+import org.eclipse.osgi.container.ModuleContainer;
+import org.eclipse.osgi.internal.hookregistry.HookRegistry;
+import org.eclipse.osgi.launch.EquinoxFactory;
+import org.eclipse.osgi.tests.OSGiTestsActivator;
+import org.eclipse.osgi.tests.bundles.classes.Activator;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleActivator;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.BundleException;
+import org.osgi.framework.Constants;
+import org.osgi.framework.FrameworkUtil;
+import org.osgi.framework.ServiceReference;
+import org.osgi.framework.connect.ConnectContent;
+import org.osgi.framework.connect.ConnectContent.ConnectEntry;
+import org.osgi.framework.connect.ConnectFrameworkFactory;
+import org.osgi.framework.connect.ConnectModule;
+import org.osgi.framework.connect.ModuleConnector;
+import org.osgi.framework.launch.Framework;
+import org.osgi.framework.namespace.BundleNamespace;
+import org.osgi.framework.namespace.HostNamespace;
+import org.osgi.framework.namespace.IdentityNamespace;
+import org.osgi.framework.wiring.BundleCapability;
+import org.osgi.framework.wiring.BundleRevision;
+import org.osgi.framework.wiring.BundleWiring;
+import org.osgi.framework.wiring.FrameworkWiring;
+import org.osgi.resource.Namespace;
+import org.osgi.service.condition.Condition;
+
+public class ConnectTests extends AbstractBundleTests {
+
+	public static Test suite() {
+		return new TestSuite(ConnectTests.class);
+	}
+
+	void cleanStorage() {
+		delete(getContext().getDataFile(getName()));
+	}
+
+	void doTestConnect(ModuleConnector moduleConnector, Map<String, String> fwkConfig, Consumer<Framework> test) {
+		doTestConnect(moduleConnector, fwkConfig, test, false);
+	}
+
+	void doTestConnect(ModuleConnector moduleConnector, Map<String, String> fwkConfig, Consumer<Framework> test,
+			boolean enableRuntimeVerification) {
+		File config = OSGiTestsActivator.getContext().getDataFile(getName());
+		config.mkdirs();
+		fwkConfig = new HashMap<>(fwkConfig);
+		fwkConfig.put(Constants.FRAMEWORK_STORAGE, config.getAbsolutePath());
+		if (enableRuntimeVerification) {
+			fwkConfig.put("osgi.signedcontent.support", "runtime");
+		}
+		ConnectFrameworkFactory fwkFactory = new EquinoxFactory();
+		Framework framework = fwkFactory.newFramework(fwkConfig, moduleConnector);
+		boolean passed = false;
+		try {
+			test.accept(framework);
+			passed = true;
+		} finally {
+			try {
+				framework.stop();
+				framework.waitForStop(10000);
+			} catch (Exception e) {
+				if (passed) {
+					sneakyThrow(e);
+				}
+			}
+		}
+	}
+
+	public static class TestCountingModuleConnector implements ModuleConnector {
+		private final AtomicInteger initializeCalled = new AtomicInteger();
+		private final Queue<String> getModuleCalled = new ConcurrentLinkedQueue<>();
+		private final AtomicInteger createBundleActivatorCalled = new AtomicInteger();
+		private final Map<String, ConnectModule> modules = new ConcurrentHashMap<>();
+
+		@Override
+		public void initialize(File storage, Map<String, String> config) {
+			initializeCalled.getAndIncrement();
+		}
+
+		@Override
+		public Optional<ConnectModule> connect(String location) throws BundleException {
+			getModuleCalled.add(location);
+			ConnectModule m = modules.get(location);
+			if (m == BUNDLE_EXCEPTION) {
+				throw new BundleException("Test fail install with getModule");
+			}
+			return Optional.ofNullable(m);
+		}
+
+		@Override
+		public Optional<BundleActivator> newBundleActivator() {
+			createBundleActivatorCalled.getAndIncrement();
+			return Optional.empty();
+		}
+
+		int getInitializeCnt() {
+			return initializeCalled.get();
+		}
+
+		List<String> getModuleLocations() {
+			return new ArrayList<>(getModuleCalled);
+		}
+
+		int getCreateBundleActivatorCnt() {
+			return createBundleActivatorCalled.get();
+		}
+
+		void setModule(String location, ConnectModule module) {
+			if (module == null) {
+				modules.remove(location);
+			} else {
+				modules.put(location, module);
+			}
+		}
+	}
+
+	public static class TestConnectModule implements ConnectModule {
+		private volatile TestConnectContent content;
+
+		public TestConnectModule(TestConnectContent content) {
+			this.content = content;
+		}
+
+		@Override
+		public TestConnectContent getContent() {
+			return content;
+		}
+
+		void setContent(TestConnectContent updatedContent) {
+			this.content = updatedContent;
+		}
+	}
+
+	public static class TestConnectContent implements ConnectContent {
+		private final Map<String, String> headers;
+		private final Map<String, ConnectEntry> entries = new LinkedHashMap<>();
+		private final ClassLoader loader;
+		private final AtomicBoolean isOpen = new AtomicBoolean();
+
+		public TestConnectContent(Map<String, String> headers, ClassLoader loader) {
+			this.headers = headers;
+			this.loader = loader;
+		}
+
+		@Override
+		public Optional<Map<String, String>> getHeaders() {
+			checkOpen();
+			return Optional.ofNullable(headers);
+		}
+
+		@SuppressWarnings("unused")
+		@Override
+		public Iterable<String> getEntries() throws IOException {
+			checkOpen();
+			return entries.keySet();
+		}
+
+		@Override
+		public Optional<ConnectEntry> getEntry(String name) {
+			checkOpen();
+			return Optional.ofNullable(entries.get(name));
+		}
+
+		@Override
+		public Optional<ClassLoader> getClassLoader() {
+			checkOpen();
+			return Optional.ofNullable(loader);
+		}
+
+		@SuppressWarnings("unused")
+		@Override
+		public void open() throws IOException {
+			if (!isOpen.compareAndSet(false, true)) {
+				throw new IllegalStateException("Already Opened.");
+			}
+		}
+
+		@SuppressWarnings("unused")
+		@Override
+		public void close() throws IOException {
+			if (!isOpen.compareAndSet(true, false)) {
+				throw new IllegalStateException("Already Closed.");
+			}
+		}
+
+		void addEntry(String path, ConnectEntry entry) {
+			entries.put(path, entry);
+		}
+
+		private void checkOpen() {
+			if (!isOpen.get()) {
+				throw new IllegalStateException("Not Opened.");
+			}
+		}
+
+		boolean isOpen() {
+			return isOpen.get();
+		}
+	}
+
+	public static class TestConnectEntryBytes implements ConnectEntry {
+		private final String name;
+		private final byte[] bytes;
+
+		public TestConnectEntryBytes(String name, byte[] bytes) {
+			this.name = name;
+			this.bytes = bytes;
+		}
+
+		@Override
+		public String getName() {
+			return name;
+		}
+
+		@Override
+		public long getContentLength() {
+			return bytes.length;
+		}
+
+		@Override
+		public long getLastModified() {
+			return 0;
+		}
+
+		@Override
+		public byte[] getBytes() {
+			return bytes.clone();
+		}
+
+		@Override
+		public InputStream getInputStream() {
+			return new ByteArrayInputStream(bytes);
+		}
+
+	}
+
+	public static class TestConnectEntryURL implements ConnectEntry {
+		private final String name;
+		private final URL content;
+
+		public TestConnectEntryURL(String name, URL content) {
+			this.name = name;
+			this.content = content;
+		}
+
+		@Override
+		public String getName() {
+			return name;
+		}
+
+		@Override
+		public long getContentLength() {
+			try {
+				return content.openConnection().getContentLengthLong();
+			} catch (IOException e) {
+				return 0;
+			}
+		}
+
+		@Override
+		public long getLastModified() {
+			try {
+				return content.openConnection().getLastModified();
+			} catch (IOException e) {
+				return 0;
+			}
+		}
+
+		@Override
+		public InputStream getInputStream() throws IOException {
+			return content.openStream();
+		}
+
+	}
+
+	static final TestConnectModule BUNDLE_EXCEPTION = new TestConnectModule(null);
+
+	public void testConnectFactoryNoModules() {
+		TestCountingModuleConnector connector = new TestCountingModuleConnector();
+
+		doTestConnect(connector, Collections.emptyMap(), (f) -> {
+			try {
+				f.start();
+				f.stop();
+				f.waitForStop(5000);
+				f.start();
+				f.stop();
+				f.waitForStop(5000);
+			} catch (Throwable t) {
+				sneakyThrow(t);
+			}
+		});
+		doTestConnect(connector, Collections.emptyMap(), (f) -> {
+			try {
+				f.start();
+				f.stop();
+			} catch (BundleException e) {
+				sneakyThrow(e);
+			}
+		});
+
+		assertEquals("Wrong number of init called.", 2, connector.getInitializeCnt());
+		assertEquals("Wrong number of create activator called.", 3, connector.getCreateBundleActivatorCnt());
+	}
+
+	public void testConnectActivator() {
+		final AtomicInteger bundleActvatorStartCalled = new AtomicInteger();
+		final AtomicInteger bundleActvatorStopCalled = new AtomicInteger();
+		ModuleConnector activatorModuleConnector = new TestCountingModuleConnector() {
+			@Override
+			public Optional<BundleActivator> newBundleActivator() {
+				super.newBundleActivator();
+				return Optional.of(new BundleActivator() {
+
+					@Override
+					public void start(BundleContext context) throws Exception {
+						bundleActvatorStartCalled.getAndIncrement();
+					}
+
+					@Override
+					public void stop(BundleContext context) throws Exception {
+						bundleActvatorStopCalled.getAndIncrement();
+					}
+				});
+			}
+		};
+
+		doTestConnect(activatorModuleConnector, Collections.emptyMap(), (f) -> {
+			try {
+				f.start();
+				f.stop();
+				f.waitForStop(5000);
+				f.start();
+				f.stop();
+				f.waitForStop(5000);
+			} catch (Exception e) {
+				sneakyThrow(e);
+			}
+		});
+		assertEquals("Wrong number of start called.", 2, bundleActvatorStartCalled.get());
+		assertEquals("Wrong number of stop called.", 2, bundleActvatorStopCalled.get());
+	}
+
+	public void testTrueCondition() {
+		final AtomicReference<ServiceReference<Condition>> trueConditionStart = new AtomicReference<>();
+		final AtomicReference<ServiceReference<Condition>> trueConditionStop = new AtomicReference<>();
+
+		ModuleConnector activatorModuleConnector = new TestCountingModuleConnector() {
+			@Override
+			public Optional<BundleActivator> newBundleActivator() {
+				super.newBundleActivator();
+				return Optional.of(new BundleActivator() {
+
+					@Override
+					public void start(BundleContext context) throws Exception {
+						trueConditionStart.set(context
+								.getServiceReferences(Condition.class,
+										'(' + Condition.CONDITION_ID + '=' + Condition.CONDITION_ID_TRUE + ')')
+								.iterator().next());
+					}
+
+					@Override
+					public void stop(BundleContext context) throws Exception {
+						trueConditionStop.set(context
+								.getServiceReferences(Condition.class,
+										'(' + Condition.CONDITION_ID + '=' + Condition.CONDITION_ID_TRUE + ')')
+								.iterator().next());
+					}
+				});
+			}
+		};
+
+		doTestConnect(activatorModuleConnector, Collections.emptyMap(), (f) -> {
+			try {
+				f.start();
+				ServiceReference<Condition> trueCondition = trueConditionStart.get();
+				assertNotNull("No true condition found.", trueCondition);
+				assertEquals("Wrong bundle.", f.getBundleContext().getBundle(), trueCondition.getBundle());
+				f.stop();
+				f.waitForStop(5000);
+
+				assertEquals("Different true condition found on start and stop.", trueCondition,
+						trueConditionStop.get());
+				assertNull("True condition should be unregistered on stop.", trueCondition.getBundle());
+
+			} catch (Exception e) {
+				sneakyThrow(e);
+			}
+		});
+	}
+
+	public void testConnectInit() {
+		final AtomicReference<File> initFile = new AtomicReference<>();
+		final AtomicReference<File> storeFile = new AtomicReference<>();
+		final AtomicReference<Map<String, String>> initConfig = new AtomicReference<>();
+		ModuleConnector initParamsModuleConnector = new TestCountingModuleConnector() {
+			@Override
+			public void initialize(File storage, Map<String, String> config) {
+				super.initialize(storage, config);
+				initFile.set(storage);
+				initConfig.set(config);
+			}
+		};
+
+		Map<String, String> config = new HashMap<>();
+		config.put("k1", "v1");
+		config.put("k2", "v2");
+
+		doTestConnect(initParamsModuleConnector, config, (f) -> {
+			try {
+				f.init();
+				BundleContext bc = f.getBundleContext();
+				storeFile.set(new File(bc.getProperty(Constants.FRAMEWORK_STORAGE)));
+			} catch (Exception e) {
+				sneakyThrow(e);
+			}
+		});
+		TestCase.assertEquals("Wrong init store file.", storeFile.get(), initFile.get());
+		assertTrue("Did not find all init configs: " + initConfig.get(),
+				initConfig.get().entrySet().containsAll(config.entrySet()));
+		try {
+			initConfig.get().put("k3", "v3");
+			fail("Expected unmodifiable map");
+		} catch (UnsupportedOperationException e) {
+			// expected
+		}
+	}
+
+	public void testConnectContentHeaders() throws IOException {
+		doTestConnectContentSimple(false);
+	}
+
+	public void testConnectContentManifest() throws IOException {
+		doTestConnectContentSimple(true);
+	}
+
+	void doTestConnectContentSimple(boolean withManifest) throws IOException {
+		TestCountingModuleConnector connector = new TestCountingModuleConnector();
+		final List<String> locations = Arrays.asList("b.1", "b.2", "b.3", "b.4");
+		for (String l : locations) {
+			connector.setModule(l, withManifest ? createSimpleManifestModule(l) : createSimpleHeadersModule(l));
+		}
+
+		doTestConnect(connector, Collections.emptyMap(), (f) -> {
+			try {
+				f.init();
+				for (String l : locations) {
+					Bundle b = f.getBundleContext().installBundle(l);
+					assertEquals("Wrong symbolic name.", l, b.getSymbolicName());
+					checkConnectTag(b);
+				}
+				checkConnectTags(f, locations);
+			} catch (Throwable t) {
+				sneakyThrow(t);
+			}
+		});
+
+		doTestConnect(connector, Collections.emptyMap(), (f) -> {
+			try {
+				f.init();
+				Bundle[] bundles = f.getBundleContext().getBundles();
+				assertEquals("Wrong number of bundles from cache.", locations.size() + 1, bundles.length);
+				for (String l : locations) {
+					Bundle b = f.getBundleContext().getBundle(l);
+					assertNotNull("No bundle at location: " + l, b);
+					assertEquals("Wrong symbolic name.", l, b.getSymbolicName());
+					checkConnectTag(b);
+					checkConnectTags(f, locations);
+				}
+			} catch (BundleException e) {
+				sneakyThrow(e);
+			}
+		});
+
+		connector.setModule("b.2", null);
+		connector.setModule("b.3", BUNDLE_EXCEPTION);
+		doTestConnect(connector, Collections.emptyMap(), (f) -> {
+			try {
+				f.init();
+				Bundle[] bundles = f.getBundleContext().getBundles();
+				assertEquals("Wrong number of bundles from cache.", locations.size() - 1, bundles.length);
+				for (String l : locations) {
+					Bundle b = f.getBundleContext().getBundle(l);
+					if ("b.2".equals(l) || "b.3".equals(l)) {
+						assertNull("Found unexpected bundle.", b);
+					} else {
+						assertNotNull("No bundle at location: " + l, b);
+						assertEquals("Wrong symbolic name.", l, b.getSymbolicName());
+						checkConnectTag(b);
+					}
+				}
+			} catch (BundleException e) {
+				sneakyThrow(e);
+			}
+		});
+	}
+
+	private static void checkConnectTag(Bundle b) {
+		final List<String> namespaces = new ArrayList<>(Arrays.asList(BundleNamespace.BUNDLE_NAMESPACE,
+				HostNamespace.HOST_NAMESPACE, IdentityNamespace.IDENTITY_NAMESPACE));
+
+		b.adapt(BundleRevision.class).getCapabilities(null).stream().filter(c -> namespaces.contains(c.getNamespace()))
+				.forEach(c -> {
+					List<String> tags = (List<String>) c.getAttributes()
+							.get(IdentityNamespace.CAPABILITY_TAGS_ATTRIBUTE);
+					assertNotNull("No tags found.", tags);
+					assertEquals("Wrong number of tags.", 1, tags.size());
+					assertTrue("Connect tag not found.", tags.contains(ConnectContent.TAG_OSGI_CONNECT));
+					namespaces.remove(c.getNamespace());
+				});
+		assertTrue("Connect tag namespaces were not removed completely. Found " + namespaces, namespaces.isEmpty());
+	}
+
+	private static void checkConnectTags(Framework f, List<String> locations) {
+		Collection<BundleCapability> osgiConnectTags = f.adapt(FrameworkWiring.class).findProviders( //
+				ModuleContainer.createRequirement(IdentityNamespace.IDENTITY_NAMESPACE, //
+						Collections.singletonMap(Namespace.REQUIREMENT_FILTER_DIRECTIVE, "(tags=osgi.connect)"), //
+						Collections.emptyMap()));
+		osgiConnectTags.forEach(c -> {
+			assertTrue("Unexpected tag on bundle: " + c.getRevision().getBundle(),
+					locations.contains(c.getRevision().getBundle().getLocation()));
+		});
+	}
+
+	public void testConnectContentActivatorsWithFrameworkLoaders() {
+		doTestConnectContentActivators(false);
+	}
+
+	public void testConnectContentActivatorsWithProvidedLoaders() {
+		doTestConnectContentActivators(true);
+	}
+
+	void doTestConnectContentActivators(boolean provideLoader) {
+		TestCountingModuleConnector connector = new TestCountingModuleConnector();
+		final List<Integer> ids = Arrays.asList(1, 2, 3);
+		for (Integer id : ids) {
+			connector.setModule(id.toString(), createAdvancedModule(id, provideLoader));
+		}
+
+		doTestConnect(connector, Collections.emptyMap(), (f) -> {
+			try {
+				f.start();
+				for (Integer id : ids) {
+					Bundle b = f.getBundleContext().installBundle(id.toString());
+					assertEquals("Wrong symbolic name.", id.toString(), b.getSymbolicName());
+					b.start();
+					ServiceReference<?>[] registered = b.getRegisteredServices();
+					assertNotNull("No services found.", registered);
+					assertEquals("Wrong number of services.", 1, registered.length);
+					assertEquals("Wrong service property.", Activator.class.getSimpleName() + id,
+							(String) registered[0].getProperty("activator"));
+					if (provideLoader) {
+						assertTrue("Expected the same classes.",
+								Activator.class.equals(b.loadClass(Activator.class.getName())));
+					} else {
+						assertFalse("Expected different classes.",
+								Activator.class.equals(b.loadClass(Activator.class.getName())));
+					}
+				}
+			} catch (Throwable t) {
+				sneakyThrow(t);
+			}
+		});
+	}
+
+	public void testConnectContentEntriesWithFrameworkLoaders() {
+		doTestConnectContentEntries(false);
+	}
+
+	public void testConnectContentEntriesWithProvidedLoaders() {
+		doTestConnectContentEntries(true);
+	}
+
+	void doTestConnectContentEntries(boolean provideLoader) {
+		TestCountingModuleConnector connector = new TestCountingModuleConnector();
+		final List<Integer> ids = Arrays.asList(1, 2, 3);
+		final Map<Integer, TestConnectModule> modules = new HashMap<>();
+		for (Integer id : ids) {
+			TestConnectModule m = createAdvancedModule(id, provideLoader);
+			modules.put(id, m);
+			connector.setModule(id.toString(), m);
+		}
+
+		doTestConnect(connector, Collections.emptyMap(), (f) -> {
+			try {
+				f.start();
+				for (Integer id : ids) {
+					Bundle b = f.getBundleContext().installBundle(id.toString());
+					assertEquals("Wrong symbolic name.", id.toString(), b.getSymbolicName());
+					TestConnectModule m = modules.get(id);
+					List<String> entries = new ArrayList<>();
+					for (String entry : m.getContent().getEntries()) {
+						entries.add(entry);
+					}
+
+					Set<String> bundleEntryUrls = new HashSet<>();
+					for (Enumeration<URL> eUrls = b.findEntries("/", "*", true); eUrls.hasMoreElements();) {
+						// URL paths always begin with '/', remove it
+						bundleEntryUrls.add(eUrls.nextElement().getPath().substring(1));
+					}
+					assertEquals("Wrong number of bundle entry URLs.", entries.size(), bundleEntryUrls.size());
+					assertTrue("Wrong bundle entry URLs: " + bundleEntryUrls, entries.containsAll(bundleEntryUrls));
+
+					List<String> bundleEntryPaths = new ArrayList<>();
+					for (Enumeration<String> ePaths = b
+							.getEntryPaths("org/eclipse/osgi/tests/bundles/resources"); ePaths.hasMoreElements();) {
+						bundleEntryPaths.add(ePaths.nextElement());
+					}
+					assertEquals("Wrong number of bundle entry paths from root.", 1, bundleEntryPaths.size());
+					assertEquals("Wrong bundle entry found at root.",
+							"org/eclipse/osgi/tests/bundles/resources/" + id + ".txt", bundleEntryPaths.get(0));
+
+					BundleWiring wiring = b.adapt(BundleWiring.class);
+					assertNotNull("No wiring.", wiring);
+					Collection<String> wiringResourcePaths = wiring.listResources("/", "*",
+							BundleWiring.LISTRESOURCES_LOCAL | BundleWiring.LISTRESOURCES_RECURSE);
+					assertEquals("Wrong number of resource paths.", entries.size(), wiringResourcePaths.size());
+					assertTrue("Wrong resource paths: " + wiringResourcePaths,
+							entries.containsAll(wiringResourcePaths));
+
+					Set<String> wiringEntryUrls = new HashSet<>();
+					for (URL url : wiring.findEntries("/", "*", BundleWiring.FINDENTRIES_RECURSE)) {
+						// URL paths always begin with '/', remove it
+						wiringEntryUrls.add(url.getPath().substring(1));
+					}
+					assertEquals("Wrong number of wiring entry URLs.", entries.size(), wiringEntryUrls.size());
+					assertTrue("Wrong wiring entry URLs: " + wiringEntryUrls, entries.containsAll(wiringEntryUrls));
+
+					String txtPathDir = "org/eclipse/osgi/tests/bundles/resources/";
+					String txtPath = txtPathDir + id + ".txt";
+					Optional<ConnectEntry> txtConnectEntry = m.getContent().getEntry(txtPath);
+					assertTrue("Could not find text entry.", txtConnectEntry.isPresent());
+
+					checkEntry(txtConnectEntry.get(), b.getEntry(txtPath), id);
+					checkEntry(txtConnectEntry.get(), b.getResource(txtPath), id);
+					Enumeration<URL> found = b.findEntries(txtPathDir, "*.txt", false);
+					checkEntry(txtConnectEntry.get(), found.nextElement(), id);
+					assertFalse("More entries found.", found.hasMoreElements());
+
+					// now try with leading '/'
+					String slashTxtPath = '/' + txtPath;
+					checkEntry(txtConnectEntry.get(), b.getEntry(slashTxtPath), id);
+					checkEntry(txtConnectEntry.get(), b.getResource(slashTxtPath), id);
+					found = b.findEntries('/' + txtPathDir, "*.txt", false);
+					checkEntry(txtConnectEntry.get(), found.nextElement(), id);
+					assertFalse("More entries found.", found.hasMoreElements());
+				}
+			} catch (Throwable t) {
+				sneakyThrow(t);
+			}
+		});
+	}
+
+	public void testOpenCloseUpdateConnectContent() {
+		final String NAME1 = "testUpdate.1";
+		final String NAME2 = "testUpdate.2";
+		TestCountingModuleConnector connector = new TestCountingModuleConnector();
+		TestConnectModule m = createSimpleHeadersModule(NAME1);
+		connector.setModule(NAME1, m);
+
+		doTestConnect(connector, Collections.emptyMap(), (f) -> {
+			try {
+				f.start();
+				Bundle b = f.getBundleContext().installBundle(NAME1);
+				assertEquals("Wrong name.", NAME1, b.getSymbolicName());
+				// make sure to open the bundle file
+				assertNull(b.getEntry("doesNotExist.txt"));
+				TestConnectContent original = m.getContent();
+				assertTrue("Original content is not open.", original.isOpen());
+
+				// set the new content but don't update
+				m.setContent(createSimpleHeadersContent(NAME2));
+
+				FrameworkWiring fwkWiring = f.adapt(FrameworkWiring.class);
+				CountDownLatch refreshDone = new CountDownLatch(1);
+				fwkWiring.refreshBundles(Collections.singletonList(b), (e) -> refreshDone.countDown());
+				refreshDone.await();
+
+				// should still be NAME1
+				assertEquals("Wrong name.", NAME1, b.getSymbolicName());
+				assertTrue("Original content is not open.", original.isOpen());
+
+				// now update should stage in the new content
+				b.update();
+				assertEquals("Wrong name.", NAME2, b.getSymbolicName());
+				// make sure to open the bundle file
+				assertNull(b.getEntry("doesNotExist.txt"));
+				TestConnectContent newContent = m.getContent();
+				assertTrue("New content is not open.", newContent.isOpen());
+				assertFalse("Original content is open.", original.isOpen());
+
+				// now update with no new content
+				b.update();
+				assertNull(b.getEntry("doesNotExist.txt"));
+				assertTrue("New content is not open.", newContent.isOpen());
+				assertFalse("Original content is open.", original.isOpen());
+			} catch (Throwable t) {
+				sneakyThrow(t);
+			}
+		});
+	}
+
+	public void testConnectBundleHeaders() throws IOException {
+		doTestConnectBundleHeaders(false, false);
+		doTestConnectBundleHeaders(true, false);
+		doTestConnectBundleHeaders(false, true);
+		doTestConnectBundleHeaders(true, true);
+	}
+
+	void doTestConnectBundleHeaders(boolean withSignedHook, boolean withManifest) throws IOException {
+		final String NAME1 = "bundle1";
+		final String NAME2 = "bundle2";
+		TestCountingModuleConnector connector = new TestCountingModuleConnector();
+		TestConnectModule m = withManifest ? createSimpleManifestModule(NAME1) : createSimpleHeadersModule(NAME1);
+		connector.setModule(NAME1, m);
+		doTestConnect(connector, Collections.emptyMap(), (f) -> {
+			try {
+				f.start();
+				Bundle b = f.getBundleContext().installBundle(NAME1);
+				Dictionary<String, String> headers1 = b.getHeaders();
+				assertEquals("Wrong name.", NAME1, b.getSymbolicName());
+				if (withManifest) {
+					assertEquals("Wrong symbolic name header.", NAME1, headers1.get(Constants.BUNDLE_SYMBOLICNAME));
+				} else {
+					checkHeaders(m.getContent().getHeaders().get(), headers1);
+				}
+				// set the new content
+				m.setContent(withManifest ? createSimpleManifestContent(NAME2) : createSimpleHeadersContent(NAME2));
+				b.update();
+				Dictionary<String, String> headers2 = b.getHeaders();
+				assertNotEquals("Headers not updated", headers1, headers2);
+				assertEquals("Wrong name.", NAME2, b.getSymbolicName());
+				if (withManifest) {
+					assertEquals("Wrong symbolic name header.", NAME2, headers2.get(Constants.BUNDLE_SYMBOLICNAME));
+				} else {
+					checkHeaders(m.getContent().getHeaders().get(), headers2);
+				}
+				b.uninstall();
+			} catch (Throwable t) {
+				sneakyThrow(t);
+			}
+		}, withSignedHook);
+	}
+
+	public void testGetConnectHeaders() throws Exception {
+		final String NAME = "bundle";
+		final AtomicReference<Dictionary<String, String>> headers1 = new AtomicReference<>();
+		final AtomicReference<Dictionary<String, String>> headers2 = new AtomicReference<>();
+
+		TestCountingModuleConnector connector = new TestCountingModuleConnector();
+		TestConnectModule m = createSimpleHeadersModule(NAME);
+		connector.setModule(NAME, m);
+		doTestConnect(connector, Collections.emptyMap(), (f) -> {
+			try {
+				f.start();
+				Bundle b = f.getBundleContext().installBundle(NAME);
+				assertEquals("Wrong name.", NAME, b.getSymbolicName());
+				headers1.set(b.getHeaders());
+				f.stop();
+				f.waitForStop(5000);
+			} catch (Throwable t) {
+				sneakyThrow(t);
+			}
+		});
+
+		doTestConnect(connector, Collections.singletonMap(HookRegistry.PROP_HOOK_CONFIGURATORS_EXCLUDE,
+				"org.eclipse.equinox.weaving.hooks.WeavingHook"), (f) -> {
+			try {
+				f.start();
+				Bundle b = f.getBundleContext().getBundle(NAME);
+				assertFalse("Content is not closed", m.getContent().isOpen());
+				// Bundle.getHeaders() will eventually call
+				// ConnectBundleFile.getConnectHeaders() which opens the connect content
+				headers2.set(b.getHeaders());
+				assertTrue("Content is not open", m.getContent().isOpen());
+				f.stop();
+				f.waitForStop(5000);
+			} catch (Throwable t) {
+				sneakyThrow(t);
+			}
+		});
+		Dictionary<String, String> h1 = headers1.get();
+		Dictionary<String, String> h2 = headers2.get();
+
+		assertEquals("Headers size not equal", h1.size(), h2.size());
+
+		for (Enumeration<String> keys = h1.keys(); keys.hasMoreElements();) {
+			String key = keys.nextElement();
+			assertEquals(key + " header value not equal", h1.get(key), h2.get(key));
+		}
+	}
+
+	public void testInstallUpdateWithInputStream() throws Exception {
+		dotestInstallUpdate(false, false);
+		dotestInstallUpdate(false, true);
+		dotestInstallUpdate(true, false);
+		dotestInstallUpdate(true, true);
+	}
+
+	void dotestInstallUpdate(boolean installWithInputStream, boolean updateWithInputStream) throws Exception {
+		final InputStream in1 = installWithInputStream ? new URL(installer.getBundleLocation("test")).openStream()
+				: null;
+		final InputStream in2 = updateWithInputStream ? new URL(installer.getBundleLocation("test2")).openStream()
+				: null;
+		final String NAME1 = installWithInputStream ? "test1" : "bundle1";
+		final String NAME2 = updateWithInputStream ? "test2" : "bundle2";
+
+		TestCountingModuleConnector connector = new TestCountingModuleConnector();
+
+		TestConnectModule m = createSimpleHeadersModule(NAME1);
+		connector.setModule(NAME1, m);
+
+		doTestConnect(connector, Collections.emptyMap(), (f) -> {
+			try {
+				f.start();
+				Bundle test = f.getBundleContext().installBundle(NAME1, in1);
+				assertEquals("Wrong name.", NAME1, test.getSymbolicName());
+				if (installWithInputStream) {
+					assertNotNull("Resource not found", test.getResource("stuff/data/resource1"));
+				}
+				m.setContent(createSimpleHeadersContent(NAME2));
+				test.update(in2);
+				assertEquals("Wrong name.", NAME2, test.getSymbolicName());
+				if (updateWithInputStream) {
+					assertNotNull("Resource not found", test.getResource("stuff/data/resource2"));
+				}
+				f.stop();
+				f.waitForStop(5000);
+			} catch (Throwable t) {
+				sneakyThrow(t);
+			} finally {
+				cleanStorage();
+			}
+		});
+	}
+
+	public void testSystemBundleContent() {
+		TestCountingModuleConnector connector = new TestCountingModuleConnector();
+		Bundle systemBundle = getContext().getBundle(Constants.SYSTEM_BUNDLE_LOCATION);
+		Map<String, String> headers = new HashMap<>(FrameworkUtil.asMap(systemBundle.getHeaders()));
+		headers.put("test.key", "test.value");
+		// remove bundle manifest version to allow java export
+		headers.remove(Constants.BUNDLE_MANIFESTVERSION);
+
+		TestConnectModule systemModule = new TestConnectModule(
+				new TestConnectContent(headers, systemBundle.adapt(BundleWiring.class).getClassLoader()));
+		connector.setModule(Constants.SYSTEM_BUNDLE_LOCATION, systemModule);
+		Consumer<Framework> test = f -> {
+			try {
+				f.init();
+				Dictionary<String, String> h = f.getHeaders();
+				assertEquals("Wrong system BSN", systemBundle.getSymbolicName(), f.getSymbolicName());
+				assertEquals("Wrong test value", "test.value", h.get("test.key"));
+			} catch (Throwable t) {
+				sneakyThrow(t);
+			}
+		};
+
+		// run twice to test clean and persistent start
+		doTestConnect(connector, Collections.emptyMap(), test);
+		doTestConnect(connector, Collections.emptyMap(), test);
+	}
+
+	private void checkHeaders(Map<String, String> expected, Dictionary<String, String> actual) {
+		assertEquals("Headers size not equals", expected.size(), actual.size());
+		for (Entry<String, String> entry : expected.entrySet()) {
+			String key = entry.getKey();
+			assertEquals(key + " header value not equal", entry.getValue(), actual.get(key));
+		}
+	}
+
+	void checkEntry(ConnectEntry expected, URL actual, Integer id) throws IOException {
+		assertNotNull("No entry found.", actual);
+		assertEquals("Wrong path.", expected.getName(), actual.getPath().substring(1));
+		URLConnection connection = actual.openConnection();
+		assertEquals("Wrong last modified.", expected.getLastModified(), connection.getLastModified());
+		assertEquals("Wrong content length.", expected.getContentLength(), connection.getContentLengthLong());
+		byte[] expectedBytes = getBytes(expected.getInputStream());
+		byte[] actualBytes = getBytes(connection.getInputStream());
+		assertEquals("Wrong input steam size.", expectedBytes.length, actualBytes.length);
+		for (int i = 0; i < expectedBytes.length; i++) {
+			assertEquals("Wrong byte at: " + i, expectedBytes[i], actualBytes[i]);
+		}
+		String actualString = new String(actualBytes);
+		assertEquals("Wrong entry string.", id.toString(), actualString);
+	}
+
+	TestConnectModule createSimpleHeadersModule(String name) {
+		return new TestConnectModule(createSimpleHeadersContent(name));
+	}
+
+	TestConnectContent createSimpleHeadersContent(String name) {
+		Map<String, String> headers = new HashMap<>();
+		headers.put(Constants.BUNDLE_MANIFESTVERSION, "2");
+		headers.put(Constants.BUNDLE_SYMBOLICNAME, name);
+		headers.put(Constants.IMPORT_PACKAGE, "org.osgi.framework");
+		return new TestConnectContent(headers, null);
+	}
+
+	TestConnectModule createSimpleManifestModule(String name) throws IOException {
+		return new TestConnectModule(createSimpleManifestContent(name));
+	}
+
+	TestConnectContent createSimpleManifestContent(String name) throws IOException {
+		Manifest manifest = new Manifest();
+		Attributes headers = manifest.getMainAttributes();
+		headers.putValue("Manifest-Version", "1");
+		headers.putValue(Constants.BUNDLE_MANIFESTVERSION, "2");
+		headers.putValue(Constants.BUNDLE_SYMBOLICNAME, name);
+		headers.putValue(Constants.IMPORT_PACKAGE, "org.osgi.framework");
+		ByteArrayOutputStream manifestBytes = new ByteArrayOutputStream();
+		manifest.write(manifestBytes);
+		TestConnectContent c = new TestConnectContent(null, null);
+		addEntry("META-INF/MANIFEST.MF", manifestBytes.toByteArray(), c);
+		return c;
+	}
+
+	TestConnectModule createAdvancedModule(Integer id, boolean provideLoader) {
+		Map<String, String> headers = new HashMap<>();
+		headers.put(Constants.BUNDLE_MANIFESTVERSION, "2");
+		headers.put(Constants.BUNDLE_SYMBOLICNAME, id.toString());
+		headers.put(Constants.IMPORT_PACKAGE, "org.osgi.framework");
+		headers.put(Constants.BUNDLE_ACTIVATOR, Activator.class.getName() + id);
+		TestConnectContent c = new TestConnectContent(headers, provideLoader ? getClass().getClassLoader() : null);
+		addEntry("org/", c);
+		addEntry("org/eclipse/", c);
+		addEntry("org/eclipse/osgi/", c);
+		addEntry("org/eclipse/osgi/tests/", c);
+		addEntry("org/eclipse/osgi/tests/bundles/", c);
+		addEntry("org/eclipse/osgi/tests/bundles/classes/", c);
+		addEntry("org/eclipse/osgi/tests/bundles/classes/Activator.class", c);
+		addEntry("org/eclipse/osgi/tests/bundles/classes/Activator" + id + ".class", c);
+		addEntry("org/eclipse/osgi/tests/bundles/resources/", c);
+		addEntry("org/eclipse/osgi/tests/bundles/resources/" + id + ".txt", c);
+		return new TestConnectModule(c);
+	}
+
+	void addEntry(String name, TestConnectContent content) {
+		content.addEntry(name, new TestConnectEntryURL(name, getClass().getResource("/" + name)));
+	}
+
+	void addEntry(String name, byte[] bytes, TestConnectContent content) {
+		content.addEntry(name, new TestConnectEntryBytes(name, bytes));
+	}
+
+	static byte[] getBytes(InputStream in) throws IOException {
+		byte[] classbytes;
+		int bytesread = 0;
+		int readcount;
+		try {
+			int length = 1024;
+			classbytes = new byte[length];
+			readloop: while (true) {
+				for (; bytesread < length; bytesread += readcount) {
+					readcount = in.read(classbytes, bytesread, length - bytesread);
+					if (readcount <= 0) /* if we didn't read anything */
+						break readloop; /* leave the loop */
+				}
+				byte[] oldbytes = classbytes;
+				length += 1024;
+				classbytes = new byte[length];
+				System.arraycopy(oldbytes, 0, classbytes, 0, bytesread);
+			}
+
+			if (classbytes.length > bytesread) {
+				byte[] oldbytes = classbytes;
+				classbytes = new byte[bytesread];
+				System.arraycopy(oldbytes, 0, classbytes, 0, bytesread);
+			}
+		} finally {
+			try {
+				in.close();
+			} catch (IOException ee) {
+				// nothing to do here
+			}
+		}
+		return classbytes;
+	}
+
+	public static <E extends Throwable> void sneakyThrow(Throwable e) throws E {
+		throw (E) e;
+	}
+}
diff --git a/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/bundles/DiscardBundleTests.java b/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/bundles/DiscardBundleTests.java
index 8fecc99..f431426 100644
--- a/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/bundles/DiscardBundleTests.java
+++ b/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/bundles/DiscardBundleTests.java
@@ -118,7 +118,7 @@
 			// will sometimes result in failure presumably due to a locked
 			// file.
 			stop(equinox);
-			rm(bundleFile);
+			delete(bundleFile);
 			equinox = restart(equinox, configuration);
 			assertDiscarded(location, equinox);
 		} finally {
@@ -215,21 +215,4 @@
 			file = new File(file, BUNDLE_MANIFEST);
 		assertTrue("Could not set last modified: " + file, file.setLastModified(file.lastModified() + 1000));
 	}
-
-	public static boolean rm(File file) {
-		if (file.exists()) {
-			if (file.isDirectory()) {
-				String list[] = file.list();
-				if (list != null) {
-					int len = list.length;
-					for (int i = 0; i < len; i++) {
-						rm(new File(file, list[i]));
-					}
-				}
-			}
-
-			return file.delete();
-		}
-		return (true);
-	}
 }
\ No newline at end of file
diff --git a/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/bundles/ExtensionBundleTests.java b/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/bundles/ExtensionBundleTests.java
index b94c08d..fb29534 100644
--- a/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/bundles/ExtensionBundleTests.java
+++ b/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/bundles/ExtensionBundleTests.java
@@ -13,6 +13,8 @@
  *******************************************************************************/
 package org.eclipse.osgi.tests.bundles;
 
+import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.List;
 import junit.framework.Test;
 import junit.framework.TestSuite;
@@ -28,6 +30,8 @@
 		return new TestSuite(ExtensionBundleTests.class);
 	}
 
+	public static List<String> events = new ArrayList<>();
+
 	public void testFrameworkExtension01() throws Exception {
 		Bundle fwkext = installer.installBundle("ext.framework.a", false); //$NON-NLS-1$
 		Bundle importer = installer.installBundle("ext.framework.a.importer"); //$NON-NLS-1$
@@ -84,4 +88,28 @@
 		BundleWire eeWire = wiring.getRequiredWires(ExecutionEnvironmentNamespace.EXECUTION_ENVIRONMENT_NAMESPACE).get(0);
 		assertEquals("Wrong provider for osgi.ee: " + eeWire.getProvider().getBundle(), 0, eeWire.getProvider().getBundle().getBundleId());
 	}
+
+	public void testActivatorOrder() throws Exception {
+		Bundle b = installer.installBundle("ext.framework.a", false);
+		Bundle bImp = installer.installBundle("ext.framework.a.importer");
+		Bundle bReq = installer.installBundle("ext.framework.a.requires");
+		installer.resolveBundles(new Bundle[] {b, bImp, bReq});
+
+		try {
+			bImp.start();
+			bReq.start();
+		} finally {
+			installer.uninstallAllBundles();
+		}
+		List<String> expectedEvents = Arrays.asList(bImp.getSymbolicName() + " STARTED", bReq.getSymbolicName() + " STARTED", bReq.getSymbolicName() + " STOPPED", bImp.getSymbolicName() + " STOPPED");
+		assertEquals("Expected number of events not found", expectedEvents.size(), events.size());
+		for (int i = 0; i < events.size(); i++) {
+			assertEquals("Expected event not found", expectedEvents.get(i), events.get(i));
+		}
+	}
+
+	public void tearDown() throws Exception {
+		super.tearDown();
+		events.clear();
+	}
 }
diff --git a/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/bundles/ImportJavaSEPackagesTests.java b/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/bundles/ImportJavaSEPackagesTests.java
index 2e4bb93..da55e92 100644
--- a/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/bundles/ImportJavaSEPackagesTests.java
+++ b/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/bundles/ImportJavaSEPackagesTests.java
@@ -109,7 +109,6 @@
 
 	public void testSystemPackages() throws Exception {
 		Map<Integer, Integer> packagesPerVersion = new HashMap<>();
-		packagesPerVersion.put(7, 56);
 		packagesPerVersion.put(8, 63);
 		if (!originalSpecVersion.startsWith("1.")) {
 			packagesPerVersion.put(9, calculateJavaPackageCount());
diff --git a/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/bundles/SystemBundleTests.java b/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/bundles/SystemBundleTests.java
index b67f9f6..2c3c875 100755
--- a/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/bundles/SystemBundleTests.java
+++ b/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/bundles/SystemBundleTests.java
@@ -793,25 +793,25 @@
 	}
 
 	public void testChangeEE() throws IOException, BundleException {
-		URL javaSE7Profile = OSGiTestsActivator.getContext().getBundle(Constants.SYSTEM_BUNDLE_LOCATION).getEntry("JavaSE-1.7.profile");
 		URL javaSE8Profile = OSGiTestsActivator.getContext().getBundle(Constants.SYSTEM_BUNDLE_LOCATION).getEntry("JavaSE-1.8.profile");
+		URL javaSE9Profile = OSGiTestsActivator.getContext().getBundle(Constants.SYSTEM_BUNDLE_LOCATION).getEntry("JavaSE-9.profile");
 
-		// configure equinox for javaSE 8
+		// configure equinox for javaSE 9
 		File config = OSGiTestsActivator.getContext().getDataFile(getName()); //$NON-NLS-1$
 		Map<String, Object> configuration = new HashMap<>();
 		configuration.put(Constants.FRAMEWORK_STORAGE, config.getAbsolutePath());
-		configuration.put("osgi.java.profile", javaSE8Profile.toExternalForm()); //$NON-NLS-1$
+		configuration.put("osgi.java.profile", javaSE9Profile.toExternalForm()); //$NON-NLS-1$
 
 		Equinox equinox = new Equinox(configuration);
 		equinox.start();
 
-		// install a bundle that requires java 8
+		// install a bundle that requires java 9
 		BundleContext systemContext = equinox.getBundleContext();
 		assertNotNull("System context is null", systemContext); //$NON-NLS-1$
 		Map<String, String> testHeaders = new HashMap<>();
 		testHeaders.put(Constants.BUNDLE_MANIFESTVERSION, "2");
 		testHeaders.put(Constants.BUNDLE_SYMBOLICNAME, getName());
-		testHeaders.put(Constants.BUNDLE_REQUIREDEXECUTIONENVIRONMENT, "JavaSE-1.8");
+		testHeaders.put(Constants.BUNDLE_REQUIREDEXECUTIONENVIRONMENT, "JavaSE-9");
 		File testBundle = createBundle(config, getName(), testHeaders);
 		Bundle b = systemContext.installBundle("reference:file:///" + testBundle.getAbsolutePath()); //$NON-NLS-1$
 		long bid = b.getBundleId();
@@ -822,8 +822,8 @@
 		// put the framework back to the RESOLVED state
 		stop(equinox);
 
-		// configure equinox for java 7
-		configuration.put("osgi.java.profile", javaSE7Profile.toExternalForm());
+		// configure equinox for java 8
+		configuration.put("osgi.java.profile", javaSE8Profile.toExternalForm());
 		equinox = new Equinox(configuration);
 		try {
 			equinox.start();
@@ -837,8 +837,8 @@
 		// put the framework back to the RESOLVED state
 		stop(equinox);
 
-		// move back to java 8
-		configuration.put("osgi.java.profile", javaSE8Profile.toExternalForm());
+		// move back to java 9
+		configuration.put("osgi.java.profile", javaSE9Profile.toExternalForm());
 		equinox = new Equinox(configuration);
 		try {
 			equinox.start();
@@ -2223,7 +2223,7 @@
 		config.mkdirs();
 		Map<String, Object> configuration = new HashMap<>();
 		configuration.put(Constants.FRAMEWORK_STORAGE, config.getAbsolutePath());
-		configuration.put(Constants.FRAMEWORK_SYSTEMCAPABILITIES, "osgi.ee; osgi.ee=JavaSE; version:Version=1.7, something.system");
+		configuration.put(Constants.FRAMEWORK_SYSTEMCAPABILITIES, "osgi.ee; osgi.ee=JavaSE; version:Version=1.8, something.system");
 		configuration.put(Constants.FRAMEWORK_SYSTEMPACKAGES, "something.system");
 		configuration.put(Constants.FRAMEWORK_SYSTEMCAPABILITIES_EXTRA, "something.extra");
 		configuration.put(Constants.FRAMEWORK_SYSTEMPACKAGES_EXTRA, "something.extra");
@@ -2294,7 +2294,6 @@
 			doTestJavaProfile("1.10.1", "JavaSE-1.8", null);
 			doTestJavaProfile("1.9", "JavaSE-1.8", null);
 			doTestJavaProfile("1.8", "JavaSE-1.8", null);
-			doTestJavaProfile("1.7", "JavaSE-1.7", null);
 			doTestJavaProfile("1.8", "JavaSE/compact3-1.8", "compact3");
 			doTestJavaProfile("1.8", "JavaSE/compact3-1.8", "\"compact3\"");
 			doTestJavaProfile("1.8", "JavaSE/compact3-1.8", " \"compact3\" ");
diff --git a/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/bundles/classes/Activator.java b/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/bundles/classes/Activator.java
new file mode 100644
index 0000000..1294453
--- /dev/null
+++ b/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/bundles/classes/Activator.java
@@ -0,0 +1,31 @@
+/*******************************************************************************
+ * Copyright (c) 2019 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.tests.bundles.classes;
+
+import java.util.Collections;
+import java.util.Hashtable;
+import org.osgi.framework.BundleActivator;
+import org.osgi.framework.BundleContext;
+
+public class Activator implements BundleActivator {
+	@Override
+	public void start(BundleContext context) throws Exception {
+		context.registerService(Activator.class, this, new Hashtable<>(Collections.singletonMap("activator", this.getClass().getSimpleName())));
+	}
+
+	@Override
+	public void stop(BundleContext context) throws Exception {
+		// do nothing
+	}
+}
diff --git a/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/bundles/classes/Activator1.java b/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/bundles/classes/Activator1.java
new file mode 100644
index 0000000..527a559
--- /dev/null
+++ b/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/bundles/classes/Activator1.java
@@ -0,0 +1,18 @@
+/*******************************************************************************
+ * Copyright (c) 2019 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.tests.bundles.classes;
+
+public class Activator1 extends Activator {
+	// nothing
+}
diff --git a/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/bundles/classes/Activator2.java b/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/bundles/classes/Activator2.java
new file mode 100644
index 0000000..a223183
--- /dev/null
+++ b/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/bundles/classes/Activator2.java
@@ -0,0 +1,18 @@
+/*******************************************************************************
+ * Copyright (c) 2019 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.tests.bundles.classes;
+
+public class Activator2 extends Activator {
+	// nothing
+}
diff --git a/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/bundles/classes/Activator3.java b/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/bundles/classes/Activator3.java
new file mode 100644
index 0000000..272821d
--- /dev/null
+++ b/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/bundles/classes/Activator3.java
@@ -0,0 +1,18 @@
+/*******************************************************************************
+ * Copyright (c) 2019 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.tests.bundles.classes;
+
+public class Activator3 extends Activator {
+	// nothing
+}
diff --git a/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/bundles/resources/1.txt b/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/bundles/resources/1.txt
new file mode 100644
index 0000000..56a6051
--- /dev/null
+++ b/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/bundles/resources/1.txt
@@ -0,0 +1 @@
+1
\ No newline at end of file
diff --git a/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/bundles/resources/2.txt b/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/bundles/resources/2.txt
new file mode 100644
index 0000000..d8263ee
--- /dev/null
+++ b/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/bundles/resources/2.txt
@@ -0,0 +1 @@
+2
\ No newline at end of file
diff --git a/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/bundles/resources/3.txt b/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/bundles/resources/3.txt
new file mode 100644
index 0000000..e440e5c
--- /dev/null
+++ b/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/bundles/resources/3.txt
@@ -0,0 +1 @@
+3
\ No newline at end of file
diff --git a/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/filter/FilterTests.java b/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/filter/FilterTests.java
index f9fbd40..8985c5c 100644
--- a/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/filter/FilterTests.java
+++ b/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/filter/FilterTests.java
@@ -483,5 +483,10 @@
 			}
 			return new CaseInsensitiveDictionaryMap(dictionary);
 		}
+
+		@Override
+		public Object adapt(Class type) {
+			return null;
+		}
 	}
 }
diff --git a/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/hooks/framework/AbstractFrameworkHookTests.java b/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/hooks/framework/AbstractFrameworkHookTests.java
index 50210a9..8dd1184 100644
--- a/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/hooks/framework/AbstractFrameworkHookTests.java
+++ b/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/hooks/framework/AbstractFrameworkHookTests.java
@@ -30,6 +30,7 @@
 import org.eclipse.osgi.tests.OSGiTestsActivator;
 import org.eclipse.osgi.tests.bundles.BundleInstaller;
 import org.osgi.framework.BundleContext;
+import org.osgi.framework.connect.FrameworkUtilHelper;
 import org.osgi.framework.launch.Framework;
 import org.osgi.framework.launch.FrameworkFactory;
 
@@ -73,7 +74,7 @@
 					throw new RuntimeException(e);
 				}
 			}
-			if (name.startsWith("org.eclipse") || name.startsWith("org.osgi.framework.FrameworkUtil")) {
+			if (name.startsWith("org.eclipse") || name.startsWith("org.osgi.framework.FrameworkUtil") || name.equals(FrameworkUtilHelper.class.getName())) {
 				Class<?> result = findLoadedClass(name);
 				if (result == null)
 					result = findClass(name);
diff --git a/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/hooks/framework/ActivatorOrderTest.java b/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/hooks/framework/ActivatorOrderTest.java
new file mode 100644
index 0000000..6d33025
--- /dev/null
+++ b/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/hooks/framework/ActivatorOrderTest.java
@@ -0,0 +1,68 @@
+/*******************************************************************************
+ * Copyright (c) 2020 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.tests.hooks.framework;
+
+import static org.eclipse.osgi.tests.bundles.AbstractBundleTests.stop;
+
+import java.io.File;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import org.eclipse.osgi.internal.hookregistry.HookRegistry;
+import org.eclipse.osgi.tests.OSGiTestsActivator;
+import org.osgi.framework.Constants;
+import org.osgi.framework.launch.Framework;
+
+public class ActivatorOrderTest extends AbstractFrameworkHookTests {
+
+	private Framework framework;
+	private static final String HOOK_CONFIGURATOR_BUNDLE = "activator.hooks.a";
+	private static final String HOOK_CONFIGURATOR_CLASS1 = "org.eclipse.osgi.tests.hooks.framework.activator.a.TestHookConfigurator1";
+	private static final String HOOK_CONFIGURATOR_CLASS2 = "org.eclipse.osgi.tests.hooks.framework.activator.a.TestHookConfigurator2";
+	private static final String HOOK_CONFIGURATOR_CLASS3 = "org.eclipse.osgi.tests.hooks.framework.activator.a.TestHookConfigurator3";
+
+	@Override
+	protected void setUp() throws Exception {
+		super.setUp();
+		String loc = bundleInstaller.getBundleLocation(HOOK_CONFIGURATOR_BUNDLE);
+		loc = loc.substring(loc.indexOf("file:"));
+		classLoader.addURL(new URL(loc));
+		File file = OSGiTestsActivator.getContext().getDataFile(getName());
+		HashMap<String, String> configuration = new HashMap<>();
+		configuration.put(Constants.FRAMEWORK_STORAGE, file.getAbsolutePath());
+		configuration.put(HookRegistry.PROP_HOOK_CONFIGURATORS, HOOK_CONFIGURATOR_CLASS1 + "," + HOOK_CONFIGURATOR_CLASS2 + "," + HOOK_CONFIGURATOR_CLASS3);
+
+		framework = createFramework(configuration);
+	}
+
+	public void testActivatorOrder() throws Exception {
+		List<String> actualEvents = new ArrayList<>();
+		Class<?> clazz1 = classLoader.loadClass(HOOK_CONFIGURATOR_CLASS1);
+		clazz1.getField("events").set(null, actualEvents);
+		Class<?> clazz2 = classLoader.loadClass(HOOK_CONFIGURATOR_CLASS2);
+		clazz2.getField("events").set(null, actualEvents);
+		Class<?> clazz3 = classLoader.loadClass(HOOK_CONFIGURATOR_CLASS3);
+		clazz3.getField("events").set(null, actualEvents);
+
+		List<String> expectedEvents = Arrays.asList("HOOK1 STARTED", "HOOK2 STARTED", "HOOK3 STARTED", "HOOK3 STOPPED", "HOOK2 STOPPED", "HOOK1 STOPPED");
+
+		initAndStart(framework);
+		stop(framework);
+		assertEquals("Activator order not as expected", expectedEvents, actualEvents);
+
+	}
+
+}
diff --git a/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/hooks/framework/AllFrameworkHookTests.java b/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/hooks/framework/AllFrameworkHookTests.java
index dc6c570..3e35b93 100644
--- a/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/hooks/framework/AllFrameworkHookTests.java
+++ b/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/hooks/framework/AllFrameworkHookTests.java
@@ -25,6 +25,7 @@
 		suite.addTest(new TestSuite(ContextFinderTests.class));
 		suite.addTest(new TestSuite(DevClassPathWithExtensionTests.class));
 		suite.addTest(new TestSuite(EmbeddedEquinoxWithURLInClassLoadTests.class));
+		suite.addTest(new TestSuite(ActivatorOrderTest.class));
 		return suite;
 	}
 }
diff --git a/bundles/org.eclipse.osgi/.classpath b/bundles/org.eclipse.osgi/.classpath
index 150b59d..d1e9a6c 100644
--- a/bundles/org.eclipse.osgi/.classpath
+++ b/bundles/org.eclipse.osgi/.classpath
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <classpath>
-	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.7"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"/>
 	<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
 	<classpathentry kind="src" path="osgi/src">
 		<attributes>
diff --git a/bundles/org.eclipse.osgi/.settings/.api_filters b/bundles/org.eclipse.osgi/.settings/.api_filters
new file mode 100644
index 0000000..f1f547e
--- /dev/null
+++ b/bundles/org.eclipse.osgi/.settings/.api_filters
@@ -0,0 +1,119 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<component id="org.eclipse.osgi" version="2">
+    <resource path="osgi/src/org/osgi/framework/FrameworkUtil.java" type="org.osgi.framework.FrameworkUtil">
+        <filter comment="Not for OSGi API" id="1141899266">
+            <message_arguments>
+                <message_argument value="1.10"/>
+                <message_argument value="3.16"/>
+                <message_argument value="asDictionary(Map&lt;? extends K,? extends V&gt;)"/>
+            </message_arguments>
+        </filter>
+        <filter comment="Not for OSGi API" id="1141899266">
+            <message_arguments>
+                <message_argument value="1.10"/>
+                <message_argument value="3.16"/>
+                <message_argument value="asMap(Dictionary&lt;? extends K,? extends V&gt;)"/>
+            </message_arguments>
+        </filter>
+        <filter comment="Not for OSGi API" id="1141899266">
+            <message_arguments>
+                <message_argument value="1.10"/>
+                <message_argument value="3.16"/>
+                <message_argument value="getBundle(ClassLoader)"/>
+            </message_arguments>
+        </filter>
+    </resource>
+    <resource path="osgi/src/org/osgi/framework/ServiceReference.java" type="org.osgi.framework.ServiceReference">
+        <filter comment="Not for OSGi API" id="403804204">
+            <message_arguments>
+                <message_argument value="org.osgi.framework.ServiceReference"/>
+                <message_argument value="adapt(Class&lt;A&gt;)"/>
+            </message_arguments>
+        </filter>
+        <filter id="403984517">
+            <message_arguments>
+                <message_argument value="org.osgi.framework.ServiceReference"/>
+                <message_argument value="org.osgi.framework.BundleReference"/>
+                <message_argument value="getBundle()"/>
+            </message_arguments>
+        </filter>
+        <filter comment="Not for OSGi API" id="1209008130">
+            <message_arguments>
+                <message_argument value="1.10"/>
+                <message_argument value="3.16"/>
+                <message_argument value="adapt(Class&lt;A&gt;)"/>
+            </message_arguments>
+        </filter>
+    </resource>
+    <resource path="osgi/src/org/osgi/framework/connect/ConnectContent.java" type="org.osgi.framework.connect.ConnectContent">
+        <filter comment="Not for OSGi API" id="1110441988">
+            <message_arguments>
+                <message_argument value="org.osgi.framework.connect.ConnectContent"/>
+            </message_arguments>
+        </filter>
+    </resource>
+    <resource path="osgi/src/org/osgi/framework/connect/ConnectFrameworkFactory.java" type="org.osgi.framework.connect.ConnectFrameworkFactory">
+        <filter comment="Not for OSGi API" id="1110441988">
+            <message_arguments>
+                <message_argument value="org.osgi.framework.connect.ConnectFrameworkFactory"/>
+            </message_arguments>
+        </filter>
+    </resource>
+    <resource path="osgi/src/org/osgi/framework/connect/ConnectModule.java" type="org.osgi.framework.connect.ConnectModule">
+        <filter comment="Not for OSGi API" id="1110441988">
+            <message_arguments>
+                <message_argument value="org.osgi.framework.connect.ConnectModule"/>
+            </message_arguments>
+        </filter>
+    </resource>
+    <resource path="osgi/src/org/osgi/framework/connect/FrameworkUtilHelper.java" type="org.osgi.framework.connect.FrameworkUtilHelper">
+        <filter comment="Not for OSGi API" id="1110441988">
+            <message_arguments>
+                <message_argument value="org.osgi.framework.connect.FrameworkUtilHelper"/>
+            </message_arguments>
+        </filter>
+    </resource>
+    <resource path="osgi/src/org/osgi/framework/connect/ModuleConnector.java" type="org.osgi.framework.connect.ModuleConnector">
+        <filter comment="Not for OSGi API" id="1110441988">
+            <message_arguments>
+                <message_argument value="org.osgi.framework.connect.ModuleConnector"/>
+            </message_arguments>
+        </filter>
+    </resource>
+    <resource path="osgi/src/org/osgi/framework/launch/FrameworkFactory.java" type="org.osgi.framework.launch.FrameworkFactory">
+        <filter comment="Not for OSGi packages" id="403804204">
+            <message_arguments>
+                <message_argument value="org.osgi.framework.launch.FrameworkFactory"/>
+                <message_argument value="newFramework(Map&lt;String,String&gt;, ConnectFactory)"/>
+            </message_arguments>
+        </filter>
+        <filter comment="Not for OSGi packages" id="1209008130">
+            <message_arguments>
+                <message_argument value="1.3"/>
+                <message_argument value="3.16"/>
+                <message_argument value="newFramework(Map&lt;String,String&gt;, ConnectFactory)"/>
+            </message_arguments>
+        </filter>
+        <filter comment="Not for OSGi packages" id="1211105284">
+            <message_arguments>
+                <message_argument value="newFramework(Map&lt;String,String&gt;, ConnectFactory)"/>
+            </message_arguments>
+        </filter>
+    </resource>
+    <resource path="osgi/src/org/osgi/framework/namespace/IdentityNamespace.java" type="org.osgi.framework.namespace.IdentityNamespace">
+        <filter comment="Not for OSGi API" id="1141899266">
+            <message_arguments>
+                <message_argument value="1.2"/>
+                <message_argument value="3.16"/>
+                <message_argument value="CAPABILITY_TAGS_ATTRIBUTE"/>
+            </message_arguments>
+        </filter>
+    </resource>
+    <resource path="osgi/src/org/osgi/service/condition/Condition.java" type="org.osgi.service.condition.Condition">
+        <filter comment="Not for OSGi API" id="1110441988">
+            <message_arguments>
+                <message_argument value="org.osgi.service.condition.Condition"/>
+            </message_arguments>
+        </filter>
+    </resource>
+</component>
diff --git a/bundles/org.eclipse.osgi/.settings/org.eclipse.jdt.core.prefs b/bundles/org.eclipse.osgi/.settings/org.eclipse.jdt.core.prefs
index d14e296..11ab09e 100644
--- a/bundles/org.eclipse.osgi/.settings/org.eclipse.jdt.core.prefs
+++ b/bundles/org.eclipse.osgi/.settings/org.eclipse.jdt.core.prefs
@@ -13,9 +13,10 @@
 org.eclipse.jdt.core.compiler.annotation.nullable=org.eclipse.jdt.annotation.Nullable
 org.eclipse.jdt.core.compiler.annotation.nullanalysis=disabled
 org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
-org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7
+org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
 org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
-org.eclipse.jdt.core.compiler.compliance=1.7
+org.eclipse.jdt.core.compiler.compliance=1.8
 org.eclipse.jdt.core.compiler.debug.lineNumber=generate
 org.eclipse.jdt.core.compiler.debug.localVariable=generate
 org.eclipse.jdt.core.compiler.debug.sourceFile=generate
@@ -31,6 +32,7 @@
 org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=enabled
 org.eclipse.jdt.core.compiler.problem.discouragedReference=error
 org.eclipse.jdt.core.compiler.problem.emptyStatement=warning
+org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled
 org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
 org.eclipse.jdt.core.compiler.problem.explicitlyClosedAutoCloseable=ignore
 org.eclipse.jdt.core.compiler.problem.fallthroughCase=ignore
@@ -69,7 +71,7 @@
 org.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod=ignore
 org.eclipse.jdt.core.compiler.problem.noEffectAssignment=warning
 org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning
-org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=error
+org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=warning
 org.eclipse.jdt.core.compiler.problem.nonnullParameterAnnotationDropped=warning
 org.eclipse.jdt.core.compiler.problem.nullAnnotationInferenceConflict=error
 org.eclipse.jdt.core.compiler.problem.nullReference=warning
@@ -87,6 +89,7 @@
 org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=ignore
 org.eclipse.jdt.core.compiler.problem.reportMethodCanBePotentiallyStatic=ignore
 org.eclipse.jdt.core.compiler.problem.reportMethodCanBeStatic=ignore
+org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=warning
 org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled
 org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning
 org.eclipse.jdt.core.compiler.problem.suppressOptionalErrors=disabled
@@ -119,7 +122,8 @@
 org.eclipse.jdt.core.compiler.problem.unusedTypeParameter=ignore
 org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning
 org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=error
-org.eclipse.jdt.core.compiler.source=1.7
+org.eclipse.jdt.core.compiler.release=disabled
+org.eclipse.jdt.core.compiler.source=1.8
 org.eclipse.jdt.core.formatter.align_assignment_statements_on_columns=false
 org.eclipse.jdt.core.formatter.align_fields_grouping_blank_lines=2147483647
 org.eclipse.jdt.core.formatter.align_type_members_on_columns=false
diff --git a/bundles/org.eclipse.osgi/.settings/org.eclipse.pde.api.tools.prefs b/bundles/org.eclipse.osgi/.settings/org.eclipse.pde.api.tools.prefs
index 5b3c8e0..8dd4a28 100644
--- a/bundles/org.eclipse.osgi/.settings/org.eclipse.pde.api.tools.prefs
+++ b/bundles/org.eclipse.osgi/.settings/org.eclipse.pde.api.tools.prefs
@@ -1,11 +1,17 @@
-#Thu Oct 08 09:47:30 CDT 2009
+ANNOTATION_ELEMENT_TYPE_ADDED_FIELD=Error
 ANNOTATION_ELEMENT_TYPE_ADDED_METHOD_WITHOUT_DEFAULT_VALUE=Error
 ANNOTATION_ELEMENT_TYPE_CHANGED_TYPE_CONVERSION=Error
 ANNOTATION_ELEMENT_TYPE_REMOVED_FIELD=Error
 ANNOTATION_ELEMENT_TYPE_REMOVED_METHOD=Error
 ANNOTATION_ELEMENT_TYPE_REMOVED_TYPE_MEMBER=Error
 API_COMPONENT_ELEMENT_TYPE_REMOVED_API_TYPE=Error
+API_COMPONENT_ELEMENT_TYPE_REMOVED_REEXPORTED_API_TYPE=Error
+API_COMPONENT_ELEMENT_TYPE_REMOVED_REEXPORTED_TYPE=Error
 API_COMPONENT_ELEMENT_TYPE_REMOVED_TYPE=Error
+API_USE_SCAN_FIELD_SEVERITY=Error
+API_USE_SCAN_METHOD_SEVERITY=Error
+API_USE_SCAN_TYPE_SEVERITY=Error
+CLASS_ELEMENT_TYPE_ADDED_FIELD=Error
 CLASS_ELEMENT_TYPE_ADDED_METHOD=Error
 CLASS_ELEMENT_TYPE_ADDED_RESTRICTIONS=Error
 CLASS_ELEMENT_TYPE_ADDED_TYPE_PARAMETER=Error
@@ -45,6 +51,7 @@
 ILLEGAL_INSTANTIATE=Warning
 ILLEGAL_OVERRIDE=Warning
 ILLEGAL_REFERENCE=Warning
+INTERFACE_ELEMENT_TYPE_ADDED_DEFAULT_METHOD=Error
 INTERFACE_ELEMENT_TYPE_ADDED_FIELD=Error
 INTERFACE_ELEMENT_TYPE_ADDED_METHOD=Error
 INTERFACE_ELEMENT_TYPE_ADDED_RESTRICTIONS=Error
@@ -56,6 +63,7 @@
 INTERFACE_ELEMENT_TYPE_REMOVED_METHOD=Error
 INTERFACE_ELEMENT_TYPE_REMOVED_TYPE_MEMBER=Error
 INTERFACE_ELEMENT_TYPE_REMOVED_TYPE_PARAMETER=Error
+INVALID_ANNOTATION=Ignore
 INVALID_JAVADOC_TAG=Ignore
 INVALID_REFERENCE_IN_SYSTEM_LIBRARIES=Error
 LEAK_EXTEND=Warning
@@ -73,6 +81,7 @@
 METHOD_ELEMENT_TYPE_CHANGED_VARARGS_TO_ARRAY=Error
 METHOD_ELEMENT_TYPE_REMOVED_ANNOTATION_DEFAULT_VALUE=Error
 METHOD_ELEMENT_TYPE_REMOVED_TYPE_PARAMETER=Error
+MISSING_EE_DESCRIPTIONS=Warning
 TYPE_PARAMETER_ELEMENT_TYPE_ADDED_CLASS_BOUND=Error
 TYPE_PARAMETER_ELEMENT_TYPE_ADDED_INTERFACE_BOUND=Error
 TYPE_PARAMETER_ELEMENT_TYPE_CHANGED_CLASS_BOUND=Error
@@ -80,10 +89,14 @@
 TYPE_PARAMETER_ELEMENT_TYPE_REMOVED_CLASS_BOUND=Error
 TYPE_PARAMETER_ELEMENT_TYPE_REMOVED_INTERFACE_BOUND=Error
 UNUSED_PROBLEM_FILTERS=Warning
+automatically_removed_unused_problem_filters=false
+changed_execution_env=Error
 eclipse.preferences.version=1
 incompatible_api_component_version=Error
 incompatible_api_component_version_include_major_without_breaking_change=Disabled
 incompatible_api_component_version_include_minor_without_api_change=Disabled
+incompatible_api_component_version_report_major_without_breaking_change=Warning
+incompatible_api_component_version_report_minor_without_api_change=Warning
 invalid_since_tag_version=Error
 malformed_since_tag=Error
 missing_since_tag=Error
diff --git a/bundles/org.eclipse.osgi/META-INF/MANIFEST.MF b/bundles/org.eclipse.osgi/META-INF/MANIFEST.MF
index bed5f7f..eb97f5f 100644
--- a/bundles/org.eclipse.osgi/META-INF/MANIFEST.MF
+++ b/bundles/org.eclipse.osgi/META-INF/MANIFEST.MF
@@ -6,6 +6,7 @@
  org.eclipse.osgi.container;version="1.5";
   uses:="org.eclipse.osgi.report.resolution,
    org.osgi.framework.wiring,
+   org.eclipse.osgi.framework.eventmgr,
    org.osgi.framework.startlevel,
    org.osgi.framework,
    org.osgi.framework.hooks.resolver,
@@ -34,7 +35,7 @@
  org.eclipse.osgi.internal.serviceregistry;x-internal:=true,
  org.eclipse.osgi.internal.signedcontent;x-internal:=true,
  org.eclipse.osgi.internal.url;x-internal:=true,
- org.eclipse.osgi.launch;version="1.0";uses:="org.osgi.framework,org.osgi.framework.launch",
+ org.eclipse.osgi.launch;version="1.1";uses:="org.osgi.framework,org.osgi.framework.launch,org.osgi.framework.connect",
  org.eclipse.osgi.report.resolution;version="1.0";uses:="org.osgi.service.resolver,org.osgi.resource",
  org.eclipse.osgi.service.datalocation;version="1.3",
  org.eclipse.osgi.service.debug;version="1.2",
@@ -52,22 +53,24 @@
  org.eclipse.osgi.storagemanager;version="1.0",
  org.eclipse.osgi.util;version="1.1",
  org.osgi.dto;version="1.1",
- org.osgi.framework;version="1.9",
+ org.osgi.framework;version="1.10",
+ org.osgi.framework.connect;version="1.0";uses:="org.osgi.framework.launch",
  org.osgi.framework.dto;version="1.8";uses:="org.osgi.dto",
  org.osgi.framework.hooks.bundle;version="1.1";uses:="org.osgi.framework",
  org.osgi.framework.hooks.resolver;version="1.0";uses:="org.osgi.framework.wiring",
  org.osgi.framework.hooks.service;version="1.1";uses:="org.osgi.framework",
  org.osgi.framework.hooks.weaving;version="1.1";uses:="org.osgi.framework.wiring",
  org.osgi.framework.launch;version="1.2";uses:="org.osgi.framework",
- org.osgi.framework.namespace;version="1.1";uses:="org.osgi.resource",
+ org.osgi.framework.namespace;version="1.2";uses:="org.osgi.resource",
  org.osgi.framework.startlevel;version="1.0";uses:="org.osgi.framework",
  org.osgi.framework.startlevel.dto;version="1.0";uses:="org.osgi.dto",
  org.osgi.framework.wiring;version="1.2";uses:="org.osgi.framework,org.osgi.resource",
  org.osgi.framework.wiring.dto;version="1.3";uses:="org.osgi.dto,org.osgi.resource.dto",
  org.osgi.resource;version="1.0",
  org.osgi.resource.dto;version="1.0";uses:="org.osgi.dto",
+ org.osgi.service.condition;version="1.0",
  org.osgi.service.condpermadmin;version="1.1.1";uses:="org.osgi.framework",
- org.osgi.service.log;version="1.4";uses:="org.osgi.framework",
+ org.osgi.service.log;version="1.5";uses:="org.osgi.framework",
  org.osgi.service.log.admin;version="1.0";uses:="org.osgi.service.log",
  org.osgi.service.packageadmin;version="1.2";uses:="org.osgi.framework",
  org.osgi.service.permissionadmin;version="1.2",
@@ -101,12 +104,12 @@
 Bundle-Description: %systemBundle
 Bundle-Copyright: %copyright
 Bundle-Vendor: %eclipse.org
-Bundle-Version: 3.15.300.qualifier
+Bundle-Version: 3.16.0.qualifier
 Bundle-Localization: systembundle
 Bundle-DocUrl: http://www.eclipse.org
 Eclipse-ExtensibleAPI: true
 Eclipse-SystemBundle: true
 Main-Class: org.eclipse.core.runtime.adaptor.EclipseStarter
-Require-Capability: osgi.ee; filter:="(| (&(osgi.ee=JavaSE)(version=1.7)) (&(osgi.ee=JavaSE/compact1)(version=1.8)) )"
+Require-Capability: osgi.ee; filter:="(| (&(osgi.ee=JavaSE)(version=1.8)) (&(osgi.ee=JavaSE/compact1)(version=1.8)) )"
 Eclipse-BundleShape: jar
 Automatic-Module-Name: org.eclipse.osgi
diff --git a/bundles/org.eclipse.osgi/META-INF/native-image/native-image.properties b/bundles/org.eclipse.osgi/META-INF/native-image/native-image.properties
new file mode 100644
index 0000000..301a266
--- /dev/null
+++ b/bundles/org.eclipse.osgi/META-INF/native-image/native-image.properties
@@ -0,0 +1,30 @@
+Args = --initialize-at-build-time=\
+org.apache.felix.resolver,\
+org.eclipse.equinox.log,\
+org.eclipse.osgi,\
+org.osgi.dto,\
+org.osgi.framework,\
+org.osgi.framework.connect,\
+org.osgi.framework.dto,\
+org.osgi.framework.hooks.bundle,\
+org.osgi.framework.hooks.resolver,\
+org.osgi.framework.hooks.service,\
+org.osgi.framework.hooks.weaving,\
+org.osgi.framework.launch,\
+org.osgi.framework.namespace,\
+org.osgi.framework.startlevel,\
+org.osgi.framework.startlevel.dto,\
+org.osgi.framework.wiring,\
+org.osgi.framework.wiring.dto,\
+org.osgi.resource,\
+org.osgi.resource.dto,\
+org.osgi.service.condpermadmin,\
+org.osgi.service.cm,\
+org.osgi.service.log,\
+org.osgi.service.log.admin,\
+org.osgi.service.packageadmin,\
+org.osgi.service.permissionadmin,\
+org.osgi.service.resolver,\
+org.osgi.service.startlevel,\
+org.osgi.service.url,\
+org.osgi.util.tracker
diff --git a/bundles/org.eclipse.osgi/META-INF/native-image/proxy-config.json b/bundles/org.eclipse.osgi/META-INF/native-image/proxy-config.json
new file mode 100644
index 0000000..50a895a
--- /dev/null
+++ b/bundles/org.eclipse.osgi/META-INF/native-image/proxy-config.json
@@ -0,0 +1,3 @@
+[
+  ["org.osgi.service.cm.SynchronousConfigurationListener"]
+]
diff --git a/bundles/org.eclipse.osgi/META-INF/native-image/reflect-config.json b/bundles/org.eclipse.osgi/META-INF/native-image/reflect-config.json
new file mode 100644
index 0000000..12dfa3e
--- /dev/null
+++ b/bundles/org.eclipse.osgi/META-INF/native-image/reflect-config.json
@@ -0,0 +1,109 @@
+[
+{
+  "name":"org.osgi.service.cm.SynchronousConfigurationListener",
+  "allDeclaredMethods":true,
+  "allPublicConstructors":true
+},
+{
+  "name":"com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderFactoryImpl",
+  "allPublicConstructors":true
+},
+{
+  "name":"com.sun.org.apache.xerces.internal.jaxp.SAXParserFactoryImpl",
+  "allPublicConstructors":true
+},
+{
+  "name":"com.sun.xml.internal.stream.XMLInputFactoryImpl",
+  "allPublicConstructors":true
+},
+{
+  "name":"java.lang.Boolean",
+  "methods":[{"name":"<init>","parameterTypes":["java.lang.String"] }]
+},
+{
+  "name":"java.lang.Object",
+  "allDeclaredMethods":true
+},
+{
+  "name":"java.lang.System",
+  "allPublicMethods":true
+},
+{
+  "name":"java.net.URL",
+  "allDeclaredFields":true
+},
+{
+  "name":"java.net.URLClassLoader",
+  "methods":[{"name":"addURL","parameterTypes":["java.net.URL"] }]
+},
+{
+  "name":"java.net.URLConnection",
+  "allDeclaredFields":true
+},
+{
+  "name":"java.util.HashSet",
+  "methods":[{"name":"clone","parameterTypes":[] }]
+},
+{
+  "name":"javax.xml.parsers.SAXParserFactory"
+},
+{
+  "name":"org.eclipse.osgi.container.ModuleWiring",
+  "fields":[{"name":"dynamicMissRef"}]
+},
+{
+  "name":"org.eclipse.osgi.internal.cds.CDSHookConfigurator",
+  "methods":[{"name":"<init>","parameterTypes":[] }]
+},
+{
+  "name":"org.eclipse.osgi.internal.connect.ConnectHookConfigurator",
+  "methods":[{"name":"<init>","parameterTypes":[] }]
+},
+{
+  "name":"org.eclipse.osgi.internal.framework.BundleContextImpl",
+  "allPublicMethods":true
+},
+{
+  "name":"org.eclipse.osgi.internal.framework.EquinoxBundle$SystemBundle",
+  "allPublicMethods":true
+},
+{
+  "name":"org.eclipse.osgi.internal.framework.SystemBundleActivator",
+  "methods":[{"name":"<init>","parameterTypes":[] }]
+},
+{
+  "name":"org.eclipse.osgi.internal.signedcontent.SignedBundleHook",
+  "methods":[{"name":"<init>","parameterTypes":[] }]
+},
+{
+  "name":"org.eclipse.osgi.launch.EquinoxFactory",
+  "methods":[{"name":"<init>","parameterTypes":[] }]
+},
+{
+  "name":"org.eclipse.osgi.service.resolver.BundleDescription"
+},
+{
+  "name":"org.osgi.service.cm.Configuration",
+  "methods":[
+    {"name":"getFactoryPid","parameterTypes":[] }, 
+    {"name":"getPid","parameterTypes":[] }, 
+    {"name":"getProperties","parameterTypes":[] }
+  ]
+},
+{
+  "name":"org.osgi.service.cm.ConfigurationAdmin",
+  "methods":[
+    {"name":"getConfiguration","parameterTypes":["java.lang.String","java.lang.String"] }, 
+    {"name":"listConfigurations","parameterTypes":["java.lang.String"] }
+  ]
+},
+{
+  "name":"org.osgi.service.cm.ConfigurationEvent",
+  "methods":[
+    {"name":"getFactoryPid","parameterTypes":[] }, 
+    {"name":"getPid","parameterTypes":[] }, 
+    {"name":"getReference","parameterTypes":[] }, 
+    {"name":"getType","parameterTypes":[] }
+  ]
+}
+]
diff --git a/bundles/org.eclipse.osgi/META-INF/native-image/resource-config.json b/bundles/org.eclipse.osgi/META-INF/native-image/resource-config.json
new file mode 100644
index 0000000..dc878ee
--- /dev/null
+++ b/bundles/org.eclipse.osgi/META-INF/native-image/resource-config.json
@@ -0,0 +1,14 @@
+{
+  "resources":[
+    {"pattern":"META-INF/services/org.osgi.framework.connect.ConnectFrameworkFactory"},
+    {"pattern":"META-INF/services/org.osgi.framework.connect.FrameworkUtilHelper"},
+    {"pattern":"META-INF/services/org.osgi.framework.launch.FrameworkFactory"},
+    {"pattern":"hookconfigurators.properties"}, 
+    {"pattern":"org/eclipse/osgi/internal/framework/osname.aliases"},
+    {"pattern":"org/eclipse/osgi/internal/framework/processor.aliases"},
+    {"pattern":"org/eclipse/osgi/internal/messages/ExternalMessages.properties"},
+    {"pattern":"org/eclipse/osgi/internal/permadmin/implied.permissions"},
+    {"pattern":"org/eclipse/osgi/internal/signedcontent/SignedContentMessages.properties"},
+    {"pattern":"org/eclipse/osgi/internal/url/SetAccessible.bytes"}
+  ]
+}
diff --git a/bundles/org.eclipse.osgi/META-INF/services/org.osgi.framework.connect.ConnectFrameworkFactory b/bundles/org.eclipse.osgi/META-INF/services/org.osgi.framework.connect.ConnectFrameworkFactory
new file mode 100644
index 0000000..6cd04c1
--- /dev/null
+++ b/bundles/org.eclipse.osgi/META-INF/services/org.osgi.framework.connect.ConnectFrameworkFactory
@@ -0,0 +1 @@
+org.eclipse.osgi.launch.EquinoxFactory
diff --git a/bundles/org.eclipse.osgi/build.properties b/bundles/org.eclipse.osgi/build.properties
index 70f107d..e6ec93e 100644
--- a/bundles/org.eclipse.osgi/build.properties
+++ b/bundles/org.eclipse.osgi/build.properties
@@ -38,4 +38,4 @@
 jars.extra.classpath = osgi/osgi.annotation.jar,\
                        osgi/function.interface.jar,\
                        osgi/j9stubs.jar
-jre.compilation.profile = JavaSE-1.7
+jre.compilation.profile = JavaSE-1.8
diff --git a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/cds/CDSHookImpls.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/cds/CDSHookImpls.java
index 5eddeaf..dfdc819 100644
--- a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/cds/CDSHookImpls.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/cds/CDSHookImpls.java
@@ -37,6 +37,7 @@
 import org.eclipse.osgi.internal.loader.classpath.ClasspathManager;
 import org.eclipse.osgi.internal.loader.classpath.FragmentClasspath;
 import org.eclipse.osgi.storage.BundleInfo.Generation;
+import org.eclipse.osgi.storage.ContentProvider.Type;
 import org.eclipse.osgi.storage.bundlefile.BundleEntry;
 import org.eclipse.osgi.storage.bundlefile.BundleFile;
 import org.eclipse.osgi.storage.bundlefile.BundleFileWrapper;
@@ -192,6 +193,9 @@
 	//////////////// BundleFileWrapperFactoryHook //////////////
 	@Override
 	public BundleFileWrapper wrapBundleFile(BundleFile bundleFile, Generation generation, boolean base) {
+		if (generation.getContentType() == Type.CONNECT) {
+			return null;
+		}
 		// wrap the real bundle file for purposes of loading shared classes.
 		CDSBundleFile newBundleFile;
 		if (!base && generation.getBundleInfo().getBundleId() != 0) {
diff --git a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/connect/ConnectBundleFile.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/connect/ConnectBundleFile.java
new file mode 100644
index 0000000..2570312
--- /dev/null
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/connect/ConnectBundleFile.java
@@ -0,0 +1,144 @@
+/*******************************************************************************
+ * Copyright (c) 2019 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.connect;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.Collections;
+import java.util.Map;
+import java.util.Optional;
+import org.eclipse.osgi.internal.debug.Debug;
+import org.eclipse.osgi.storage.BundleInfo;
+import org.eclipse.osgi.storage.bundlefile.BundleEntry;
+import org.eclipse.osgi.storage.bundlefile.CloseableBundleFile;
+import org.eclipse.osgi.storage.bundlefile.MRUBundleFileList;
+import org.osgi.framework.connect.ConnectContent;
+import org.osgi.framework.connect.ConnectContent.ConnectEntry;
+import org.osgi.framework.connect.ConnectModule;
+
+public class ConnectBundleFile extends CloseableBundleFile<ConnectEntry> {
+	public class ConnectBundleEntry extends BundleEntry {
+		private final ConnectEntry connectEntry;
+
+		public ConnectBundleEntry(ConnectEntry entry) {
+			this.connectEntry = entry;
+		}
+
+		@Override
+		public InputStream getInputStream() throws IOException {
+			return ConnectBundleFile.this.getInputStream(connectEntry);
+		}
+
+		@Override
+		public byte[] getBytes() throws IOException {
+			return connectEntry.getBytes();
+		}
+
+		@Override
+		public long getSize() {
+			return connectEntry.getContentLength();
+		}
+
+		@Override
+		public String getName() {
+			return connectEntry.getName();
+		}
+
+		@Override
+		public long getTime() {
+			return connectEntry.getLastModified();
+		}
+
+		@Override
+		public URL getFileURL() {
+			File file = ConnectBundleFile.this.getFile(getName(), false);
+			if (file != null) {
+				try {
+					return file.toURI().toURL();
+				} catch (MalformedURLException e) {
+					// should never happen
+				}
+			}
+			return null;
+		}
+
+		@Override
+		public URL getLocalURL() {
+			// TODO Not sure what to do here
+			throw new UnsupportedOperationException();
+		}
+	}
+
+	private final ConnectContent content;
+
+	public ConnectBundleFile(ConnectModule module, File basefile, BundleInfo.Generation generation, MRUBundleFileList mruList, Debug debug) throws IOException {
+		super(basefile, generation, mruList, debug);
+		this.content = module.getContent();
+	}
+
+	@Override
+	protected void doOpen() throws IOException {
+		content.open();
+	}
+
+	@Override
+	protected Iterable<String> getPaths() {
+		try {
+			return content.getEntries();
+		} catch (IOException e) {
+			return Collections.emptyList();
+		}
+	}
+
+	@Override
+	protected BundleEntry findEntry(String path) {
+		if (path.length() > 0 && path.charAt(0) == '/') {
+			path = path.substring(1);
+		}
+		return content.getEntry(path).map(ConnectBundleEntry::new).orElse(null);
+	}
+
+	@Override
+	protected void doClose() throws IOException {
+		content.close();
+	}
+
+	@Override
+	protected void postClose() {
+		// do nothing
+	}
+
+	@Override
+	protected InputStream doGetInputStream(ConnectEntry entry) throws IOException {
+		return entry.getInputStream();
+	}
+
+	public Map<String, String> getConnectHeaders() {
+		if (!lockOpen()) {
+			return null;
+		}
+		try {
+			return content.getHeaders().orElse(null);
+		} finally {
+			releaseOpen();
+		}
+	}
+
+	Optional<ClassLoader> getClassLoader() {
+		return content.getClassLoader();
+	}
+}
diff --git a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/connect/ConnectHookConfigurator.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/connect/ConnectHookConfigurator.java
new file mode 100644
index 0000000..a7e764c
--- /dev/null
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/connect/ConnectHookConfigurator.java
@@ -0,0 +1,190 @@
+/*******************************************************************************
+ * Copyright (c) 2019 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.connect;
+
+import static org.eclipse.osgi.internal.framework.EquinoxContainer.sneakyThrow;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URLConnection;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import org.eclipse.osgi.container.Module;
+import org.eclipse.osgi.container.ModuleContainerAdaptor.ModuleEvent;
+import org.eclipse.osgi.container.ModuleRevisionBuilder;
+import org.eclipse.osgi.internal.framework.EquinoxConfiguration;
+import org.eclipse.osgi.internal.framework.EquinoxContainer.ConnectModules;
+import org.eclipse.osgi.internal.hookregistry.ActivatorHookFactory;
+import org.eclipse.osgi.internal.hookregistry.ClassLoaderHook;
+import org.eclipse.osgi.internal.hookregistry.HookConfigurator;
+import org.eclipse.osgi.internal.hookregistry.HookRegistry;
+import org.eclipse.osgi.internal.hookregistry.StorageHookFactory;
+import org.eclipse.osgi.internal.hookregistry.StorageHookFactory.StorageHook;
+import org.eclipse.osgi.internal.loader.BundleLoader;
+import org.eclipse.osgi.internal.loader.ModuleClassLoader;
+import org.eclipse.osgi.storage.BundleInfo.Generation;
+import org.eclipse.osgi.storage.bundlefile.BundleFile;
+import org.eclipse.osgi.storage.bundlefile.BundleFileWrapperChain;
+import org.osgi.framework.BundleActivator;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.BundleException;
+import org.osgi.framework.connect.ConnectContent;
+import org.osgi.framework.connect.ConnectModule;
+import org.osgi.framework.connect.ModuleConnector;
+import org.osgi.framework.namespace.BundleNamespace;
+import org.osgi.framework.namespace.HostNamespace;
+import org.osgi.framework.namespace.IdentityNamespace;
+
+public class ConnectHookConfigurator implements HookConfigurator {
+	static final Collection<String> CONNECT_TAG_NAMESPACES = new ArrayList<>(Arrays.asList(
+			BundleNamespace.BUNDLE_NAMESPACE, HostNamespace.HOST_NAMESPACE, IdentityNamespace.IDENTITY_NAMESPACE));
+
+	@Override
+	public void addHooks(final HookRegistry hookRegistry) {
+		final ConnectModules connectModules = hookRegistry.getContainer().getConnectModules();
+		ModuleConnector moduleConnector = connectModules.getModuleConnector();
+
+		hookRegistry.addStorageHookFactory(new StorageHookFactory<Object, Object, StorageHook<Object, Object>>() {
+			@Override
+			protected StorageHook<Object, Object> createStorageHook(Generation generation) {
+				final ConnectModule m = connectModules.getConnectModule(generation.getBundleInfo().getLocation());
+
+				return new StorageHook<Object, Object>(generation, this.getClass()) {
+					boolean hasModule = false;
+
+					@Override
+					public void save(Object saveContext, DataOutputStream os) throws IOException {
+						os.writeBoolean(m != null);
+					}
+
+					@Override
+					public void load(Object loadContext, DataInputStream is) throws IOException {
+						hasModule = is.readBoolean();
+					}
+
+					@Override
+					public void validate() throws IllegalStateException {
+						// make sure we have the module still from the factory
+						if (hasModule && m == null) {
+							throw new IllegalStateException("Connect Factory no longer has the module at locataion: " + generation.getBundleInfo().getLocation()); //$NON-NLS-1$
+						}
+					}
+
+					@Override
+					public ModuleRevisionBuilder adaptModuleRevisionBuilder(ModuleEvent operation, Module origin, ModuleRevisionBuilder builder) {
+						if (m != null) {
+							builder.getCapabilities()
+								.stream() //
+								.filter(c -> CONNECT_TAG_NAMESPACES.contains(c.getNamespace())) //
+								.forEach((c) -> {
+									c.getAttributes().compute(IdentityNamespace.CAPABILITY_TAGS_ATTRIBUTE, (k, v) -> {
+										if (v == null) {
+											return Collections.singletonList(ConnectContent.TAG_OSGI_CONNECT);
+										}
+										if (v instanceof List) {
+											@SuppressWarnings({"unchecked", "rawtypes"})
+											List<String> l = new ArrayList<>((List) v);
+											l.add(ConnectContent.TAG_OSGI_CONNECT);
+											return Collections.unmodifiableList(l);
+										}
+										// should not get here, but just recover 
+										return Arrays.asList(v, ConnectContent.TAG_OSGI_CONNECT);
+									});
+								});
+							return builder;
+						}
+						return null;
+					}
+				};
+			}
+
+			@Override
+			public URLConnection handleContentConnection(Module module, String location, InputStream in) {
+				if (in != null) {
+					// Do not call ModuleConnector method connect when input stream is non null.
+					return null;
+				}
+				if (location == null) {
+					location = module.getLocation();
+				}
+				try {
+					ConnectModule m = connectModules.connect(location);
+					if (m != null) {
+						return ConnectInputStream.URL_CONNECTION_INSTANCE;
+					}
+				} catch (IllegalStateException e) {
+					if (e.getCause() instanceof BundleException) {
+						sneakyThrow(e.getCause());
+					}
+				}
+				return null;
+			}
+		});
+
+		if (moduleConnector == null) {
+			return;
+		}
+
+		hookRegistry.addClassLoaderHook(new ClassLoaderHook() {
+			@Override
+			public ModuleClassLoader createClassLoader(ClassLoader parent, EquinoxConfiguration configuration, BundleLoader delegate, Generation generation) {
+				ConnectModule m = connectModules.getConnectModule(generation.getBundleInfo().getLocation());
+				if (m != null) {
+					BundleFile bundlefile = generation.getBundleFile();
+					if (bundlefile instanceof BundleFileWrapperChain) {
+						BundleFileWrapperChain chain = (BundleFileWrapperChain) bundlefile;
+						while (chain.getNext() != null) {
+							chain = chain.getNext();
+						}
+						bundlefile = chain.getBundleFile();
+					}
+					if (bundlefile instanceof ConnectBundleFile) {
+						return ((ConnectBundleFile) bundlefile).getClassLoader().map((l) //
+						-> new DelegatingConnectClassLoader(parent, configuration, delegate, generation, l)).orElse(null);
+					}
+				}
+				return null;
+			}
+		});
+
+		hookRegistry.addActivatorHookFactory(new ActivatorHookFactory() {
+
+			@Override
+			public BundleActivator createActivator() {
+				final List<BundleActivator> activators = new ArrayList<>();
+				moduleConnector.newBundleActivator().ifPresent((a) -> activators.add(a));
+				return new BundleActivator() {
+					@Override
+					public void start(BundleContext context) throws Exception {
+						for (BundleActivator activator : activators) {
+							activator.start(context);
+						}
+					}
+
+					@Override
+					public void stop(BundleContext context) throws Exception {
+						for (BundleActivator activator : activators) {
+							activator.stop(context);
+						}
+					}
+				};
+			}
+		});
+	}
+}
diff --git a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/connect/ConnectInputStream.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/connect/ConnectInputStream.java
new file mode 100644
index 0000000..1d5ed69
--- /dev/null
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/connect/ConnectInputStream.java
@@ -0,0 +1,55 @@
+/*******************************************************************************
+ * Copyright (c) 2019 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.connect;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URLConnection;
+import org.eclipse.osgi.storage.ContentProvider;
+
+public class ConnectInputStream extends InputStream implements ContentProvider {
+	static final ConnectInputStream INSTANCE = new ConnectInputStream();
+	static final URLConnection URL_CONNECTION_INSTANCE = new URLConnection(null) {
+		@Override
+		public void connect() throws IOException {
+			connected = true;
+		}
+
+		@Override
+		public InputStream getInputStream() throws IOException {
+			return INSTANCE;
+		}
+	};
+
+	private ConnectInputStream() {
+	}
+
+	/* This method should not be called.
+	 */
+	@Override
+	public int read() throws IOException {
+		throw new IOException();
+	}
+
+	public File getContent() {
+		return null;
+	}
+
+	@Override
+	public Type getType() {
+		return Type.CONNECT;
+	}
+
+}
diff --git a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/connect/DelegatingConnectClassLoader.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/connect/DelegatingConnectClassLoader.java
new file mode 100644
index 0000000..d9e1cf5
--- /dev/null
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/connect/DelegatingConnectClassLoader.java
@@ -0,0 +1,67 @@
+/*******************************************************************************
+ * Copyright (c) 2019 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.connect;
+
+import java.io.IOException;
+import java.net.URL;
+import java.util.Collections;
+import java.util.Enumeration;
+import org.eclipse.osgi.internal.framework.EquinoxConfiguration;
+import org.eclipse.osgi.internal.loader.BundleLoader;
+import org.eclipse.osgi.internal.loader.EquinoxClassLoader;
+import org.eclipse.osgi.storage.BundleInfo.Generation;
+
+public class DelegatingConnectClassLoader extends EquinoxClassLoader {
+	static {
+		try {
+			ClassLoader.registerAsParallelCapable();
+		} catch (Throwable t) {
+			// ignore any error
+		}
+	}
+	private final ClassLoader connectClassLoader;
+
+	public DelegatingConnectClassLoader(ClassLoader parent, EquinoxConfiguration configuration, BundleLoader delegate, Generation generation, ClassLoader connectClassLoader) {
+		super(parent, configuration, delegate, generation);
+		this.connectClassLoader = connectClassLoader;
+	}
+
+	@Override
+	public Class<?> findLocalClass(String classname) throws ClassNotFoundException {
+		if (connectClassLoader == null) {
+			throw new ClassNotFoundException();
+		}
+		return connectClassLoader.loadClass(classname);
+	}
+
+	@Override
+	public URL findLocalResource(String resource) {
+		if (connectClassLoader == null) {
+			return null;
+		}
+		return connectClassLoader.getResource(resource);
+	}
+
+	@Override
+	public Enumeration<URL> findLocalResources(String resource) {
+		if (connectClassLoader == null) {
+			return Collections.enumeration(Collections.<URL> emptyList());
+		}
+		try {
+			return connectClassLoader.getResources(resource);
+		} catch (IOException e) {
+			return Collections.enumeration(Collections.<URL> emptyList());
+		}
+	}
+}
diff --git a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/framework/BundleContextImpl.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/framework/BundleContextImpl.java
index 0f059c8..29e9fa9 100644
--- a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/framework/BundleContextImpl.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/framework/BundleContextImpl.java
@@ -15,10 +15,8 @@
 package org.eclipse.osgi.internal.framework;
 
 import java.io.File;
-import java.io.IOException;
 import java.io.InputStream;
 import java.lang.reflect.InvocationTargetException;
-import java.net.URLConnection;
 import java.security.AccessController;
 import java.security.PrivilegedAction;
 import java.security.PrivilegedActionException;
@@ -182,14 +180,9 @@
 	@Override
 	public Bundle installBundle(String location, InputStream in) throws BundleException {
 		checkValid();
-		try {
-			URLConnection content = container.getStorage().getContentConnection(null, location, in);
-			Generation generation = container.getStorage().install(bundle.getModule(), location, content);
-			return generation.getRevision().getBundle();
-		} catch (IOException e) {
-			throw new BundleException("Error reading bundle content.", e); //$NON-NLS-1$
-		}
 
+		Generation generation = container.getStorage().install(bundle.getModule(), location, in);
+		return generation.getRevision().getBundle();
 	}
 
 	/**
diff --git a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/framework/ContextFinder.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/framework/ContextFinder.java
index 2ea40c9..fe0c79a 100644
--- a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/framework/ContextFinder.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/framework/ContextFinder.java
@@ -31,7 +31,9 @@
 	static final class Finder extends SecurityManager {
 		@Override
 		public Class<?>[] getClassContext() {
-			return super.getClassContext();
+			Class<?>[] result = super.getClassContext();
+			// note that Android returns null, so handling this by returning empty
+			return result == null ? new Class[0] : result;
 		}
 	}
 
diff --git a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/framework/DTOBuilder.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/framework/DTOBuilder.java
index 9607429..86ee2d0 100644
--- a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/framework/DTOBuilder.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/framework/DTOBuilder.java
@@ -15,17 +15,44 @@
 package org.eclipse.osgi.internal.framework;
 
 import java.lang.reflect.Array;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.IdentityHashMap;
+import java.util.List;
+import java.util.ListIterator;
+import java.util.Map;
+import java.util.Set;
 import org.osgi.dto.DTO;
-import org.osgi.framework.*;
-import org.osgi.framework.dto.*;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.Constants;
+import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.framework.ServiceReference;
+import org.osgi.framework.Version;
+import org.osgi.framework.dto.BundleDTO;
+import org.osgi.framework.dto.FrameworkDTO;
+import org.osgi.framework.dto.ServiceReferenceDTO;
 import org.osgi.framework.startlevel.BundleStartLevel;
 import org.osgi.framework.startlevel.FrameworkStartLevel;
 import org.osgi.framework.startlevel.dto.BundleStartLevelDTO;
 import org.osgi.framework.startlevel.dto.FrameworkStartLevelDTO;
-import org.osgi.framework.wiring.*;
-import org.osgi.framework.wiring.dto.*;
-import org.osgi.resource.dto.*;
+import org.osgi.framework.wiring.BundleCapability;
+import org.osgi.framework.wiring.BundleRequirement;
+import org.osgi.framework.wiring.BundleRevision;
+import org.osgi.framework.wiring.BundleRevisions;
+import org.osgi.framework.wiring.BundleWire;
+import org.osgi.framework.wiring.BundleWiring;
+import org.osgi.framework.wiring.dto.BundleRevisionDTO;
+import org.osgi.framework.wiring.dto.BundleWireDTO;
+import org.osgi.framework.wiring.dto.BundleWiringDTO;
+import org.osgi.framework.wiring.dto.FrameworkWiringDTO;
+import org.osgi.resource.dto.CapabilityDTO;
+import org.osgi.resource.dto.CapabilityRefDTO;
+import org.osgi.resource.dto.RequirementDTO;
+import org.osgi.resource.dto.RequirementRefDTO;
+import org.osgi.resource.dto.WireDTO;
 
 public class DTOBuilder {
 	private final Map<BundleRevision, BundleRevisionDTO> resources;
@@ -318,7 +345,7 @@
 			size = references == null ? 0 : references.length;
 			List<ServiceReferenceDTO> refDTOs = newList(size);
 			for (int i = 0; i < size; i++) {
-				ServiceReferenceDTO serviceRefDTO = getServiceReferenceDTO(references[i]);
+				ServiceReferenceDTO serviceRefDTO = newServiceReferenceDTO(references[i]);
 				if (serviceRefDTO != null) {
 					refDTOs.add(serviceRefDTO);
 				}
@@ -335,17 +362,12 @@
 		return (Map<String, Object>) m;
 	}
 
-	private static ServiceReferenceDTO getServiceReferenceDTO(ServiceReference<?> ref) {
+	public static ServiceReferenceDTO newServiceReferenceDTO(ServiceReference<?> ref) {
 		if (ref == null) {
 			return null;
 		}
-		Bundle b = ref.getBundle();
-		if (b == null) {
-			// service has been unregistered
-			return null;
-		}
+
 		ServiceReferenceDTO dto = new ServiceReferenceDTO();
-		dto.bundle = b.getBundleId();
 		String[] keys = ref.getPropertyKeys();
 		Map<String, Object> properties = newMap(keys.length);
 		for (String k : keys) {
@@ -353,6 +375,9 @@
 			if (Constants.SERVICE_ID.equals(k)) {
 				dto.id = ((Long) v).longValue();
 			}
+			if (Constants.SERVICE_BUNDLEID.equals(k)) {
+				dto.bundle = ((Long) v).longValue();
+			}
 			properties.put(k, mapValue(v));
 		}
 		dto.properties = properties;
@@ -383,7 +408,7 @@
 		final int length = references.length;
 		List<ServiceReferenceDTO> refDTOs = new ArrayList<>(length);
 		for (int i = 0; i < length; i++) {
-			ServiceReferenceDTO dto = getServiceReferenceDTO(references[i]);
+			ServiceReferenceDTO dto = newServiceReferenceDTO(references[i]);
 			if (dto != null) {
 				refDTOs.add(dto);
 			}
diff --git a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/framework/EquinoxBundle.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/framework/EquinoxBundle.java
index 3dbc4df..56c5eee 100644
--- a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/framework/EquinoxBundle.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/framework/EquinoxBundle.java
@@ -480,13 +480,9 @@
 
 	@Override
 	public void update(InputStream input) throws BundleException {
-		try {
-			Storage storage = equinoxContainer.getStorage();
-			storage.update(module, storage.getContentConnection(module, null, input));
-			signerInfos = null;
-		} catch (IOException e) {
-			throw new BundleException("Error reading bundle content.", e); //$NON-NLS-1$
-		}
+		Storage storage = equinoxContainer.getStorage();
+		storage.update(module, input);
+		signerInfos = null;
 	}
 
 	@Override
@@ -971,7 +967,7 @@
 	}
 
 	/**
-	 * Check for permission to get a service.
+	 * Check for permission to adapt.
 	 */
 	private <A> void checkAdaptPermission(Class<A> adapterType) {
 		SecurityManager sm = System.getSecurityManager();
diff --git a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/framework/EquinoxContainer.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/framework/EquinoxContainer.java
index af1b7d0..04f6809 100644
--- a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/framework/EquinoxContainer.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/framework/EquinoxContainer.java
@@ -13,20 +13,29 @@
  *******************************************************************************/
 package org.eclipse.osgi.internal.framework;
 
+import java.io.File;
 import java.io.IOException;
+import java.lang.ref.WeakReference;
 import java.lang.reflect.Method;
+import java.net.URL;
 import java.security.AccessController;
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
+import java.util.WeakHashMap;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
 import java.util.concurrent.Executors;
 import java.util.concurrent.ScheduledExecutorService;
 import java.util.concurrent.ThreadFactory;
 import org.eclipse.osgi.framework.eventmgr.ListenerQueue;
 import org.eclipse.osgi.framework.log.FrameworkLogEntry;
 import org.eclipse.osgi.framework.util.SecureAction;
+import org.eclipse.osgi.internal.connect.ConnectBundleFile;
+import org.eclipse.osgi.internal.debug.Debug;
 import org.eclipse.osgi.internal.framework.legacy.PackageAdminImpl;
 import org.eclipse.osgi.internal.framework.legacy.StartLevelImpl;
 import org.eclipse.osgi.internal.hookregistry.ClassLoaderHook;
@@ -36,7 +45,9 @@
 import org.eclipse.osgi.internal.messages.Msg;
 import org.eclipse.osgi.internal.serviceregistry.ServiceRegistry;
 import org.eclipse.osgi.signedcontent.SignedContentFactory;
+import org.eclipse.osgi.storage.BundleInfo;
 import org.eclipse.osgi.storage.Storage;
+import org.eclipse.osgi.storage.bundlefile.MRUBundleFileList;
 import org.eclipse.osgi.util.ManifestElement;
 import org.eclipse.osgi.util.NLS;
 import org.osgi.framework.AdminPermission;
@@ -44,6 +55,9 @@
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.BundleException;
 import org.osgi.framework.Constants;
+import org.osgi.framework.connect.ConnectContent;
+import org.osgi.framework.connect.ConnectModule;
+import org.osgi.framework.connect.ModuleConnector;
 import org.osgi.service.packageadmin.PackageAdmin;
 import org.osgi.service.startlevel.StartLevel;
 import org.osgi.util.tracker.ServiceTracker;
@@ -53,6 +67,7 @@
 	public static final String NAME = "org.eclipse.osgi"; //$NON-NLS-1$
 	static final SecureAction secureAction = AccessController.doPrivileged(SecureAction.createSecureAction());
 
+	private final ConnectModules connectModules;
 	private final EquinoxConfiguration equinoxConfig;
 	private final EquinoxLogServices logServices;
 	private final Storage storage;
@@ -75,7 +90,7 @@
 	private ScheduledExecutorService executor;
 	private StorageSaver storageSaver;
 
-	public EquinoxContainer(Map<String, ?> configuration) {
+	public EquinoxContainer(Map<String, ?> configuration, ModuleConnector moduleConnector) {
 		ClassLoader platformClassLoader = null;
 		try {
 			Method getPlatformClassLoader = ClassLoader.class.getMethod("getPlatformClassLoader"); //$NON-NLS-1$
@@ -89,6 +104,10 @@
 		this.equinoxConfig = new EquinoxConfiguration(configuration, new HookRegistry(this));
 		this.logServices = new EquinoxLogServices(this.equinoxConfig);
 		this.equinoxConfig.logMessages(this.logServices);
+		this.connectModules = new ConnectModules(moduleConnector);
+
+		initConnectFramework(moduleConnector, this.equinoxConfig);
+
 		this.equinoxConfig.getHookRegistry().initialize();
 		try {
 			this.storage = Storage.createStorage(this);
@@ -133,6 +152,17 @@
 		isProcessClassRecursionSupportedByAll = supportRecursion;
 	}
 
+	private static void initConnectFramework(ModuleConnector moduleConnector, EquinoxConfiguration equinoxConfig) {
+		if (moduleConnector == null) {
+			return;
+		}
+		URL configUrl = equinoxConfig.getEquinoxLocations().getConfigurationLocation().getURL();
+		final File fwkStore = new File(configUrl.getPath());
+		@SuppressWarnings({"rawtypes", "unchecked"})
+		Map<String, String> config = (Map) equinoxConfig.getInitialConfig();
+		moduleConnector.initialize(fwkStore, Collections.unmodifiableMap(config));
+	}
+
 	public Storage getStorage() {
 		return storage;
 	}
@@ -331,4 +361,62 @@
 	public ClassLoader getBootLoader() {
 		return bootLoader;
 	}
+
+	public ConnectModules getConnectModules() {
+		return connectModules;
+	}
+
+	public static class ConnectModules {
+		final ModuleConnector moduleConnector;
+		private final ConcurrentMap<String, ConnectModule> connectModules = new ConcurrentHashMap<>();
+		private final WeakHashMap<ConnectContent, WeakReference<ConnectBundleFile>> contents = new WeakHashMap<>();
+
+		public ConnectModules(ModuleConnector moduleConnector) {
+			this.moduleConnector = moduleConnector;
+		}
+
+		public ConnectModule connect(String location) {
+			if (moduleConnector == null) {
+				return null;
+			}
+			ConnectModule result = connectModules.compute(location, (k, v) -> {
+				try {
+					return moduleConnector.connect(location).orElse(null);
+				} catch (BundleException e) {
+					throw new IllegalStateException(e);
+				}
+			});
+			return result;
+		}
+
+		public ConnectBundleFile getConnectBundleFile(ConnectModule module, File basefile,
+				BundleInfo.Generation generation, MRUBundleFileList mruList, Debug debug) throws IOException {
+			ConnectContent content = module.getContent();
+			synchronized (contents) {
+				WeakReference<ConnectBundleFile> ref = contents.get(content);
+				if (ref != null) {
+					ConnectBundleFile bundleFile = ref.get();
+					if (bundleFile != null) {
+						return bundleFile;
+					}
+				}
+				ConnectBundleFile bundleFile = new ConnectBundleFile(module, basefile, generation, mruList, debug);
+				contents.put(content, new WeakReference<>(bundleFile));
+				return bundleFile;
+			}
+		}
+
+		public ModuleConnector getModuleConnector() {
+			return moduleConnector;
+		}
+
+		public ConnectModule getConnectModule(String location) {
+			return connectModules.get(location);
+		}
+	}
+
+	@SuppressWarnings("unchecked")
+	public static <E extends Throwable> void sneakyThrow(Throwable e) throws E {
+		throw (E) e;
+	}
 }
diff --git a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/framework/FilterImpl.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/framework/FilterImpl.java
index d0ccb36..528eba6 100644
--- a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/framework/FilterImpl.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/framework/FilterImpl.java
@@ -32,6 +32,7 @@
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
+import java.util.function.Function;
 import org.eclipse.osgi.framework.util.CaseInsensitiveDictionaryMap;
 import org.eclipse.osgi.internal.debug.Debug;
 import org.eclipse.osgi.internal.messages.Msg;
@@ -514,17 +515,9 @@
 			if (value1 instanceof Collection<?>) {
 				return compare_Collection((Collection<?>) value1);
 			}
-			if (value1 instanceof Integer) {
-				return compare_Integer(((Integer) value1).intValue());
-			}
-			if (value1 instanceof Long) {
-				return compare_Long(((Long) value1).longValue());
-			}
-			if (value1 instanceof Byte) {
-				return compare_Byte(((Byte) value1).byteValue());
-			}
-			if (value1 instanceof Short) {
-				return compare_Short(((Short) value1).shortValue());
+			if (value1 instanceof Integer || value1 instanceof Long || value1 instanceof Byte
+					|| value1 instanceof Short) {
+				return compare_Long(((Number) value1).longValue());
 			}
 			if (value1 instanceof Character) {
 				return compare_Character(((Character) value1).charValue());
@@ -571,7 +564,7 @@
 					if (debug) {
 						Debug.println(operation() + "(" + value1 + "," + value() + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
 					}
-					if (compare_Integer(value1)) {
+					if (compare_Long(value1)) {
 						return true;
 					}
 				}
@@ -595,7 +588,7 @@
 					if (debug) {
 						Debug.println(operation() + "(" + value1 + "," + value() + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
 					}
-					if (compare_Byte(value1)) {
+					if (compare_Long(value1)) {
 						return true;
 					}
 				}
@@ -607,7 +600,7 @@
 					if (debug) {
 						Debug.println(operation() + "(" + value1 + "," + value() + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
 					}
-					if (compare_Short(value1)) {
+					if (compare_Long(value1)) {
 						return true;
 					}
 				}
@@ -684,10 +677,6 @@
 			return false;
 		}
 
-		boolean compare_Byte(byte byteval) {
-			return false;
-		}
-
 		boolean compare_Character(char charval) {
 			return false;
 		}
@@ -700,18 +689,10 @@
 			return false;
 		}
 
-		boolean compare_Integer(int intval) {
-			return false;
-		}
-
 		boolean compare_Long(long longval) {
 			return false;
 		}
 
-		boolean compare_Short(short shortval) {
-			return false;
-		}
-
 		/**
 		 * Encode the value string such that '(', '*', ')' and '\' are escaped.
 		 *
@@ -864,12 +845,23 @@
 
 	static class Equal extends Item {
 		final String value;
+		private Object cached;
 
 		Equal(String attr, String value, boolean debug) {
 			super(attr, debug);
 			this.value = value;
 		}
 
+		private <T> T convert(Class<T> type, Function<String, ? extends T> converter) {
+			@SuppressWarnings("unchecked")
+			T converted = (T) cached;
+			if ((converted != null) && type.isInstance(converted)) {
+				return converted;
+			}
+			cached = converted = converter.apply(value.trim());
+			return converted;
+		}
+
 		@Override
 		String operation() {
 			return "EQUAL"; //$NON-NLS-1$
@@ -892,7 +884,7 @@
 		@Override
 		boolean compare_Version(Version value1) {
 			try {
-				Version version2 = Version.valueOf(value);
+				Version version2 = convert(Version.class, Version::valueOf);
 				return comparison(value1.compareTo(version2));
 			} catch (Exception e) {
 				// if the valueOf or compareTo method throws an exception
@@ -902,22 +894,11 @@
 
 		@Override
 		boolean compare_Boolean(boolean boolval) {
-			boolean boolval2 = Boolean.parseBoolean(value.trim());
+			boolean boolval2 = convert(Boolean.class, Boolean::valueOf).booleanValue();
 			return comparison(Boolean.compare(boolval, boolval2));
 		}
 
 		@Override
-		boolean compare_Byte(byte byteval) {
-			byte byteval2;
-			try {
-				byteval2 = Byte.parseByte(value.trim());
-			} catch (IllegalArgumentException e) {
-				return false;
-			}
-			return comparison(Byte.compare(byteval, byteval2));
-		}
-
-		@Override
 		boolean compare_Character(char charval) {
 			char charval2;
 			try {
@@ -932,7 +913,7 @@
 		boolean compare_Double(double doubleval) {
 			double doubleval2;
 			try {
-				doubleval2 = Double.parseDouble(value.trim());
+				doubleval2 = convert(Double.class, Double::valueOf).doubleValue();
 			} catch (IllegalArgumentException e) {
 				return false;
 			}
@@ -943,7 +924,7 @@
 		boolean compare_Float(float floatval) {
 			float floatval2;
 			try {
-				floatval2 = Float.parseFloat(value.trim());
+				floatval2 = convert(Float.class, Float::valueOf).floatValue();
 			} catch (IllegalArgumentException e) {
 				return false;
 			}
@@ -951,21 +932,10 @@
 		}
 
 		@Override
-		boolean compare_Integer(int intval) {
-			int intval2;
-			try {
-				intval2 = Integer.parseInt(value.trim());
-			} catch (IllegalArgumentException e) {
-				return false;
-			}
-			return comparison(Integer.compare(intval, intval2));
-		}
-
-		@Override
 		boolean compare_Long(long longval) {
 			long longval2;
 			try {
-				longval2 = Long.parseLong(value.trim());
+				longval2 = convert(Long.class, Long::valueOf).longValue();
 			} catch (IllegalArgumentException e) {
 				return false;
 			}
@@ -973,17 +943,6 @@
 		}
 
 		@Override
-		boolean compare_Short(short shortval) {
-			short shortval2;
-			try {
-				shortval2 = Short.parseShort(value.trim());
-			} catch (IllegalArgumentException e) {
-				return false;
-			}
-			return comparison(Short.compare(shortval, shortval2));
-		}
-
-		@Override
 		boolean compare_Comparable(Comparable<Object> value1) {
 			Object value2 = valueOf(value1.getClass());
 			if (value2 == null) {
diff --git a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/framework/SystemBundleActivator.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/framework/SystemBundleActivator.java
index b1917a1..44e488c 100644
--- a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/framework/SystemBundleActivator.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/framework/SystemBundleActivator.java
@@ -40,6 +40,7 @@
 import org.osgi.framework.BundleException;
 import org.osgi.framework.Constants;
 import org.osgi.framework.ServiceRegistration;
+import org.osgi.service.condition.Condition;
 import org.osgi.service.condpermadmin.ConditionalPermissionAdmin;
 import org.osgi.service.packageadmin.PackageAdmin;
 import org.osgi.service.permissionadmin.PermissionAdmin;
@@ -72,6 +73,11 @@
 
 		FrameworkDebugOptions dbgOptions = (FrameworkDebugOptions) configuration.getDebugOptions();
 		dbgOptions.start(bc);
+		Hashtable<String, Object> props = new Hashtable<>(7);
+		props.clear();
+
+		props.put(Condition.CONDITION_ID, Condition.CONDITION_ID_TRUE);
+		register(bc, Condition.class, Condition.INSTANCE, false, props);
 
 		SecurityAdmin sa = bundle.getEquinoxContainer().getStorage().getSecurityAdmin();
 		ClassLoader tccl = bundle.getEquinoxContainer().getContextFinder();
@@ -84,7 +90,7 @@
 		register(bc, PermissionAdmin.class, sa, null);
 		register(bc, ConditionalPermissionAdmin.class, sa, null);
 
-		Hashtable<String, Object> props = new Hashtable<>(7);
+
 		props.clear();
 		props.put(Constants.SERVICE_RANKING, Integer.MIN_VALUE);
 		register(bc, Resolver.class, new ResolverImpl(new Logger(0), null), false, props);
diff --git a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/hookregistry/FrameworkUtilHelper.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/hookregistry/FrameworkUtilHelper.java
deleted file mode 100644
index 5bfb4e3..0000000
--- a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/hookregistry/FrameworkUtilHelper.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2018 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.hookregistry;
-
-import org.osgi.framework.Bundle;
-import org.osgi.framework.FrameworkUtil;
-
-/**
- * The helper provides alternative implementations for methods in the
- * {@link FrameworkUtil} class.  While this is not a hook, it is possible
- * for framework fragments to provide a META-INF/services configuration
- * to allow their own implementation to be loaded by the {@link FrameworkUtil}
- * class.
- */
-public class FrameworkUtilHelper {
-	/**
-	 * See {@link FrameworkUtil#getBundle(Class)}
-	 * @param classFromBundle a class defined by a bundle class loader.
-	 * @return A Bundle for the specified bundle class or null if the
-	 * specified class was not defined by a bundle class loader.
-	 */
-	public Bundle getBundle(Class<?> classFromBundle) {
-		return null;
-	}
-}
diff --git a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/hookregistry/HookRegistry.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/hookregistry/HookRegistry.java
index 552438a..5990f4c 100644
--- a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/hookregistry/HookRegistry.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/hookregistry/HookRegistry.java
@@ -24,6 +24,7 @@
 import java.util.Properties;
 import org.eclipse.osgi.framework.log.FrameworkLogEntry;
 import org.eclipse.osgi.internal.cds.CDSHookConfigurator;
+import org.eclipse.osgi.internal.connect.ConnectHookConfigurator;
 import org.eclipse.osgi.internal.framework.EquinoxConfiguration;
 import org.eclipse.osgi.internal.framework.EquinoxContainer;
 import org.eclipse.osgi.internal.hooks.DevClassLoadingHook;
@@ -106,6 +107,8 @@
 		List<FrameworkLogEntry> errors = new ArrayList<>(0); // optimistic that no errors will occur
 		mergeFileHookConfigurators(configurators, errors);
 		mergePropertyHookConfigurators(configurators);
+		// make sure to add connect configurator first always
+		configurators.add(0, ConnectHookConfigurator.class.getName());
 		synchronized (this) {
 			addClassLoaderHook(new DevClassLoadingHook(container.getConfiguration()));
 			addClassLoaderHook(new EclipseLazyStarter(container));
diff --git a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/hooks/DevClassLoadingHook.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/hooks/DevClassLoadingHook.java
index 8a4eb82..8d26f1f 100644
--- a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/hooks/DevClassLoadingHook.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/hooks/DevClassLoadingHook.java
@@ -19,8 +19,11 @@
 import org.eclipse.osgi.framework.util.KeyedElement;
 import org.eclipse.osgi.internal.framework.EquinoxConfiguration;
 import org.eclipse.osgi.internal.hookregistry.ClassLoaderHook;
-import org.eclipse.osgi.internal.loader.classpath.*;
+import org.eclipse.osgi.internal.loader.classpath.ClasspathEntry;
+import org.eclipse.osgi.internal.loader.classpath.ClasspathManager;
+import org.eclipse.osgi.internal.loader.classpath.FragmentClasspath;
 import org.eclipse.osgi.storage.BundleInfo.Generation;
+import org.eclipse.osgi.storage.ContentProvider.Type;
 import org.eclipse.osgi.storage.bundlefile.BundleFile;
 
 public class DevClassLoadingHook extends ClassLoaderHook implements KeyedElement {
@@ -36,6 +39,10 @@
 
 	@Override
 	public boolean addClassPathEntry(ArrayList<ClasspathEntry> cpEntries, String cp, ClasspathManager hostmanager, Generation sourceGeneration) {
+		// if this is a connect bundle just ignore
+		if (sourceGeneration.getContentType() == Type.CONNECT) {
+			return false;
+		}
 		// first check that we are in devmode for this sourcedata
 		String[] devClassPaths = !configuration.inDevelopmentMode() ? null : configuration.getDevClassPath(sourceGeneration.getRevision().getSymbolicName());
 		if (devClassPaths == null || devClassPaths.length == 0)
diff --git a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/loader/sources/PackageSource.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/loader/sources/PackageSource.java
index 556b07e..021a79e 100644
--- a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/loader/sources/PackageSource.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/loader/sources/PackageSource.java
@@ -22,7 +22,6 @@
 import org.eclipse.osgi.internal.framework.EquinoxBundle;
 import org.eclipse.osgi.internal.framework.EquinoxContainer;
 import org.eclipse.osgi.internal.loader.BundleLoader;
-import org.eclipse.osgi.internal.loader.SystemBundleLoader;
 import org.osgi.framework.Bundle;
 import org.osgi.framework.ServiceFactory;
 import org.osgi.service.packageadmin.PackageAdmin;
@@ -114,78 +113,111 @@
 	 * @param container the equinox container
 	 * @return true if assignable given package wiring
 	 */
-	public static boolean isServiceAssignableTo(Bundle registrant, Bundle client, String className, Class<?> serviceClass, EquinoxContainer container) {
+	public static boolean isServiceAssignableTo(Bundle registrant, Bundle client, String className,
+			Class<?> serviceClass, boolean checkInternal, EquinoxContainer container) {
 		// 1) if the registrant == client always return true
 		if (registrant == client) {
 			return true;
 		}
 		// 2) get the package name from the specified className
 		String pkgName = BundleLoader.getPackageName(className);
-		if (pkgName.startsWith("java.")) //$NON-NLS-1$
+		if (pkgName.startsWith("java.")) { //$NON-NLS-1$
 			return true;
+		}
 
 		BundleLoader producerBL = getBundleLoader(registrant);
-		if (producerBL == null)
+		if (producerBL == null) {
 			return false;
-		BundleLoader consumerBL = getBundleLoader(client);
-		if (consumerBL == null)
-			return false;
-		// 3) for the specified bundle, find the wiring for the package.  If no wiring is found return true
-		PackageSource consumerSource = consumerBL.getPackageSource(pkgName);
-		if (consumerSource == null)
-			return true;
-		// work around the issue when the package is in the EE and we delegate to boot for that package
-		if (container.isBootDelegationPackage(pkgName)) {
-			Bundle systemBundle = container.getStorage().getModuleContainer().getModule(0).getBundle();
-			SystemBundleLoader systemLoader = (SystemBundleLoader) getBundleLoader(systemBundle);
-			if (systemLoader.isExportedPackage(pkgName)) {
-				return true; // in this case we have a common source from the EE
-			}
 		}
+		BundleLoader consumerBL = getBundleLoader(client);
+		if (consumerBL == null) {
+			return false;
+		}
+		// 3) for the specified bundle, find the wiring for the package.  If no wiring is found return true
+		PackageSource consumerSource = getSourceFromLoader(consumerBL, pkgName, className, checkInternal);
+		if (consumerSource == null) {
+			// confirmed no source for consumer
+			return true;
+		}
+		// if boot delegate just return true
+		if (container.isBootDelegationPackage(pkgName)) {
+			return true;
+		}
+
 		// 4) For the registrant bundle, find the wiring for the package.
-		PackageSource producerSource = producerBL.getPackageSource(pkgName);
+		PackageSource producerSource = getSourceFromLoader(producerBL, pkgName, className, checkInternal);
 		if (producerSource == null) {
+			// confirmed no local class either; now check service object
 			if (serviceClass != null && ServiceFactory.class.isAssignableFrom(serviceClass)) {
 				@SuppressWarnings("deprecation")
 				Bundle bundle = container.getPackageAdmin().getBundle(serviceClass);
-				if (bundle != null && bundle != registrant)
+				if (bundle != null && bundle != registrant) {
 					// in this case we have a wacky ServiceFactory that is doing something we cannot
-					// verify if it is correct.  Instead of failing we allow the assignment and hope for the best
+					// verify if it is correct. Instead of failing we allow the assignment and hope
+					// for the best
 					// bug 326918
 					return true;
+				}
 			}
-			// 5) If no wiring is found for the registrant bundle then find the wiring for the classloader of the service object.  If no wiring is found return false.
-			producerSource = getPackageSource(serviceClass, pkgName, container.getPackageAdmin());
-			if (producerSource == null)
+			// 5) If no wiring is found for the registrant bundle then find the wiring for
+			// the classloader of the service object. If no wiring is found return false.
+			producerSource = getPackageSource(serviceClass, pkgName, className, checkInternal,
+					container.getPackageAdmin());
+			if (producerSource == null) {
 				return false;
+			}
 		}
 		// 6) If the two wirings found are equal then return true; otherwise return false.
 		return producerSource.hasCommonSource(consumerSource);
 	}
 
-	private static PackageSource getPackageSource(Class<?> serviceClass, String pkgName, @SuppressWarnings("deprecation") PackageAdmin packageAdmin) {
-		if (serviceClass == null)
+	private static PackageSource getSourceFromLoader(BundleLoader loader, String pkgName, String className,
+			boolean checkInternal) {
+		PackageSource source = loader.getPackageSource(pkgName);
+		if (source != null || !checkInternal) {
+			return source;
+		}
+		try {
+			if (loader.findLocalClass(className) != null) {
+				// create a source that represents the private package
+				return (new SingleSourcePackage(pkgName, loader));
+			}
+		} catch (ClassNotFoundException e) {
+			// ignore
+		}
+		return null;
+	}
+
+	private static PackageSource getPackageSource(Class<?> serviceClass, String pkgName, String className,
+			boolean checkInternal,
+			@SuppressWarnings("deprecation") PackageAdmin packageAdmin) {
+		if (serviceClass == null) {
 			return null;
+		}
 		@SuppressWarnings("deprecation")
 		Bundle serviceBundle = packageAdmin.getBundle(serviceClass);
-		if (serviceBundle == null)
+		if (serviceBundle == null) {
 			return null;
+		}
 		BundleLoader producerBL = getBundleLoader(serviceBundle);
-		if (producerBL == null)
+		if (producerBL == null) {
 			return null;
-		PackageSource producerSource = producerBL.getPackageSource(pkgName);
-		if (producerSource != null)
+		}
+		PackageSource producerSource = getSourceFromLoader(producerBL, pkgName, className, checkInternal);
+		if (producerSource != null) {
 			return producerSource;
+		}
 		// try the interfaces
 		Class<?>[] interfaces = serviceClass.getInterfaces();
 		// note that getInterfaces never returns null
 		for (Class<?> intf : interfaces) {
-			producerSource = getPackageSource(intf, pkgName, packageAdmin);
-			if (producerSource != null)
+			producerSource = getPackageSource(intf, pkgName, className, checkInternal, packageAdmin);
+			if (producerSource != null) {
 				return producerSource;
+			}
 		}
 		// try super class
-		return getPackageSource(serviceClass.getSuperclass(), pkgName, packageAdmin);
+		return getPackageSource(serviceClass.getSuperclass(), pkgName, className, checkInternal, packageAdmin);
 	}
 
 	private static BundleLoader getBundleLoader(Bundle bundle) {
diff --git a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/log/EventAdminAdapter.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/log/EventAdminAdapter.java
index fe62d5a..7ff945e 100644
--- a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/log/EventAdminAdapter.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/log/EventAdminAdapter.java
@@ -13,8 +13,12 @@
  *******************************************************************************/
 package org.eclipse.osgi.internal.log;
 
-import java.util.*;
-import org.osgi.framework.*;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.HashSet;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.Constants;
+import org.osgi.framework.ServiceReference;
 import org.osgi.util.tracker.ServiceTracker;
 import org.osgi.util.tracker.ServiceTrackerCustomizer;
 
@@ -42,8 +46,8 @@
 	}
 
 	public void start() {
-		eventAdminTracker.open();
-		eventHandlerTracker.open();
+		eventAdminTracker.open(true);
+		eventHandlerTracker.open(true);
 	}
 
 	public void stop() {
diff --git a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/permadmin/implied.permissions b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/permadmin/implied.permissions
index 50f98ad..9273890 100644
--- a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/permadmin/implied.permissions
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/permadmin/implied.permissions
@@ -53,3 +53,5 @@
 (org.osgi.framework.CapabilityPermission "osgi.ee" "require")
 # Added for OSGi R6
 (org.osgi.framework.CapabilityPermission "osgi.native" "require")
+# Added for OSGi R8
+(org.osgi.framework.ServicePermission "org.osgi.service.condition.Condition" "get")
diff --git a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/serviceregistry/FilteredServiceListener.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/serviceregistry/FilteredServiceListener.java
index 7468872..e57ae09 100644
--- a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/serviceregistry/FilteredServiceListener.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/serviceregistry/FilteredServiceListener.java
@@ -17,7 +17,14 @@
 import org.eclipse.osgi.internal.debug.Debug;
 import org.eclipse.osgi.internal.framework.BundleContextImpl;
 import org.eclipse.osgi.internal.framework.FilterImpl;
-import org.osgi.framework.*;
+import org.osgi.framework.AllServiceListener;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.Constants;
+import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.framework.ServiceEvent;
+import org.osgi.framework.ServiceListener;
+import org.osgi.framework.ServiceReference;
+import org.osgi.framework.UnfilteredServiceListener;
 import org.osgi.framework.hooks.service.ListenerHook;
 
 /**
@@ -104,7 +111,7 @@
 		if (event == null) {
 			return;
 		}
-		if (allservices || ServiceRegistry.isAssignableTo(context, reference)) {
+		if (allservices || ServiceRegistry.isAssignableTo(context, objectClass, reference)) {
 			if (debug.DEBUG_EVENTS) {
 				String listenerName = listener.getClass().getName() + "@" + Integer.toHexString(System.identityHashCode(listener)); //$NON-NLS-1$
 				Debug.println("dispatchFilteredServiceEvent(" + listenerName + ")"); //$NON-NLS-1$ //$NON-NLS-2$
diff --git a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/serviceregistry/ServiceReferenceImpl.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/serviceregistry/ServiceReferenceImpl.java
index 3cafc16..f04cf42 100644
--- a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/serviceregistry/ServiceReferenceImpl.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/serviceregistry/ServiceReferenceImpl.java
@@ -15,7 +15,14 @@
 package org.eclipse.osgi.internal.serviceregistry;
 
 import java.util.Dictionary;
-import org.osgi.framework.*;
+import org.eclipse.osgi.internal.framework.DTOBuilder;
+import org.osgi.framework.AdaptPermission;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.Constants;
+import org.osgi.framework.ServiceReference;
+import org.osgi.framework.ServiceRegistration;
+import org.osgi.framework.dto.ServiceReferenceDTO;
 
 /**
  * A reference to a service.
@@ -175,7 +182,7 @@
 	 */
 	@Override
 	public boolean isAssignableTo(Bundle bundle, String className) {
-		return registration.isAssignableTo(bundle, className);
+		return registration.isAssignableTo(bundle, className, true);
 	}
 
 	/**
@@ -318,4 +325,22 @@
 	public Dictionary<String, Object> getProperties() {
 		return registration.getPropertiesCopy();
 	}
+
+	@SuppressWarnings("unchecked")
+	@Override
+	public <A> A adapt(Class<A> type) {
+		checkAdaptPermission(type);
+		if (ServiceReferenceDTO.class.equals(type)) {
+			return (A) DTOBuilder.newServiceReferenceDTO(this);
+		}
+		return null;
+	}
+
+	private <A> void checkAdaptPermission(Class<A> adapterType) {
+		SecurityManager sm = System.getSecurityManager();
+		if (sm == null) {
+			return;
+		}
+		sm.checkPermission(new AdaptPermission(adapterType.getName(), registration.getRegisteringBundle(), AdaptPermission.ADAPT));
+	}
 }
diff --git a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/serviceregistry/ServiceRegistrationImpl.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/serviceregistry/ServiceRegistrationImpl.java
index 0d1e51e..a0dc562 100644
--- a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/serviceregistry/ServiceRegistrationImpl.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/serviceregistry/ServiceRegistrationImpl.java
@@ -709,8 +709,9 @@
 		}
 	}
 
-	boolean isAssignableTo(Bundle client, String className) {
-		return PackageSource.isServiceAssignableTo(bundle, client, className, service.getClass(), context.getContainer());
+	boolean isAssignableTo(Bundle client, String className, boolean checkInternal) {
+		return PackageSource.isServiceAssignableTo(bundle, client, className, service.getClass(), checkInternal,
+				context.getContainer());
 	}
 
 	/**
diff --git a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/serviceregistry/ServiceRegistry.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/serviceregistry/ServiceRegistry.java
index 934cc0c..4cdcd97 100644
--- a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/serviceregistry/ServiceRegistry.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/serviceregistry/ServiceRegistry.java
@@ -383,7 +383,7 @@
 			} catch (IllegalStateException e) {
 				continue; // got unregistered, don't return reference
 			}
-			if (allservices || isAssignableTo(context, reference)) {
+			if (allservices || isAssignableTo(context, clazz, reference)) {
 				try { /* test for permission to get the service */
 					checkGetServicePermission(reference);
 				} catch (SecurityException se) {
@@ -1206,11 +1206,11 @@
 		return true;
 	}
 
-	static boolean isAssignableTo(BundleContextImpl context, ServiceReferenceImpl<?> reference) {
+	static boolean isAssignableTo(BundleContextImpl context, String clazz, ServiceReferenceImpl<?> reference) {
 		Bundle bundle = context.getBundleImpl();
 		String[] clazzes = reference.getClasses();
 		for (int i = 0, len = clazzes.length; i < len; i++)
-			if (!reference.isAssignableTo(bundle, clazzes[i]))
+			if (!reference.getRegistration().isAssignableTo(bundle, clazzes[i], clazzes[i] == clazz))
 				return false;
 		return true;
 	}
diff --git a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/signedcontent/SignatureBlockProcessor.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/signedcontent/SignatureBlockProcessor.java
index defe49a..bef43d0 100644
--- a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/signedcontent/SignatureBlockProcessor.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/signedcontent/SignatureBlockProcessor.java
@@ -105,7 +105,7 @@
 
 		// Step 1, verify the .SF file is signed by the private key that corresponds to the public key
 		// in the .RSA/.DSA file
-		String baseFile = bf.getBaseFile() != null ? bf.getBaseFile().toString() : null;
+		String baseFile = String.valueOf(bf.getBaseFile());
 		PKCS7Processor processor = new PKCS7Processor(pkcs7Bytes, 0, pkcs7Bytes.length, signer, baseFile);
 		// call the Step 1 in the Jar File Verification algorithm
 		processor.verifySFSignature(sfBytes, 0, sfBytes.length);
@@ -169,7 +169,7 @@
 
 				// check if the the computed digest value of manifest file equals to the digest value in the .sf file
 				if (!digestValue.equals(manifestDigest)) {
-					SignatureException se = new SignatureException(NLS.bind(SignedContentMessages.Security_File_Is_Tampered, new String[] {signedBundle.getBaseFile().toString()}));
+					SignatureException se = new SignatureException(NLS.bind(SignedContentMessages.Security_File_Is_Tampered, new String[] {String.valueOf(signedBundle.getBaseFile())}));
 					signedBundleHook.log(se.getMessage(), FrameworkLogEntry.ERROR, se);
 					throw se;
 				}
diff --git a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/signedcontent/SignedBundleFile.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/signedcontent/SignedBundleFile.java
index 7e9d88c..5f3cf84 100644
--- a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/signedcontent/SignedBundleFile.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/signedcontent/SignedBundleFile.java
@@ -17,11 +17,20 @@
 import java.io.IOException;
 import java.io.InputStream;
 import java.net.URL;
-import java.security.*;
-import java.security.cert.*;
+import java.security.InvalidKeyException;
+import java.security.NoSuchAlgorithmException;
+import java.security.NoSuchProviderException;
+import java.security.SignatureException;
+import java.security.cert.CertificateException;
+import java.security.cert.CertificateExpiredException;
+import java.security.cert.CertificateNotYetValidException;
 import java.util.Date;
-import org.eclipse.osgi.signedcontent.*;
-import org.eclipse.osgi.storage.bundlefile.*;
+import org.eclipse.osgi.signedcontent.SignedContent;
+import org.eclipse.osgi.signedcontent.SignedContentEntry;
+import org.eclipse.osgi.signedcontent.SignerInfo;
+import org.eclipse.osgi.storage.bundlefile.BundleEntry;
+import org.eclipse.osgi.storage.bundlefile.BundleFile;
+import org.eclipse.osgi.storage.bundlefile.BundleFileWrapper;
 import org.eclipse.osgi.util.NLS;
 
 /**
@@ -73,7 +82,7 @@
 			// double check that no signer thinks it should exist
 			SignedContentEntry signedEntry = signedContent.getSignedEntry(path);
 			if (signedEntry != null)
-				throw new SecurityException(NLS.bind(SignedContentMessages.file_is_removed_from_jar, path, getBaseFile().toString()));
+				throw new SecurityException(NLS.bind(SignedContentMessages.file_is_removed_from_jar, path, String.valueOf(getBaseFile())));
 			return null;
 		}
 		return new SignedBundleEntry(be);
diff --git a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/signedcontent/SignedContentImpl.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/signedcontent/SignedContentImpl.java
index 5b741d0..f8acc8d 100644
--- a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/signedcontent/SignedContentImpl.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/signedcontent/SignedContentImpl.java
@@ -196,7 +196,7 @@
 				exception = e;
 			}
 			if (entry == null)
-				throw new InvalidContentException(NLS.bind(SignedContentMessages.file_is_removed_from_jar, entryName, currentContent.getBaseFile().toString()), exception);
+				throw new InvalidContentException(NLS.bind(SignedContentMessages.file_is_removed_from_jar, entryName, String.valueOf(currentContent.getBaseFile())), exception);
 
 			if (entry.getSize() > VERIFY_LIMIT) {
 				try (InputStream in = entry.getInputStream()) {
diff --git a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/launch/Equinox.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/launch/Equinox.java
index 049334f..901df37 100644
--- a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/launch/Equinox.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/launch/Equinox.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2008, 2013 IBM Corporation and others.
+ * Copyright (c) 2008, 2020 IBM Corporation and others.
  *
  * This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License 2.0
@@ -13,12 +13,24 @@
  *******************************************************************************/
 package org.eclipse.osgi.launch;
 
-import java.io.*;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
 import java.net.URL;
 import java.security.cert.X509Certificate;
-import java.util.*;
+import java.util.Dictionary;
+import java.util.Enumeration;
+import java.util.List;
+import java.util.Map;
 import org.eclipse.osgi.internal.framework.EquinoxContainer;
-import org.osgi.framework.*;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.BundleException;
+import org.osgi.framework.FrameworkEvent;
+import org.osgi.framework.FrameworkListener;
+import org.osgi.framework.ServiceReference;
+import org.osgi.framework.Version;
+import org.osgi.framework.connect.ModuleConnector;
 import org.osgi.framework.launch.Framework;
 
 /**
@@ -31,7 +43,14 @@
 	private final Framework systemBundle;
 
 	public Equinox(Map<String, ?> configuration) {
-		EquinoxContainer container = new EquinoxContainer(configuration);
+		this(configuration, null);
+	}
+
+	/**
+	 * @since 3.16
+	 */
+	public Equinox(Map<String, ?> configuration, ModuleConnector moduleConnector) {
+		EquinoxContainer container = new EquinoxContainer(configuration, moduleConnector);
 		systemBundle = (Framework) container.getStorage().getModuleContainer().getModule(0).getBundle();
 	}
 
diff --git a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/launch/EquinoxFactory.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/launch/EquinoxFactory.java
index 17d9c04..fd1ad8a 100644
--- a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/launch/EquinoxFactory.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/launch/EquinoxFactory.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2012 IBM Corporation and others.
+ * Copyright (c) 2009, 2020 IBM Corporation and others.
  *
  * This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License 2.0
@@ -14,6 +14,8 @@
 package org.eclipse.osgi.launch;
 
 import java.util.Map;
+import org.osgi.framework.connect.ConnectFrameworkFactory;
+import org.osgi.framework.connect.ModuleConnector;
 import org.osgi.framework.launch.Framework;
 import org.osgi.framework.launch.FrameworkFactory;
 
@@ -21,11 +23,15 @@
  * The framework factory implementation for the Equinox framework.
  * @since 3.5
  */
-public class EquinoxFactory implements FrameworkFactory {
+public class EquinoxFactory implements FrameworkFactory, ConnectFrameworkFactory {
 
 	@Override
 	public Framework newFramework(Map<String, String> configuration) {
-		return new Equinox(configuration);
+		return newFramework(configuration, null);
 	}
 
+	@Override
+	public Framework newFramework(Map<String, String> configuration, ModuleConnector moduleConnector) {
+		return new Equinox(configuration, moduleConnector);
+	}
 }
diff --git a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/storage/BundleInfo.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/storage/BundleInfo.java
index 60133ef..ee5caae 100644
--- a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/storage/BundleInfo.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/storage/BundleInfo.java
@@ -38,6 +38,7 @@
 import org.eclipse.osgi.framework.log.FrameworkLogEntry;
 import org.eclipse.osgi.framework.util.CaseInsensitiveDictionaryMap;
 import org.eclipse.osgi.framework.util.ThreadInfoReport;
+import org.eclipse.osgi.internal.connect.ConnectBundleFile;
 import org.eclipse.osgi.internal.container.LockSet;
 import org.eclipse.osgi.internal.debug.Debug;
 import org.eclipse.osgi.internal.framework.EquinoxConfiguration;
@@ -45,15 +46,18 @@
 import org.eclipse.osgi.internal.hookregistry.StorageHookFactory;
 import org.eclipse.osgi.internal.hookregistry.StorageHookFactory.StorageHook;
 import org.eclipse.osgi.internal.messages.Msg;
+import org.eclipse.osgi.storage.ContentProvider.Type;
 import org.eclipse.osgi.storage.Storage.StorageException;
 import org.eclipse.osgi.storage.bundlefile.BundleEntry;
 import org.eclipse.osgi.storage.bundlefile.BundleFile;
+import org.eclipse.osgi.storage.bundlefile.BundleFileWrapperChain;
 import org.eclipse.osgi.storage.url.BundleResourceHandler;
 import org.eclipse.osgi.storage.url.bundleentry.Handler;
 import org.eclipse.osgi.util.ManifestElement;
 import org.eclipse.osgi.util.NLS;
 import org.osgi.framework.BundleException;
 import org.osgi.framework.Constants;
+import org.osgi.framework.connect.ConnectModule;
 
 public final class BundleInfo {
 	public static final String OSGI_BUNDLE_MANIFEST = "META-INF/MANIFEST.MF"; //$NON-NLS-1$
@@ -67,7 +71,6 @@
 		private final Dictionary<String, String> cachedHeaders;
 		private File content;
 		private boolean isDirectory;
-		private boolean isReference;
 		private boolean hasPackageInfo;
 		private BundleFile bundleFile;
 		private Map<String, String> rawHeaders;
@@ -78,17 +81,18 @@
 		private List<StorageHook<?, ?>> storageHooks;
 		private long lastModified;
 		private boolean isMRJar;
+		private Type contentType;
 
 		Generation(long generationId) {
 			this.generationId = generationId;
 			this.cachedHeaders = new CachedManifest(this, Collections.<String, String> emptyMap());
 		}
 
-		Generation(long generationId, File content, boolean isDirectory, boolean isReference, boolean hasPackageInfo, Map<String, String> cached, long lastModified, boolean isMRJar) {
+		Generation(long generationId, File content, boolean isDirectory, Type contentType, boolean hasPackageInfo, Map<String, String> cached, long lastModified, boolean isMRJar) {
 			this.generationId = generationId;
 			this.content = content;
 			this.isDirectory = isDirectory;
-			this.isReference = isReference;
+			this.contentType = contentType;
 			this.hasPackageInfo = hasPackageInfo;
 			this.cachedHeaders = new CachedManifest(this, cached);
 			this.lastModified = lastModified;
@@ -98,7 +102,7 @@
 		public BundleFile getBundleFile() {
 			synchronized (genMonitor) {
 				if (bundleFile == null) {
-					if (getBundleId() == 0 && content == null) {
+					if (getBundleId() == 0 && content == null && contentType != Type.CONNECT) {
 						bundleFile = new SystemBundleFile();
 					} else {
 						bundleFile = getStorage().createBundleFile(content, this, isDirectory, true);
@@ -127,7 +131,20 @@
 		Map<String, String> getRawHeaders() {
 			synchronized (genMonitor) {
 				if (rawHeaders == null) {
-					BundleEntry manifest = getBundleFile().getEntry(OSGI_BUNDLE_MANIFEST);
+					BundleFile bFile = getBundleFile();
+
+					if (this.contentType == Type.CONNECT) {
+						ConnectBundleFile connectContent = bFile instanceof BundleFileWrapperChain ? //
+								((BundleFileWrapperChain) bFile).getWrappedType(ConnectBundleFile.class) : //
+								(ConnectBundleFile) bFile;
+
+						Map<String, String> connectHeaders = connectContent.getConnectHeaders();
+						if (connectHeaders != null) {
+							return rawHeaders = connectHeaders;
+						}
+					}
+
+					BundleEntry manifest = bFile.getEntry(OSGI_BUNDLE_MANIFEST);
 					if (manifest == null) {
 						rawHeaders = Collections.emptyMap();
 					} else {
@@ -211,12 +228,6 @@
 			}
 		}
 
-		public boolean isReference() {
-			synchronized (this.genMonitor) {
-				return this.isReference;
-			}
-		}
-
 		public boolean hasPackageInfo() {
 			synchronized (this.genMonitor) {
 				return this.hasPackageInfo;
@@ -235,11 +246,25 @@
 			}
 		}
 
-		void setContent(File content, boolean isReference) {
+		public Type getContentType() {
+			synchronized (this.genMonitor) {
+				return this.contentType;
+			}
+		}
+
+		void setContent(File content, Type contentType) {
+			if (getBundleId() == 0) {
+				// check connect for content first
+				ConnectModule connected = getStorage().getEquinoxContainer().getConnectModules().connect(getLocation());
+				if (connected != null) {
+					content = null;
+					contentType = Type.CONNECT;
+				}
+			}
 			synchronized (this.genMonitor) {
 				this.content = content;
 				this.isDirectory = content == null ? false : Storage.secureAction.isDirectory(content);
-				this.isReference = isReference;
+				this.contentType = contentType;
 				setLastModified(content);
 			}
 		}
@@ -485,9 +510,9 @@
 		}
 	}
 
-	Generation restoreGeneration(long generationId, File content, boolean isDirectory, boolean isReference, boolean hasPackageInfo, Map<String, String> cached, long lastModified, boolean isMRJar) {
+	Generation restoreGeneration(long generationId, File content, boolean isDirectory, Type contentType, boolean hasPackageInfo, Map<String, String> cached, long lastModified, boolean isMRJar) {
 		synchronized (this.infoMonitor) {
-			Generation restoredGeneration = new Generation(generationId, content, isDirectory, isReference, hasPackageInfo, cached, lastModified, isMRJar);
+			Generation restoredGeneration = new Generation(generationId, content, isDirectory, contentType, hasPackageInfo, cached, lastModified, isMRJar);
 			return restoredGeneration;
 		}
 	}
diff --git a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/storage/ContentProvider.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/storage/ContentProvider.java
new file mode 100644
index 0000000..50f3f34
--- /dev/null
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/storage/ContentProvider.java
@@ -0,0 +1,48 @@
+/*******************************************************************************
+ * Copyright (c) 2019 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.storage;
+
+import java.io.File;
+import org.osgi.framework.BundleException;
+
+/**
+ * A content provider is a marker interface that is used
+ * but the framework internally to handle different kinds of
+ * bundles.  For example, reference installed bundles or
+ * connect bundles.  The type of the provider indicates
+ * how the framework will handle the install or update
+ * of the bundle content.
+ */
+public interface ContentProvider {
+
+	/**
+	 * The type of the provided content
+	 */
+	public enum Type {
+		REFERENCE, CONNECT, DEFAULT;
+	}
+
+	/**
+	 * A file of the content, may be {@code null}
+	 * @return the file, may be {@code null}
+	 * @throws BundleException 
+	 */
+	File getContent() throws BundleException;
+
+	/**
+	 * The type of content
+	 * @return the type of content
+	 */
+	Type getType();
+}
diff --git a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/storage/FrameworkExtensionInstaller.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/storage/FrameworkExtensionInstaller.java
index 3013700..fba1658 100644
--- a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/storage/FrameworkExtensionInstaller.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/storage/FrameworkExtensionInstaller.java
@@ -39,6 +39,7 @@
 import org.eclipse.osgi.internal.messages.Msg;
 import org.eclipse.osgi.internal.url.MultiplexingFactory;
 import org.eclipse.osgi.storage.BundleInfo.Generation;
+import org.eclipse.osgi.storage.ContentProvider.Type;
 import org.eclipse.osgi.util.NLS;
 import org.osgi.framework.Bundle;
 import org.osgi.framework.BundleActivator;
@@ -181,6 +182,11 @@
 	 * @return a list of classpath files for an extension bundle
 	 */
 	private File[] getExtensionFiles(ModuleRevision revision) {
+		Generation generation = (Generation) revision.getRevisionInfo();
+		if (generation.getContentType() == Type.CONNECT) {
+			// Don't do anything for connect bundles
+			return new File[0];
+		}
 		List<ModuleCapability> metaDatas = revision.getModuleCapabilities(EquinoxModuleDataNamespace.MODULE_DATA_NAMESPACE);
 		@SuppressWarnings("unchecked")
 		List<String> paths = metaDatas.isEmpty() ? null : (List<String>) metaDatas.get(0).getAttributes().get(EquinoxModuleDataNamespace.CAPABILITY_CLASSPATH);
@@ -238,7 +244,9 @@
 			current = new ArrayMap<>(hookActivators.getKeys(), hookActivators.getValues());
 			hookActivators.clear();
 		}
-		for (BundleActivator activator : current) {
+		// indexing into the current collection the hard way to reverse de-activation
+		for (int i = current.getKeys().size() - 1; i >= 0; i--) {
+			BundleActivator activator = current.getKey(i);
 			try {
 				activator.stop(context);
 			} catch (Exception e) {
diff --git a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/storage/Storage.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/storage/Storage.java
index e6933f0..22a91e2 100644
--- a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/storage/Storage.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/storage/Storage.java
@@ -83,6 +83,7 @@
 import org.eclipse.osgi.internal.url.URLStreamHandlerFactoryImpl;
 import org.eclipse.osgi.service.datalocation.Location;
 import org.eclipse.osgi.storage.BundleInfo.Generation;
+import org.eclipse.osgi.storage.ContentProvider.Type;
 import org.eclipse.osgi.storage.bundlefile.BundleEntry;
 import org.eclipse.osgi.storage.bundlefile.BundleFile;
 import org.eclipse.osgi.storage.bundlefile.BundleFileWrapper;
@@ -92,7 +93,6 @@
 import org.eclipse.osgi.storage.bundlefile.NestedDirBundleFile;
 import org.eclipse.osgi.storage.bundlefile.ZipBundleFile;
 import org.eclipse.osgi.storage.url.reference.Handler;
-import org.eclipse.osgi.storage.url.reference.ReferenceInputStream;
 import org.eclipse.osgi.storagemanager.ManagedOutputStream;
 import org.eclipse.osgi.storagemanager.StorageManager;
 import org.eclipse.osgi.util.ManifestElement;
@@ -104,6 +104,7 @@
 import org.osgi.framework.Filter;
 import org.osgi.framework.InvalidSyntaxException;
 import org.osgi.framework.Version;
+import org.osgi.framework.connect.ConnectModule;
 import org.osgi.framework.namespace.HostNamespace;
 import org.osgi.framework.namespace.NativeNamespace;
 import org.osgi.framework.namespace.PackageNamespace;
@@ -135,9 +136,10 @@
 
 	}
 
-	public static final int VERSION = 5;
-	private static final int MR_JAR_VERSION = 4;
+	public static final int VERSION = 6;
+	private static final int CONTENT_TYPE_VERSION = 6;
 	private static final int CACHED_SYSTEM_CAPS_VERION = 5;
+	private static final int MR_JAR_VERSION = 4;
 	private static final int LOWEST_VERSION_SUPPORTED = 3;
 	public static final String BUNDLE_DATA_DIR = "data"; //$NON-NLS-1$
 	public static final String BUNDLE_FILE_NAME = "bundleFile"; //$NON-NLS-1$
@@ -186,8 +188,9 @@
 	}
 
 	private Storage(EquinoxContainer container, String[] cachedInfo) throws IOException {
-		// default to Java 7 since that is our min
-		Version javaVersion = Version.valueOf("1.7"); //$NON-NLS-1$
+		// default to Java 8 since that is our min
+		Version defaultVersion = Version.valueOf("1.8"); //$NON-NLS-1$
+		Version javaVersion = defaultVersion;
 		// set the profile and EE based off of the java.specification.version
 		String javaSpecVersionProp = System.getProperty(EquinoxConfiguration.PROP_JVM_SPEC_VERSION);
 		StringTokenizer st = new StringTokenizer(javaSpecVersionProp, " _-"); //$NON-NLS-1$
@@ -202,6 +205,12 @@
 		} catch (IllegalArgumentException e) {
 			// do nothing
 		}
+		if (javaVersion.compareTo(defaultVersion) < 0) {
+			// the Java specification property is wrong, we are compiled to the
+			// defaultVersion
+			// just use it instead.
+			javaVersion = defaultVersion;
+		}
 		runtimeVersion = javaVersion;
 		javaSpecVersion = javaSpecVersionProp;
 		mruList = new MRUBundleFileList(getBundleFileLimit(container.getConfiguration()), container.getConfiguration().getDebug());
@@ -364,6 +373,9 @@
 			}
 		}
 		File content = generation.getContent();
+		if (content == null) {
+			return false;
+		}
 		if (getConfiguration().inCheckConfigurationMode()) {
 			if (generation.isDirectory()) {
 				content = new File(content, "META-INF/MANIFEST.MF"); //$NON-NLS-1$
@@ -386,7 +398,7 @@
 				newGeneration = info.createGeneration();
 
 				File contentFile = getSystemContent();
-				newGeneration.setContent(contentFile, false);
+				newGeneration.setContent(contentFile, Type.DEFAULT);
 
 				// First we must make sure the VM profile has been loaded
 				loadVMProfile(newGeneration);
@@ -412,7 +424,7 @@
 					File contentFile = currentGeneration.getContent();
 					if (systemNeedsUpdate(contentFile, currentRevision, currentGeneration, extraCapabilities, extraExports, cachedInfo)) {
 						newGeneration = currentGeneration.getBundleInfo().createGeneration();
-						newGeneration.setContent(contentFile, false);
+						newGeneration.setContent(contentFile, Type.DEFAULT);
 						ModuleRevisionBuilder newBuilder = getBuilder(newGeneration, extraCapabilities, extraExports);
 						moduleContainer.update(systemModule, newBuilder, newGeneration);
 						moduleContainer.refresh(Collections.singleton(systemModule));
@@ -565,41 +577,47 @@
 		return osgiLocation.isReadOnly();
 	}
 
-	public URLConnection getContentConnection(Module module, String bundleLocation, final InputStream in) throws IOException {
-		List<StorageHookFactory<?, ?, ?>> storageHooks = getConfiguration().getHookRegistry().getStorageHookFactories();
-		for (StorageHookFactory<?, ?, ?> storageHook : storageHooks) {
-			URLConnection hookContent = storageHook.handleContentConnection(module, bundleLocation, in);
-			if (hookContent != null) {
-				return hookContent;
-			}
-		}
-
-		if (in != null) {
-			return new URLConnection(null) {
-				/**
-				 * @throws IOException
-				 */
-				@Override
-				public void connect() throws IOException {
-					connected = true;
+	public URLConnection getContentConnection(Module module, String bundleLocation, final InputStream in)
+			throws BundleException {
+		try {
+			List<StorageHookFactory<?, ?, ?>> storageHooks = getConfiguration().getHookRegistry()
+					.getStorageHookFactories();
+			for (StorageHookFactory<?, ?, ?> storageHook : storageHooks) {
+				URLConnection hookContent = storageHook.handleContentConnection(module, bundleLocation, in);
+				if (hookContent != null) {
+					return hookContent;
 				}
-
-				/**
-				 * @throws IOException
-				 */
-				@Override
-				public InputStream getInputStream() throws IOException {
-					return (in);
-				}
-			};
-		}
-		if (module == null) {
-			if (bundleLocation == null) {
-				throw new IllegalArgumentException("Module and location cannot be null"); //$NON-NLS-1$
 			}
-			return getContentConnection(bundleLocation);
+
+			if (in != null) {
+				return new URLConnection(null) {
+					/**
+					 * @throws IOException
+					 */
+					@Override
+					public void connect() throws IOException {
+						connected = true;
+					}
+
+					/**
+					 * @throws IOException
+					 */
+					@Override
+					public InputStream getInputStream() throws IOException {
+						return (in);
+					}
+				};
+			}
+			if (module == null) {
+				if (bundleLocation == null) {
+					throw new IllegalArgumentException("Module and location cannot be null"); //$NON-NLS-1$
+				}
+				return getContentConnection(bundleLocation);
+			}
+			return getContentConnection(getUpdateLocation(module));
+		} catch (IOException e) {
+			throw new BundleException("Error reading bundle content.", e); //$NON-NLS-1$
 		}
-		return getContentConnection(getUpdateLocation(module));
 	}
 
 	private String getUpdateLocation(final Module module) {
@@ -651,7 +669,8 @@
 		return new URL(spec);
 	}
 
-	public Generation install(Module origin, String bundleLocation, URLConnection content) throws BundleException {
+	public Generation install(Module origin, String bundleLocation, InputStream toInstall) throws BundleException {
+		URLConnection content = getContentConnection(null, bundleLocation, toInstall);
 		if (osgiLocation.isReadOnly()) {
 			throw new BundleException("The framework storage area is read only.", BundleException.INVALID_OPERATION); //$NON-NLS-1$
 		}
@@ -689,16 +708,18 @@
 			return (Generation) existingLocation.getCurrentRevision().getRevisionInfo();
 		}
 
-		boolean isReference = in instanceof ReferenceInputStream;
-		File staged = stageContent(in, sourceURL);
+		ContentProvider contentProvider = getContentProvider(in, sourceURL);
+		Type contentType = contentProvider.getType();
+		File staged = contentProvider.getContent();
+
 		Generation generation = null;
 		try {
 			Long nextID = moduleDatabase.getAndIncrementNextId();
 			BundleInfo info = new BundleInfo(this, nextID, bundleLocation, 0);
 			generation = info.createGeneration();
 
-			File contentFile = getContentFile(staged, isReference, nextID, generation.getGenerationId());
-			generation.setContent(contentFile, isReference);
+			File contentFile = getContentFile(staged, contentType, nextID, generation.getGenerationId());
+			generation.setContent(contentFile, contentType);
 			// Check that we can open the bundle file
 			generation.getBundleFile().open();
 			setStorageHooks(generation);
@@ -714,7 +735,7 @@
 			}
 			return generation;
 		} catch (Throwable t) {
-			if (!isReference) {
+			if (contentType == Type.DEFAULT) {
 				try {
 					delete(staged);
 				} catch (IOException e) {
@@ -744,6 +765,24 @@
 		}
 	}
 
+	ContentProvider getContentProvider(final InputStream in, final URL sourceURL) {
+		if (in instanceof ContentProvider) {
+			return (ContentProvider) in;
+		}
+		return new ContentProvider() {
+
+			@Override
+			public Type getType() {
+				return Type.DEFAULT;
+			}
+
+			@Override
+			public File getContent() throws BundleException {
+				return stageContent(in, sourceURL);
+			}
+		};
+	}
+
 	private void setStorageHooks(Generation generation) throws BundleException {
 		if (generation.getBundleInfo().getBundleId() == 0) {
 			return; // ignore system bundle
@@ -881,7 +920,11 @@
 		ModuleRevision current = module.getCurrentRevision();
 		Generation currentGen = (Generation) current.getRevisionInfo();
 		File content = currentGen.getContent();
-		String spec = (currentGen.isReference() ? "reference:" : "") + content.toURI().toString(); //$NON-NLS-1$ //$NON-NLS-2$
+		if (content == null) {
+			// TODO Handle connect bundle
+			return;
+		}
+		String spec = (currentGen.getContentType() == Type.REFERENCE ? "reference:" : "") + content.toURI().toString(); //$NON-NLS-1$ //$NON-NLS-2$
 		URLConnection contentConn;
 		try {
 			contentConn = getContentConnection(spec);
@@ -891,7 +934,12 @@
 		update(module, contentConn);
 	}
 
-	public Generation update(Module module, URLConnection content) throws BundleException {
+	public Generation update(Module module, InputStream updateIn) throws BundleException {
+		return update(module, getContentConnection(module, null, updateIn));
+	}
+
+	private Generation update(Module module, URLConnection content) throws BundleException {
+
 		if (osgiLocation.isReadOnly()) {
 			throw new BundleException("The framework storage area is read only.", BundleException.INVALID_OPERATION); //$NON-NLS-1$
 		}
@@ -902,8 +950,11 @@
 		} catch (Throwable e) {
 			throw new BundleException("Error reading bundle content.", e); //$NON-NLS-1$
 		}
-		boolean isReference = in instanceof ReferenceInputStream;
-		File staged = stageContent(in, sourceURL);
+
+		ContentProvider contentProvider = getContentProvider(in, sourceURL);
+		Type contentType = contentProvider.getType();
+		File staged = contentProvider.getContent();
+
 		ModuleRevision current = module.getCurrentRevision();
 		Generation currentGen = (Generation) current.getRevisionInfo();
 
@@ -911,8 +962,8 @@
 		Generation newGen = bundleInfo.createGeneration();
 
 		try {
-			File contentFile = getContentFile(staged, isReference, bundleInfo.getBundleId(), newGen.getGenerationId());
-			newGen.setContent(contentFile, isReference);
+			File contentFile = getContentFile(staged, contentType, bundleInfo.getBundleId(), newGen.getGenerationId());
+			newGen.setContent(contentFile, contentType);
 			// Check that we can open the bundle file
 			newGen.getBundleFile().open();
 			setStorageHooks(newGen);
@@ -920,7 +971,7 @@
 			ModuleRevisionBuilder builder = getBuilder(newGen);
 			moduleContainer.update(module, builder, newGen);
 		} catch (Throwable t) {
-			if (!isReference) {
+			if (contentType == Type.DEFAULT) {
 				try {
 					delete(staged);
 				} catch (IOException e) {
@@ -946,14 +997,14 @@
 		return newGen;
 	}
 
-	private File getContentFile(final File staged, final boolean isReference, final long bundleID, final long generationID) throws BundleException {
+	private File getContentFile(final File staged, Type contentType, final long bundleID, final long generationID) throws BundleException {
 		if (System.getSecurityManager() == null)
-			return getContentFile0(staged, isReference, bundleID, generationID);
+			return getContentFile0(staged, contentType, bundleID, generationID);
 		try {
 			return AccessController.doPrivileged(new PrivilegedExceptionAction<File>() {
 				@Override
 				public File run() throws BundleException {
-					return getContentFile0(staged, isReference, bundleID, generationID);
+					return getContentFile0(staged, contentType, bundleID, generationID);
 				}
 			});
 		} catch (PrivilegedActionException e) {
@@ -963,9 +1014,10 @@
 		}
 	}
 
-	File getContentFile0(File staged, boolean isReference, long bundleID, long generationID) throws BundleException {
-		File contentFile;
-		if (!isReference) {
+	File getContentFile0(File staged, Type contentType, long bundleID, long generationID) throws BundleException {
+		File contentFile = staged;
+
+		if (contentType == Type.DEFAULT) {
 			File generationRoot = new File(childRoot, bundleID + "/" + generationID); //$NON-NLS-1$
 			generationRoot.mkdirs();
 			if (!generationRoot.isDirectory()) {
@@ -978,8 +1030,6 @@
 				throw new BundleException("Error while renaming bundle file to final location: " + contentFile, //$NON-NLS-1$
 						BundleException.READ_ERROR, e);
 			}
-		} else {
-			contentFile = staged;
 		}
 		return contentFile;
 	}
@@ -1058,7 +1108,7 @@
 		return result;
 	}
 
-	private File stageContent(final InputStream in, final URL sourceURL) throws BundleException {
+	File stageContent(final InputStream in, final URL sourceURL) throws BundleException {
 		if (System.getSecurityManager() == null)
 			return stageContent0(in, sourceURL);
 		try {
@@ -1078,10 +1128,6 @@
 	File stageContent0(InputStream in, URL sourceURL) throws BundleException {
 		File outFile = null;
 		try {
-			if (in instanceof ReferenceInputStream) {
-				return ((ReferenceInputStream) in).getReference();
-			}
-
 			outFile = File.createTempFile(BUNDLE_FILE_NAME, ".tmp", childRoot); //$NON-NLS-1$
 			String protocol = sourceURL == null ? null : sourceURL.getProtocol();
 
@@ -1138,9 +1184,16 @@
 	}
 
 	public BundleFile createBundleFile(File content, Generation generation, boolean isDirectory, boolean isBase) {
-		BundleFile result;
+		BundleFile result = null;
+		ConnectModule connectModule = null;
+		if (generation.getContentType() == Type.CONNECT) {
+			connectModule = equinoxContainer.getConnectModules().getConnectModule(generation.getBundleInfo().getLocation());
+		}
 		try {
-			if (isDirectory) {
+			if (connectModule != null && isBase) {
+				result = equinoxContainer.getConnectModules().getConnectBundleFile(connectModule, content, generation,
+						mruList, getConfiguration().getDebug());
+			} else if (isDirectory) {
 				boolean strictPath = Boolean.parseBoolean(equinoxContainer.getConfiguration().getConfiguration(EquinoxConfiguration.PROPERTY_STRICT_BUNDLE_ENTRY_PATH, Boolean.FALSE.toString()));
 				result = new DirBundleFile(content, strictPath);
 			} else {
@@ -1344,13 +1397,14 @@
 			out.writeLong(bundleInfo.getNextGenerationId());
 			out.writeLong(generation.getGenerationId());
 			out.writeBoolean(generation.isDirectory());
-			out.writeBoolean(generation.isReference());
+			Type contentType = generation.getContentType();
+			out.writeInt(contentType.ordinal());
 			out.writeBoolean(generation.hasPackageInfo());
-			if (bundleInfo.getBundleId() == 0) {
-				// just write empty string for system bundle content in this case
+			if (bundleInfo.getBundleId() == 0 || contentType == Type.CONNECT) {
+				// just write empty string for system bundle content and connect content in this case
 				out.writeUTF(""); //$NON-NLS-1$
 			} else {
-				if (generation.isReference()) {
+				if (contentType == Type.REFERENCE) {
 					// make reference installs relative to the install path
 					out.writeUTF(new FilePath(installPath).makeRelative(new FilePath(generation.getContent().getAbsolutePath())));
 				} else {
@@ -1450,13 +1504,23 @@
 		int numInfos = in.readInt();
 		Map<Long, Generation> result = new HashMap<>(numInfos);
 		List<Generation> generations = new ArrayList<>(numInfos);
+		Type[] contentTypes = Type.values();
 		for (int i = 0; i < numInfos; i++) {
 			long infoId = in.readLong();
 			String infoLocation = ObjectPool.intern(in.readUTF());
 			long nextGenId = in.readLong();
 			long generationId = in.readLong();
 			boolean isDirectory = in.readBoolean();
-			boolean isReference = in.readBoolean();
+
+			Type contentType = Type.DEFAULT;
+			if (version >= CONTENT_TYPE_VERSION) {
+				contentType = contentTypes[in.readInt()];
+			} else {
+				if (in.readBoolean()) {
+					contentType = Type.REFERENCE;
+				}
+			}
+
 			boolean hasPackageInfo = in.readBoolean();
 			String contentPath = in.readUTF();
 			long lastModified = in.readLong();
@@ -1473,37 +1537,58 @@
 			}
 			boolean isMRJar = (version >= MR_JAR_VERSION) ? in.readBoolean() : false;
 
-			File content;
-			if (infoId == 0) {
-				content = getSystemContent();
-				isDirectory = content != null ? content.isDirectory() : false;
-				// Note that we do not do any checking for absolute paths with
-				// the system bundle.  We always take the content as discovered
-				// by getSystemContent()
-			} else {
-				content = new File(contentPath);
-				if (!content.isAbsolute()) {
-					// make sure it has the absolute location instead
-					if (isReference) {
-						// reference installs are relative to the installPath
-						content = new File(installPath, contentPath);
-					} else {
-						// normal installs are relative to the storage area
-						content = getFile(contentPath, true);
+			File content = null;
+			if (contentType != Type.CONNECT) {
+				if (infoId == 0) {
+					content = getSystemContent();
+					isDirectory = content != null ? content.isDirectory() : false;
+					// Note that we do not do any checking for absolute paths with
+					// the system bundle. We always take the content as discovered
+					// by getSystemContent()
+				} else {
+					content = new File(contentPath);
+					if (!content.isAbsolute()) {
+						// make sure it has the absolute location instead
+						switch (contentType) {
+						case REFERENCE:
+							// reference installs are relative to the installPath
+							content = new File(installPath, contentPath);
+							break;
+						case DEFAULT:
+							// normal installs are relative to the storage area
+							content = getFile(contentPath, true);
+							break;
+						default:
+							throw new IllegalArgumentException("Unknown type: " + contentType); //$NON-NLS-1$
+						}
 					}
 				}
 			}
-
 			BundleInfo info = new BundleInfo(this, infoId, infoLocation, nextGenId);
-			Generation generation = info.restoreGeneration(generationId, content, isDirectory, isReference, hasPackageInfo, cachedHeaders, lastModified, isMRJar);
+			Generation generation = info.restoreGeneration(generationId, content, isDirectory, contentType, hasPackageInfo, cachedHeaders, lastModified, isMRJar);
 			result.put(infoId, generation);
 			generations.add(generation);
 		}
 
+		connectPersistentBundles(generations);
 		loadStorageHookData(generations, in);
 		return result;
 	}
 
+	private void connectPersistentBundles(List<Generation> generations) {
+		generations.forEach(g -> {
+			try {
+				if (g.getContentType() == Type.CONNECT) {
+					equinoxContainer.getConnectModules().connect(g.getBundleInfo().getLocation());
+				}
+			} catch (IllegalStateException e) {
+				if (!(e.getCause() instanceof BundleException)) {
+					throw e;
+				}
+			}
+		});
+	}
+
 	private void loadStorageHookData(List<Generation> generations, DataInputStream in) throws IOException {
 		List<StorageHookFactory<?, ?, ?>> factories = new ArrayList<>(getConfiguration().getHookRegistry().getStorageHookFactories());
 		Map<Generation, List<StorageHook<?, ?>>> hookMap = new HashMap<>();
@@ -1695,7 +1780,7 @@
 			}
 			if (profileIn == null)
 				// the profile url is still null then use the min profile the framework can use
-				profileIn = findInSystemBundle(systemGeneration, "JavaSE-1.7.profile"); //$NON-NLS-1$
+				profileIn = findInSystemBundle(systemGeneration, "JavaSE-1.8.profile"); //$NON-NLS-1$
 			if (profileIn != null) {
 				try {
 					result.load(new BufferedInputStream(profileIn));
@@ -2217,4 +2302,8 @@
 		}
 		return storageStream;
 	}
+
+	EquinoxContainer getEquinoxContainer() {
+		return equinoxContainer;
+	}
 }
diff --git a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/storage/bundlefile/CloseableBundleFile.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/storage/bundlefile/CloseableBundleFile.java
index 73720b9..aeb4cc5 100644
--- a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/storage/bundlefile/CloseableBundleFile.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/storage/bundlefile/CloseableBundleFile.java
@@ -72,7 +72,7 @@
 	 * Checks if the bundle file is open
 	 * @return true if the bundle file is open and locked
 	 */
-	private boolean lockOpen() {
+	protected boolean lockOpen() {
 		try {
 			open(true);
 			return true;
@@ -98,6 +98,13 @@
 	}
 
 	/**
+	 * Unlocks the open lock
+	 */
+	protected void releaseOpen() {
+		openLock.unlock();
+	}
+
+	/**
 	 * Opens this bundle file.
 	 * @param keepLock true if the open lock should be retained
 	 * @throws IOException
@@ -162,7 +169,7 @@
 			}
 			return getExtractFile(dirName);
 		} finally {
-			openLock.unlock();
+			releaseOpen();
 		}
 	}
 
@@ -219,7 +226,7 @@
 				generation.getBundleInfo().getStorage().getLogServices().log(EquinoxContainer.NAME, FrameworkLogEntry.ERROR, "Unable to extract content: " + generation.getRevision() + ": " + entry, e); //$NON-NLS-1$ //$NON-NLS-2$
 			}
 		} finally {
-			openLock.unlock();
+			releaseOpen();
 		}
 		return null;
 	}
@@ -251,7 +258,7 @@
 				}
 			}
 		} finally {
-			openLock.unlock();
+			releaseOpen();
 		}
 		return false;
 	}
@@ -264,7 +271,7 @@
 		try {
 			return findEntry(path);
 		} finally {
-			openLock.unlock();
+			releaseOpen();
 		}
 	}
 
@@ -307,7 +314,7 @@
 			}
 			return result.size() == 0 ? null : Collections.enumeration(result);
 		} finally {
-			openLock.unlock();
+			releaseOpen();
 		}
 	}
 
@@ -449,7 +456,7 @@
 			}
 			return in;
 		} finally {
-			openLock.unlock();
+			releaseOpen();
 		}
 	}
 
@@ -542,7 +549,9 @@
 		}
 
 		private IOException enrichExceptionWithBaseFile(IOException e) {
-			return new IOException(getBaseFile().toString(), e);
+			File baseFile = getBaseFile();
+			String extraInfo = baseFile == null ? generation.getBundleInfo().getLocation() : baseFile.toString();
+			return new IOException(extraInfo, e);
 		}
 	}
 }
diff --git a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/storage/url/reference/ReferenceInputStream.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/storage/url/reference/ReferenceInputStream.java
index b9ff45f..1ce4ba3 100644
--- a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/storage/url/reference/ReferenceInputStream.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/storage/url/reference/ReferenceInputStream.java
@@ -17,12 +17,13 @@
 import java.io.File;
 import java.io.IOException;
 import java.io.InputStream;
+import org.eclipse.osgi.storage.ContentProvider;
 
 /**
  * InputStream subclass which provides a reference (via File) to the data
  * rather than allowing the input stream to be directly read.
  */
-public class ReferenceInputStream extends InputStream {
+public class ReferenceInputStream extends InputStream implements ContentProvider {
 	private final File reference;
 
 	public ReferenceInputStream(File reference) {
@@ -37,6 +38,16 @@
 	}
 
 	public File getReference() {
+		return getContent();
+	}
+
+	@Override
+	public File getContent() {
 		return reference;
 	}
+
+	@Override
+	public Type getType() {
+		return Type.REFERENCE;
+	}
 }
diff --git a/bundles/org.eclipse.osgi/osgi/src/org/osgi/framework/BundlePermission.java b/bundles/org.eclipse.osgi/osgi/src/org/osgi/framework/BundlePermission.java
index 7b08160..7a45b1c 100644
--- a/bundles/org.eclipse.osgi/osgi/src/org/osgi/framework/BundlePermission.java
+++ b/bundles/org.eclipse.osgi/osgi/src/org/osgi/framework/BundlePermission.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) OSGi Alliance (2004, 2016). All Rights Reserved.
+ * Copyright (c) OSGi Alliance (2004, 2019). All Rights Reserved.
  * 
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -543,7 +543,7 @@
 			// work our way up the tree...
 			int last;
 			int offset = requestedName.length() - 1;
-			while ((last = requestedName.lastIndexOf(".", offset)) != -1) {
+			while ((last = requestedName.lastIndexOf('.', offset)) != -1) {
 				requestedName = requestedName.substring(0, last + 1) + "*";
 				bp = pc.get(requestedName);
 				if (bp != null) {
diff --git a/bundles/org.eclipse.osgi/osgi/src/org/osgi/framework/CapabilityPermission.java b/bundles/org.eclipse.osgi/osgi/src/org/osgi/framework/CapabilityPermission.java
index 8a38df0..c7bae50 100644
--- a/bundles/org.eclipse.osgi/osgi/src/org/osgi/framework/CapabilityPermission.java
+++ b/bundles/org.eclipse.osgi/osgi/src/org/osgi/framework/CapabilityPermission.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) OSGi Alliance (2000, 2017). All Rights Reserved.
+ * Copyright (c) OSGi Alliance (2000, 2019). All Rights Reserved.
  * 
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -714,7 +714,7 @@
 			/* work our way up the tree... */
 			int last;
 			int offset = requestedName.length() - 1;
-			while ((last = requestedName.lastIndexOf(".", offset)) != -1) {
+			while ((last = requestedName.lastIndexOf('.', offset)) != -1) {
 				requestedName = requestedName.substring(0, last + 1) + "*";
 				cp = pc.get(requestedName);
 				if (cp != null) {
diff --git a/bundles/org.eclipse.osgi/osgi/src/org/osgi/framework/Constants.java b/bundles/org.eclipse.osgi/osgi/src/org/osgi/framework/Constants.java
index 41e648a..57af872 100644
--- a/bundles/org.eclipse.osgi/osgi/src/org/osgi/framework/Constants.java
+++ b/bundles/org.eclipse.osgi/osgi/src/org/osgi/framework/Constants.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) OSGi Alliance (2000, 2018). All Rights Reserved.
+ * Copyright (c) OSGi Alliance (2000, 2020). All Rights Reserved.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -1025,7 +1025,6 @@
 	/**
 	 * Framework environment property identifying whether the Framework supports
 	 * bootclasspath extension bundles.
-	 * 
 	 * <p>
 	 * If the value of this property is {@code true}, then the Framework
 	 * supports bootclasspath extension bundles. The default value is
@@ -1035,6 +1034,7 @@
 	 * {@code BundleContext.getProperty} method.
 	 * 
 	 * @since 1.3
+	 * @deprecated As of 1.10.
 	 */
 	String	SUPPORTS_BOOTCLASSPATH_EXTENSION		= "org.osgi.supports.bootclasspath.extension";
 
@@ -1574,7 +1574,7 @@
 	String	SERVICE_IMPORTED_CONFIGS				= "service.imported.configs";
 
 	/**
-	 * Service property identifying the intents that this service implement.
+	 * Service property identifying the intents that this service implements.
 	 * This property has a dual purpose:
 	 * <ul>
 	 * <li>A bundle can use this service property to notify the distribution
@@ -1833,8 +1833,8 @@
 	 * Service property identifying the monotonically increasing change count of
 	 * a service.
 	 * <p>
-	 * A service may optional provide this property to indicate there has been a
-	 * change in some data provided by the service. The change count must be
+	 * A service may provide this property to indicate there has been a change
+	 * in some data provided by the service. The change count must be
 	 * incremented with a positive value every time the data provided by the
 	 * service is changed. The service announces the modified change count by
 	 * updating its service properties with the new value for this service
diff --git a/bundles/org.eclipse.osgi/osgi/src/org/osgi/framework/FrameworkEvent.java b/bundles/org.eclipse.osgi/osgi/src/org/osgi/framework/FrameworkEvent.java
index b3072b2..bcff061 100644
--- a/bundles/org.eclipse.osgi/osgi/src/org/osgi/framework/FrameworkEvent.java
+++ b/bundles/org.eclipse.osgi/osgi/src/org/osgi/framework/FrameworkEvent.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) OSGi Alliance (2004, 2016). All Rights Reserved.
+ * Copyright (c) OSGi Alliance (2004, 2020). All Rights Reserved.
  * 
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -148,13 +148,13 @@
 
 	/**
 	 * The Framework has stopped and the boot class path has changed.
-	 * 
 	 * <p>
 	 * This event is fired when the Framework has been stopped because of a stop
 	 * operation on the system bundle and a bootclasspath extension bundle has
 	 * been installed or updated. The source of this event is the System Bundle.
 	 * 
 	 * @since 1.5
+	 * @deprecated As of 1.10.
 	 */
 	public final static int	STOPPED_BOOTCLASSPATH_MODIFIED	= 0x00000100;
 
@@ -173,9 +173,9 @@
 	 * The Framework has stopped and the framework requires a new class loader
 	 * to restart.
 	 * <p>
-	 * This event is fired when the Framework has been stopped because of a stop
-	 * operation on the system bundle and the framework requires a new class
-	 * loader to be used to restart. For example, if a framework extension
+	 * This event is fired when the Framework has been stopped because of a
+	 * refresh operation on the system bundle and the framework requires a new
+	 * class loader to be used to restart. For example, if a framework extension
 	 * bundle has been refreshed. The source of this event is the System Bundle.
 	 * 
 	 * @since 1.9
@@ -244,7 +244,6 @@
 	 * <li>{@link #PACKAGES_REFRESHED}</li>
 	 * <li>{@link #STARTLEVEL_CHANGED}</li>
 	 * <li>{@link #STOPPED}</li>
-	 * <li>{@link #STOPPED_BOOTCLASSPATH_MODIFIED}</li>
 	 * <li>{@link #STOPPED_UPDATE}</li>
 	 * <li>{@link #WAIT_TIMEDOUT}</li>
 	 * </ul>
diff --git a/bundles/org.eclipse.osgi/osgi/src/org/osgi/framework/FrameworkUtil.java b/bundles/org.eclipse.osgi/osgi/src/org/osgi/framework/FrameworkUtil.java
index 8003880..587b532 100644
--- a/bundles/org.eclipse.osgi/osgi/src/org/osgi/framework/FrameworkUtil.java
+++ b/bundles/org.eclipse.osgi/osgi/src/org/osgi/framework/FrameworkUtil.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) OSGi Alliance (2005, 2016). All Rights Reserved.
+ * Copyright (c) OSGi Alliance (2005, 2020). All Rights Reserved.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -16,16 +16,27 @@
 
 package org.osgi.framework;
 
+import static java.util.Objects.requireNonNull;
+
 import java.security.AccessController;
 import java.security.PrivilegedAction;
+import java.util.AbstractMap;
+import java.util.AbstractSet;
 import java.util.ArrayList;
 import java.util.Collections;
+import java.util.Dictionary;
+import java.util.Enumeration;
 import java.util.Iterator;
 import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Optional;
 import java.util.ServiceLoader;
+import java.util.Set;
+
 import javax.security.auth.x500.X500Principal;
 import org.eclipse.osgi.internal.framework.FilterImpl;
-import org.eclipse.osgi.internal.hookregistry.FrameworkUtilHelper;
+import org.osgi.framework.connect.FrameworkUtilHelper;
 
 /**
  * Framework Utility class.
@@ -185,60 +196,72 @@
 		return DNChainMatching.match(matchPattern, dnChain);
 	}
 
+	/**
+	 * Return a {@code Bundle} for the specified bundle class loader.
+	 * 
+	 * @param bundleClassLoader A bundle class loader.
+	 * @return An Optional containing {@code Bundle} for the specified bundle
+	 *         class loader or an empty Optional if the specified class loader
+	 *         is not associated with a specific bundle.
+	 * @since 1.10
+	 */
+	public static Optional<Bundle> getBundle(ClassLoader bundleClassLoader) {
+		requireNonNull(bundleClassLoader);
+		return Optional
+				.ofNullable((bundleClassLoader instanceof BundleReference)
+						? ((BundleReference) bundleClassLoader).getBundle()
+						: null);
+	}
+
+	/**
+	 * Return a {@code Bundle} for the specified bundle class.
+	 * 
+	 * @param classFromBundle A class defined by a bundle.
+	 * @return A {@code Bundle} for the specified bundle class or {@code null}
+	 *         if the specified class was not defined by a bundle.
+	 * @since 1.5
+	 */
+	public static Bundle getBundle(Class< ? > classFromBundle) {
+		// We use doPriv since the caller may not have permission
+		// to call getClassLoader.
+		Optional<ClassLoader> cl = Optional
+				.ofNullable(AccessController.doPrivileged(
+						(PrivilegedAction<ClassLoader>) () -> classFromBundle
+								.getClassLoader()));
+
+		return cl.flatMap(FrameworkUtil::getBundle)
+				.orElseGet(() -> helpers.stream()
+						.map(helper -> helper.getBundle(classFromBundle))
+						.filter(Optional::isPresent)
+						.map(Optional::get)
+						.findFirst()
+						.orElse(null));
+	}
+
 	private final static List<FrameworkUtilHelper> helpers;
 	static {
 		List<FrameworkUtilHelper> l = new ArrayList<>();
 		try {
-			ServiceLoader<FrameworkUtilHelper> helperLoader = AccessController.doPrivileged(new PrivilegedAction<ServiceLoader<FrameworkUtilHelper>>() {
-				@Override
-				public ServiceLoader<FrameworkUtilHelper> run() {
-					return ServiceLoader.load(FrameworkUtilHelper.class, FrameworkUtilHelper.class.getClassLoader());
-				}
-			});
-			for (Iterator<FrameworkUtilHelper> iHelpers = helperLoader.iterator(); iHelpers.hasNext();) {
-				l.add(iHelpers.next());
+			ServiceLoader<FrameworkUtilHelper> helperLoader = AccessController
+					.doPrivileged(
+							(PrivilegedAction<ServiceLoader<FrameworkUtilHelper>>) () -> ServiceLoader
+									.load(FrameworkUtilHelper.class,
+											FrameworkUtilHelper.class
+													.getClassLoader()));
+			helperLoader.forEach(l::add);
+		} catch (Throwable error) {
+			// try hard not to fail static <clinit>
+			try {
+				Thread t = Thread.currentThread();
+				t.getUncaughtExceptionHandler().uncaughtException(t, error);
+			} catch (Throwable ignored) {
+				// we ignore this
 			}
-		} catch (Throwable t) {
-			// should not fail out of static initializers
-			t.printStackTrace();
 		}
 		helpers = Collections.unmodifiableList(l);
 	}
 
 	/**
-	 * Return a {@code Bundle} for the specified bundle class. The returned
-	 * {@code Bundle} is the bundle associated with the bundle class loader
-	 * which defined the specified class.
-	 * 
-	 * @param classFromBundle A class defined by a bundle class loader.
-	 * @return A {@code Bundle} for the specified bundle class or {@code null}
-	 *         if the specified class was not defined by a bundle class loader.
-	 * @since 1.5
-	 */
-	public static Bundle getBundle(final Class<?> classFromBundle) {
-		// We use doPriv since the caller may not have permission
-		// to call getClassLoader.
-		Object cl = AccessController.doPrivileged(new PrivilegedAction<Object>() {
-			@Override
-			public Object run() {
-				return classFromBundle.getClassLoader();
-			}
-		});
-
-		if (cl instanceof BundleReference) {
-			return ((BundleReference) cl).getBundle();
-		}
-
-		for (FrameworkUtilHelper helper : helpers) {
-			Bundle b = helper.getBundle(classFromBundle);
-			if (b != null) {
-				return b;
-			}
-		}
-		return null;
-	}
-
-	/**
 	 * This class contains a method to match a distinguished name (DN) chain
 	 * against and DN chain pattern.
 	 * <p>
@@ -680,4 +703,357 @@
 			return sb.toString();
 		}
 	}
+
+	/**
+	 * Return a Map wrapper around a Dictionary.
+	 *
+	 * @param <K> The type of the key.
+	 * @param <V> The type of the value.
+	 * @param dictionary The dictionary to wrap.
+	 * @return A Map object which wraps the specified dictionary. If the
+	 *         specified dictionary can be cast to a Map, then the specified
+	 *         dictionary is returned.
+	 * @since 1.10
+	 */
+	public static <K, V> Map<K,V> asMap(
+			Dictionary< ? extends K, ? extends V> dictionary) {
+		if (dictionary instanceof Map) {
+			@SuppressWarnings("unchecked")
+			Map<K,V> coerced = (Map<K,V>) dictionary;
+			return coerced;
+		}
+		return new DictionaryAsMap<>(dictionary);
+	}
+
+	private static class DictionaryAsMap<K, V> extends AbstractMap<K,V> {
+		private final Dictionary<K,V> dict;
+
+		@SuppressWarnings("unchecked")
+		DictionaryAsMap(Dictionary< ? extends K, ? extends V> dict) {
+			this.dict = (Dictionary<K,V>) requireNonNull(dict);
+		}
+
+		Iterator<K> keys() {
+			List<K> keys = new ArrayList<>(dict.size());
+			for (Enumeration<K> e = dict.keys(); e.hasMoreElements();) {
+				keys.add(e.nextElement());
+			}
+			return keys.iterator();
+		}
+
+		@Override
+		public int size() {
+			return dict.size();
+		}
+
+		@Override
+		public boolean isEmpty() {
+			return dict.isEmpty();
+		}
+
+		@Override
+		public boolean containsKey(Object key) {
+			if (key == null) {
+				return false;
+			}
+			return dict.get(key) != null;
+		}
+
+		@Override
+		public V get(Object key) {
+			if (key == null) {
+				return null;
+			}
+			return dict.get(key);
+		}
+
+		@Override
+		public V put(K key, V value) {
+			return dict.put(
+					requireNonNull(key,
+							"a Dictionary cannot contain a null key"),
+					requireNonNull(value,
+							"a Dictionary cannot contain a null value"));
+		}
+
+		@Override
+		public V remove(Object key) {
+			if (key == null) {
+				return null;
+			}
+			return dict.remove(key);
+		}
+
+		@Override
+		public void clear() {
+			for (Iterator<K> iter = keys(); iter.hasNext();) {
+				dict.remove(iter.next());
+			}
+		}
+
+		@Override
+		public Set<K> keySet() {
+			return new KeySet();
+		}
+
+		@Override
+		public Set<Map.Entry<K,V>> entrySet() {
+			return new EntrySet();
+		}
+
+		@Override
+		public String toString() {
+			return dict.toString();
+		}
+
+		final class KeySet extends AbstractSet<K> {
+			@Override
+			public Iterator<K> iterator() {
+				return new KeyIterator();
+			}
+
+			@Override
+			public int size() {
+				return DictionaryAsMap.this.size();
+			}
+
+			@Override
+			public boolean isEmpty() {
+				return DictionaryAsMap.this.isEmpty();
+			}
+
+			@Override
+			public boolean contains(Object key) {
+				return DictionaryAsMap.this.containsKey(key);
+			}
+
+			@Override
+			public boolean remove(Object key) {
+				return DictionaryAsMap.this.remove(key) != null;
+			}
+
+			@Override
+			public void clear() {
+				DictionaryAsMap.this.clear();
+			}
+		}
+
+		final class KeyIterator implements Iterator<K> {
+			private final Iterator<K>	keys	= DictionaryAsMap.this.keys();
+			private K					key		= null;
+
+			@Override
+			public boolean hasNext() {
+				return keys.hasNext();
+			}
+
+			@Override
+			public K next() {
+				return key = keys.next();
+			}
+
+			@Override
+			public void remove() {
+				if (key == null) {
+					throw new IllegalStateException();
+				}
+				DictionaryAsMap.this.remove(key);
+				key = null;
+			}
+		}
+
+		final class EntrySet extends AbstractSet<Map.Entry<K,V>> {
+			@Override
+			public Iterator<Map.Entry<K,V>> iterator() {
+				return new EntryIterator();
+			}
+
+			@Override
+			public int size() {
+				return DictionaryAsMap.this.size();
+			}
+
+			@Override
+			public boolean isEmpty() {
+				return DictionaryAsMap.this.isEmpty();
+			}
+
+			@Override
+			public boolean contains(Object o) {
+				if (o instanceof Map.Entry) {
+					Map.Entry< ? , ? > e = (Map.Entry< ? , ? >) o;
+					return containsEntry(e);
+				}
+				return false;
+			}
+
+			private boolean containsEntry(Map.Entry< ? , ? > e) {
+				Object key = e.getKey();
+				if (key == null) {
+					return false;
+				}
+				Object value = e.getValue();
+				if (value == null) {
+					return false;
+				}
+				return Objects.equals(DictionaryAsMap.this.get(key), value);
+			}
+
+			@Override
+			public boolean remove(Object o) {
+				if (o instanceof Map.Entry) {
+					Map.Entry< ? , ? > e = (Map.Entry< ? , ? >) o;
+					if (containsEntry(e)) {
+						DictionaryAsMap.this.remove(e.getKey());
+						return true;
+					}
+				}
+				return false;
+			}
+
+			@Override
+			public void clear() {
+				DictionaryAsMap.this.clear();
+			}
+		}
+
+		final class EntryIterator implements Iterator<Map.Entry<K,V>> {
+			private final Iterator<K>	keys	= DictionaryAsMap.this.keys();
+			private K					key		= null;
+
+			@Override
+			public boolean hasNext() {
+				return keys.hasNext();
+			}
+
+			@Override
+			public Map.Entry<K,V> next() {
+				return new Entry(key = keys.next());
+			}
+
+			@Override
+			public void remove() {
+				if (key == null) {
+					throw new IllegalStateException();
+				}
+				DictionaryAsMap.this.remove(key);
+				key = null;
+			}
+		}
+
+		final class Entry extends SimpleEntry<K,V> {
+			private static final long serialVersionUID = 1L;
+
+			Entry(K key) {
+				super(key, DictionaryAsMap.this.get(key));
+			}
+
+			@Override
+			public V setValue(V value) {
+				DictionaryAsMap.this.put(getKey(), value);
+				return super.setValue(value);
+			}
+		}
+	}
+
+	/**
+	 * Return a Dictionary wrapper around a Map.
+	 *
+	 * @param <K> The type of the key.
+	 * @param <V> The type of the value.
+	 * @param map The map to wrap.
+	 * @return A Dictionary object which wraps the specified map. If the
+	 *         specified map can be cast to a Dictionary, then the specified map
+	 *         is returned.
+	 * @since 1.10
+	 */
+	public static <K, V> Dictionary<K,V> asDictionary(
+			Map< ? extends K, ? extends V> map) {
+		if (map instanceof Dictionary) {
+			@SuppressWarnings("unchecked")
+			Dictionary<K,V> coerced = (Dictionary<K,V>) map;
+			return coerced;
+		}
+		return new MapAsDictionary<>(map);
+	}
+
+	private static class MapAsDictionary<K, V> extends Dictionary<K,V> {
+		private final Map<K,V> map;
+
+		@SuppressWarnings("unchecked")
+		MapAsDictionary(Map< ? extends K, ? extends V> map) {
+			this.map = (Map<K,V>) requireNonNull(map);
+			boolean nullKey;
+			try {
+				nullKey = map.containsKey(null);
+			} catch (NullPointerException e) {
+				nullKey = false; // map does not allow null key
+			}
+			if (nullKey) {
+				throw new NullPointerException(
+						"a Dictionary cannot contain a null key");
+			}
+			boolean nullValue;
+			try {
+				nullValue = map.containsValue(null);
+			} catch (NullPointerException e) {
+				nullValue = false; // map does not allow null value
+			}
+			if (nullValue) {
+				throw new NullPointerException(
+						"a Dictionary cannot contain a null value");
+			}
+		}
+
+		@Override
+		public int size() {
+			return map.size();
+		}
+
+		@Override
+		public boolean isEmpty() {
+			return map.isEmpty();
+		}
+
+		@Override
+		public Enumeration<K> keys() {
+			return Collections.enumeration(map.keySet());
+		}
+
+		@Override
+		public Enumeration<V> elements() {
+			return Collections.enumeration(map.values());
+		}
+
+		@Override
+		public V get(Object key) {
+			if (key == null) {
+				return null;
+			}
+			return map.get(key);
+		}
+
+		@Override
+		public V put(K key, V value) {
+			return map.put(
+					requireNonNull(key,
+							"a Dictionary cannot contain a null key"),
+					requireNonNull(value,
+							"a Dictionary cannot contain a null value"));
+		}
+
+		@Override
+		public V remove(Object key) {
+			if (key == null) {
+				return null;
+			}
+			return map.remove(key);
+		}
+
+		@Override
+		public String toString() {
+			return map.toString();
+		}
+	}
+
 }
diff --git a/bundles/org.eclipse.osgi/osgi/src/org/osgi/framework/PackagePermission.java b/bundles/org.eclipse.osgi/osgi/src/org/osgi/framework/PackagePermission.java
index 264ccd6..cc8cd62 100644
--- a/bundles/org.eclipse.osgi/osgi/src/org/osgi/framework/PackagePermission.java
+++ b/bundles/org.eclipse.osgi/osgi/src/org/osgi/framework/PackagePermission.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) OSGi Alliance (2000, 2017). All Rights Reserved.
+ * Copyright (c) OSGi Alliance (2000, 2019). All Rights Reserved.
  * 
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -713,7 +713,7 @@
 			/* work our way up the tree... */
 			int last;
 			int offset = requestedName.length() - 1;
-			while ((last = requestedName.lastIndexOf(".", offset)) != -1) {
+			while ((last = requestedName.lastIndexOf('.', offset)) != -1) {
 				requestedName = requestedName.substring(0, last + 1) + "*";
 				pp = pc.get(requestedName);
 				if (pp != null) {
diff --git a/bundles/org.eclipse.osgi/osgi/src/org/osgi/framework/ServicePermission.java b/bundles/org.eclipse.osgi/osgi/src/org/osgi/framework/ServicePermission.java
index 8db61d0..a6b5252 100644
--- a/bundles/org.eclipse.osgi/osgi/src/org/osgi/framework/ServicePermission.java
+++ b/bundles/org.eclipse.osgi/osgi/src/org/osgi/framework/ServicePermission.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) OSGi Alliance (2000, 2017). All Rights Reserved.
+ * Copyright (c) OSGi Alliance (2000, 2019). All Rights Reserved.
  * 
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -866,7 +866,7 @@
 		// work our way up the tree...
 		int last;
 		int offset = requestedName.length() - 1;
-		while ((last = requestedName.lastIndexOf(".", offset)) != -1) {
+		while ((last = requestedName.lastIndexOf('.', offset)) != -1) {
 			requestedName = requestedName.substring(0, last + 1) + "*";
 			sp = pc.get(requestedName);
 			if (sp != null) {
diff --git a/bundles/org.eclipse.osgi/osgi/src/org/osgi/framework/ServiceReference.java b/bundles/org.eclipse.osgi/osgi/src/org/osgi/framework/ServiceReference.java
index 1454244..adb91d7 100644
--- a/bundles/org.eclipse.osgi/osgi/src/org/osgi/framework/ServiceReference.java
+++ b/bundles/org.eclipse.osgi/osgi/src/org/osgi/framework/ServiceReference.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) OSGi Alliance (2000, 2017). All Rights Reserved.
+ * Copyright (c) OSGi Alliance (2000, 2019). All Rights Reserved.
  * 
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -53,7 +53,8 @@
  * @author $Id$
  */
 @ProviderType
-public interface ServiceReference<S> extends Comparable<Object> {
+public interface ServiceReference<S>
+		extends Comparable<Object>, BundleReference {
 	/**
 	 * Returns the property value to which the specified property key is mapped
 	 * in the properties {@code Dictionary} object of the service referenced by
@@ -109,6 +110,7 @@
 	 *         already been unregistered.
 	 * @see BundleContext#registerService(String[],Object,Dictionary)
 	 */
+	@Override
 	public Bundle getBundle();
 
 	/**
@@ -131,14 +133,24 @@
 	 * <p>
 	 * This method performs the following checks:
 	 * <ol>
+	 * <li>If the specified bundle is equal to the bundle that registered the
+	 * service referenced by this {@code ServiceReference} (registrant bundle)
+	 * return {@code true}.</li>
 	 * <li>Get the package name from the specified class name.</li>
-	 * <li>For the bundle that registered the service referenced by this
-	 * {@code ServiceReference} (registrant bundle); find the source for the
-	 * package. If no source is found then return {@code true} if the registrant
-	 * bundle is equal to the specified bundle; otherwise return {@code false}.</li>
-	 * <li>If the package source of the registrant bundle is equal to the
-	 * package source of the specified bundle then return {@code true};
-	 * otherwise return {@code false}.</li>
+	 * <li>For the specified bundle; find the source for the package. If no
+	 * source is found then return {@code true} (use of reflection is assumed by
+	 * the specified bundle).</li>
+	 * <li>For the registrant bundle; find the source for the package. If the
+	 * package source is found then return {@code true} if the package source
+	 * equals the package source of the specified bundle; otherwise return
+	 * {@code false}.</li>
+	 * <li>If no package source is found for the registrant bundle then
+	 * determine the package source based on the service object. If the service
+	 * object is a {@code ServiceFactory} and the factory implementation is not
+	 * from the registrant bundle return {@code true}; otherwise attempt to find
+	 * the package source based on the service object class. If the package
+	 * source is found and is equal to package source of the specified bundle
+	 * return {@code true}; otherwise return {@code false}.</li>
 	 * </ol>
 	 * 
 	 * @param bundle The {@code Bundle} object to check.
@@ -148,8 +160,8 @@
 	 *         bundle use the same source for the package of the specified class
 	 *         name. Otherwise {@code false} is returned.
 	 * @throws IllegalArgumentException If the specified {@code Bundle} was not
-	 *         created by the same framework instance as this
-	 *         {@code ServiceReference}.
+	 *             created by the same framework instance as this
+	 *             {@code ServiceReference}.
 	 * @since 1.3
 	 */
 	public boolean isAssignableTo(Bundle bundle, String className);
@@ -212,4 +224,27 @@
 	 * @since 1.9
 	 */
 	public Dictionary<String,Object> getProperties();
+
+	/**
+	 * Adapt this {@code ServiceReference} object to the specified type.
+	 * <p>
+	 * Adapting this {@code ServiceReference} object to the specified type may
+	 * require certain checks, including security checks, to succeed. If a check
+	 * does not succeed, then this {@code ServiceReference} object cannot be
+	 * adapted and {@code null} is returned.
+	 * 
+	 * @param <A> The type to which this {@code ServiceReference} object is to
+	 *            be adapted.
+	 * @param type Class object for the type to which this
+	 *            {@code ServiceReference} object is to be adapted.
+	 * @return The object, of the specified type, to which this
+	 *         {@code ServiceReference} object has been adapted or {@code null}
+	 *         if this {@code ServiceReference} object cannot be adapted to the
+	 *         specified type.
+	 * @throws SecurityException If the caller does not have the appropriate
+	 *             {@code AdaptPermission[type,this,ADAPT]}, and the Java
+	 *             Runtime Environment supports permissions.
+	 * @since 1.10
+	 */
+	<A> A adapt(Class<A> type);
 }
diff --git a/bundles/org.eclipse.osgi/osgi/src/org/osgi/framework/connect/ConnectContent.java b/bundles/org.eclipse.osgi/osgi/src/org/osgi/framework/connect/ConnectContent.java
new file mode 100644
index 0000000..9e455f9
--- /dev/null
+++ b/bundles/org.eclipse.osgi/osgi/src/org/osgi/framework/connect/ConnectContent.java
@@ -0,0 +1,218 @@
+/*
+ * Copyright (c) OSGi Alliance (2019, 2020). All Rights Reserved.
+ *
+ * Licensed 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.osgi.framework.connect;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Map;
+import java.util.Optional;
+
+import org.osgi.annotation.versioning.ConsumerType;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.launch.Framework;
+import org.osgi.framework.namespace.IdentityNamespace;
+import org.osgi.framework.wiring.BundleRevisions;
+
+/**
+ * A {@code ConnectContent} provides a {@link Framework} instance access to the
+ * content of a {@link ConnectModule}.
+ * <p>
+ * A framework may {@link #open() open} and {@link #close() close} the content
+ * for a {@link ConnectModule} multiple times while the {@code ConnectContent}
+ * is in use by the framework. The framework must close the
+ * {@code ConnectContent} once the {@code ConnectContent} is no longer used as
+ * the content of a current bundle revision or an in use bundle revision.
+ * <p>
+ * An entry in a {@code ConnectContent} is identified by a path name that is a
+ * solidus (<code>'/' \u002F</code>) separated path. A {@code ConnectContent}
+ * may treat directories as entries. A directory entry path name will end with a
+ * solidus. A directory entry may be located using a path name that omits the
+ * trailing solidus.
+ * 
+ * @see BundleRevisions
+ * @ThreadSafe
+ * @author $Id$
+ */
+@ConsumerType
+public interface ConnectContent {
+	/**
+	 * The {@code osgi.identity}
+	 * {@link IdentityNamespace#CAPABILITY_TAGS_ATTRIBUTE tags} attribute value
+	 * used by the framework to tag connect bundle revisions.
+	 */
+	String TAG_OSGI_CONNECT = "osgi.connect";
+
+	/**
+	 * Returns the Manifest headers and values of this {@code ConnectContent}.
+	 * 
+	 * @return An {@code Optional} containing the Manifest headers and values
+	 *         for this {@code ConnectContent}, or an empty {@code Optional} if
+	 *         the framework should handle parsing the Manifest of the content
+	 *         itself.
+	 * @throws IllegalStateException If this {@code ConnectContent} has been
+	 *             closed.
+	 */
+	Optional<Map<String,String>> getHeaders();
+
+	/**
+	 * Returns the entry names available in this {@code ConnectContent}.
+	 * 
+	 * @return An {@code Iterable} which can supply the available entry names.
+	 * @throws IOException If an error occurs reading this
+	 *             {@code ConnectContent}.
+	 * @throws IllegalStateException If this {@code ConnectContent} has been
+	 *             closed.
+	 */
+	Iterable<String> getEntries() throws IOException;
+
+	/**
+	 * Returns the {@link ConnectEntry} for the specified path name in this
+	 * content.
+	 * <p>
+	 * The {@link Optional#empty() empty} value is returned if an entry with the
+	 * specified path name does not exist. The path must not start with a
+	 * &quot;/&quot; and is relative to the root of this content. A connect
+	 * entry for a directory will have a path name that ends with a slash ('/').
+	 * 
+	 * @param path The path name of the entry.
+	 * @return An {@code Optional} containing the {@link ConnectEntry} for the
+	 *         specified path, or an empty {@code Optional} if no entry for
+	 *         specified path can be found.
+	 * @throws IllegalStateException If this {@code ConnectContent} has been
+	 *             closed.
+	 */
+	Optional<ConnectEntry> getEntry(String path);
+
+	/**
+	 * Returns a class loader for this {@code ConnectContent}.
+	 * <p>
+	 * This method is called by the framework for {@link Bundle#RESOLVED
+	 * resolved} bundles only and will be called at most once while a bundle is
+	 * resolved. If a bundle associated with a {@link ConnectModule} is
+	 * refreshed and resolved again, the framework will ask the
+	 * {@code ConnectContent} for the class loader again. This allows for a
+	 * {@code ConnectContent} to reuse or create a new class loader each time
+	 * the bundle revision is resolved.
+	 * 
+	 * @return An {@code Optional} containing the class loader for this
+	 *         {@code ConnectContent}, or an empty {@code Optional} if framework
+	 *         should handle creating a class loader for the bundle revision
+	 *         associated with this {@code ConnectContent}.
+	 * @throws IllegalStateException If this {@code ConnectContent} has been
+	 *             closed.
+	 */
+	Optional<ClassLoader> getClassLoader();
+
+	/**
+	 * Opens this {@code ConnectContent}.
+	 * <p>
+	 * The framework will open the content when it needs to access the content
+	 * for a bundle revision associated with this {@code ConnectContent}. The
+	 * framework may defer calling this method until requests to access the
+	 * bundle revision content are made.
+	 * 
+	 * @throws IOException If an error occurred opening this
+	 *             {@code ConnectContent}.
+	 */
+	void open() throws IOException;
+
+	/**
+	 * Closes this {@code ConnectContent}.
+	 * 
+	 * @throws IOException If an error occurred closing this
+	 *             {@code ConnectContent}.
+	 */
+	void close() throws IOException;
+
+	/**
+	 * Represents the entry of a {@code ConnectContent}.
+	 */
+	@ConsumerType
+	public interface ConnectEntry {
+		/**
+		 * Returns the path name of this entry.
+		 * 
+		 * @return The path name of this entry.
+		 */
+		String getName();
+
+		/**
+		 * Returns the content length of this entry.
+		 * 
+		 * @return The content length of the entry, or {@code -1} if the content
+		 *         length is not known.
+		 */
+		public long getContentLength();
+
+		/**
+		 * Returns the last modification time of this entry.
+		 * 
+		 * @return The last modification time of this entry measured in
+		 *         milliseconds since the epoch (00:00:00 GMT, January 1, 1970).
+		 */
+		public long getLastModified();
+
+		/**
+		 * Returns the content of this entry.
+		 * 
+		 * @return The content of this entry.
+		 * @throws IOException If an error occurs reading the content.
+		 */
+		default byte[] getBytes() throws IOException {
+			long longLength = getContentLength();
+			if (longLength > Integer.MAX_VALUE - 8) {
+				throw new IOException(
+						"Entry is to big to fit into a byte[]: " + getName());
+			}
+
+			try (InputStream in = getInputStream()) {
+				int length = (int) longLength;
+				if (length > 0) {
+					int bytesread = 0;
+					byte[] result = new byte[length];
+					int readcount = 0;
+					while (bytesread < length) {
+						readcount = in.read(result, bytesread,
+								length - bytesread);
+						bytesread += readcount;
+						if (readcount <= 0) {
+							break;
+						}
+					}
+					return result;
+				} else {
+					ByteArrayOutputStream buffer = new ByteArrayOutputStream();
+					int nRead;
+					byte[] data = new byte[1024];
+					while ((nRead = in.read(data, 0, data.length)) > 0) {
+						buffer.write(data, 0, nRead);
+					}
+					buffer.flush();
+					return buffer.toByteArray();
+				}
+			}
+		}
+
+		/**
+		 * Returns an input stream for the content of this entry.
+		 * 
+		 * @return An input stream for the content of this entry.
+		 * @throws IOException If an error occurs reading the content.
+		 */
+		InputStream getInputStream() throws IOException;
+	}
+}
diff --git a/bundles/org.eclipse.osgi/osgi/src/org/osgi/framework/connect/ConnectFrameworkFactory.java b/bundles/org.eclipse.osgi/osgi/src/org/osgi/framework/connect/ConnectFrameworkFactory.java
new file mode 100644
index 0000000..fee4e88
--- /dev/null
+++ b/bundles/org.eclipse.osgi/osgi/src/org/osgi/framework/connect/ConnectFrameworkFactory.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) OSGi Alliance (2019, 2020). All Rights Reserved.
+ *
+ * Licensed 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.osgi.framework.connect;
+
+import java.util.Map;
+
+import org.osgi.annotation.versioning.ProviderType;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.launch.Framework;
+
+/**
+ * A factory for creating {@link Framework} instances.
+ * <p>
+ * If a framework supports {@link ModuleConnector}, then the implementation jar
+ * must contain the following resource:
+ * 
+ * <pre>
+ * /META-INF/services/org.osgi.framework.connect.ConnectFrameworkFactory
+ * </pre>
+ * 
+ * This UTF-8 encoded resource must contain the name of the framework
+ * implementation's ConnectFrameworkFactory implementation class. Space and tab
+ * characters, including blank lines, in the resource must be ignored. The
+ * number sign ({@code '#'} &#92;u0023) and all characters following it on each
+ * line are a comment and must be ignored.
+ * <p>
+ * Launchers can find the name of the ConnectFrameworkFactory implementation
+ * class in the resource and then load and construct a ConnectFrameworkFactory
+ * object for the framework implementation. The ConnectFrameworkFactory
+ * implementation class must have a public, no-argument constructor. Java&#8482;
+ * SE 6 introduced the {@code ServiceLoader} class which can create a
+ * ConnectFrameworkFactory instance from the resource.
+ * 
+ * @ThreadSafe
+ * @author $Id$
+ */
+@ProviderType
+public interface ConnectFrameworkFactory {
+	/**
+	 * Create a new {@link Framework} instance using the specified
+	 * {@link ModuleConnector module connector}.
+	 * 
+	 * @param configuration The framework properties to configure the new
+	 *            framework instance. If framework properties are not provided
+	 *            by the configuration argument, the created framework instance
+	 *            must use some reasonable default configuration appropriate for
+	 *            the current VM. For example, the system packages for the
+	 *            current execution environment should be properly exported. The
+	 *            specified configuration argument may be {@code null}. The
+	 *            created framework instance must copy any information needed
+	 *            from the specified configuration argument since the
+	 *            configuration argument can be changed after the framework
+	 *            instance has been created.
+	 * @param moduleConnector The module connector that the new framework
+	 *            instance will use. The specified module connector argument may
+	 *            be {@code null}.
+	 * @return A new, configured {@link Framework} instance. The framework
+	 *         instance must be in the {@link Bundle#INSTALLED} state.
+	 * @throws SecurityException If the caller does not have
+	 *             {@code AllPermission}, and the Java Runtime Environment
+	 *             supports permissions.
+	 * @see ModuleConnector
+	 */
+	Framework newFramework(Map<String,String> configuration,
+			ModuleConnector moduleConnector);
+}
diff --git a/bundles/org.eclipse.osgi/osgi/src/org/osgi/framework/connect/ConnectModule.java b/bundles/org.eclipse.osgi/osgi/src/org/osgi/framework/connect/ConnectModule.java
new file mode 100644
index 0000000..d81245b
--- /dev/null
+++ b/bundles/org.eclipse.osgi/osgi/src/org/osgi/framework/connect/ConnectModule.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) OSGi Alliance (2019, 2020). All Rights Reserved.
+ *
+ * Licensed 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.osgi.framework.connect;
+
+import java.io.IOException;
+
+import org.osgi.annotation.versioning.ConsumerType;
+import org.osgi.framework.launch.Framework;
+import org.osgi.framework.wiring.BundleRevision;
+
+/**
+ * A {@code ConnectModule} is used by a {@link Framework} instance to access the
+ * content of the connected bundle.
+ * 
+ * @ThreadSafe
+ * @author $Id$
+ */
+@ConsumerType
+public interface ConnectModule {
+	/**
+	 * Returns the current content of this connect module.
+	 * <p>
+	 * The framework must call this method when it needs to access the content
+	 * for the current {@link BundleRevision bundle revision} of this
+	 * {@code ConnectModule}. The framework may defer opening the returned
+	 * {@link ConnectContent} until requests to access the bundle revision
+	 * content are made.
+	 * 
+	 * @return The current {@link ConnectContent} of this {@code ConnectModule}.
+	 * @throws IOException If an error occurred getting the content.
+	 * @see ModuleConnector#connect(String)
+	 */
+	ConnectContent getContent() throws IOException;
+}
diff --git a/bundles/org.eclipse.osgi/osgi/src/org/osgi/framework/connect/FrameworkUtilHelper.java b/bundles/org.eclipse.osgi/osgi/src/org/osgi/framework/connect/FrameworkUtilHelper.java
new file mode 100644
index 0000000..f7b54ab
--- /dev/null
+++ b/bundles/org.eclipse.osgi/osgi/src/org/osgi/framework/connect/FrameworkUtilHelper.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) OSGi Alliance (2019, 2020). All Rights Reserved.
+ *
+ * Licensed 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.osgi.framework.connect;
+
+import java.util.Optional;
+
+import org.osgi.annotation.versioning.ConsumerType;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.FrameworkUtil;
+
+/**
+ * A helper for the {@link FrameworkUtil} class.
+ * <p>
+ * This helper provides alternative implementations for methods on
+ * {@link FrameworkUtil}.
+ */
+@ConsumerType
+public interface FrameworkUtilHelper {
+	/**
+	 * Returns the {@link Bundle} associated with the specified class.
+	 * <p>
+	 * This helper method is called by {@link FrameworkUtil#getBundle(Class)} if
+	 * the standard implementation of {@link FrameworkUtil} is unable to find
+	 * the bundle.
+	 * 
+	 * @param classFromBundle A class associated with a bundle.
+	 * @return An {@code Optional} containing the {@link Bundle} for the
+	 *         specified class, or an empty {@code Optional} if the specified
+	 *         class is not from a bundle.
+	 */
+	default Optional<Bundle> getBundle(Class< ? > classFromBundle) {
+		return Optional.empty();
+	}
+}
diff --git a/bundles/org.eclipse.osgi/osgi/src/org/osgi/framework/connect/ModuleConnector.java b/bundles/org.eclipse.osgi/osgi/src/org/osgi/framework/connect/ModuleConnector.java
new file mode 100644
index 0000000..5ee358a
--- /dev/null
+++ b/bundles/org.eclipse.osgi/osgi/src/org/osgi/framework/connect/ModuleConnector.java
@@ -0,0 +1,105 @@
+/*
+ * Copyright (c) OSGi Alliance (2019, 2020). All Rights Reserved.
+ *
+ * Licensed 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.osgi.framework.connect;
+
+import java.io.File;
+import java.util.Map;
+import java.util.Optional;
+
+import org.osgi.annotation.versioning.ConsumerType;
+import org.osgi.framework.BundleActivator;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.BundleException;
+import org.osgi.framework.Constants;
+import org.osgi.framework.FrameworkListener;
+import org.osgi.framework.launch.Framework;
+
+/**
+ * A {@code ModuleConnector} provides connections to instances of
+ * {@link ConnectModule} that are used by a {@link Framework} instance to
+ * connect installed bundles locations with content provided by the
+ * {@code ModuleConnector}.
+ * <p>
+ * This allows a {@code ModuleConnector} to provide content and classes for a
+ * connected bundle installed in the {@code Framework}. A
+ * {@code ModuleConnector} is provided when
+ * {@link ConnectFrameworkFactory#newFramework(Map, ModuleConnector) creating} a
+ * framework instance. Because a {@code ModuleConnector} instance can
+ * participate in the initialization of the {@code Framework} and the life cycle
+ * of a {@code Framework} instance the {@code ModuleConnector} instance should
+ * only be used with a single {@code Framework} instance at a time.
+ * 
+ * @ThreadSafe
+ * @author $Id$
+ */
+@ConsumerType
+public interface ModuleConnector {
+
+	/**
+	 * Initializes this {@code ModuleConnector} with the
+	 * {@link Constants#FRAMEWORK_STORAGE framework persistent storage} file and
+	 * framework properties configured for a {@link Framework} instance.
+	 * <p>
+	 * This method is called once by a {@link Framework} instance and is called
+	 * before any other methods on this module connector are called.
+	 * 
+	 * @param storage The persistent storage area used by the {@link Framework}
+	 *            or {@code null} if the platform does not have file system
+	 *            support.
+	 * @param configuration An unmodifiable map of framework configuration
+	 *            properties that were used to configure the new framework
+	 *            instance.
+	 */
+	void initialize(File storage, Map<String,String> configuration);
+
+	/**
+	 * Connects a bundle location with a {@link ConnectModule}.
+	 * <p>
+	 * When the result is empty, then the framework must handle reading the
+	 * content of the bundle itself. Otherwise, the returned
+	 * {@link ConnectModule} must be used by the framework to access the content
+	 * of the bundle.
+	 * 
+	 * @param location The bundle location used to install a bundle.
+	 * @return An {@code Optional} containing the {@link ConnectModule} for the
+	 *         specified bundle location, or an empty {@code Optional} if the
+	 *         framework must handle reading the content of the bundle itself.
+	 * @throws BundleException If the location cannot be handled.
+	 */
+	Optional<ConnectModule> connect(String location) throws BundleException;
+
+	/**
+	 * Creates a new activator for this {@code ModuleConnector}.
+	 * <p>
+	 * This method is called by the framework during framework
+	 * {@link Framework#init(FrameworkListener...) initialization}. Returning an
+	 * activator allows this {@code ModuleConnector} to participate in the
+	 * framework life cycle. If an activator is returned:
+	 * <ul>
+	 * <li>The framework will call the activator's
+	 * {@link BundleActivator#start(BundleContext) start} method prior to
+	 * activating any extension bundles.</li>
+	 * <li>The framework will call the activator's
+	 * {@link BundleActivator#stop(BundleContext) stop} method after
+	 * deactivating any extension bundles.</li>
+	 * </ul>
+	 * 
+	 * @return An {@code Optional} containing a new {@link BundleActivator} for
+	 *         this {@code ModuleConnector}, or an empty {@code Optional} if no
+	 *         {@link BundleActivator} is necessary.
+	 */
+	Optional<BundleActivator> newBundleActivator();
+}
diff --git a/bundles/org.eclipse.osgi/osgi/src/org/osgi/framework/connect/package-info.java b/bundles/org.eclipse.osgi/osgi/src/org/osgi/framework/connect/package-info.java
new file mode 100644
index 0000000..b7344ca
--- /dev/null
+++ b/bundles/org.eclipse.osgi/osgi/src/org/osgi/framework/connect/package-info.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) OSGi Alliance (2019, 2020). All Rights Reserved.
+ * 
+ * Licensed 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.
+ */
+
+/**
+ * Framework Connect Package Version 1.0.
+ * <p>
+ * Bundles wishing to use this package must list the package in the
+ * Import-Package header of the bundle's manifest.
+ * <p>
+ * Example import for consumers using the API in this package:
+ * <p>
+ * {@code  Import-Package: org.osgi.framework.connect; version="[1.0,2.0)"}
+ * 
+ * @author $Id$
+ */
+
+@Version("1.0")
+package org.osgi.framework.connect;
+
+import org.osgi.annotation.versioning.Version;
diff --git a/bundles/org.eclipse.osgi/osgi/src/org/osgi/framework/dto/ServiceReferenceDTO.java b/bundles/org.eclipse.osgi/osgi/src/org/osgi/framework/dto/ServiceReferenceDTO.java
index 87265de..8ac26a2 100644
--- a/bundles/org.eclipse.osgi/osgi/src/org/osgi/framework/dto/ServiceReferenceDTO.java
+++ b/bundles/org.eclipse.osgi/osgi/src/org/osgi/framework/dto/ServiceReferenceDTO.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) OSGi Alliance (2012, 2014). All Rights Reserved.
+ * Copyright (c) OSGi Alliance (2012, 2019). All Rights Reserved.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -17,16 +17,17 @@
 package org.osgi.framework.dto;
 
 import java.util.Map;
+
 import org.osgi.dto.DTO;
 import org.osgi.framework.Constants;
 import org.osgi.framework.ServiceReference;
 
 /**
  * Data Transfer Object for a ServiceReference.
- * 
  * <p>
  * {@code ServiceReferenceDTO}s for all registered services can be obtained from
- * a {@link FrameworkDTO}. A started Bundle can be adapted to provide a
+ * a {@link FrameworkDTO}. A {@link ServiceReference} can be adapted to a
+ * {@code ServiceReferenceDTO}. A started Bundle can be adapted to provide a
  * {@code ServiceReferenceDTO[]} of the services registered by the Bundle. A
  * {@code ServiceReferenceDTO} obtained from a framework must convert service
  * property values which are not valid value types for DTOs to type
diff --git a/bundles/org.eclipse.osgi/osgi/src/org/osgi/framework/hooks/weaving/WeavingException.java b/bundles/org.eclipse.osgi/osgi/src/org/osgi/framework/hooks/weaving/WeavingException.java
index 7575fc1..29ebe64 100644
--- a/bundles/org.eclipse.osgi/osgi/src/org/osgi/framework/hooks/weaving/WeavingException.java
+++ b/bundles/org.eclipse.osgi/osgi/src/org/osgi/framework/hooks/weaving/WeavingException.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) OSGi Alliance (2010, 2013). All Rights Reserved.
+ * Copyright (c) OSGi Alliance (2010, 2020). All Rights Reserved.
  * 
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -18,8 +18,7 @@
 
 /**
  * A weaving exception used to indicate that the class load should be failed but
- * the weaving hook must not be blacklisted by the framework.
- * 
+ * the weaving hook must not be deny listed by the framework.
  * <p>
  * This exception conforms to the general purpose exception chaining mechanism.
  * 
diff --git a/bundles/org.eclipse.osgi/osgi/src/org/osgi/framework/hooks/weaving/WeavingHook.java b/bundles/org.eclipse.osgi/osgi/src/org/osgi/framework/hooks/weaving/WeavingHook.java
index 8d99df5..e5b5412 100644
--- a/bundles/org.eclipse.osgi/osgi/src/org/osgi/framework/hooks/weaving/WeavingHook.java
+++ b/bundles/org.eclipse.osgi/osgi/src/org/osgi/framework/hooks/weaving/WeavingHook.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) OSGi Alliance (2010, 2013). All Rights Reserved.
+ * Copyright (c) OSGi Alliance (2010, 2020). All Rights Reserved.
  * 
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -42,24 +42,23 @@
 public interface WeavingHook {
 	/**
 	 * Weaving hook method.
-	 * 
+	 * <p>
 	 * This method can modify the specified woven class object to weave the
 	 * class being defined.
-	 * 
 	 * <p>
 	 * If this method throws any exception, the framework must log the exception
 	 * and fail the class load in progress. This weaving hook service must be
-	 * blacklisted by the framework and must not be called again. The
-	 * blacklisting of this weaving hook service must expire when this weaving
-	 * hook service is unregistered. However, this method can throw a
+	 * deny listed by the framework and must not be called again. The deny
+	 * listing of this weaving hook service must expire when this weaving hook
+	 * service is unregistered. However, this method can throw a
 	 * {@link WeavingException} to deliberately fail the class load in progress
-	 * without being blacklisted by the framework.
+	 * without being deny listed by the framework.
 	 * 
 	 * @param wovenClass The {@link WovenClass} object that represents the data
-	 *        that will be used to define the class.
+	 *            that will be used to define the class.
 	 * @throws WeavingException If this weaving hook wants to deliberately fail
-	 *         the class load in progress without being blacklisted by the
-	 *         framework
+	 *             the class load in progress without being deny listed by the
+	 *             framework
 	 */
 	public void weave(WovenClass wovenClass);
 }
diff --git a/bundles/org.eclipse.osgi/osgi/src/org/osgi/framework/launch/Framework.java b/bundles/org.eclipse.osgi/osgi/src/org/osgi/framework/launch/Framework.java
index 7fa6797..bf960bd 100644
--- a/bundles/org.eclipse.osgi/osgi/src/org/osgi/framework/launch/Framework.java
+++ b/bundles/org.eclipse.osgi/osgi/src/org/osgi/framework/launch/Framework.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) OSGi Alliance (2008, 2018). All Rights Reserved.
+ * Copyright (c) OSGi Alliance (2008, 2020). All Rights Reserved.
  * 
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -19,6 +19,7 @@
 import java.io.InputStream;
 import java.net.URL;
 import java.util.Enumeration;
+
 import org.osgi.annotation.versioning.ProviderType;
 import org.osgi.framework.Bundle;
 import org.osgi.framework.BundleException;
@@ -117,37 +118,33 @@
 	 * A Framework Event is returned to indicate why this Framework has stopped.
 	 * 
 	 * @param timeout Maximum number of milliseconds to wait until this
-	 *        Framework has completely stopped. A value of zero will wait
-	 *        indefinitely.
+	 *            Framework has completely stopped. A value of zero will wait
+	 *            indefinitely.
 	 * @return A Framework Event indicating the reason this method returned. The
 	 *         following {@code FrameworkEvent} types may be returned by this
 	 *         method.
 	 *         <ul>
 	 *         <li>{@link FrameworkEvent#STOPPED STOPPED} - This Framework has
-	 *         been stopped. </li>
-	 * 
+	 *         been stopped.</li>
 	 *         <li>{@link FrameworkEvent#STOPPED_UPDATE STOPPED_UPDATE} - This
 	 *         Framework has been updated which has shutdown and will now
 	 *         restart.</li>
-	 * 
-	 *         <li> {@link FrameworkEvent#STOPPED_BOOTCLASSPATH_MODIFIED
-	 *         STOPPED_BOOTCLASSPATH_MODIFIED} - This Framework has been stopped
-	 *         and a bootclasspath extension bundle has been installed or
-	 *         updated. The VM must be restarted in order for the changed boot
-	 *         class path to take effect. </li>
-	 * 
+	 *         <li>{@link FrameworkEvent#STOPPED_SYSTEM_REFRESHED
+	 *         STOPPED_SYSTEM_REFRESHED} - The Framework has been stopped
+	 *         because of a refresh operation on the system bundle. A new class
+	 *         loader must be used to restart the Framework.</li>
 	 *         <li>{@link FrameworkEvent#ERROR ERROR} - The Framework
 	 *         encountered an error while shutting down or an error has occurred
-	 *         which forced the framework to shutdown. </li>
-	 * 
-	 *         <li> {@link FrameworkEvent#WAIT_TIMEDOUT WAIT_TIMEDOUT} - This
+	 *         which forced the framework to shutdown.</li>
+	 *         <li>{@link FrameworkEvent#WAIT_TIMEDOUT WAIT_TIMEDOUT} - This
 	 *         method has timed out and returned before this Framework has
 	 *         stopped.</li>
 	 *         </ul>
 	 * @throws InterruptedException If another thread interrupted the current
-	 *         thread before or while the current thread was waiting for this
-	 *         Framework to completely stop. The <i>interrupted status</i> of
-	 *         the current thread is cleared when this exception is thrown.
+	 *             thread before or while the current thread was waiting for
+	 *             this Framework to completely stop. The <i>interrupted
+	 *             status</i> of the current thread is cleared when this
+	 *             exception is thrown.
 	 * @throws IllegalArgumentException If the value of timeout is negative.
 	 */
 	FrameworkEvent waitForStop(long timeout) throws InterruptedException;
diff --git a/bundles/org.eclipse.osgi/osgi/src/org/osgi/framework/launch/FrameworkFactory.java b/bundles/org.eclipse.osgi/osgi/src/org/osgi/framework/launch/FrameworkFactory.java
index c1647bc..ecb53ee 100644
--- a/bundles/org.eclipse.osgi/osgi/src/org/osgi/framework/launch/FrameworkFactory.java
+++ b/bundles/org.eclipse.osgi/osgi/src/org/osgi/framework/launch/FrameworkFactory.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) OSGi Alliance (2009, 2013). All Rights Reserved.
+ * Copyright (c) OSGi Alliance (2009, 2019). All Rights Reserved.
  * 
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -17,6 +17,7 @@
 package org.osgi.framework.launch;
 
 import java.util.Map;
+
 import org.osgi.annotation.versioning.ProviderType;
 import org.osgi.framework.Bundle;
 
diff --git a/bundles/org.eclipse.osgi/osgi/src/org/osgi/framework/launch/package-info.java b/bundles/org.eclipse.osgi/osgi/src/org/osgi/framework/launch/package-info.java
index db5e926..70417d3 100644
--- a/bundles/org.eclipse.osgi/osgi/src/org/osgi/framework/launch/package-info.java
+++ b/bundles/org.eclipse.osgi/osgi/src/org/osgi/framework/launch/package-info.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) OSGi Alliance (2010, 2014). All Rights Reserved.
+ * Copyright (c) OSGi Alliance (2010, 2019). All Rights Reserved.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
diff --git a/bundles/org.eclipse.osgi/osgi/src/org/osgi/framework/namespace/HostNamespace.java b/bundles/org.eclipse.osgi/osgi/src/org/osgi/framework/namespace/HostNamespace.java
index 9f789ca..79484b4 100644
--- a/bundles/org.eclipse.osgi/osgi/src/org/osgi/framework/namespace/HostNamespace.java
+++ b/bundles/org.eclipse.osgi/osgi/src/org/osgi/framework/namespace/HostNamespace.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) OSGi Alliance (2012, 2014). All Rights Reserved.
+ * Copyright (c) OSGi Alliance (2012, 2020). All Rights Reserved.
  * 
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -54,13 +54,13 @@
  * </ul>
  * 
  * <p>
- * A non-fragment resource with the with the
- * {@link IdentityNamespace#TYPE_BUNDLE osgi.bundle} type
- * {@link IdentityNamespace#CAPABILITY_TYPE_ATTRIBUTE identity} provides zero or
- * one<sup>&#8224;</sup> host capabilities. A fragment resource with the
- * {@link IdentityNamespace#TYPE_FRAGMENT osgi.fragment} type
- * {@link IdentityNamespace#CAPABILITY_TYPE_ATTRIBUTE identity} must not declare
- * a host capability and must declare exactly one host requirement.
+ * A non-fragment resource with the {@link IdentityNamespace#TYPE_BUNDLE
+ * osgi.bundle} type {@link IdentityNamespace#CAPABILITY_TYPE_ATTRIBUTE
+ * identity} provides zero or one<sup>&#8224;</sup> host capabilities. A
+ * fragment resource with the {@link IdentityNamespace#TYPE_FRAGMENT
+ * osgi.fragment} type {@link IdentityNamespace#CAPABILITY_TYPE_ATTRIBUTE
+ * identity} must not declare a host capability and must declare exactly one
+ * host requirement.
  * <p>
  * &#8224; A resource with no bundle symbolic name must not provide a host
  * capability.
@@ -135,7 +135,6 @@
 	 * fragment. The default value is {@link #EXTENSION_FRAMEWORK framework}.
 	 * 
 	 * @see #EXTENSION_FRAMEWORK
-	 * @see #EXTENSION_BOOTCLASSPATH
 	 */
 	public final static String	REQUIREMENT_EXTENSION_DIRECTIVE				= "extension";
 
@@ -153,6 +152,7 @@
 	 * loaded by the boot class loader.
 	 * 
 	 * @see #REQUIREMENT_EXTENSION_DIRECTIVE
+	 * @deprecated As of 1.2.
 	 */
 	public final static String	EXTENSION_BOOTCLASSPATH						= "bootclasspath";
 
diff --git a/bundles/org.eclipse.osgi/osgi/src/org/osgi/framework/namespace/IdentityNamespace.java b/bundles/org.eclipse.osgi/osgi/src/org/osgi/framework/namespace/IdentityNamespace.java
index 7bc7a11..d2357fa 100644
--- a/bundles/org.eclipse.osgi/osgi/src/org/osgi/framework/namespace/IdentityNamespace.java
+++ b/bundles/org.eclipse.osgi/osgi/src/org/osgi/framework/namespace/IdentityNamespace.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) OSGi Alliance (2012, 2013). All Rights Reserved.
+ * Copyright (c) OSGi Alliance (2012, 2020). All Rights Reserved.
  * 
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -105,6 +105,16 @@
 	public static final String	TYPE_UNKNOWN						= "unknown";
 
 	/**
+	 * The attribute value that contains tags for the resource. A tag is used to
+	 * identify an aspect of the resource that is not otherwise expressed by the
+	 * capabilities of the resource. The value of this attribute must be of type
+	 * {@code List<String>}.
+	 * 
+	 * @since 1.2
+	 */
+	public static final String	CAPABILITY_TAGS_ATTRIBUTE			= "tags";
+
+	/**
 	 * The capability attribute that contains a human readable copyright notice
 	 * for the resource. See the {@code Bundle-Copyright} manifest header.
 	 */
diff --git a/bundles/org.eclipse.osgi/osgi/src/org/osgi/framework/namespace/NativeNamespace.java b/bundles/org.eclipse.osgi/osgi/src/org/osgi/framework/namespace/NativeNamespace.java
index fc91420..f252fb2 100644
--- a/bundles/org.eclipse.osgi/osgi/src/org/osgi/framework/namespace/NativeNamespace.java
+++ b/bundles/org.eclipse.osgi/osgi/src/org/osgi/framework/namespace/NativeNamespace.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) OSGi Alliance (2012, 2016). All Rights Reserved.
+ * Copyright (c) OSGi Alliance (2012, 2020). All Rights Reserved.
  * 
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -44,7 +44,7 @@
 	 * The capability attribute contains alias values of the
 	 * {@link Constants#FRAMEWORK_OS_NAME org.osgi.framework.os.name} launching
 	 * property value according to the
-	 * <a href="https://www.osgi.org/developer/specifications/reference/">OSGi
+	 * <a href="https://docs.osgi.org/reference/">OSGi
 	 * Specification References</a>. The value of this attribute must be of type
 	 * {@code List<String>}.
 	 */
@@ -62,7 +62,7 @@
 	 * The capability attribute contains alias values of the
 	 * {@link Constants#FRAMEWORK_PROCESSOR org.osgi.framework.processor}
 	 * launching property value according to the
-	 * <a href="https://www.osgi.org/developer/specifications/reference/">OSGi
+	 * <a href="https://docs.osgi.org/reference/">OSGi
 	 * Specification References</a>. The value of this attribute must be of type
 	 * {@code List<String>}.
 	 */
diff --git a/bundles/org.eclipse.osgi/osgi/src/org/osgi/framework/namespace/package-info.java b/bundles/org.eclipse.osgi/osgi/src/org/osgi/framework/namespace/package-info.java
index e89f34a..43f3804 100644
--- a/bundles/org.eclipse.osgi/osgi/src/org/osgi/framework/namespace/package-info.java
+++ b/bundles/org.eclipse.osgi/osgi/src/org/osgi/framework/namespace/package-info.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) OSGi Alliance (2012, 2013). All Rights Reserved.
+ * Copyright (c) OSGi Alliance (2012, 2019). All Rights Reserved.
  * 
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -15,7 +15,7 @@
  */
 
 /**
- * Namespace Package Version 1.1.
+ * Namespace Package Version 1.2.
  * 
  * <p>
  * Bundles should not need to import this package at runtime since all
@@ -25,7 +25,7 @@
  * @author $Id$
  */
 
-@Version("1.1")
+@Version("1.2")
 package org.osgi.framework.namespace;
 
 import org.osgi.annotation.versioning.Version;
diff --git a/bundles/org.eclipse.osgi/osgi/src/org/osgi/framework/package-info.java b/bundles/org.eclipse.osgi/osgi/src/org/osgi/framework/package-info.java
index 818d4ae..5b79565 100644
--- a/bundles/org.eclipse.osgi/osgi/src/org/osgi/framework/package-info.java
+++ b/bundles/org.eclipse.osgi/osgi/src/org/osgi/framework/package-info.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) OSGi Alliance (2010, 2016). All Rights Reserved.
+ * Copyright (c) OSGi Alliance (2010, 2019). All Rights Reserved.
  * 
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -15,19 +15,19 @@
  */
 
 /**
- * Framework Package Version 1.9.
+ * Framework Package Version 1.10.
  * <p>
  * Bundles wishing to use this package must list the package in the
  * Import-Package header of the bundle's manifest.
  * <p>
  * Example import for consumers using the API in this package:
  * <p>
- * {@code  Import-Package: org.osgi.framework; version="[1.9,2.0)"}
+ * {@code  Import-Package: org.osgi.framework; version="[1.10,2.0)"}
  * 
  * @author $Id$
  */
 
-@Version("1.9")
+@Version("1.10")
 package org.osgi.framework;
 
 import org.osgi.annotation.versioning.Version;
diff --git a/bundles/org.eclipse.osgi/osgi/src/org/osgi/service/condition/Condition.java b/bundles/org.eclipse.osgi/osgi/src/org/osgi/service/condition/Condition.java
new file mode 100644
index 0000000..9736e5e
--- /dev/null
+++ b/bundles/org.eclipse.osgi/osgi/src/org/osgi/service/condition/Condition.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) OSGi Alliance (2020). All Rights Reserved.
+ * 
+ * Licensed 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.osgi.service.condition;
+
+import org.osgi.annotation.versioning.ConsumerType;
+
+/**
+ * Condition Service interface.
+ * <p>
+ * In dynamic systems, such as OSGi, one of the more challenging problems can be
+ * to define when a system or part of it is ready to do work. The answer can
+ * change depending on the individual perspective. The developer of a web server
+ * might say, the system is ready when the server starts listening on port 80.
+ * An application developer however would define the system as ready when the
+ * database connection is up and all servlets are registered. Taking the
+ * application developers view, the web server should start listening on port 80
+ * when the application is ready and not beforehand.
+ * <p>
+ * The {@code Condition} service interface is a marker interface designed to
+ * address this issue. Its role is to provide a dependency that can be tracked.
+ * It acts as a defined signal to other services.
+ * <p>
+ * A {@code Condition} service must be registered with the
+ * {@link Condition#CONDITION_ID} service property.
+ * 
+ * @ThreadSafe
+ * @author $Id$
+ */
+@ConsumerType
+public interface Condition {
+
+	/**
+	 * Service property identifying a condition's unique identifier.
+	 * <p>
+	 * Since a {@code Condition} service can potentially describe more then one
+	 * condition, the type of this service property is {@code String+}.
+	 */
+	String		CONDITION_ID		= "osgi.condition.id";
+
+	/**
+	 * The unique identifier for the default True condition.
+	 * <p>
+	 * The default True condition is registered by the framework during
+	 * framework initialization and therefore can always be relied upon.
+	 * 
+	 * @see Condition#CONDITION_ID
+	 */
+	String		CONDITION_ID_TRUE	= "true";
+
+	/**
+	 * A condition instance that can be used to register {@code Condition}
+	 * services.
+	 * <p>
+	 * This can be helpful to avoid a bundle having to implement this interface
+	 * to register a {@code Condition} service
+	 */
+	Condition	INSTANCE			= new ConditionImpl();
+}
+
+final class ConditionImpl implements Condition {
+	ConditionImpl() {
+	}
+}
diff --git a/bundles/org.eclipse.osgi/osgi/src/org/osgi/service/condition/package-info.java b/bundles/org.eclipse.osgi/osgi/src/org/osgi/service/condition/package-info.java
new file mode 100644
index 0000000..52df94e
--- /dev/null
+++ b/bundles/org.eclipse.osgi/osgi/src/org/osgi/service/condition/package-info.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) OSGi Alliance (2020). All Rights Reserved.
+ * 
+ * Licensed 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.
+ */
+
+/**
+ * Condition Service Package Version 1.0.
+ * <p>
+ * Bundles wishing to use this package must list the package in the
+ * Import-Package header of the bundle's manifest. This package has two types of
+ * users: the consumers that use the API in this package and the providers that
+ * implement the API in this package.
+ * <p>
+ * Example import for consumers using the API in this package:
+ * <p>
+ * {@code  Import-Package: org.osgi.service.condition; version="[1.0,2.0)"}
+ * <p>
+ * Example import for providers implementing the API in this package:
+ * <p>
+ * {@code  Import-Package: org.osgi.service.condition; version="[1.0,1.1)"}
+ * 
+ * @author $Id$
+ */
+
+@Version("1.0")
+package org.osgi.service.condition;
+
+import org.osgi.annotation.versioning.Version;
diff --git a/bundles/org.eclipse.osgi/osgi/src/org/osgi/service/log/LogService.java b/bundles/org.eclipse.osgi/osgi/src/org/osgi/service/log/LogService.java
index 55d1069..b5b08d7 100644
--- a/bundles/org.eclipse.osgi/osgi/src/org/osgi/service/log/LogService.java
+++ b/bundles/org.eclipse.osgi/osgi/src/org/osgi/service/log/LogService.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) OSGi Alliance (2000, 2016). All Rights Reserved.
+ * Copyright (c) OSGi Alliance (2000, 2020). All Rights Reserved.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -75,9 +75,11 @@
 	 * The {@code ServiceReference} field and the {@code Throwable} field of the
 	 * {@code LogEntry} object will be set to {@code null}.
 	 * <p>
-	 * This method will log to the {@link Logger} named {@code "LogService"} for
-	 * the bundle. The specified level is mapped to a {@link LogLevel} as
-	 * follows:
+	 * This method will log to the bundle's {@link Logger} named
+	 * {@code "LogService.<bsn>"} where {@code <bsn>} is the Bundle Symbolic
+	 * Name of the bundle.
+	 * <p>
+	 * The specified level is mapped to a {@link LogLevel} as follows:
 	 * <ul>
 	 * <li>{@link #LOG_ERROR} - {@link LogLevel#ERROR}</li>
 	 * <li>{@link #LOG_WARNING} - {@link LogLevel#WARN}</li>
@@ -105,9 +107,11 @@
 	 * The {@code ServiceReference} field of the {@code LogEntry} object will be
 	 * set to {@code null}.
 	 * <p>
-	 * This method will log to the {@link Logger} named {@code "LogService"} for
-	 * the bundle. The specified level is mapped to a {@link LogLevel} as
-	 * follows:
+	 * This method will log to the bundle's {@link Logger} named
+	 * {@code "LogService.<bsn>"} where {@code <bsn>} is the Bundle Symbolic
+	 * Name of the bundle.
+	 * <p>
+	 * The specified level is mapped to a {@link LogLevel} as follows:
 	 * <ul>
 	 * <li>{@link #LOG_ERROR} - {@link LogLevel#ERROR}</li>
 	 * <li>{@link #LOG_WARNING} - {@link LogLevel#WARN}</li>
@@ -138,9 +142,11 @@
 	 * The {@code Throwable} field of the {@code LogEntry} will be set to
 	 * {@code null}.
 	 * <p>
-	 * This method will log to the {@link Logger} named {@code "LogService"} for
-	 * the bundle. The specified level is mapped to a {@link LogLevel} as
-	 * follows:
+	 * This method will log to the bundle's {@link Logger} named
+	 * {@code "LogService.<bsn>"} where {@code <bsn>} is the Bundle Symbolic
+	 * Name of the bundle.
+	 * <p>
+	 * The specified level is mapped to a {@link LogLevel} as follows:
 	 * <ul>
 	 * <li>{@link #LOG_ERROR} - {@link LogLevel#ERROR}</li>
 	 * <li>{@link #LOG_WARNING} - {@link LogLevel#WARN}</li>
@@ -168,9 +174,11 @@
 	 * Logs a message with an exception associated and a
 	 * {@code ServiceReference} object.
 	 * <p>
-	 * This method will log to the {@link Logger} named {@code "LogService"} for
-	 * the bundle. The specified level is mapped to a {@link LogLevel} as
-	 * follows:
+	 * This method will log to the bundle's {@link Logger} named
+	 * {@code "LogService.<bsn>"} where {@code <bsn>} is the Bundle Symbolic
+	 * Name of the bundle.
+	 * <p>
+	 * The specified level is mapped to a {@link LogLevel} as follows:
 	 * <ul>
 	 * <li>{@link #LOG_ERROR} - {@link LogLevel#ERROR}</li>
 	 * <li>{@link #LOG_WARNING} - {@link LogLevel#WARN}</li>
diff --git a/bundles/org.eclipse.osgi/osgi/src/org/osgi/service/log/package-info.java b/bundles/org.eclipse.osgi/osgi/src/org/osgi/service/log/package-info.java
index 81c287a..b053188 100644
--- a/bundles/org.eclipse.osgi/osgi/src/org/osgi/service/log/package-info.java
+++ b/bundles/org.eclipse.osgi/osgi/src/org/osgi/service/log/package-info.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) OSGi Alliance (2010, 2016). All Rights Reserved.
+ * Copyright (c) OSGi Alliance (2010, 2020). All Rights Reserved.
  * 
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -15,7 +15,7 @@
  */
 
 /**
- * Log Service Package Version 1.4.
+ * Log Service Package Version 1.5.
  * <p>
  * Bundles wishing to use this package must list the package in the
  * Import-Package header of the bundle's manifest. This package has two types of
@@ -24,15 +24,15 @@
  * <p>
  * Example import for consumers using the API in this package:
  * <p>
- * {@code  Import-Package: org.osgi.service.log; version="[1.4,2.0)"}
+ * {@code  Import-Package: org.osgi.service.log; version="[1.5,2.0)"}
  * <p>
  * Example import for providers implementing the API in this package:
  * <p>
- * {@code  Import-Package: org.osgi.service.log; version="[1.4,1.5)"}
+ * {@code  Import-Package: org.osgi.service.log; version="[1.5,1.6)"}
  * 
  * @author $Id$
  */
-@Version("1.4")
+@Version("1.5")
 package org.osgi.service.log;
 
 import org.osgi.annotation.versioning.Version;
diff --git a/bundles/org.eclipse.osgi/osgi/src/org/osgi/service/resolver/Resolver.java b/bundles/org.eclipse.osgi/osgi/src/org/osgi/service/resolver/Resolver.java
index 86bff00..e4011e1 100644
--- a/bundles/org.eclipse.osgi/osgi/src/org/osgi/service/resolver/Resolver.java
+++ b/bundles/org.eclipse.osgi/osgi/src/org/osgi/service/resolver/Resolver.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) OSGi Alliance (2006, 2017). All Rights Reserved.
+ * Copyright (c) OSGi Alliance (2006, 2019). All Rights Reserved.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -14,10 +14,6 @@
  * limitations under the License.
  */
 
-// This document is an experimental draft to enable interoperability
-// between bundle repositories. There is currently no commitment to
-// turn this draft into an official specification.
-
 package org.osgi.service.resolver;
 
 import java.util.List;
diff --git a/bundles/org.eclipse.osgi/pom.xml b/bundles/org.eclipse.osgi/pom.xml
index 74fdea8..8fcf699 100644
--- a/bundles/org.eclipse.osgi/pom.xml
+++ b/bundles/org.eclipse.osgi/pom.xml
@@ -19,7 +19,7 @@
   </parent>
   <groupId>org.eclipse.osgi</groupId>
   <artifactId>org.eclipse.osgi</artifactId>
-  <version>3.15.300-SNAPSHOT</version>
+  <version>3.16.0-SNAPSHOT</version>
   <packaging>eclipse-plugin</packaging>
 
   <build>
diff --git a/bundles/org.eclipse.osgi/supplement/.classpath b/bundles/org.eclipse.osgi/supplement/.classpath
index 098194c..eca7bdb 100644
--- a/bundles/org.eclipse.osgi/supplement/.classpath
+++ b/bundles/org.eclipse.osgi/supplement/.classpath
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <classpath>
-	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.7"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"/>
 	<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
 	<classpathentry kind="src" path="src"/>
 	<classpathentry kind="output" path="bin"/>
diff --git a/bundles/org.eclipse.osgi/supplement/.settings/org.eclipse.jdt.core.prefs b/bundles/org.eclipse.osgi/supplement/.settings/org.eclipse.jdt.core.prefs
index e88e78e..ccae001 100644
--- a/bundles/org.eclipse.osgi/supplement/.settings/org.eclipse.jdt.core.prefs
+++ b/bundles/org.eclipse.osgi/supplement/.settings/org.eclipse.jdt.core.prefs
@@ -7,9 +7,9 @@
 org.eclipse.jdt.core.classpath.exclusionPatterns=enabled
 org.eclipse.jdt.core.classpath.multipleOutputLocations=enabled
 org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
-org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
 org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
-org.eclipse.jdt.core.compiler.compliance=1.7
+org.eclipse.jdt.core.compiler.compliance=1.8
 org.eclipse.jdt.core.compiler.debug.lineNumber=generate
 org.eclipse.jdt.core.compiler.debug.localVariable=generate
 org.eclipse.jdt.core.compiler.debug.sourceFile=generate
@@ -70,23 +70,27 @@
 org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=enabled
 org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=error
 org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning
-org.eclipse.jdt.core.compiler.source=1.7
+org.eclipse.jdt.core.compiler.source=1.8
 org.eclipse.jdt.core.formatter.align_type_members_on_columns=false
+org.eclipse.jdt.core.formatter.alignment_for_additive_operator=16
 org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16
 org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=16
 org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call=16
 org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation=16
 org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression=16
 org.eclipse.jdt.core.formatter.alignment_for_assignment=0
-org.eclipse.jdt.core.formatter.alignment_for_binary_expression=16
+org.eclipse.jdt.core.formatter.alignment_for_bitwise_operator=16
 org.eclipse.jdt.core.formatter.alignment_for_compact_if=16
 org.eclipse.jdt.core.formatter.alignment_for_conditional_expression=80
 org.eclipse.jdt.core.formatter.alignment_for_enum_constants=0
 org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer=16
+org.eclipse.jdt.core.formatter.alignment_for_logical_operator=16
 org.eclipse.jdt.core.formatter.alignment_for_multiple_fields=16
+org.eclipse.jdt.core.formatter.alignment_for_multiplicative_operator=16
 org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration=16
 org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration=16
 org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation=16
+org.eclipse.jdt.core.formatter.alignment_for_string_concatenation=16
 org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration=16
 org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration=16
 org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration=16
@@ -156,11 +160,12 @@
 org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration=insert
 org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body=insert
 org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_after_additive_operator=insert
 org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter=insert
 org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator=insert
 org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation=do not insert
 org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration=do not insert
-org.eclipse.jdt.core.formatter.insert_space_after_binary_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_after_bitwise_operator=insert
 org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments=insert
 org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters=insert
 org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block=insert
@@ -190,6 +195,8 @@
 org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments=insert
 org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters=insert
 org.eclipse.jdt.core.formatter.insert_space_after_ellipsis=insert
+org.eclipse.jdt.core.formatter.insert_space_after_logical_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_after_multiplicative_operator=insert
 org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference=do not insert
 org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments=do not insert
 org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters=do not insert
@@ -213,12 +220,16 @@
 org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator=do not insert
 org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional=insert
 org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_relational_operator=insert
 org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_after_shift_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_after_string_concatenation=insert
 org.eclipse.jdt.core.formatter.insert_space_after_unary_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_additive_operator=insert
 org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter=insert
 org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator=insert
 org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration=insert
-org.eclipse.jdt.core.formatter.insert_space_before_binary_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_before_bitwise_operator=insert
 org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference=do not insert
 org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments=do not insert
 org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters=do not insert
@@ -264,6 +275,8 @@
 org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments=do not insert
 org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters=do not insert
 org.eclipse.jdt.core.formatter.insert_space_before_ellipsis=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_logical_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_before_multiplicative_operator=insert
 org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference=do not insert
 org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments=do not insert
 org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters=do not insert
@@ -299,8 +312,11 @@
 org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator=do not insert
 org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional=insert
 org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_relational_operator=insert
 org.eclipse.jdt.core.formatter.insert_space_before_semicolon=do not insert
 org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_shift_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_before_string_concatenation=insert
 org.eclipse.jdt.core.formatter.insert_space_before_unary_operator=do not insert
 org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference=do not insert
 org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer=do not insert
@@ -323,6 +339,10 @@
 org.eclipse.jdt.core.formatter.tabulation.char=tab
 org.eclipse.jdt.core.formatter.tabulation.size=4
 org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations=false
-org.eclipse.jdt.core.formatter.wrap_before_binary_operator=true
+org.eclipse.jdt.core.formatter.wrap_before_additive_operator=true
+org.eclipse.jdt.core.formatter.wrap_before_bitwise_operator=true
+org.eclipse.jdt.core.formatter.wrap_before_logical_operator=true
+org.eclipse.jdt.core.formatter.wrap_before_multiplicative_operator=true
+org.eclipse.jdt.core.formatter.wrap_before_string_concatenation=true
 org.eclipse.jdt.core.incompatibleJDKLevel=ignore
 org.eclipse.jdt.core.incompleteClasspath=error
diff --git a/bundles/org.eclipse.osgi/supplement/META-INF/MANIFEST.MF b/bundles/org.eclipse.osgi/supplement/META-INF/MANIFEST.MF
index caa323e..de14a4b 100644
--- a/bundles/org.eclipse.osgi/supplement/META-INF/MANIFEST.MF
+++ b/bundles/org.eclipse.osgi/supplement/META-INF/MANIFEST.MF
@@ -2,7 +2,7 @@
 Bundle-ManifestVersion: 2
 Bundle-Name: %pluginName
 Bundle-SymbolicName: org.eclipse.equinox.supplement
-Bundle-Version: 1.9.300.qualifier
+Bundle-Version: 1.10.0.qualifier
 Bundle-Vendor: %providerName
 Bundle-Localization: plugin
 Export-Package: org.eclipse.equinox.log;version="1.1",
@@ -18,7 +18,7 @@
  org.eclipse.osgi.service.urlconversion;version="1.0",
  org.eclipse.osgi.storagemanager;version="1.0",
  org.eclipse.osgi.util;version="1.1"
-Bundle-RequiredExecutionEnvironment: JavaSE-1.7
+Bundle-RequiredExecutionEnvironment: JavaSE-1.8
 Import-Package: org.osgi.framework,
  org.osgi.framework.hooks.resolver,
  org.osgi.resource,
diff --git a/bundles/org.eclipse.osgi/supplement/pom.xml b/bundles/org.eclipse.osgi/supplement/pom.xml
index 6a0b34f..8901111 100644
--- a/bundles/org.eclipse.osgi/supplement/pom.xml
+++ b/bundles/org.eclipse.osgi/supplement/pom.xml
@@ -21,7 +21,7 @@
 
   <groupId>org.eclipse.equinox</groupId>
   <artifactId>org.eclipse.equinox.supplement</artifactId>
-  <version>1.9.300-SNAPSHOT</version>
+  <version>1.10.0-SNAPSHOT</version>
   <packaging>eclipse-plugin</packaging>
 
 </project>