You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@felix.apache.org by du...@apache.org on 2018/05/09 11:53:12 UTC

svn commit: r1831246 [1/2] - in /felix/trunk/systemready: ./ docs/ src/ src/main/ src/main/java/ src/main/java/org/ src/main/java/org/apache/ src/main/java/org/apache/felix/ src/main/java/org/apache/felix/systemready/ src/main/java/org/apache/felix/sys...

Author: dulvac
Date: Wed May  9 11:53:11 2018
New Revision: 1831246

URL: http://svn.apache.org/viewvc?rev=1831246&view=rev
Log:
FELIX-5848 [contribution] Contribute System Ready to felix

Added:
    felix/trunk/systemready/LICENSE
    felix/trunk/systemready/README.md
    felix/trunk/systemready/bnd.bnd
    felix/trunk/systemready/docs/
    felix/trunk/systemready/docs/README.md
    felix/trunk/systemready/pom.xml
    felix/trunk/systemready/src/
    felix/trunk/systemready/src/main/
    felix/trunk/systemready/src/main/java/
    felix/trunk/systemready/src/main/java/org/
    felix/trunk/systemready/src/main/java/org/apache/
    felix/trunk/systemready/src/main/java/org/apache/felix/
    felix/trunk/systemready/src/main/java/org/apache/felix/systemready/
    felix/trunk/systemready/src/main/java/org/apache/felix/systemready/CheckStatus.java
    felix/trunk/systemready/src/main/java/org/apache/felix/systemready/Status.java
    felix/trunk/systemready/src/main/java/org/apache/felix/systemready/SystemReady.java
    felix/trunk/systemready/src/main/java/org/apache/felix/systemready/SystemReadyCheck.java
    felix/trunk/systemready/src/main/java/org/apache/felix/systemready/SystemReadyMonitor.java
    felix/trunk/systemready/src/main/java/org/apache/felix/systemready/SystemStatus.java
    felix/trunk/systemready/src/main/java/org/apache/felix/systemready/impl/
    felix/trunk/systemready/src/main/java/org/apache/felix/systemready/impl/ComponentsCheck.java
    felix/trunk/systemready/src/main/java/org/apache/felix/systemready/impl/FrameworkStartCheck.java
    felix/trunk/systemready/src/main/java/org/apache/felix/systemready/impl/ServicesCheck.java
    felix/trunk/systemready/src/main/java/org/apache/felix/systemready/impl/SystemReadyMonitorImpl.java
    felix/trunk/systemready/src/main/java/org/apache/felix/systemready/impl/Tracker.java
    felix/trunk/systemready/src/main/java/org/apache/felix/systemready/impl/servlet/
    felix/trunk/systemready/src/main/java/org/apache/felix/systemready/impl/servlet/StatusWriterJson.java
    felix/trunk/systemready/src/main/java/org/apache/felix/systemready/impl/servlet/SystemReadyServlet.java
    felix/trunk/systemready/src/main/java/org/apache/felix/systemready/package-info.java
    felix/trunk/systemready/src/main/java/org/apache/felix/systemready/rootcause/
    felix/trunk/systemready/src/main/java/org/apache/felix/systemready/rootcause/DSComp.java
    felix/trunk/systemready/src/main/java/org/apache/felix/systemready/rootcause/DSRef.java
    felix/trunk/systemready/src/main/java/org/apache/felix/systemready/rootcause/DSRootCause.java
    felix/trunk/systemready/src/main/java/org/apache/felix/systemready/rootcause/RootCauseCommand.java
    felix/trunk/systemready/src/main/java/org/apache/felix/systemready/rootcause/RootCausePrinter.java
    felix/trunk/systemready/src/test/
    felix/trunk/systemready/src/test/java/
    felix/trunk/systemready/src/test/java/org/
    felix/trunk/systemready/src/test/java/org/apache/
    felix/trunk/systemready/src/test/java/org/apache/felix/
    felix/trunk/systemready/src/test/java/org/apache/felix/systemready/
    felix/trunk/systemready/src/test/java/org/apache/felix/systemready/StateTest.java
    felix/trunk/systemready/src/test/java/org/apache/felix/systemready/osgi/
    felix/trunk/systemready/src/test/java/org/apache/felix/systemready/osgi/ComponentsCheckTest.java
    felix/trunk/systemready/src/test/java/org/apache/felix/systemready/osgi/DSRootCauseTest.java
    felix/trunk/systemready/src/test/java/org/apache/felix/systemready/osgi/FrameworkStartTest.java
    felix/trunk/systemready/src/test/java/org/apache/felix/systemready/osgi/ServicesCheckTest.java
    felix/trunk/systemready/src/test/java/org/apache/felix/systemready/osgi/ServletTest.java
    felix/trunk/systemready/src/test/java/org/apache/felix/systemready/osgi/SystemReadyMonitorTest.java
    felix/trunk/systemready/src/test/java/org/apache/felix/systemready/osgi/examples/
    felix/trunk/systemready/src/test/java/org/apache/felix/systemready/osgi/examples/CompWithCyclicRef.java
    felix/trunk/systemready/src/test/java/org/apache/felix/systemready/osgi/examples/CompWithMissingConfig.java
    felix/trunk/systemready/src/test/java/org/apache/felix/systemready/osgi/examples/CompWithMissingRef.java
    felix/trunk/systemready/src/test/java/org/apache/felix/systemready/osgi/examples/CompWithMissingRef2.java
    felix/trunk/systemready/src/test/java/org/apache/felix/systemready/osgi/examples/CompWithoutService.java
    felix/trunk/systemready/src/test/java/org/apache/felix/systemready/osgi/examples/CompWithoutService2.java
    felix/trunk/systemready/src/test/java/org/apache/felix/systemready/osgi/examples/TestSystemReadyCheck.java
    felix/trunk/systemready/src/test/java/org/apache/felix/systemready/osgi/util/
    felix/trunk/systemready/src/test/java/org/apache/felix/systemready/osgi/util/BaseTest.java
    felix/trunk/systemready/src/test/java/org/apache/felix/systemready/osgi/util/BndDSOptions.java
    felix/trunk/systemready/src/test/resources/
    felix/trunk/systemready/src/test/resources/exam.properties
    felix/trunk/systemready/src/test/resources/logback.xml
Modified:
    felix/trunk/systemready/   (props changed)

Propchange: felix/trunk/systemready/
------------------------------------------------------------------------------
--- svn:ignore (added)
+++ svn:ignore Wed May  9 11:53:11 2018
@@ -0,0 +1,3 @@
+.idea
+*.iml
+target

Added: felix/trunk/systemready/LICENSE
URL: http://svn.apache.org/viewvc/felix/trunk/systemready/LICENSE?rev=1831246&view=auto
==============================================================================
--- felix/trunk/systemready/LICENSE (added)
+++ felix/trunk/systemready/LICENSE Wed May  9 11:53:11 2018
@@ -0,0 +1,201 @@
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   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.

