2 * Copyright (c) 2016, 2017 Red Hat, Inc. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
8 package org.opendaylight.odlparent.bundlestest.lib;
10 import static org.apache.karaf.bundle.core.BundleState.Active;
11 import static org.apache.karaf.bundle.core.BundleState.Installed;
12 import static org.apache.karaf.bundle.core.BundleState.Waiting;
14 import java.util.ArrayList;
15 import java.util.Collections;
16 import java.util.EnumMap;
17 import java.util.HashMap;
18 import java.util.List;
20 import org.apache.karaf.bundle.core.BundleInfo;
21 import org.apache.karaf.bundle.core.BundleService;
22 import org.apache.karaf.bundle.core.BundleState;
23 import org.osgi.framework.Bundle;
24 import org.osgi.framework.BundleContext;
27 * {@link BundleDiagInfos} implementation.
29 * @author Michael Vorburger.ch
31 // intentionally just package-local
32 final class BundleDiagInfosImpl implements BundleDiagInfos {
33 private static final long serialVersionUID = 1L;
35 private static final Map<String, BundleState> WHITELISTED_BUNDLES;
38 WHITELISTED_BUNDLES = new HashMap<>();
39 WHITELISTED_BUNDLES.put("slf4j.log4j12", Installed);
40 WHITELISTED_BUNDLES.put("org.apache.karaf.scr.management", Waiting); // ODLPARENT-144
43 private final List<String> okBundleStateInfoTexts;
44 private final List<String> nokBundleStateInfoTexts;
45 private final List<String> whitelistedBundleStateInfoTexts;
46 private final Map<BundleState, Integer> bundleStatesCounters;
47 private final Map<BundleSymbolicNameWithVersion, BundleState> bundlesStateMap;
50 * Create an instance. The collections provided as arguments will be kept as-is; it’s up to the caller
51 * to ensure they’re handled defensively, as appropriate.
53 * @param okBundleStateInfoTexts information about bundles in OK state.
54 * @param nokBundleStateInfoTexts information about bundles not in OK state.
55 * @param whitelistedBundleStateInfoTexts information about whitelisted bundles.
56 * @param bundleStatesCounters bundle state counters.
57 * @param bundlesStateMap bundle state map (state of each bundle).
59 private BundleDiagInfosImpl(List<String> okBundleStateInfoTexts, List<String> nokBundleStateInfoTexts,
60 List<String> whitelistedBundleStateInfoTexts, Map<BundleState, Integer> bundleStatesCounters,
61 Map<BundleSymbolicNameWithVersion, BundleState> bundlesStateMap) {
62 this.okBundleStateInfoTexts = okBundleStateInfoTexts;
63 this.nokBundleStateInfoTexts = nokBundleStateInfoTexts;
64 this.whitelistedBundleStateInfoTexts = whitelistedBundleStateInfoTexts;
65 this.bundleStatesCounters = bundleStatesCounters;
66 this.bundlesStateMap = bundlesStateMap;
69 public static BundleDiagInfos forContext(BundleContext bundleContext, BundleService bundleService) {
70 List<String> okBundleStateInfoTexts = new ArrayList<>();
71 List<String> nokBundleStateInfoTexts = new ArrayList<>();
72 List<String> whitelistedBundleStateInfoTexts = new ArrayList<>();
73 Map<BundleSymbolicNameWithVersion, BundleState> bundlesStateMap = new HashMap<>();
74 Map<BundleState, Integer> bundleStatesCounters = new EnumMap<>(BundleState.class);
75 for (BundleState bundleState : BundleState.values()) {
76 bundleStatesCounters.put(bundleState, 0);
79 for (Bundle bundle : bundleContext.getBundles()) {
80 String bundleSymbolicName = bundle.getSymbolicName();
81 BundleSymbolicNameWithVersion bundleSymbolicNameWithVersion
82 = new BundleSymbolicNameWithVersion(bundleSymbolicName, bundle.getVersion().toString());
84 BundleInfo karafBundleInfo = bundleService.getInfo(bundle);
85 BundleState karafBundleState = karafBundleInfo.getState();
86 bundlesStateMap.put(bundleSymbolicNameWithVersion, karafBundleState);
88 String bundleStateDiagText = "OSGi state = " + bundleStateToText(bundle.getState())
89 + ", Karaf bundleState = " + karafBundleState;
90 String diagText = bundleService.getDiag(bundle);
91 if (!diagText.isEmpty()) {
92 bundleStateDiagText += ", due to: " + diagText;
95 if (WHITELISTED_BUNDLES.get(bundleSymbolicName) != null) {
96 if (WHITELISTED_BUNDLES.get(bundleSymbolicName).equals(karafBundleState)) {
97 String msg = "WHITELISTED " + bundleSymbolicNameWithVersion + ": " + bundleStateDiagText;
98 whitelistedBundleStateInfoTexts.add(msg);
103 bundleStatesCounters.compute(karafBundleState, (key, counter) -> counter + 1);
105 // BundleState comparison as in Karaf's "diag" command,
106 // see https://github.com/apache/karaf/blob/master/bundle/core/src/main/java/org/apache/karaf/bundle/command/Diag.java
107 // but we intentionally, got a little further than Karaf's "diag" command,
108 // and instead of only checking some states, we check what's really Active,
109 // but accept that some remain just Resolved:
110 if (karafBundleState != Active && karafBundleState != BundleState.Resolved) {
111 String msg = "NOK " + bundleSymbolicNameWithVersion + ": " + bundleStateDiagText;
112 nokBundleStateInfoTexts.add(msg);
114 String msg = "OK " + bundleSymbolicNameWithVersion + ": " + bundleStateDiagText;
115 okBundleStateInfoTexts.add(msg);
119 return new BundleDiagInfosImpl(Collections.unmodifiableList(okBundleStateInfoTexts),
120 Collections.unmodifiableList(nokBundleStateInfoTexts),
121 Collections.unmodifiableList(whitelistedBundleStateInfoTexts),
122 Collections.unmodifiableMap(bundleStatesCounters), Collections.unmodifiableMap(bundlesStateMap));
125 private static String bundleStateToText(int state) {
126 return switch (state) {
127 case Bundle.INSTALLED -> "Installed";
128 case Bundle.RESOLVED -> "Resolved";
129 case Bundle.STARTING -> "Starting";
130 case Bundle.ACTIVE -> "Active";
131 case Bundle.STOPPING -> "Stopping";
132 case Bundle.UNINSTALLED -> "Uninstalled";
133 default -> state + "???";
138 public SystemState getSystemState() {
139 if (bundleStatesCounters.get(BundleState.Failure) > 0) {
140 return SystemState.Failure;
141 } else if (bundleStatesCounters.get(BundleState.Stopping) > 0) {
142 return SystemState.Stopping;
143 } else if (bundleStatesCounters.get(BundleState.Installed) == 0
144 // No, just Resolved is OK, so do not: && bundleStatesCounters.get(BundleState.Resolved) == 0
145 && bundleStatesCounters.get(BundleState.Unknown) == 0
146 && bundleStatesCounters.get(BundleState.GracePeriod) == 0
147 && bundleStatesCounters.get(BundleState.Waiting) == 0
148 && bundleStatesCounters.get(BundleState.Starting) == 0
149 // BundleState.Active *should* be ~= total # of bundles (minus Resolved, and whitelisted installed)
150 && bundleStatesCounters.get(BundleState.Stopping) == 0
151 && bundleStatesCounters.get(BundleState.Failure) == 0) {
152 return SystemState.Active;
154 return SystemState.Booting;
159 public String getFullDiagnosticText() {
160 StringBuilder sb = new StringBuilder(getSummaryText());
161 int failureNumber = 1;
162 for (String nokBundleStateInfoText : getNokBundleStateInfoTexts()) {
164 sb.append(failureNumber++);
166 sb.append(nokBundleStateInfoText);
168 return sb.toString();
172 public String getSummaryText() {
173 return "diag: " + getSystemState() + " " + bundleStatesCounters.toString();
177 public Map<BundleSymbolicNameWithVersion, BundleState> getBundlesStateMap() {
178 return bundlesStateMap;
182 public List<String> getNokBundleStateInfoTexts() {
183 return nokBundleStateInfoTexts;
187 public List<String> getOkBundleStateInfoTexts() {
188 return okBundleStateInfoTexts;
192 public List<String> getWhitelistedBundleStateInfoTexts() {
193 return whitelistedBundleStateInfoTexts;
197 public String toString() {
198 return getFullDiagnosticText();