/* * 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.karaf.bundle.state.blueprint.internal; import java.io.PrintWriter; import java.io.StringWriter; import java.text.SimpleDateFormat; import java.util.Date; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import org.apache.karaf.bundle.core.BundleState; import org.apache.karaf.bundle.core.BundleStateService; import org.osgi.framework.Bundle; import org.osgi.framework.BundleEvent; import org.osgi.framework.BundleListener; import org.osgi.service.blueprint.container.BlueprintEvent; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * TODO: use event instance to receive WAIT topics notifications from blueprint * extender */ public class BlueprintStateService implements org.osgi.service.blueprint.container.BlueprintListener, BundleListener, BundleStateService { private static final Logger LOG = LoggerFactory.getLogger(BlueprintStateService.class); private final Map<Long, BlueprintEvent> states; public BlueprintStateService() { states = new ConcurrentHashMap<Long, BlueprintEvent>(); } @Override public String getName() { return BundleStateService.NAME_BLUEPRINT; } @Override public String getDiag(Bundle bundle) { BlueprintEvent event = states.get(bundle.getBundleId()); if (event == null) { return null; } if (event.getType() != BlueprintEvent.FAILURE && event.getType() != BlueprintEvent.GRACE_PERIOD && event.getType() != BlueprintEvent.WAITING) { return null; } StringBuilder message = new StringBuilder(); Date date = new Date(event.getTimestamp()); SimpleDateFormat df = new SimpleDateFormat(); message.append(df.format(date) + "\n"); if (event.getCause() != null) { message.append("Exception: \n"); addMessages(message, event.getCause()); } if (event.getDependencies() != null) { message.append("Missing dependencies: \n"); for (String dep : event.getDependencies()) { message.append(dep + " "); } message.append("\n"); } return message.toString(); } public void addMessages(StringBuilder message, Throwable ex) { message.append(ex.getMessage()); message.append("\n"); StringWriter errorWriter = new StringWriter(); ex.printStackTrace(new PrintWriter(errorWriter)); message.append(errorWriter.toString()); message.append("\n"); } @Override public BundleState getState(Bundle bundle) { BlueprintEvent event = states.get(bundle.getBundleId()); BundleState state = getState(event); return (bundle.getState() != Bundle.ACTIVE) ? BundleState.Unknown : state; } @Override public void blueprintEvent(BlueprintEvent blueprintEvent) { if (LOG.isDebugEnabled()) { BundleState state = getState(blueprintEvent); LOG.debug("Blueprint app state changed to " + state + " for bundle " + blueprintEvent.getBundle().getBundleId()); } states.put(blueprintEvent.getBundle().getBundleId(), blueprintEvent); } @Override public void bundleChanged(BundleEvent event) { if (event.getType() == BundleEvent.UNINSTALLED) { states.remove(event.getBundle().getBundleId()); } } private BundleState getState(BlueprintEvent blueprintEvent) { if (blueprintEvent == null) { return BundleState.Unknown; } switch (blueprintEvent.getType()) { case BlueprintEvent.CREATING: return BundleState.Starting; case BlueprintEvent.CREATED: return BundleState.Active; case BlueprintEvent.DESTROYING: return BundleState.Stopping; case BlueprintEvent.DESTROYED: return BundleState.Resolved; case BlueprintEvent.FAILURE: return BundleState.Failure; case BlueprintEvent.GRACE_PERIOD: return BundleState.GracePeriod; case BlueprintEvent.WAITING: return BundleState.Waiting; default: return BundleState.Unknown; } } }