Added: felix/trunk/systemready/README.md
URL: http://svn.apache.org/viewvc/felix/trunk/systemready/README.md?rev=1831246&view=auto
==============================================================================
--- felix/trunk/systemready/README.md (added)
+++ felix/trunk/systemready/README.md Wed May  9 11:53:11 2018
@@ -0,0 +1,40 @@
+# OSGi system ready check framework
+
+In OSGi there is always the question of when a system is fully operational after startup. This project provides a framework to configure and create so called system checks and signal the ready of an OSGi based system. In addition to the framework, we also provide some generic checks that give a solid basis, like a check waiting for the startup of bundles to finish, as well as certain OSGi services being present. Additionally, root cause analysis in case of error states is conveniently presented. Custom checks can be created to provide in-depth checks for your own functionality.
+
+## Usage
+
+See [reference documentation](docs/README.md).
+
+## Error reporting and root cause analysis
+
+When a system fails to become ready after a certain amount of time, the follow up question is : "What is wrong?". So the framework also provides a way for each system check to report back information about errors.
+
+One typical error is that a DS component does not come up because some mandatory dependency is not present. This dependency can be a configuration or maybe a service reference. In many cases, a trivial error like a missing configuration for a low level component can cause a lot of other components to fail to register. The root cause analysis allows traversing the trees of components and to narrow the reason for the system not being ready to a minimal number of possible causes for the failure state.
+
+## Use cases
+
+Typical use cases for the system ready check ordered by the phase of the development cycle.
+
+### Development
+* Coarse check of a pax exam based setup before letting the actual junit tests work on the system
+* Determining the root cause of a pax exam based setup not starting
+
+### QA
+* Starting system tests as soon as a system is ready for the tests to proceed
+* Determining the root cause for an OSGi based system not starting up
+
+### Deployment
+* Signaling when a system is ready after an upgrade so that it can receive traffic in the case of blue / green deployments
+
+### Production
+* Periodic _Ready health checks_ for system and signaling this state to monitoring systems
+* Container automation and driving _autopilot container_ deployments.
+
+## Added value when using the system ready framework
+
+* Increased deployment resilience as deployments are checked before being exposed
+* Faster deployments / upgrades by replacing fixed, error-prone waits with ready based waits
+* Lower bug tracking efforts in tests as root causes are easier to find
+* Configurability of _when_ a certain deployment is considered ready (e.g. after content sync with an external service)
+

Added: felix/trunk/systemready/bnd.bnd
URL: http://svn.apache.org/viewvc/felix/trunk/systemready/bnd.bnd?rev=1831246&view=auto
==============================================================================
--- felix/trunk/systemready/bnd.bnd (added)
+++ felix/trunk/systemready/bnd.bnd Wed May  9 11:53:11 2018
@@ -0,0 +1,6 @@
+Export-Package: \
+	org.apache.felix.systemready,\
+	org.apache.felix.systemready.rootcause
+Import-Package: \
+	javax.servlet*;resolution:=optional,\
+	*
\ No newline at end of file

Added: felix/trunk/systemready/docs/README.md
URL: http://svn.apache.org/viewvc/felix/trunk/systemready/docs/README.md?rev=1831246&view=auto
==============================================================================
--- felix/trunk/systemready/docs/README.md (added)
+++ felix/trunk/systemready/docs/README.md Wed May  9 11:53:11 2018
@@ -0,0 +1,104 @@
+# Reference Documentation
+
+This project provides a framework to configure and create so called _system ready checks_ and report the _ready_ of an application on top of an OSGi system.
+
+## Requirements:
+
+* Configuration Admin Service
+* Service Component Runtime
+
+See below for a hands on example in Apache Karaf.
+
+## Services Check
+
+Ready check that is shipped in the core bundle and checks for the presence of listed services by interface name or filter.
+
+Mandatory configuration with pid: `ServicesCheck`
+
+* `services.list=<List of service interfaces or filters to check>`
+
+The check reports GREEN when all services are currently present and YELLOW if at least one service is missing.
+
+In the details the check reports all missing services. If a service is backed by a DS component then automatically a root cause analysis is executed. If such a service is missing then unresolved references are shown in a tree with detailed information about each component. At the leafs of the tree the root causes can be found.
+
+## Component Check
+
+Ready check that is shipped in the core bundle and checks for the presence of listed DS components by name.
+
+Mandatory configuration with pid: `ComponentsCheck`
+
+* `components.list=<List of component names to check>`
+
+The check reports GREEN when all components are satisfied. It also provides root cause analysis.
+The main difference to th Service Check is that the checked component does not need to offer an OSGi service.
+
+## Providing additional custom checks
+
+Implement the org.apache.felix.systemready.core.SystemReadyCheck interface and register
+your instance as a service. The SystemReadyMonitor will pick up your service automatically.
+
+Your service should avoid references to other services that come up late, as a late appearing check could
+make the aggregated state oscilate during startup. One option to avoid this is to refer to a late service using an optional dependency and return a YELLOW state until it is up.
+
+## System Ready Monitor service
+
+The service org.apache.felix.systemready.core.SystemReadyMonitor tracks all SystemReadyCheck services and periodically checks them. It creates an aggregated status and detailed report of the status of the system.
+
+This report can be queried by calling the service. Additionally the system ready servlet can provide this status over http.
+
+For an example see the [test case](../src/test/java/org/apache/felix/systemready/core/osgi/SystemReadyMonitorTest.java).
+
+## Ready servlet
+
+The Ready servlet provides the aggregated state of the system over http in json format.
+It is registered on the path `/system/console/ready`.
+
+This is an example of a ready system with just the services check.
+```
+{
+  "systemStatus": "GREEN", 
+  "checks": [
+    { "check": "Services Check", "status": "GREEN", "details": "" }, 
+  ]
+}
+```
+
+## Root cause command
+
+For quickly checking for a root cause of a problem with a declarative services component there is also a handy command.
+
+`rootcause <ds-compoment-name>`
+
+It prints the top level status of a DS component as well as the tree of DS unsatisfied components it depends on together with their status.
+
+This is a sample output from the DSRootCause tests. It shows the cause of a component that depends on some other components. The root cause of CompWithMissingRef2 not being satisfied is that CompWithMissingConfig is missing its mandatory config.
+
+```
+Component CompWithMissingRef2 unsatisfied references
+  ref other interface CompWithMissingRef
+    Component CompWithMissingRef unsatisfied references
+      ref other interface CompWithMissingConfig
+        Component CompWithMissingConfig missing config on pid [CompWithMissingConfig]
+```
+
+## Example of using the system ready service framework in Apache Karaf
+
+Download, install and run Apache Karaf 4.1.x. Inside the karaf shell execute this:
+
+```
+feature:install scr http-whiteboard
+config:property-set --pid ServicesCheck services.list org.osgi.service.log.LogService
+config:property-set --pid SystemReadyServlet osgi.http.whiteboard.context.select "(osgi.http.whiteboard.context.name=default)"
+install -s mvn:org.apache.felix/org.apache.felix.systemready/0.1.0-SNAPSHOT
+```
+
+Point your browser to http://localhost:8181/system/console/ready .
+
+Check the status of a DS component:
+
+```
+rootcause SystemReadyMonitor
+ Component SystemReadyMonitor statisfied
+```
+
+Try this with some of your own components.

