/* * 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.ipojo.arch.gogo; import static java.lang.String.format; import java.io.ByteArrayOutputStream; import java.io.PrintStream; import java.util.ArrayList; import java.util.Dictionary; import java.util.List; import org.apache.felix.ipojo.ComponentInstance; import org.apache.felix.ipojo.Factory; import org.apache.felix.ipojo.HandlerFactory; import org.apache.felix.ipojo.annotations.Component; import org.apache.felix.ipojo.annotations.Instantiate; import org.apache.felix.ipojo.annotations.Provides; import org.apache.felix.ipojo.annotations.Requires; import org.apache.felix.ipojo.annotations.ServiceProperty; import org.apache.felix.ipojo.architecture.Architecture; import org.apache.felix.ipojo.architecture.InstanceDescription; import org.apache.felix.ipojo.extender.ExtensionDeclaration; import org.apache.felix.ipojo.extender.InstanceDeclaration; import org.apache.felix.ipojo.extender.TypeDeclaration; import org.apache.felix.service.command.Descriptor; /** * iPOJO Arch command giving information about the current * system architecture. This is a Gogo command. * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a> */ @Component(public_factory = false, immediate = true) @Instantiate @Provides(specifications = Arch.class) public class Arch { /** * Defines the command scope (ipojo). */ @ServiceProperty(name = "osgi.command.scope", value = "ipojo") String m_scope; /** * Defines the functions (commands). */ @ServiceProperty(name = "osgi.command.function", value = "{}") String[] m_function = new String[] { "instances", "instance", "factory", "component", "factories", "components", "handlers", "extensions" }; /** * Instance architecture services. */ @Requires(optional = true) private Architecture[] m_archs; /** * Factory services. */ @Requires(optional = true) private Factory[] m_factories; /** * Handler Factory services. */ @Requires(optional = true) private HandlerFactory[] m_handlers; /** * The instance declaration services. */ @Requires(optional = true) private InstanceDeclaration[] m_instances; /** * The type declaration services. */ @Requires(optional = true) private TypeDeclaration[] m_types; /** * The extension declaration services. */ @Requires(optional = true) private ExtensionDeclaration[] m_extensions; /** * Displays iPOJO instances. */ @Descriptor("Display iPOJO instances") public void instances() { StringBuilder buffer = new StringBuilder(); for (Architecture m_arch : m_archs) { InstanceDescription instance = m_arch.getInstanceDescription(); if (instance.getState() == ComponentInstance.VALID) { buffer.append(format("Instance %s -> valid%n", instance.getName())); } if (instance.getState() == ComponentInstance.INVALID) { buffer.append(format("Instance %s -> invalid%n", instance.getName())); } if (instance.getState() == ComponentInstance.STOPPED) { buffer.append(format("Instance %s -> stopped%n", instance.getName())); } } for (InstanceDeclaration instance : m_instances) { // Only print unbound instances (others already printed above) if (!instance.getStatus().isBound()) { buffer.append(format("Instance %s of type %s is not bound.%n", name(instance.getConfiguration()), instance.getConfiguration().get("component"))); buffer.append(format(" Reason: %s", instance.getStatus().getMessage())); buffer.append("\n"); } } if (buffer.length() == 0) { buffer.append("No instances \n"); } System.out.println(buffer.toString()); } private String name(Dictionary<String, Object> configuration) { String name = (String) configuration.get("instance.name"); if (name == null) { name = "unnamed"; } return name; } /** * Displays the architecture of a specific instance. * @param instance the instance name */ @Descriptor("Display the architecture of a specific instance") public void instance(@Descriptor("target instance name") String instance) { StringBuilder sb = new StringBuilder(); for (Architecture m_arch : m_archs) { InstanceDescription id = m_arch.getInstanceDescription(); if (id.getName().equalsIgnoreCase(instance)) { sb.append(id.getDescription()); sb.append('\n'); } } for (InstanceDeclaration instanceDeclaration : m_instances) { if (!instanceDeclaration.getStatus().isBound()) { if (instance.equals(name(instanceDeclaration.getConfiguration()))) { sb.append(format("InstanceDeclaration %s not bound to its factory%n", instance)); sb.append(format(" type: %s%n", instanceDeclaration.getComponentName())); sb.append(format(" reason: %s%n", instanceDeclaration.getStatus().getMessage())); Throwable throwable = instanceDeclaration.getStatus().getThrowable(); if (throwable != null) { ByteArrayOutputStream os = new ByteArrayOutputStream(); throwable.printStackTrace(new PrintStream(os)); sb.append(" throwable: "); sb.append(os.toString()); } } } } if (sb.length() == 0) { System.err.printf("Instance named '%s' not found", instance); } else { System.out.print(sb); } } /** * Displays the information about a specific factory. * Note that factory name are not unique, so all matching * factories are displayed. * @param name the factory name */ @Descriptor("Display the information about a specific factory / component") public void component(@Descriptor("target factory name") String name) { factory(name); } /** * Displays the information about a specific factory. * Note that factory name are not unique, so all matching * factories are displayed. * @param name the factory name */ @Descriptor("Display the information about a specific factory") public void factory(@Descriptor("target factory name") String name) { List<Factory> factories = new ArrayList<Factory>(); List<TypeDeclaration> types = new ArrayList<TypeDeclaration>(); // Looking for public factories for (Factory factory : m_factories) { if (factory.getName().equalsIgnoreCase(name)) { factories.add(factory); } } // Looking for all unbound or private bound types for (TypeDeclaration type : m_types) { if (name.equalsIgnoreCase(type.getComponentName())) { // (Public + Unbound) or private types have no exported factories if (!type.isPublic() || (!type.getStatus().isBound() && type.isPublic())) { types.add(type); } } } if (factories.isEmpty() && types.isEmpty()) { System.err.println("Factory " + name + " not found"); return; } // Display found factories and types for (Factory factory : factories) { System.out.println(factory.getComponentDescription()); } for (TypeDeclaration type : types) { if (!type.getStatus().isBound()) { // Unbound: maybe private or public type System.out.printf("Factory %s is not bound%n", type.getComponentName()); System.out.printf(" reason: %s%n", type.getStatus().getMessage()); Throwable throwable = type.getStatus().getThrowable(); if (throwable != null) { System.out.print(" throwable: "); throwable.printStackTrace(System.out); } } else { // Bound, this is only a private factory System.out.printf("Factory %s is bound - Private%n", type.getComponentName()); } } } /** * Displays the list of public iPOJO factories. */ @Descriptor("Display iPOJO factories / components") public void components() { factories(); } /** * Displays the list of public iPOJO factories. */ @Descriptor("Display iPOJO factories") public void factories() { StringBuilder buffer = new StringBuilder(); for (Factory m_factory : m_factories) { if (m_factory.getMissingHandlers().size() == 0) { buffer.append(format("Factory %s (VALID)%n", m_factory.getName())); } else { buffer.append(format("Factory %s (INVALID: %s)%n", m_factory.getName(), m_factory.getMissingHandlers())); } } for (TypeDeclaration type : m_types) { if (!type.isPublic()) { // Private factories: always display them // Cannot display much more than presence/absence since the TypeDeclaration API does not // give access to the underlying Factory or description (if valid) if (type.getStatus().isBound()) { buffer.append(format("Factory %s (UNKNOWN) - Private%n", type.getComponentName())); } else { // Unbound type means that required extension is not available // We'll say that the factory is INVALID even if in reality it's not even instantiated buffer.append(format("Factory %s (INVALID) - Private%n", type.getComponentName())); buffer.append(format(" -> %s", type.getStatus().getMessage())); } } else { if (!type.getStatus().isBound()) { buffer.append(format("Factory %s is not bound%n", type.getComponentName())); buffer.append(format(" -> %s%n", type.getStatus().getMessage())); } } } if (buffer.length() == 0) { buffer.append("No factories \n"); } System.out.println(buffer.toString()); } /** * Displays the list of available handlers. */ @Descriptor("Display iPOJO handlers") public void handlers() { PrintStream out = System.out; for (HandlerFactory m_handler : m_handlers) { String name = m_handler.getHandlerName(); if ("composite".equals(m_handler.getType())) { name = name + " [composite]"; } if (m_handler.getMissingHandlers().size() == 0) { out.println("Handler " + name + " (VALID)"); } else { out.println("Handler " + name + " (INVALID : " + m_handler.getMissingHandlers() + ")"); } } for (TypeDeclaration type : m_types) { if (!type.getStatus().isBound()) { out.println("HandlerFactory " + type.getComponentName() + " is not bound"); out.println(" -> " + type.getStatus().getMessage()); } } } /** * Displays the list of available extensions. */ @Descriptor("Display iPOJO extensions") public void extensions() { PrintStream out = System.out; out.println("Available extensions:"); for (ExtensionDeclaration extension : m_extensions) { out.println(" * " + extension.getExtensionName()); } } }