blob: 97906cc4504309f18097b3d8316b1848b983c35f [file] [log] [blame]
/*
* 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.webconsole.plugins.ds.internal;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import java.util.TreeSet;
import org.apache.felix.inventory.Format;
import org.apache.felix.inventory.InventoryPrinter;
import org.apache.felix.utils.json.JSONWriter;
import org.apache.felix.webconsole.WebConsoleUtil;
import org.osgi.framework.Constants;
import org.osgi.framework.dto.ServiceReferenceDTO;
import org.osgi.service.component.ComponentConstants;
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.SatisfiedReferenceDTO;
/**
* ComponentConfigurationPrinter prints the available SCR services.
*/
class ComponentConfigurationPrinter implements InventoryPrinter
{
private final ServiceComponentRuntime scrService;
private final WebConsolePlugin plugin;
ComponentConfigurationPrinter(ServiceComponentRuntime scrService, WebConsolePlugin plugin)
{
this.scrService = scrService;
this.plugin = plugin;
}
/**
* @see org.apache.felix.inventory.InventoryPrinter#print(java.io.PrintWriter, org.apache.felix.inventory.Format, boolean)
*/
@Override
public void print(PrintWriter pw, Format format, boolean isZip)
{
final List<ComponentDescriptionDTO> noConfig = new ArrayList<>();
final List<ComponentDescriptionDTO> disabled = new ArrayList<>();
final List<ComponentConfigurationDTO> configurations = new ArrayList<>();
final Collection<ComponentDescriptionDTO> descs = scrService.getComponentDescriptionDTOs();
for(final ComponentDescriptionDTO d : descs)
{
if ( !scrService.isComponentEnabled(d) )
{
disabled.add(d);
}
else
{
final Collection<ComponentConfigurationDTO> configs = scrService.getComponentConfigurationDTOs(d);
if ( configs.isEmpty() )
{
noConfig.add(d);
}
else
{
configurations.addAll(configs);
}
}
}
Collections.sort(configurations, Util.COMPONENT_COMPARATOR);
if (Format.JSON.equals(format))
{
disabled.addAll(noConfig);
try
{
printComponentsJson(pw, disabled, configurations, isZip);
} catch (IOException ignore)
{
// ignore
}
}
else
{
printComponentsText(pw, disabled, noConfig, configurations);
}
}
private final void printComponentsJson(final PrintWriter pw,
final List<ComponentDescriptionDTO> disabled,
final List<ComponentConfigurationDTO> configurations,
final boolean details) throws IOException
{
final JSONWriter jw = new JSONWriter(pw);
jw.object();
jw.key("components"); //$NON-NLS-1$
jw.array();
// render disabled descriptions
for(final ComponentDescriptionDTO cd : disabled)
{
plugin.component(jw, cd, null, details);
}
// render configurations
for (final ComponentConfigurationDTO cfg : configurations)
{
plugin.component(jw, cfg.description, cfg, details);
}
jw.endArray();
jw.endObject();
}
private static final String SEP = "----------------------------------------------------------------------";
private static final void printComponentsText(final PrintWriter pw,
final List<ComponentDescriptionDTO> disabled,
final List<ComponentDescriptionDTO> noConfig,
final List<ComponentConfigurationDTO> configurations)
{
if ( !disabled.isEmpty())
{
pw.println(SEP);
pw.println("Disabled components:");
pw.println(SEP);
for(final ComponentDescriptionDTO cd : disabled)
{
disabledComponent(pw, cd);
}
pw.println();
}
if ( !noConfig.isEmpty())
{
pw.println(SEP);
pw.println("Components with missing configuration in Config Admin:");
pw.println(SEP);
for(final ComponentDescriptionDTO cd : noConfig)
{
disabledComponent(pw, cd);
}
pw.println();
}
pw.println(SEP);
if (configurations.isEmpty())
{
pw.println("Status: No Component Configurations");
pw.println(SEP);
}
else
{
pw.println("Component Configurations:");
pw.println(SEP);
// order components by id
TreeMap<Long, ComponentConfigurationDTO> componentMap = new TreeMap<>();
for(final ComponentConfigurationDTO cfg : configurations)
{
componentMap.put(new Long(cfg.id), cfg);
}
// render components
for (final ComponentConfigurationDTO cfg : componentMap.values())
{
component(pw, cfg);
}
}
}
private static final void component(PrintWriter pw, final ComponentConfigurationDTO cfg)
{
pw.print(cfg.id);
pw.print("=[");
pw.print(cfg.description.name);
pw.println("]");
pw.println(" Bundle=" + cfg.description.bundle.symbolicName + " ("
+ cfg.description.bundle.id + ")");
pw.println(" State=" + toStateString(cfg.state));
if ( cfg.state == ComponentConfigurationDTO.FAILED_ACTIVATION ) {
pw.println(" Failure=" + cfg.failure);
}
pw.println(" DefaultState="
+ (cfg.description.defaultEnabled ? "enabled" : "disabled"));
pw.println(" Activation=" + (cfg.description.immediate ? "immediate" : "delayed"));
pw.println(" ConfigurationPolicy=" + cfg.description.configurationPolicy);
listServices(pw, cfg.description);
if ( cfg.service != null ) {
pw.println(" ServiceId=" + String.valueOf(cfg.service.id));
}
listReferences(pw, cfg.description, cfg);
listProperties(pw, cfg.description, cfg);
pw.println();
}
private static final void disabledComponent(PrintWriter pw, final ComponentDescriptionDTO description)
{
pw.println(description.name);
pw.println(" Bundle=" + description.bundle.symbolicName + " ("
+ description.bundle.id + ")");
pw.println(" DefaultState="
+ (description.defaultEnabled ? "enabled" : "disabled"));
pw.println(" Activation=" + (description.immediate ? "immediate" : "delayed"));
pw.println(" ConfigurationPolicy=" + description.configurationPolicy);
listServices(pw, description);
listReferences(pw, description, null);
listProperties(pw, description, null);
pw.println();
}
private static void listServices(PrintWriter pw, final ComponentDescriptionDTO cfg)
{
String[] services = cfg.serviceInterfaces;
if (services == null)
{
return;
}
if ( cfg.scope != null ) {
pw.println(" ServiceType=" + cfg.scope);
}
StringBuffer buf = new StringBuffer();
for (int i = 0; i < services.length; i++)
{
if (i > 0)
{
buf.append(", ");
}
buf.append(services[i]);
}
pw.println(" Services=" + buf);
}
private static SatisfiedReferenceDTO findReference(final ComponentConfigurationDTO component, final String name)
{
for(final SatisfiedReferenceDTO dto : component.satisfiedReferences)
{
if ( dto.name.equals(name))
{
return dto;
}
}
return null;
}
private static final void listReferences(PrintWriter pw,
final ComponentDescriptionDTO description,
final ComponentConfigurationDTO configuration)
{
for(final ReferenceDTO dto : description.references)
{
final SatisfiedReferenceDTO satisfiedRef = configuration == null ? null : findReference(configuration, dto.name);
pw.print(" Reference=");
pw.print(dto.name);
if ( configuration != null )
{
pw.print(", ");
pw.print(satisfiedRef != null ? "Satisfied" : "Unsatisfied");
}
pw.println();
pw.println(" Service Name: " + dto.interfaceName);
if (dto.target != null)
{
pw.println(" Target Filter: " + dto.target);
}
pw.println(" Cardinality: " + dto.cardinality);
pw.println(" Policy: " + dto.policy);
pw.println(" Policy Option: " + dto.policyOption);
// list bound services
if ( satisfiedRef != null )
{
for(final ServiceReferenceDTO sref : satisfiedRef.boundServices )
{
pw.print(" Bound Service: ID ");
pw.print(sref.properties.get(Constants.SERVICE_ID));
String name = (String) sref.properties.get(ComponentConstants.COMPONENT_NAME);
if (name == null)
{
name = (String) sref.properties.get(Constants.SERVICE_PID);
if (name == null)
{
name = (String) sref.properties.get(Constants.SERVICE_DESCRIPTION);
}
}
if (name != null)
{
pw.print(" (");
pw.print(name);
pw.print(")");
}
pw.println();
}
}
else
{
pw.println(" No Services bound");
}
}
}
private static final void listProperties(PrintWriter pw,
final ComponentDescriptionDTO description,
final ComponentConfigurationDTO cfg)
{
Map<String, Object> props = cfg == null ? description.properties : cfg.properties;
if (props != null)
{
pw.println(" Properties=");
TreeSet<String> keys = new TreeSet<>(props.keySet());
for (Iterator<String> ki = keys.iterator(); ki.hasNext();)
{
String key = ki.next();
Object value = props.get(key);
value = WebConsoleUtil.toString(value);
if (value.getClass().isArray())
{
value = Arrays.asList((Object[]) value);
}
pw.println(" " + key + "=" + value);
}
}
if ( cfg == null && description.factoryProperties != null ) {
pw.println(" FactoryProperties=");
TreeSet<String> keys = new TreeSet<>(description.factoryProperties.keySet());
for (Iterator<String> ki = keys.iterator(); ki.hasNext();)
{
String key = ki.next();
Object value = props.get(key);
value = WebConsoleUtil.toString(value);
if (value.getClass().isArray())
{
value = Arrays.asList((Object[]) value);
}
pw.println(" " + key + "=" + value);
}
}
}
static final String toStateString(int state)
{
switch (state)
{
case ComponentConfigurationDTO.ACTIVE:
return "active";
case ComponentConfigurationDTO.SATISFIED:
return "satisfied";
case ComponentConfigurationDTO.UNSATISFIED_CONFIGURATION:
return "unsatisfied (configuration)";
case ComponentConfigurationDTO.UNSATISFIED_REFERENCE:
return "unsatisfied (reference)";
case ComponentConfigurationDTO.FAILED_ACTIVATION:
return "failed activation";
default:
return String.valueOf(state);
}
}
}