Added: felix/trunk/systemready/pom.xml
URL: http://svn.apache.org/viewvc/felix/trunk/systemready/pom.xml?rev=1831246&view=auto
==============================================================================
--- felix/trunk/systemready/pom.xml (added)
+++ felix/trunk/systemready/pom.xml Wed May  9 11:53:11 2018
@@ -0,0 +1,187 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!--
+        Licensed to the Apache Software Foundation (ASF) under one or more contributor license
+        agreements. See the NOTICE file distributed with this work for additional information
+        regarding copyright ownership. The ASF licenses this file to you under the Apache License,
+        Version 2.0 (the "License"); you may not use this file except in compliance with the
+        License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
+        Unless required by applicable law or agreed to in writing, software distributed under the
+        License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
+        either express or implied. See the License for the specific language governing permissions
+        and limitations under the License.
+    -->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>org.apache</groupId>
+        <artifactId>apache</artifactId>
+        <version>19</version>
+        <relativePath/>
+    </parent>
+
+    <groupId>org.apache.felix</groupId>
+    <artifactId>org.apache.felix.systemready</artifactId>
+    <version>0.1.0-SNAPSHOT</version>
+    <name>Apache Felix - System Ready</name>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-compiler-plugin</artifactId>
+                <configuration>
+                    <source>8</source>
+                    <target>8</target>
+                </configuration>
+            </plugin>
+            <plugin>
+                <groupId>biz.aQute.bnd</groupId>
+                <artifactId>bnd-maven-plugin</artifactId>
+                <version>3.5.0</version>
+                <executions>
+                    <execution>
+                        <goals>
+                            <goal>bnd-process</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-jar-plugin</artifactId>
+                <configuration>
+                    <archive>
+                        <manifestFile>${project.build.outputDirectory}/META-INF/MANIFEST.MF</manifestFile>
+                    </archive>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+
+
+    <dependencies>
+        <dependency>
+            <groupId>javax.servlet</groupId>
+            <artifactId>servlet-api</artifactId>
+            <version>2.5</version>
+            <scope>provided</scope>
+            <optional>true</optional>
+        </dependency>
+        <dependency>
+            <groupId>org.osgi</groupId>
+            <artifactId>osgi.cmpn</artifactId>
+            <version>6.0.0</version>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.osgi</groupId>
+            <artifactId>org.osgi.core</artifactId>
+            <version>6.0.0</version>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.osgi</groupId>
+            <artifactId>osgi.annotation</artifactId>
+            <version>6.0.1</version>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>slf4j-api</artifactId>
+            <version>1.7.6</version>
+            <scope>provided</scope>
+        </dependency>
+        
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+            <version>4.12</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.mockito</groupId>
+            <artifactId>mockito-all</artifactId>
+            <version>1.9.5</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.servicemix.bundles</groupId>
+            <artifactId>org.apache.servicemix.bundles.hamcrest</artifactId>
+            <version>1.3_1</version>
+            <scope>test</scope>
+        </dependency>
+        
+        <dependency>
+            <groupId>org.ops4j.pax.exam</groupId>
+            <artifactId>pax-exam-container-native</artifactId>
+            <version>${exam.version}</version>
+            <scope>test</scope>
+        </dependency>
+ 
+        <dependency>
+            <groupId>org.ops4j.pax.exam</groupId>
+            <artifactId>pax-exam-junit4</artifactId>
+            <version>${exam.version}</version>
+            <scope>test</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>org.ops4j.pax.exam</groupId>
+            <artifactId>pax-exam-cm</artifactId>
+            <version>${exam.version}</version>
+            <scope>test</scope>
+        </dependency>
+ 
+        <dependency>
+            <groupId>org.ops4j.pax.exam</groupId>
+            <artifactId>pax-exam-link-mvn</artifactId>
+            <version>${exam.version}</version>
+            <scope>test</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.felix</groupId>
+            <artifactId>org.apache.felix.framework</artifactId>
+            <version>5.6.10</version>
+            <scope>test</scope>
+        </dependency>
+ 
+        <dependency>
+            <groupId>ch.qos.logback</groupId>
+            <artifactId>logback-core</artifactId>
+            <version>1.0.13</version>
+            <scope>test</scope>
+        </dependency>
+ 
+        <dependency>
+            <groupId>ch.qos.logback</groupId>
+            <artifactId>logback-classic</artifactId>
+            <version>1.0.13</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>javax.inject</groupId>
+            <artifactId>javax.inject</artifactId>
+            <version>1</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.ops4j.pax.tinybundles</groupId>
+            <artifactId>tinybundles</artifactId>
+            <version>3.0.0</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.awaitility</groupId>
+            <artifactId>awaitility</artifactId>
+            <version>3.1.0</version>
+            <scope>test</scope>
+        </dependency>
+    </dependencies>
+
+    <properties>
+        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+        <exam.version>4.11.0</exam.version>
+    </properties>
+</project>

Added: felix/trunk/systemready/src/main/java/org/apache/felix/systemready/CheckStatus.java
URL: http://svn.apache.org/viewvc/felix/trunk/systemready/src/main/java/org/apache/felix/systemready/CheckStatus.java?rev=1831246&view=auto
==============================================================================
--- felix/trunk/systemready/src/main/java/org/apache/felix/systemready/CheckStatus.java (added)
+++ felix/trunk/systemready/src/main/java/org/apache/felix/systemready/CheckStatus.java Wed May  9 11:53:11 2018
@@ -0,0 +1,42 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.systemready;
+
+/**
+ * Wrapper for storing the name of a check and its {{Status}}
+ */
+public class CheckStatus {
+    private String checkName;
+    private Status status;
+
+    public CheckStatus(String checkName, Status status) {
+        this.checkName = checkName;
+        this.status = status;
+    }
+
+    public String getCheckName() {
+        return checkName;
+    }
+
+    public Status getStatus() {
+        return status;
+    }
+
+
+}

Added: felix/trunk/systemready/src/main/java/org/apache/felix/systemready/Status.java
URL: http://svn.apache.org/viewvc/felix/trunk/systemready/src/main/java/org/apache/felix/systemready/Status.java?rev=1831246&view=auto
==============================================================================
--- felix/trunk/systemready/src/main/java/org/apache/felix/systemready/Status.java (added)
+++ felix/trunk/systemready/src/main/java/org/apache/felix/systemready/Status.java Wed May  9 11:53:11 2018
@@ -0,0 +1,66 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.systemready;
+
+import static java.util.stream.Collectors.minBy;
+
+import java.util.stream.Stream;
+
+public class Status {
+    // Be aware that the order of the enum declarations matters for the Comparator
+    public enum State { RED, YELLOW, GREEN;
+        /**
+         * returns {{GREEN}} for {{true}} and {{YELLOW}} for {{false}}
+         */
+        public static State fromBoolean(boolean ready) {
+            return (ready) ? State.GREEN : State.YELLOW;
+        }
+        
+        public static State worstOf(Stream<State> states) {
+            return states.collect(minBy(State::compareTo)).orElse(State.GREEN);
+        }
+    }
+    
+    private State state;
+
+    private String details;
+    
+    public Status(State state, String details) {
+        this.state = state;
+        this.details = details;
+    }
+    
+    public State getState() {
+        return state;
+    }
+    
+    public String getDetails() {
+        return details;
+    }
+
+    @Override
+    public String toString() {
+        return "CheckStatus{" +
+                "state=" + state +
+                ", details='" + details + '\'' +
+                '}';
+    }
+    
+    
+}

