blob: 4cdf823a53e5b00cc44a1208c711d70874c56f18 [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.scr.impl;
import java.io.PrintStream;
import java.lang.reflect.Constructor;
import java.util.Arrays;
import java.util.Collections;
import java.util.Dictionary;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.TreeSet;
import org.apache.felix.scr.Component;
import org.apache.felix.scr.Reference;
import org.apache.felix.scr.ScrService;
import org.apache.felix.scr.impl.config.ScrConfiguration;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.Constants;
import org.osgi.framework.ServiceReference;
/**
* The <code>ScrCommand</code> class provides the implementations for the
* Apache Felix Gogo and legacy Apache Felix Shell commands. The
* {@link #register(BundleContext, ScrService, ScrConfiguration)} method
* instantiates and registers the Gogo and Shell commands as possible.
*/
class ScrCommand
{
private final BundleContext bundleContext;
private final ScrService scrService;
private final ScrConfiguration scrConfiguration;
static void register(BundleContext bundleContext, ScrService scrService, ScrConfiguration scrConfiguration)
{
final ScrCommand cmd = new ScrCommand(bundleContext, scrService, scrConfiguration);
/*
* Register the Gogo Command as a service of its own class.
* Due to a race condition during project building (this class is
* compiled for Java 1.3 compatibility before the required
* ScrGogoCommand class compiled for Java 5 compatibility) this uses
* reflection to load and instantiate the class. Any failure during this
* process is just ignored.
*/
try
{
final String scrGogoCommandClassName = "org.apache.felix.scr.impl.ScrGogoCommand";
final Class scrGogoCommandClass = scrService.getClass().getClassLoader().loadClass(scrGogoCommandClassName);
final Constructor c = scrGogoCommandClass.getConstructor(new Class[]
{ ScrCommand.class });
final Object gogoCmd = c.newInstance(new Object[]
{ cmd });
final Hashtable props = new Hashtable();
props.put("osgi.command.scope", "scr");
props.put("osgi.command.function", new String[]
{ "config", "disable", "enable", "info", "list" });
props.put(Constants.SERVICE_DESCRIPTION, "SCR Gogo Shell Support");
props.put(Constants.SERVICE_VENDOR, "The Apache Software Foundation");
bundleContext.registerService(scrGogoCommandClassName, gogoCmd, props);
}
catch (Throwable t)
{
// Might be thrown if running in a pre-Java 5 VM
}
// We dynamically import the impl service API, so it
// might not actually be available, so be ready to catch
// the exception when we try to register the command service.
try
{
// Register "scr" impl command service as a
// wrapper for the bundle repository service.
final Hashtable props = new Hashtable();
props.put(Constants.SERVICE_DESCRIPTION, "SCR Legacy Shell Support");
props.put(Constants.SERVICE_VENDOR, "The Apache Software Foundation");
bundleContext.registerService(org.apache.felix.shell.Command.class.getName(), new ScrShellCommand(cmd),
props);
}
catch (Throwable th)
{
// Ignore.
}
}
private ScrCommand(BundleContext bundleContext, ScrService scrService, ScrConfiguration scrConfiguration)
{
this.bundleContext = bundleContext;
this.scrService = scrService;
this.scrConfiguration = scrConfiguration;
}
// ---------- Actual implementation
void list(final String bundleIdentifier, final PrintStream out, final PrintStream err)
{
Component[] components;
if (bundleIdentifier != null)
{
Bundle bundle = null;
try
{
long bundleId = Long.parseLong(bundleIdentifier);
bundle = bundleContext.getBundle(bundleId);
}
catch (NumberFormatException nfe)
{
// might be a bundle symbolic name
Bundle[] bundles = bundleContext.getBundles();
for (int i = 0; i < bundles.length; i++)
{
if (bundleIdentifier.equals(bundles[i].getSymbolicName()))
{
bundle = bundles[i];
break;
}
}
}
if (bundle == null)
{
err.println("Missing bundle with ID " + bundleIdentifier);
return;
}
if (ComponentRegistry.isBundleActive(bundle))
{
components = scrService.getComponents(bundle);
if (components == null)
{
out.println("Bundle " + bundleIdentifier + " declares no components");
return;
}
}
else
{
out.println("Bundle " + bundleIdentifier + " is not active");
return;
}
}
else
{
components = scrService.getComponents();
if (components == null)
{
out.println("No components registered");
return;
}
}
out.println(" Id State Name");
for ( Component component : components )
{
out.print( '[' );
out.print( pad( String.valueOf( component.getId() ), -4 ) );
out.print( "] [" );
out.print( pad( toStateString( component.getState() ), 13 ) );
out.print( "] " );
out.print( component.getName() );
out.println();
}
}
void info(final String componentId, PrintStream out, PrintStream err)
{
Component[] components = getComponentFromArg(componentId, err);
if (components == null)
{
return;
}
for ( Component component : components )
{
out.print( "ID: " );
out.println( component.getId() );
out.print( "Name: " );
out.println( component.getName() );
out.print( "Bundle: " );
out.println( component.getBundle().getSymbolicName() + " (" + component.getBundle().getBundleId() + ")" );
out.print( "State: " );
out.println( toStateString( component.getState() ) );
out.print( "Default State: " );
out.println( component.isDefaultEnabled() ? "enabled" : "disabled" );
out.print( "Activation: " );
out.println( component.isImmediate() ? "immediate" : "delayed" );
// DS 1.1 new features
out.print( "Configuration Policy: " );
out.println( component.getConfigurationPolicy() );
out.print( "Activate Method: " );
out.print( component.getActivate() );
if ( component.isActivateDeclared() )
{
out.print( " (declared in the descriptor)" );
}
out.println();
out.print( "Deactivate Method: " );
out.print( component.getDeactivate() );
if ( component.isDeactivateDeclared() )
{
out.print( " (declared in the descriptor)" );
}
out.println();
out.print( "Modified Method: " );
if ( component.getModified() != null )
{
out.print( component.getModified() );
}
else
{
out.print( "-" );
}
out.println();
out.print( "Configuration Pid: " );
out.print( component.getConfigurationPid() );
if ( component.isConfigurationPidDeclared() )
{
out.print( " (declared in the descriptor)" );
}
out.println();
if ( component.getFactory() != null )
{
out.print( "Factory: " );
out.println( component.getFactory() );
}
String[] services = component.getServices();
if ( services != null )
{
out.print( "Services: " );
out.println( services[0] );
for ( int i = 1; i < services.length; i++ )
{
out.print( " " );
out.println( services[i] );
}
out.print( "Service Type: " );
out.println( component.isServiceFactory() ? "service factory" : "service" );
}
Reference[] refs = component.getReferences();
if ( refs != null )
{
for ( Reference ref : refs )
{
out.print( "Reference: " );
out.println( ref.getName() );
out.print( " Satisfied: " );
out.println( ref.isSatisfied() ? "satisfied" : "unsatisfied" );
out.print( " Service Name: " );
out.println( ref.getServiceName() );
if ( ref.getTarget() != null )
{
out.print( " Target Filter: " );
out.println( ref.getTarget() );
}
out.print( " Multiple: " );
out.println( ref.isMultiple() ? "multiple" : "single" );
out.print( " Optional: " );
out.println( ref.isOptional() ? "optional" : "mandatory" );
out.print( " Policy: " );
out.println( ref.isStatic() ? "static" : "dynamic" );
out.print( " Policy option: " );
out.println( ref.isReluctant() ? "reluctant" : "greedy" );
ServiceReference[] serviceRefs = ref.getBoundServiceReferences();
if ( serviceRefs != null )
{
out.print( " Bound to:" );
for ( int k = 0; k < serviceRefs.length; k++ )
{
out.print( " " );
out.println( serviceRefs[k] );
}
}
}
}
Dictionary props = component.getProperties();
if ( props != null )
{
out.println( "Properties:" );
TreeSet keys = new TreeSet( Collections.list( props.keys() ) );
for ( Object key : keys )
{
out.print( " " );
out.print( key );
out.print( " = " );
Object prop = props.get( key );
if ( prop.getClass().isArray() )
{
prop = Arrays.asList( ( Object[] ) prop );
}
out.print( prop );
out.println();
}
}
}
}
void change(final String componentIdentifier, PrintStream out, PrintStream err, boolean enable)
{
Component[] components = getComponentFromArg(componentIdentifier, err);
if (components == null)
{
return;
}
for ( Component component : components )
{
if ( component.getState() == Component.STATE_DISPOSED )
{
err.println( "Component " + component.getName() + " already disposed, cannot change state" );
}
else if ( enable )
{
if ( component.getState() == Component.STATE_DISABLED )
{
component.enable();
out.println( "Component " + component.getName() + " enabled" );
}
else
{
out.println( "Component " + component.getName() + " already enabled" );
}
}
else
{
if ( component.getState() != Component.STATE_DISABLED )
{
component.disable();
out.println( "Component " + component.getName() + " disabled" );
}
else
{
out.println( "Component " + component.getName() + " already disabled" );
}
}
}
}
void config(PrintStream out)
{
out.print("Log Level: ");
out.println(scrConfiguration.getLogLevel());
out.print("Component Factory with Factory Configuration: ");
out.println(scrConfiguration.isFactoryEnabled() ? "Supported" : "Unsupported");
}
private String pad(String value, int size)
{
boolean right = size < 0;
size = right ? -size : size;
if (value.length() >= size)
{
return value;
}
char[] buf = new char[size];
int padLen = size - value.length();
int valOff = right ? padLen : 0;
int padOff = right ? 0 : value.length();
value.getChars(0, value.length(), buf, valOff);
Arrays.fill(buf, padOff, padOff + padLen, ' ');
return new String(buf);
}
private String toStateString(int state)
{
switch (state)
{
case Component.STATE_DISABLED:
return "disabled";
case Component.STATE_UNSATISFIED:
return "unsatisfied";
case Component.STATE_ACTIVE:
return "active";
case Component.STATE_REGISTERED:
return "registered";
case Component.STATE_FACTORY:
return "factory";
case Component.STATE_DISPOSED:
return "disposed";
case Component.STATE_ENABLING:
return "enabling";
case Component.STATE_ENABLED:
return "enabled";
case Component.STATE_ACTIVATING:
return "activating";
case Component.STATE_DEACTIVATING:
return "deactivating";
case Component.STATE_DISABLING:
return "disabling";
case Component.STATE_DISPOSING:
return "disposing";
default:
return String.valueOf(state);
}
}
private Component[] getComponentFromArg(final String componentIdentifier, PrintStream err)
{
Component[] components = null;
if (componentIdentifier != null)
{
try
{
long componentId = Long.parseLong(componentIdentifier);
Component component = scrService.getComponent(componentId);
if (component == null)
{
err.println("Missing Component with ID " + componentId);
}
else
{
components = new Component[]
{ component };
}
}
catch (NumberFormatException nfe)
{
// check whether it is a component name
components = scrService.getComponents(componentIdentifier);
if (components == null)
{
err.println("Missing Component with ID " + componentIdentifier);
}
}
}
else
{
err.println("Component ID required");
}
return components;
}
}