blob: 44477e60ea0d39dda300d0bc762c6b07f30e0d7b [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.gogo.command;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.net.MalformedURLException;
import java.net.URL;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.Dictionary;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.TreeMap;
import org.apache.felix.service.command.Descriptor;
import org.apache.felix.service.command.Parameter;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.BundleException;
import org.osgi.framework.BundleReference;
import org.osgi.framework.Constants;
import org.osgi.framework.InvalidSyntaxException;
import org.osgi.framework.ServiceReference;
import org.osgi.service.log.LogEntry;
import org.osgi.service.log.LogReaderService;
import org.osgi.service.log.LogService;
import org.osgi.service.packageadmin.PackageAdmin;
import org.osgi.service.startlevel.StartLevel;
public class Basic
{
private final BundleContext m_bc;
public Basic(BundleContext bc)
{
m_bc = bc;
}
@Descriptor("query bundle start level")
public void bundlelevel(@Descriptor("bundle to query") Bundle bundle)
{
// Keep track of service references.
List<ServiceReference> refs = new ArrayList();
// Get start level service.
StartLevel sl = Util.getService(m_bc, StartLevel.class, refs);
if (sl == null)
{
System.out.println("Start Level service is unavailable.");
}
// Get the bundle start level.
else
{
if (bundle != null)
{
System.out.println(bundle + " is level " + sl.getBundleStartLevel(bundle));
}
}
Util.ungetServices(m_bc, refs);
}
@Descriptor("set bundle start level or initial bundle start level")
public void bundlelevel(
@Descriptor("set the bundle's start level") @Parameter(names = { "-s",
"--setlevel" }, presentValue = "true", absentValue = "false") boolean set,
@Descriptor("set the initial bundle start level") @Parameter(names = { "-i",
"--setinitial" }, presentValue = "true", absentValue = "false") boolean initial,
@Descriptor("target level") int level,
@Descriptor("target identifiers") Bundle[] bundles)
{
// Keep track of service references.
List<ServiceReference> refs = new ArrayList();
// Get start level service.
StartLevel sl = Util.getService(m_bc, StartLevel.class, refs);
if (sl == null)
{
System.out.println("Start Level service is unavailable.");
}
else if (set && initial)
{
System.out.println("Cannot specify '-s' and '-i' at the same time.");
}
else if (!set && !initial)
{
System.out.println("Must specify either '-s' or '-i'.");
}
else if (level <= 0)
{
System.out.println("Specified start level must be greater than zero.");
}
// Set the initial bundle start level.
else if (initial)
{
if ((bundles != null) && (bundles.length == 0))
{
sl.setInitialBundleStartLevel(level);
}
else
{
System.out.println("Cannot specify bundles when setting initial start level.");
}
}
// Set the bundle start level.
else if (set)
{
if ((bundles != null) && (bundles.length != 0))
{
for (Bundle bundle : bundles)
{
sl.setBundleStartLevel(bundle, level);
}
}
else
{
System.out.println("Must specify target bundles.");
}
}
Util.ungetServices(m_bc, refs);
}
@Descriptor("query framework active start level")
public void frameworklevel()
{
// Keep track of service references.
List<ServiceReference> refs = new ArrayList();
// Get start level service.
StartLevel sl = Util.getService(m_bc, StartLevel.class, refs);
if (sl == null)
{
System.out.println("Start Level service is unavailable.");
}
System.out.println("Level is " + sl.getStartLevel());
Util.ungetServices(m_bc, refs);
}
@Descriptor("set framework active start level")
public void frameworklevel(@Descriptor("target start level") int level)
{
// Keep track of service references.
List<ServiceReference> refs = new ArrayList();
// Get start level service.
StartLevel sl = Util.getService(m_bc, StartLevel.class, refs);
if (sl == null)
{
System.out.println("Start Level service is unavailable.");
}
sl.setStartLevel(level);
Util.ungetServices(m_bc, refs);
}
@Descriptor("display bundle headers")
public void headers(@Descriptor("target bundles") Bundle[] bundles)
{
bundles = ((bundles == null) || (bundles.length == 0)) ? m_bc.getBundles()
: bundles;
for (Bundle bundle : bundles)
{
String title = Util.getBundleName(bundle);
System.out.println("\n" + title);
System.out.println(Util.getUnderlineString(title.length()));
Dictionary dict = bundle.getHeaders();
Enumeration keys = dict.keys();
while (keys.hasMoreElements())
{
Object k = (String) keys.nextElement();
Object v = dict.get(k);
System.out.println(k + " = " + Util.getValueString(v));
}
}
}
@Descriptor("displays available commands")
public void help()
{
Map<String, List<Method>> commands = getCommands();
for (String name : commands.keySet())
{
System.out.println(name);
}
}
@Descriptor("displays information about a specific command")
public void help(@Descriptor("target command") String name)
{
Map<String, List<Method>> commands = getCommands();
List<Method> methods = null;
// If the specified command doesn't have a scope, then
// search for matching methods by ignoring the scope.
int scopeIdx = name.indexOf(':');
if (scopeIdx < 0)
{
for (Entry<String, List<Method>> entry : commands.entrySet())
{
String k = entry.getKey().substring(entry.getKey().indexOf(':') + 1);
if (name.equals(k))
{
name = entry.getKey();
methods = entry.getValue();
break;
}
}
}
// Otherwise directly look up matching methods.
else
{
methods = commands.get(name);
}
if ((methods != null) && (methods.size() > 0))
{
for (Method m : methods)
{
Descriptor d = m.getAnnotation(Descriptor.class);
if (d == null)
{
System.out.println("\n" + m.getName());
}
else
{
System.out.println("\n" + m.getName() + " - " + d.value());
}
System.out.println(" scope: " + name.substring(0, name.indexOf(':')));
// Get flags and options.
Class[] paramTypes = m.getParameterTypes();
Map<String, Parameter> flags = new TreeMap();
Map<String, String> flagDescs = new TreeMap();
Map<String, Parameter> options = new TreeMap();
Map<String, String> optionDescs = new TreeMap();
List<String> params = new ArrayList();
Annotation[][] anns = m.getParameterAnnotations();
for (int paramIdx = 0; paramIdx < anns.length; paramIdx++)
{
Parameter p = findAnnotation(anns[paramIdx], Parameter.class);
d = findAnnotation(anns[paramIdx], Descriptor.class);
if (p != null)
{
if (p.presentValue().equals(Parameter.UNSPECIFIED))
{
options.put(p.names()[0], p);
if (d != null)
{
optionDescs.put(p.names()[0], d.value());
}
}
else
{
flags.put(p.names()[0], p);
if (d != null)
{
flagDescs.put(p.names()[0], d.value());
}
}
}
else if (d != null)
{
params.add(paramTypes[paramIdx].getSimpleName());
params.add(d.value());
}
else
{
params.add(paramTypes[paramIdx].getSimpleName());
params.add("");
}
}
// Print flags and options.
if (flags.size() > 0)
{
System.out.println(" flags:");
for (Entry<String, Parameter> entry : flags.entrySet())
{
// Print all aliases.
String[] names = entry.getValue().names();
System.out.print(" " + names[0]);
for (int aliasIdx = 1; aliasIdx < names.length; aliasIdx++)
{
System.out.print(", " + names[aliasIdx]);
}
System.out.println(" " + flagDescs.get(entry.getKey()));
}
}
if (options.size() > 0)
{
System.out.println(" options:");
for (Entry<String, Parameter> entry : options.entrySet())
{
// Print all aliases.
String[] names = entry.getValue().names();
System.out.print(" " + names[0]);
for (int aliasIdx = 1; aliasIdx < names.length; aliasIdx++)
{
System.out.print(", " + names[aliasIdx]);
}
System.out.println(" "
+ optionDescs.get(entry.getKey())
+ ((entry.getValue().absentValue() == null) ? ""
: " [optional]"));
}
}
if (params.size() > 0)
{
System.out.println(" parameters:");
for (Iterator<String> it = params.iterator(); it.hasNext();)
{
System.out.println(" " + it.next() + " " + it.next());
}
}
}
}
}
private static <T extends Annotation> T findAnnotation(Annotation[] anns,
Class<T> clazz)
{
for (int i = 0; (anns != null) && (i < anns.length); i++)
{
if (clazz.isInstance(anns[i]))
{
return clazz.cast(anns[i]);
}
}
return null;
}
private Map<String, List<Method>> getCommands()
{
ServiceReference[] refs = null;
try
{
refs = m_bc.getAllServiceReferences(null, "(osgi.command.scope=*)");
}
catch (InvalidSyntaxException ex)
{
// This should never happen.
}
Map<String, List<Method>> commands = new TreeMap();
for (ServiceReference ref : refs)
{
Object svc = m_bc.getService(ref);
if (svc != null)
{
String scope = (String) ref.getProperty("osgi.command.scope");
Object ofunc = ref.getProperty("osgi.command.function");
String[] funcs = (ofunc instanceof String[]) ? (String[]) ofunc
: new String[] { String.valueOf(ofunc) };
for (String func : funcs)
{
commands.put(scope + ":" + func, new ArrayList());
}
if (!commands.isEmpty())
{
Method[] methods = svc.getClass().getMethods();
for (Method method : methods)
{
List<Method> commandMethods = commands.get(scope + ":"
+ method.getName());
if (commandMethods != null)
{
commandMethods.add(method);
}
}
}
// Remove any missing commands.
Iterator<Entry<String, List<Method>>> it = commands.entrySet().iterator();
while (it.hasNext())
{
if (it.next().getValue().size() == 0)
{
it.remove();
}
}
}
}
return commands;
}
@Descriptor("install bundle using URLs")
public void install(@Descriptor("target URLs") String[] urls)
{
StringBuffer sb = new StringBuffer();
for (String url : urls)
{
String location = url.trim();
Bundle bundle = null;
try
{
bundle = m_bc.installBundle(location, null);
}
catch (IllegalStateException ex)
{
System.err.println(ex.toString());
}
catch (BundleException ex)
{
if (ex.getNestedException() != null)
{
System.err.println(ex.getNestedException().toString());
}
else
{
System.err.println(ex.toString());
}
}
catch (Exception ex)
{
System.err.println(ex.toString());
}
if (bundle != null)
{
if (sb.length() > 0)
{
sb.append(", ");
}
sb.append(bundle.getBundleId());
}
}
if (sb.toString().indexOf(',') > 0)
{
System.out.println("Bundle IDs: " + sb.toString());
}
else if (sb.length() > 0)
{
System.out.println("Bundle ID: " + sb.toString());
}
}
@Descriptor("list all installed bundles")
public void lb(
@Descriptor("show location") @Parameter(names = { "-l", "--location" }, presentValue = "true", absentValue = "false") boolean showLoc,
@Descriptor("show symbolic name") @Parameter(names = { "-s", "--symbolicname" }, presentValue = "true", absentValue = "false") boolean showSymbolic,
@Descriptor("show update location") @Parameter(names = { "-u", "--updatelocation" }, presentValue = "true", absentValue = "false") boolean showUpdate)
{
lb(showLoc, showSymbolic, showUpdate, null);
}
@Descriptor("list installed bundles matching a substring")
public void lb(
@Descriptor("show location") @Parameter(names = { "-l", "--location" }, presentValue = "true", absentValue = "false") boolean showLoc,
@Descriptor("show symbolic name") @Parameter(names = { "-s", "--symbolicname" }, presentValue = "true", absentValue = "false") boolean showSymbolic,
@Descriptor("show update location") @Parameter(names = { "-u", "--updatelocation" }, presentValue = "true", absentValue = "false") boolean showUpdate,
@Descriptor("subtring matched against name or symbolic name") String pattern)
{
// Keep track of service references.
List<ServiceReference> refs = new ArrayList();
// Get start level service.
StartLevel sl = Util.getService(m_bc, StartLevel.class, refs);
if (sl == null)
{
System.out.println("Start Level service is unavailable.");
}
List<Bundle> found = new ArrayList();
if (pattern == null)
{
found.addAll(Arrays.asList(m_bc.getBundles()));
}
else
{
Bundle[] bundles = m_bc.getBundles();
for (int i = 0; i < bundles.length; i++)
{
Bundle bundle = bundles[i];
String name = (String) bundle.getHeaders().get(Constants.BUNDLE_NAME);
if (matchBundleName(bundle.getSymbolicName(), pattern)
|| matchBundleName(name, pattern))
{
found.add(bundle);
}
}
}
if (found.size() > 0)
{
printBundleList((Bundle[]) found.toArray(new Bundle[found.size()]), sl,
showLoc, showSymbolic, showUpdate);
}
else
{
System.out.println("No matching bundles found");
}
Util.ungetServices(m_bc, refs);
}
private boolean matchBundleName(String name, String pattern)
{
return (name != null) && name.toLowerCase().contains(pattern.toLowerCase());
}
@Descriptor("display all matching log entries")
public void log(
@Descriptor("minimum log level [ debug | info | warn | error ]") String logLevel)
{
log(-1, logLevel);
}
@Descriptor("display some matching log entries")
public void log(@Descriptor("maximum number of entries") int maxEntries,
@Descriptor("minimum log level [ debug | info | warn | error ]") String logLevel)
{
// Keep track of service references.
List<ServiceReference> refs = new ArrayList();
// Get start level service.
LogReaderService lrs = Util.getService(m_bc, LogReaderService.class, refs);
if (lrs == null)
{
System.out.println("Log reader service is unavailable.");
}
else
{
Enumeration entries = lrs.getLog();
int minLevel = logLevelAsInt(logLevel);
int index = 0;
while (entries.hasMoreElements() && (maxEntries < 0 || index < maxEntries))
{
LogEntry entry = (LogEntry) entries.nextElement();
if (entry.getLevel() <= minLevel)
{
display(entry);
index++;
}
}
Util.ungetServices(m_bc, refs);
}
}
private void display(LogEntry entry)
{
SimpleDateFormat sdf = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss");
StringBuffer buffer = new StringBuffer();
buffer.append(sdf.format(new Date(entry.getTime()))).append(" ");
buffer.append(logLevelAsString(entry.getLevel())).append(" - ");
buffer.append("Bundle: ").append(entry.getBundle().getSymbolicName());
if (entry.getServiceReference() != null)
{
buffer.append(" - ");
buffer.append(entry.getServiceReference().toString());
}
buffer.append(" - ").append(entry.getMessage());
if (entry.getException() != null)
{
buffer.append(" - ");
StringWriter writer = new StringWriter();
PrintWriter pw = new PrintWriter(writer);
entry.getException().printStackTrace(pw);
buffer.append(writer.toString());
}
System.out.println(buffer.toString());
}
private static int logLevelAsInt(String logLevel)
{
if ("error".equalsIgnoreCase(logLevel))
{
return LogService.LOG_ERROR;
}
else if ("warn".equalsIgnoreCase(logLevel))
{
return LogService.LOG_WARNING;
}
else if ("info".equalsIgnoreCase(logLevel))
{
return LogService.LOG_INFO;
}
return LogService.LOG_DEBUG;
}
private static String logLevelAsString(int level)
{
switch (level)
{
case LogService.LOG_ERROR:
return "ERROR";
case LogService.LOG_WARNING:
return "WARNING";
case LogService.LOG_INFO:
return "INFO";
default:
return "DEBUG";
}
}
@Descriptor("refresh bundles")
public void refresh(
@Descriptor("target bundles (can be null or empty)") Bundle[] bundles)
{
if ((bundles != null) && (bundles.length == 0))
{
bundles = null;
}
// Keep track of service references.
List<ServiceReference> refs = new ArrayList();
// Get package admin service.
PackageAdmin pa = Util.getService(m_bc, PackageAdmin.class, refs);
if (pa == null)
{
System.out.println("Package Admin service is unavailable.");
}
pa.refreshPackages((bundles == null) ? null : bundles);
Util.ungetServices(m_bc, refs);
}
@Descriptor("resolve bundles")
public void resolve(
@Descriptor("target bundles (can be null or empty)") Bundle[] bundles)
{
if ((bundles != null) && (bundles.length == 0))
{
bundles = null;
}
// Keep track of service references.
List<ServiceReference> refs = new ArrayList();
// Get package admin service.
PackageAdmin pa = Util.getService(m_bc, PackageAdmin.class, refs);
if (pa == null)
{
System.out.println("Package Admin service is unavailable.");
}
if (!pa.resolveBundles(bundles))
{
System.out.println("Not all bundles could be resolved.");
}
Util.ungetServices(m_bc, refs);
}
@Descriptor("start bundles")
public void start(
@Descriptor("start bundle transiently") @Parameter(names = { "-t", "--transient" }, presentValue = "true", absentValue = "false") boolean trans,
@Descriptor("use declared activation policy") @Parameter(names = { "-p",
"--policy" }, presentValue = "true", absentValue = "false") boolean policy,
@Descriptor("target bundle identifiers or URLs") String[] ss)
{
int options = 0;
// Check for "transient" switch.
if (trans)
{
options |= Bundle.START_TRANSIENT;
}
// Check for "start policy" switch.
if (policy)
{
options |= Bundle.START_ACTIVATION_POLICY;
}
// There should be at least one bundle id.
if ((ss != null) && (ss.length >= 1))
{
for (String s : ss)
{
String id = s.trim();
try
{
Bundle bundle = null;
// The id may be a number or a URL, so check.
if (Character.isDigit(id.charAt(0)))
{
long l = Long.parseLong(id);
bundle = m_bc.getBundle(l);
}
else
{
bundle = m_bc.installBundle(id);
}
if (bundle != null)
{
bundle.start(options);
}
else
{
System.err.println("Bundle ID " + id + " is invalid.");
}
}
catch (NumberFormatException ex)
{
System.err.println("Unable to parse id '" + id + "'.");
}
catch (BundleException ex)
{
if (ex.getNestedException() != null)
{
ex.printStackTrace();
System.err.println(ex.getNestedException().toString());
}
else
{
System.err.println(ex.toString());
}
}
catch (Exception ex)
{
System.err.println(ex.toString());
}
}
}
else
{
System.err.println("Incorrect number of arguments");
}
}
@Descriptor("stop bundles")
public void stop(@Descriptor("stop bundle transiently") @Parameter(names = { "-t",
"--transient" }, presentValue = "true", absentValue = "false") boolean trans,
@Descriptor("target bundles") Bundle[] bundles)
{
if ((bundles == null) || (bundles.length == 0))
{
System.out.println("Please specify the bundles to stop.");
}
int options = 0;
// Check for "transient" switch.
if (trans)
{
options |= Bundle.STOP_TRANSIENT;
}
for (Bundle bundle : bundles)
{
try
{
bundle.stop(options);
}
catch (BundleException ex)
{
if (ex.getNestedException() != null)
{
System.err.println(ex.getNestedException().toString());
}
else
{
System.err.println(ex.toString());
}
}
catch (Exception ex)
{
System.err.println(ex.toString());
}
}
}
@Descriptor("uninstall bundles")
public void uninstall(@Descriptor("target bundles") Bundle[] bundles)
{
if ((bundles == null) || (bundles.length == 0))
{
System.out.println("Please specify the bundles to uninstall.");
}
else
{
try
{
for (Bundle bundle : bundles)
{
bundle.uninstall();
}
}
catch (BundleException ex)
{
if (ex.getNestedException() != null)
{
ex.printStackTrace();
System.err.println(ex.getNestedException().toString());
}
else
{
System.err.println(ex.toString());
}
}
catch (Exception ex)
{
System.err.println(ex.toString());
}
}
}
@Descriptor("update bundle")
public void update(@Descriptor("target bundle") Bundle bundle)
{
try
{
// Get the bundle.
if (bundle != null)
{
bundle.update();
}
}
catch (BundleException ex)
{
if (ex.getNestedException() != null)
{
System.err.println(ex.getNestedException().toString());
}
else
{
System.err.println(ex.toString());
}
}
catch (Exception ex)
{
System.err.println(ex.toString());
}
}
@Descriptor("update bundle from URL")
public void update(@Descriptor("target bundle") Bundle bundle,
@Descriptor("URL from where to retrieve bundle") String location)
{
if (location != null)
{
try
{
// Get the bundle.
if (bundle != null)
{
InputStream is = new URL(location).openStream();
bundle.update(is);
}
else
{
System.err.println("Please specify a bundle to update");
}
}
catch (MalformedURLException ex)
{
System.err.println("Unable to parse URL");
}
catch (IOException ex)
{
System.err.println("Unable to open input stream: " + ex);
}
catch (BundleException ex)
{
if (ex.getNestedException() != null)
{
System.err.println(ex.getNestedException().toString());
}
else
{
System.err.println(ex.toString());
}
}
catch (Exception ex)
{
System.err.println(ex.toString());
}
}
else
{
System.err.println("Must specify a location.");
}
}
@Descriptor("determines from where a bundle loads a class")
public void which(@Descriptor("target bundle") Bundle bundle,
@Descriptor("target class name") String className)
{
if (bundle == null)
{
System.err.println("Please specify a bundle");
}
else
{
Class clazz = null;
try
{
clazz = bundle.loadClass(className);
if (clazz.getClassLoader() == null)
{
System.out.println("Loaded from: boot class loader");
}
else if (clazz.getClassLoader() instanceof BundleReference)
{
Bundle p = ((BundleReference) clazz.getClassLoader()).getBundle();
System.out.println("Loaded from: " + p);
}
else
{
System.out.println("Loaded from: " + clazz.getClassLoader());
}
}
catch (ClassNotFoundException ex)
{
System.out.println("Class not found");
}
}
}
private static void printBundleList(Bundle[] bundles, StartLevel startLevel,
boolean showLoc, boolean showSymbolic, boolean showUpdate)
{
// Display active start level.
if (startLevel != null)
{
System.out.println("START LEVEL " + startLevel.getStartLevel());
}
// Determine last column.
String lastColumn = "Name";
if (showLoc)
{
lastColumn = "Location";
}
else if (showSymbolic)
{
lastColumn = "Symbolic name";
}
else if (showUpdate)
{
lastColumn = "Update location";
}
// Print column headers.
if (startLevel != null)
{
System.out.println(String.format("%5s|%-11s|%5s|%s", "ID", "State", "Level",
lastColumn));
}
else
{
System.out.println(String.format("%5s|%-11s|%s", "ID", "State", lastColumn));
}
for (Bundle bundle : bundles)
{
// Get the bundle name or location.
String name = (String) bundle.getHeaders().get(Constants.BUNDLE_NAME);
// If there is no name, then default to symbolic name.
name = (name == null) ? bundle.getSymbolicName() : name;
// If there is no symbolic name, resort to location.
name = (name == null) ? bundle.getLocation() : name;
// Overwrite the default value is the user specifically
// requested to display one or the other.
if (showLoc)
{
name = bundle.getLocation();
}
else if (showSymbolic)
{
name = bundle.getSymbolicName();
name = (name == null) ? "<no symbolic name>" : name;
}
else if (showUpdate)
{
name = (String) bundle.getHeaders().get(Constants.BUNDLE_UPDATELOCATION);
name = (name == null) ? bundle.getLocation() : name;
}
// Show bundle version if not showing location.
name = (!showLoc && !showUpdate) ? name + " (" + bundle.getVersion() + ")"
: name;
// Get the bundle's start level.
int level = (startLevel == null) ? -1
: startLevel.getBundleStartLevel(bundle);
if (level < 0)
{
System.out.println(String.format("%5d|%-11s|%s", bundle.getBundleId(),
getStateString(bundle), name, bundle.getVersion()));
}
else
{
System.out.println(String.format("%5d|%-11s|%5d|%s",
bundle.getBundleId(), getStateString(bundle), level, name,
bundle.getVersion()));
}
}
}
private static String getStateString(Bundle bundle)
{
int state = bundle.getState();
if (state == Bundle.ACTIVE)
{
return "Active ";
}
else if (state == Bundle.INSTALLED)
{
return "Installed ";
}
else if (state == Bundle.RESOLVED)
{
return "Resolved ";
}
else if (state == Bundle.STARTING)
{
return "Starting ";
}
else if (state == Bundle.STOPPING)
{
return "Stopping ";
}
else
{
return "Unknown ";
}
}
}