Added: felix/trunk/systemready/src/main/java/org/apache/felix/systemready/SystemReady.java
URL: http://svn.apache.org/viewvc/felix/trunk/systemready/src/main/java/org/apache/felix/systemready/SystemReady.java?rev=1831246&view=auto
==============================================================================
--- felix/trunk/systemready/src/main/java/org/apache/felix/systemready/SystemReady.java (added)
+++ felix/trunk/systemready/src/main/java/org/apache/felix/systemready/SystemReady.java Wed May  9 11:53:11 2018
@@ -0,0 +1,26 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.systemready;
+
+/**
+ * Marker service that is registered when all system checks succeed.
+ */
+public interface SystemReady {
+
+}

Added: felix/trunk/systemready/src/main/java/org/apache/felix/systemready/SystemReadyCheck.java
URL: http://svn.apache.org/viewvc/felix/trunk/systemready/src/main/java/org/apache/felix/systemready/SystemReadyCheck.java?rev=1831246&view=auto
==============================================================================
--- felix/trunk/systemready/src/main/java/org/apache/felix/systemready/SystemReadyCheck.java (added)
+++ felix/trunk/systemready/src/main/java/org/apache/felix/systemready/SystemReadyCheck.java Wed May  9 11:53:11 2018
@@ -0,0 +1,44 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.systemready;
+
+/**
+ * Ready check services provide custom logic for signaling
+ * that particular criteria are met for when an instance is considered "ready".
+ *
+ * Examples: An asynchronous integration with another instance or a third-party service
+ *
+ * {@see SystemReadyMonitor}
+ *
+ */
+public interface SystemReadyCheck {
+
+    /**
+     *
+     * @return the name of this check. E.g. component name
+     */
+    String getName();
+
+    /**
+     *
+     * @return the state of the system
+     */
+    Status getStatus();
+
+}

Added: felix/trunk/systemready/src/main/java/org/apache/felix/systemready/SystemReadyMonitor.java
URL: http://svn.apache.org/viewvc/felix/trunk/systemready/src/main/java/org/apache/felix/systemready/SystemReadyMonitor.java?rev=1831246&view=auto
==============================================================================
--- felix/trunk/systemready/src/main/java/org/apache/felix/systemready/SystemReadyMonitor.java (added)
+++ felix/trunk/systemready/src/main/java/org/apache/felix/systemready/SystemReadyMonitor.java Wed May  9 11:53:11 2018
@@ -0,0 +1,35 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.systemready;
+
+/**
+ * Checks that all registered ready and builds an aggregated state of the system.
+ * The aggregated state is the worst state of all checks.
+ */
+public interface SystemReadyMonitor  {
+    /**
+     * @return true if aggregated state is GREEN
+     */
+    boolean isReady();
+    
+    /**
+     * @return detailed system state
+     */
+    SystemStatus getStatus();
+}

Added: felix/trunk/systemready/src/main/java/org/apache/felix/systemready/SystemStatus.java
URL: http://svn.apache.org/viewvc/felix/trunk/systemready/src/main/java/org/apache/felix/systemready/SystemStatus.java?rev=1831246&view=auto
==============================================================================
--- felix/trunk/systemready/src/main/java/org/apache/felix/systemready/SystemStatus.java (added)
+++ felix/trunk/systemready/src/main/java/org/apache/felix/systemready/SystemStatus.java Wed May  9 11:53:11 2018
@@ -0,0 +1,40 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.systemready;
+
+import java.util.Collection;
+
+public class SystemStatus {
+    Status.State state;
+    Collection<CheckStatus> checkStates;
+    
+    public SystemStatus(Status.State state, Collection<CheckStatus> checkStates) {
+        super();
+        this.state = state;
+        this.checkStates = checkStates;
+    }
+
+    public Status.State getState() {
+        return state;
+    }
+    
+    public Collection<CheckStatus> getCheckStates() {
+        return checkStates;
+    }
+}

Added: felix/trunk/systemready/src/main/java/org/apache/felix/systemready/impl/ComponentsCheck.java
URL: http://svn.apache.org/viewvc/felix/trunk/systemready/src/main/java/org/apache/felix/systemready/impl/ComponentsCheck.java?rev=1831246&view=auto
==============================================================================
--- felix/trunk/systemready/src/main/java/org/apache/felix/systemready/impl/ComponentsCheck.java (added)
+++ felix/trunk/systemready/src/main/java/org/apache/felix/systemready/impl/ComponentsCheck.java Wed May  9 11:53:11 2018
@@ -0,0 +1,108 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.systemready.impl;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.stream.Collectors;
+
+import org.apache.felix.systemready.Status;
+import org.apache.felix.systemready.SystemReadyCheck;
+import org.apache.felix.systemready.rootcause.DSComp;
+import org.apache.felix.systemready.rootcause.DSRootCause;
+import org.apache.felix.systemready.rootcause.RootCausePrinter;
+import org.osgi.framework.BundleContext;
+import org.osgi.service.component.annotations.Activate;
+import org.osgi.service.component.annotations.Component;
+import org.osgi.service.component.annotations.ConfigurationPolicy;
+import org.osgi.service.component.annotations.Deactivate;
+import org.osgi.service.component.annotations.Reference;
+import org.osgi.service.component.runtime.ServiceComponentRuntime;
+import org.osgi.service.metatype.annotations.AttributeDefinition;
+import org.osgi.service.metatype.annotations.Designate;
+import org.osgi.service.metatype.annotations.ObjectClassDefinition;
+
+@Component(
+        name = "ComponentsCheck",
+        configurationPolicy = ConfigurationPolicy.REQUIRE
+)
+@Designate(ocd=ComponentsCheck.Config.class)
+public class ComponentsCheck implements SystemReadyCheck {
+
+    @ObjectClassDefinition(
+            name="DS Components System Ready Check",
+            description="System ready check that checks a list of DS components"
+                + "and provides root cause analysis in case of errors"
+    )
+    public @interface Config {
+
+        @AttributeDefinition(name = "Components list", description = "The components that need to come up before this check reports GREEN")
+        String[] components_list();
+
+    }
+
+    private List<String> componentsList;
+    
+    DSRootCause analyzer;
+
+    @Reference
+    ServiceComponentRuntime scr;
+
+    @Activate
+    public void activate(final BundleContext ctx, final Config config) throws InterruptedException {
+        this.analyzer = new DSRootCause(scr);
+        componentsList = Arrays.asList(config.components_list());
+    }
+
+    @Deactivate
+    protected void deactivate() {
+    }
+
+
+    @Override
+    public String getName() {
+        return "Components Check";
+    }
+
+    @Override
+    public Status getStatus() {
+        StringBuilder details = new StringBuilder();
+        List<DSComp> watchedComps = scr.getComponentDescriptionDTOs().stream()
+            .filter(desc -> componentsList.contains(desc.name))
+            .map(analyzer::getRootCause)
+            .collect(Collectors.toList());
+        if (watchedComps.size() < componentsList.size()) {
+            throw new IllegalStateException("Not all named components could be found");
+        };
+        watchedComps.stream().forEach(dsComp -> addDetails(dsComp, details));
+        final Status.State state = Status.State.worstOf(watchedComps.stream().map(this::status));
+        return new Status(state, details.toString());
+    }
+    
+    private Status.State status(DSComp component) {
+        boolean missingConfig = component.config == null && "require".equals(component.desc.configurationPolicy);
+        return (missingConfig || !component.unsatisfied.isEmpty()) ? Status.State.YELLOW : Status.State.GREEN;
+    }
+
+    private void addDetails(DSComp component, StringBuilder details) {
+        RootCausePrinter printer = new RootCausePrinter(st -> details.append(st + "\n"));
+        printer.print(component);
+    }
+
+}

Added: felix/trunk/systemready/src/main/java/org/apache/felix/systemready/impl/FrameworkStartCheck.java
URL: http://svn.apache.org/viewvc/felix/trunk/systemready/src/main/java/org/apache/felix/systemready/impl/FrameworkStartCheck.java?rev=1831246&view=auto
==============================================================================
--- felix/trunk/systemready/src/main/java/org/apache/felix/systemready/impl/FrameworkStartCheck.java (added)
+++ felix/trunk/systemready/src/main/java/org/apache/felix/systemready/impl/FrameworkStartCheck.java Wed May  9 11:53:11 2018
@@ -0,0 +1,100 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.systemready.impl;
+
+import org.apache.felix.systemready.Status;
+import org.apache.felix.systemready.SystemReadyCheck;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.FrameworkEvent;
+import org.osgi.service.component.annotations.Activate;
+import org.osgi.service.component.annotations.Component;
+import org.osgi.service.component.annotations.ConfigurationPolicy;
+import org.osgi.service.component.annotations.Deactivate;
+import org.osgi.service.metatype.annotations.AttributeDefinition;
+import org.osgi.service.metatype.annotations.Designate;
+import org.osgi.service.metatype.annotations.ObjectClassDefinition;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+@Component(
+        name = "FrameworkStartCheck",
+        configurationPolicy = ConfigurationPolicy.OPTIONAL
+)
+@Designate(ocd=FrameworkStartCheck.Config.class)
+public class FrameworkStartCheck implements SystemReadyCheck {
+
+    public static final String FRAMEWORK_STARTED = "Framework started";
+    public static final String FRAMEWORK_START_CHECK_NAME = "Framework Start Check";
+
+    @ObjectClassDefinition(
+            name="OSGi Installer System Ready Check",
+            description="System ready that waits for the framework started OSGi event"
+    )
+    public @interface Config {
+
+        @AttributeDefinition(name = "Timeout (seconds)", description = "Number of seconds after which this is considered a failure")
+        long timeout() default 1000;
+
+    }
+
+    private final Logger log = LoggerFactory.getLogger(getClass());
+    private BundleContext bundleContext;
+
+    private int count = 0;
+    private Status state;
+
+    @Activate
+    protected void activate(final BundleContext ctx, final Config config) throws InterruptedException {
+        this.bundleContext = ctx;
+        this.bundleContext.addFrameworkListener(this::frameworkEvent);
+
+        if (bundleContext.getBundle(0).getState() == Bundle.ACTIVE) {
+            // The system bundle was already started when I joined
+            this.state = new Status(Status.State.GREEN, FRAMEWORK_STARTED);
+        } else {
+            this.state = new Status(Status.State.YELLOW, "No OSGi Framework events received so far");
+        }
+        log.info("Activated");
+    }
+
+    @Deactivate
+    protected void deactivate() throws InterruptedException {
+        this.bundleContext = null;
+    }
+
+    @Override
+    public String getName() {
+        return FRAMEWORK_START_CHECK_NAME;
+    }
+
+    @Override
+    public Status getStatus() {
+        return this.state;
+    }
+
+    public void frameworkEvent(FrameworkEvent event) {
+        if (event.getType() == FrameworkEvent.STARTLEVEL_CHANGED) {
+            this.count ++;
+            this.state = new Status(Status.State.YELLOW, "Received " + count + " startlevel changes so far");
+        } else if (event.getType() == FrameworkEvent.STARTED) {
+            this.state = new Status(Status.State.GREEN, FRAMEWORK_STARTED);
+        } // TODO: RED on timeout?
+    }
+}

Added: felix/trunk/systemready/src/main/java/org/apache/felix/systemready/impl/ServicesCheck.java
URL: http://svn.apache.org/viewvc/felix/trunk/systemready/src/main/java/org/apache/felix/systemready/impl/ServicesCheck.java?rev=1831246&view=auto
==============================================================================
--- felix/trunk/systemready/src/main/java/org/apache/felix/systemready/impl/ServicesCheck.java (added)
+++ felix/trunk/systemready/src/main/java/org/apache/felix/systemready/impl/ServicesCheck.java Wed May  9 11:53:11 2018
@@ -0,0 +1,123 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.systemready.impl;
+
+import static java.util.stream.Collectors.toList;
+
+import java.util.*;
+
+import org.apache.felix.systemready.SystemReadyCheck;
+import org.apache.felix.systemready.rootcause.DSComp;
+import org.apache.felix.systemready.Status;
+import org.apache.felix.systemready.Status.State;
+import org.apache.felix.systemready.rootcause.DSRootCause;
+import org.apache.felix.systemready.rootcause.RootCausePrinter;
+import org.osgi.framework.BundleContext;
+import org.osgi.service.component.annotations.Activate;
+import org.osgi.service.component.annotations.Component;
+import org.osgi.service.component.annotations.ConfigurationPolicy;
+import org.osgi.service.component.annotations.Deactivate;
+import org.osgi.service.component.annotations.Reference;
+import org.osgi.service.component.runtime.ServiceComponentRuntime;
+import org.osgi.service.metatype.annotations.AttributeDefinition;
+import org.osgi.service.metatype.annotations.Designate;
+import org.osgi.service.metatype.annotations.ObjectClassDefinition;
+
+@Component(
+        name = "ServicesCheck",
+        configurationPolicy = ConfigurationPolicy.REQUIRE
+)
+@Designate(ocd=ServicesCheck.Config.class)
+public class ServicesCheck implements SystemReadyCheck {
+
+    @ObjectClassDefinition(
+            name="Services Registered System Ready Check",
+            description="System ready check that waits for a list of services to be registered"
+    )
+    public @interface Config {
+
+        @AttributeDefinition(name = "Services list", description = "The services that need to be registered for the check to pass")
+        String[] services_list();
+
+    }
+
+    private List<String> servicesList;
+
+    private Map<String, Tracker> trackers;
+    
+    DSRootCause analyzer;
+
+    @Reference
+    private ServiceComponentRuntime scr;
+
+    @Activate
+    public void activate(final BundleContext ctx, final Config config) throws InterruptedException {
+        analyzer = new DSRootCause(scr);
+        trackers = new HashMap<>();
+        servicesList = Arrays.asList(config.services_list());
+        for (String serviceName : servicesList) {
+            Tracker tracker = new Tracker(ctx, serviceName);
+            trackers.put(serviceName, tracker); 
+        }
+    }
+
+    @Deactivate
+    protected void deactivate() {
+        trackers.values().stream().forEach(Tracker::close);
+        trackers.clear();
+    }
+
+
+    @Override
+    public String getName() {
+        return "Services Check";
+    }
+
+    @Override
+    public Status getStatus() {
+        boolean allPresent = trackers.values().stream().allMatch(Tracker::present);
+        // TODO: RED on timeouts
+        final Status.State state = State.fromBoolean(allPresent);
+        return new Status(state, getDetails()); // TODO: out of sync? do we care?
+    }
+
+    private String getDetails() {
+        List<String> missing = getMissing();
+        StringBuilder missingSt = new StringBuilder();
+        RootCausePrinter printer = new RootCausePrinter(st -> missingSt.append(st + "\n"));
+        for (String iface : missing) {
+            Optional<DSComp> rootCause = analyzer.getRootCause(iface);
+            if (rootCause.isPresent()) {
+                printer.print(rootCause.get());
+            } else {
+                missingSt.append("Missing service without matching DS component: " + iface);
+            }
+        }
+        return missingSt.toString();
+    }
+
+    private List<String> getMissing() {
+        List<String> missing = trackers.entrySet().stream()
+                .filter(entry -> !entry.getValue().present())
+                .map(entry -> entry.getKey())
+                .collect(toList());
+        return missing;
+    }
+
+}

Added: felix/trunk/systemready/src/main/java/org/apache/felix/systemready/impl/SystemReadyMonitorImpl.java
URL: http://svn.apache.org/viewvc/felix/trunk/systemready/src/main/java/org/apache/felix/systemready/impl/SystemReadyMonitorImpl.java?rev=1831246&view=auto
==============================================================================
--- felix/trunk/systemready/src/main/java/org/apache/felix/systemready/impl/SystemReadyMonitorImpl.java (added)
+++ felix/trunk/systemready/src/main/java/org/apache/felix/systemready/impl/SystemReadyMonitorImpl.java Wed May  9 11:53:11 2018
@@ -0,0 +1,154 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.systemready.impl;
+
+import java.util.*;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicReference;
+import java.util.stream.Collectors;
+
+import org.apache.felix.systemready.CheckStatus;
+import org.apache.felix.systemready.Status;
+import org.apache.felix.systemready.SystemReadyCheck;
+import org.apache.felix.systemready.SystemReady;
+import org.apache.felix.systemready.SystemReadyMonitor;
+import org.apache.felix.systemready.SystemStatus;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceRegistration;
+import org.osgi.service.component.annotations.Activate;
+import org.osgi.service.component.annotations.Component;
+import org.osgi.service.component.annotations.Deactivate;
+import org.osgi.service.component.annotations.Reference;
+import org.osgi.service.component.annotations.ReferencePolicy;
+import org.osgi.service.component.annotations.ReferencePolicyOption;
+import org.osgi.service.metatype.annotations.AttributeDefinition;
+import org.osgi.service.metatype.annotations.Designate;
+import org.osgi.service.metatype.annotations.ObjectClassDefinition;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+@Component(
+        name = "SystemReadyMonitor"
+)
+@Designate(ocd = SystemReadyMonitorImpl.Config.class)
+public class SystemReadyMonitorImpl implements SystemReadyMonitor {
+
+    @ObjectClassDefinition(
+            name = "System Ready Monitor",
+            description = "System ready monitor for System Ready Checks"
+    )
+    public @interface Config {
+
+        @AttributeDefinition(name = "Poll interval",
+                description = "Number of milliseconds between subsequents updates of all the checks")
+        long poll_interval() default 5000;
+
+    }
+
+    private final Logger log = LoggerFactory.getLogger(getClass());
+
+    @Reference(policyOption = ReferencePolicyOption.GREEDY, policy = ReferencePolicy.DYNAMIC)
+    private volatile List<SystemReadyCheck> checks;
+
+    private BundleContext context;
+
+    private ServiceRegistration<SystemReady> sreg;
+
+    private ScheduledExecutorService executor;
+    
+    private AtomicReference<SystemStatus> systemState;
+
+    private static final CheckStatus frameworkStartingStatus = new CheckStatus("implicit check",
+            new Status(Status.State.YELLOW, "Framework is starting"));
+
+
+    @Activate
+    public void activate(BundleContext context, final Config config) {
+        this.context = context;
+        this.systemState = new AtomicReference<>(new SystemStatus(Status.State.YELLOW, Collections.emptyList()));
+        this.executor = Executors.newSingleThreadScheduledExecutor();
+        this.executor.scheduleAtFixedRate(this::check, 0, config.poll_interval(), TimeUnit.MILLISECONDS);
+        log.info("Activated");
+    }
+
+    @Deactivate
+    public void deactivate() {
+        executor.shutdown();
+    }
+
+    @Override
+    /**
+     * Returns whether the system is ready or not
+     */
+    public boolean isReady() {
+        return systemState.get().getState() == Status.State.GREEN;
+    }
+
+    @Override
+    /**
+     * Returns a map of the statuses of all the checks
+     */
+    public SystemStatus getStatus() {
+        return systemState.get();
+    }
+
+    private void check() {
+        Status.State prevState = systemState.get().getState();
+        List<CheckStatus> statuses = (isFrameworkStartingAndCheckMissing()) ? Arrays.asList(frameworkStartingStatus) : evaluateAllChecks();
+        Status.State currState = Status.State.worstOf(statuses.stream().map(status -> status.getStatus().getState()));
+        this.systemState.set(new SystemStatus(currState, statuses));
+        if (currState != prevState) {
+            manageMarkerService(currState);
+        }
+    }
+
+    private boolean isFrameworkStartingAndCheckMissing() {
+        return (checks.stream().noneMatch(c -> c.getClass().equals(FrameworkStartCheck.class)))
+                && (context.getBundle(0).getState() != Bundle.ACTIVE);
+    }
+
+    private List<CheckStatus> evaluateAllChecks() {
+        return checks.stream()
+                .map(SystemReadyMonitorImpl::getStatus)
+                .sorted(Comparator.comparing(CheckStatus::getCheckName))
+                .collect(Collectors.toList());
+    }
+    
+    private void manageMarkerService(Status.State currState) {
+        if (currState == Status.State.GREEN) {
+            SystemReady readyService = new SystemReady() {
+            };
+            sreg = context.registerService(SystemReady.class, readyService, null);
+        } else {
+            sreg.unregister();
+        }
+    }
+
+    private static final CheckStatus getStatus(SystemReadyCheck c) {
+        try {
+            return new CheckStatus(c.getName(), c.getStatus());
+        } catch (Throwable e) {
+            return new CheckStatus(c.getClass().getName(), new Status(Status.State.RED, e.getMessage()));
+        }
+    }
+
+}

Added: felix/trunk/systemready/src/main/java/org/apache/felix/systemready/impl/Tracker.java
URL: http://svn.apache.org/viewvc/felix/trunk/systemready/src/main/java/org/apache/felix/systemready/impl/Tracker.java?rev=1831246&view=auto
==============================================================================
--- felix/trunk/systemready/src/main/java/org/apache/felix/systemready/impl/Tracker.java (added)
+++ felix/trunk/systemready/src/main/java/org/apache/felix/systemready/impl/Tracker.java Wed May  9 11:53:11 2018
@@ -0,0 +1,53 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.systemready.impl;
+
+import java.io.Closeable;
+
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.Filter;
+import org.osgi.framework.FrameworkUtil;
+import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.util.tracker.ServiceTracker;
+
+class Tracker implements Closeable {
+    private ServiceTracker<?,?> stracker;
+
+    public Tracker(BundleContext context, String nameOrFilter) {
+        String filterSt = nameOrFilter.startsWith("(") ? nameOrFilter : String.format("(objectClass=%s)", nameOrFilter);
+        Filter filter;
+        try {
+            filter = FrameworkUtil.createFilter(filterSt);
+        } catch (InvalidSyntaxException e) {
+            throw new IllegalArgumentException("Error creating filter for " + nameOrFilter);
+        }
+        this.stracker = new ServiceTracker<>(context, filter, null);
+        this.stracker.open();
+    }
+    
+    public boolean present() {
+        return this.stracker.getTrackingCount() > 0;
+    }
+
+    @Override
+    public void close() {
+        stracker.close();
+    }
+    
+}

Added: felix/trunk/systemready/src/main/java/org/apache/felix/systemready/impl/servlet/StatusWriterJson.java
URL: http://svn.apache.org/viewvc/felix/trunk/systemready/src/main/java/org/apache/felix/systemready/impl/servlet/StatusWriterJson.java?rev=1831246&view=auto
==============================================================================
--- felix/trunk/systemready/src/main/java/org/apache/felix/systemready/impl/servlet/StatusWriterJson.java (added)
+++ felix/trunk/systemready/src/main/java/org/apache/felix/systemready/impl/servlet/StatusWriterJson.java Wed May  9 11:53:11 2018
@@ -0,0 +1,55 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.systemready.impl.servlet;
+
+import java.io.PrintWriter;
+import java.util.stream.Collectors;
+
+import org.apache.felix.systemready.CheckStatus;
+import org.apache.felix.systemready.SystemStatus;
+
+public class StatusWriterJson {
+
+    private PrintWriter writer;
+
+    public StatusWriterJson(PrintWriter writer) {
+        this.writer = writer;
+    }
+    
+    public void write(SystemStatus systemState) {
+        writer.println("{");
+        writer.println(String.format("  \"systemStatus\": \"%s\", ", systemState.getState().name()));
+        writer.println("  \"checks\": [");
+        String states = systemState.getCheckStates().stream()
+                .map(this:: getStatus)
+                .collect(Collectors.joining(",\n"));
+        writer.println(states);
+        writer.println("  ]");
+        writer.println("}");
+    }
+
+    private String getStatus(CheckStatus status) {
+        return String.format(
+                "    { \"check\": \"%s\", \"status\": \"%s\", \"details\": \"%s\" }", 
+                status.getCheckName(),
+                status.getStatus().getState().name(), 
+                status.getStatus().getDetails());
+    }
+
+}

Added: felix/trunk/systemready/src/main/java/org/apache/felix/systemready/impl/servlet/SystemReadyServlet.java
URL: http://svn.apache.org/viewvc/felix/trunk/systemready/src/main/java/org/apache/felix/systemready/impl/servlet/SystemReadyServlet.java?rev=1831246&view=auto
==============================================================================
--- felix/trunk/systemready/src/main/java/org/apache/felix/systemready/impl/servlet/SystemReadyServlet.java (added)
+++ felix/trunk/systemready/src/main/java/org/apache/felix/systemready/impl/servlet/SystemReadyServlet.java Wed May  9 11:53:11 2018
@@ -0,0 +1,101 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.systemready.impl.servlet;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.Map;
+
+import javax.servlet.Servlet;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.felix.systemready.SystemReadyMonitor;
+import org.apache.felix.systemready.SystemStatus;
+import org.apache.felix.systemready.Status;
+import org.osgi.framework.BundleContext;
+import org.osgi.service.component.annotations.Activate;
+import org.osgi.service.component.annotations.Component;
+import org.osgi.service.component.annotations.Reference;
+import org.osgi.service.http.whiteboard.HttpWhiteboardConstants;
+import org.osgi.service.metatype.annotations.AttributeDefinition;
+import org.osgi.service.metatype.annotations.Designate;
+import org.osgi.service.metatype.annotations.ObjectClassDefinition;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Provide aggregated ready information using a servlet
+ */
+@Component(
+        name = "SystemReadyServlet",
+        service = Servlet.class,
+        property = {
+                HttpWhiteboardConstants.HTTP_WHITEBOARD_SERVLET_PATTERN + "=" + "/system/console/ready",
+                HttpWhiteboardConstants.HTTP_WHITEBOARD_CONTEXT_SELECT + "=" + "(osgi.http.whiteboard.context.name=org.osgi.service.http)"
+        }
+)
+@Designate(ocd=SystemReadyServlet.Config.class)
+public class SystemReadyServlet extends HttpServlet {
+    private static final long serialVersionUID = 1L;
+
+    @ObjectClassDefinition(
+            name ="System Ready Servlet",
+            description="Servlet exposing a configurable http endpoint for showing the status reported by the system ready monitor"
+    )
+    public @interface Config {
+
+        @AttributeDefinition(name = "Servlet Path")
+        String osgi_http_whiteboard_servlet_pattern() default SystemReadyServlet.DEFAULT_PATH;
+        
+        @AttributeDefinition(name = "Servlet Context")
+        String osgi_http_whiteboard_context_select();
+
+    }
+
+    @Reference
+    private SystemReadyMonitor monitor;
+
+    private static final String DEFAULT_PATH = "/system/console/ready";
+
+    private static final Logger LOG = LoggerFactory.getLogger(SystemReadyServlet.class);
+
+    @Activate
+    protected void activate(final BundleContext ctx, final Map<String, Object> properties, final Config config) {
+        final String path = config.osgi_http_whiteboard_servlet_pattern();
+        LOG.info("Registered servlet to listen on {}", path);
+    }
+
+    /**
+     * Process polling requests
+     */
+    @Override
+    protected void doGet(HttpServletRequest request, HttpServletResponse response)
+            throws ServletException, IOException {
+        SystemStatus systemState = this.monitor.getStatus();
+        if (! (systemState.getState() == Status.State.GREEN)) {
+            response.setStatus(HttpServletResponse.SC_SERVICE_UNAVAILABLE);
+        }
+        PrintWriter writer = response.getWriter();
+        new StatusWriterJson(writer).write(systemState);
+    }
+
+}

Added: felix/trunk/systemready/src/main/java/org/apache/felix/systemready/package-info.java
URL: http://svn.apache.org/viewvc/felix/trunk/systemready/src/main/java/org/apache/felix/systemready/package-info.java?rev=1831246&view=auto
==============================================================================
--- felix/trunk/systemready/src/main/java/org/apache/felix/systemready/package-info.java (added)
+++ felix/trunk/systemready/src/main/java/org/apache/felix/systemready/package-info.java Wed May  9 11:53:11 2018
@@ -0,0 +1,23 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+@org.osgi.annotation.versioning.Version("0.1.0")
+package org.apache.felix.systemready;
+
+

Added: felix/trunk/systemready/src/main/java/org/apache/felix/systemready/rootcause/DSComp.java
URL: http://svn.apache.org/viewvc/felix/trunk/systemready/src/main/java/org/apache/felix/systemready/rootcause/DSComp.java?rev=1831246&view=auto
==============================================================================
--- felix/trunk/systemready/src/main/java/org/apache/felix/systemready/rootcause/DSComp.java (added)
+++ felix/trunk/systemready/src/main/java/org/apache/felix/systemready/rootcause/DSComp.java Wed May  9 11:53:11 2018
@@ -0,0 +1,32 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.systemready.rootcause;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.osgi.dto.DTO;
+import org.osgi.service.component.runtime.dto.ComponentConfigurationDTO;
+import org.osgi.service.component.runtime.dto.ComponentDescriptionDTO;
+
+public class DSComp extends DTO {
+    public ComponentDescriptionDTO desc;
+    public ComponentConfigurationDTO config;
+    public List<DSRef> unsatisfied = new ArrayList<>();
+}

Added: felix/trunk/systemready/src/main/java/org/apache/felix/systemready/rootcause/DSRef.java
URL: http://svn.apache.org/viewvc/felix/trunk/systemready/src/main/java/org/apache/felix/systemready/rootcause/DSRef.java?rev=1831246&view=auto
==============================================================================
--- felix/trunk/systemready/src/main/java/org/apache/felix/systemready/rootcause/DSRef.java (added)
+++ felix/trunk/systemready/src/main/java/org/apache/felix/systemready/rootcause/DSRef.java Wed May  9 11:53:11 2018
@@ -0,0 +1,31 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.systemready.rootcause;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.osgi.dto.DTO;
+
+public class DSRef extends DTO {
+    public String name;
+    public String iface;
+    public String filter;
+    public List<DSComp> candidates = new ArrayList<>();
+}

Added: felix/trunk/systemready/src/main/java/org/apache/felix/systemready/rootcause/DSRootCause.java
URL: http://svn.apache.org/viewvc/felix/trunk/systemready/src/main/java/org/apache/felix/systemready/rootcause/DSRootCause.java?rev=1831246&view=auto
==============================================================================
--- felix/trunk/systemready/src/main/java/org/apache/felix/systemready/rootcause/DSRootCause.java (added)
+++ felix/trunk/systemready/src/main/java/org/apache/felix/systemready/rootcause/DSRootCause.java Wed May  9 11:53:11 2018
@@ -0,0 +1,97 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.systemready.rootcause;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.List;
+import java.util.Optional;
+import java.util.stream.Collectors;
+
+import org.osgi.service.component.runtime.ServiceComponentRuntime;
+import org.osgi.service.component.runtime.dto.ComponentConfigurationDTO;
+import org.osgi.service.component.runtime.dto.ComponentDescriptionDTO;
+import org.osgi.service.component.runtime.dto.ReferenceDTO;
+import org.osgi.service.component.runtime.dto.UnsatisfiedReferenceDTO;
+
+public class DSRootCause {
+
+    private static final int MAX_RECURSION = 10;
+    
+    private ServiceComponentRuntime scr;
+    
+    public DSRootCause(ServiceComponentRuntime scr) {
+        this.scr = scr;
+    }
+    
+    public Optional<DSComp> getRootCause(String iface) {
+        return scr.getComponentDescriptionDTOs().stream()
+            .filter(desc -> offersInterface(desc, iface))
+            .map(this::getRootCause)
+            .findFirst();
+    }
+    
+    public DSComp getRootCause(ComponentDescriptionDTO desc) {
+        return getRootCause(desc, 0);
+    }
+
+    private DSComp getRootCause(ComponentDescriptionDTO desc, int level) {
+        if (level > MAX_RECURSION) {
+            throw new IllegalStateException("Aborting after because of cyclic references");
+        }
+        DSComp dsComp = new DSComp();
+        dsComp.desc = desc;
+        Collection<ComponentConfigurationDTO> instances = scr.getComponentConfigurationDTOs(desc);
+        if (instances.isEmpty()) {
+            return dsComp;
+        }
+        for (ComponentConfigurationDTO instance : instances) {
+            for (UnsatisfiedReferenceDTO ref : instance.unsatisfiedReferences) {
+                ReferenceDTO refdef = getReference(desc, ref.name);
+                DSRef unresolvedRef = createRef(ref, refdef);
+                unresolvedRef.candidates = getCandidates(ref, refdef, level + 1);
+                dsComp.unsatisfied.add(unresolvedRef);
+            }
+        }
+        return dsComp;
+    }
+
+    private DSRef createRef(UnsatisfiedReferenceDTO unsatifiedRef, ReferenceDTO refdef) {
+        DSRef ref = new DSRef();
+        ref.name = unsatifiedRef.name;
+        ref.filter = unsatifiedRef.target;
+        ref.iface = refdef.interfaceName;
+        return ref;
+    }
+
+    private List<DSComp> getCandidates(UnsatisfiedReferenceDTO ref, ReferenceDTO refdef, int level) {
+        return scr.getComponentDescriptionDTOs().stream()
+                .filter(desc -> offersInterface(desc, refdef.interfaceName))
+                .map(desc -> getRootCause(desc, level)).collect(Collectors.toList());
+    }
+
+    private boolean offersInterface(ComponentDescriptionDTO desc, String interfaceName) {
+        return Arrays.asList(desc.serviceInterfaces).contains(interfaceName);
+    }
+
+    private ReferenceDTO getReference(ComponentDescriptionDTO desc, String name) {
+        return Arrays.asList(desc.references).stream().filter(ref -> ref.name.equals(name)).findFirst().get();
+    }
+
+}

Added: felix/trunk/systemready/src/main/java/org/apache/felix/systemready/rootcause/RootCauseCommand.java
URL: http://svn.apache.org/viewvc/felix/trunk/systemready/src/main/java/org/apache/felix/systemready/rootcause/RootCauseCommand.java?rev=1831246&view=auto
==============================================================================
--- felix/trunk/systemready/src/main/java/org/apache/felix/systemready/rootcause/RootCauseCommand.java (added)
+++ felix/trunk/systemready/src/main/java/org/apache/felix/systemready/rootcause/RootCauseCommand.java Wed May  9 11:53:11 2018
@@ -0,0 +1,46 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.systemready.rootcause;
+
+import org.osgi.service.component.annotations.Component;
+import org.osgi.service.component.annotations.Reference;
+import org.osgi.service.component.runtime.ServiceComponentRuntime;
+import org.osgi.service.component.runtime.dto.ComponentDescriptionDTO;
+
+@Component(
+        service = RootCauseCommand.class,
+        property = {
+                "osgi.command.scope=ready", //
+                "osgi.command.function=rootcause"
+        }
+        )
+public class RootCauseCommand {
+    
+    @Reference
+    ServiceComponentRuntime scr;
+    
+    public DSComp rootcause(String componentName) {
+        ComponentDescriptionDTO cdesc = scr.getComponentDescriptionDTOs().stream()
+            .filter(desc -> desc.name.equals(componentName))
+            .findFirst().get();
+        DSComp rootCause = new DSRootCause(scr).getRootCause(cdesc);
+        new RootCausePrinter().print(rootCause);
+        return rootCause;
+    }
+}