/*
* Copyright (c) 2003, KNOPFLERFISH project
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following
* conditions are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* - Neither the name of the KNOPFLERFISH project nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.knopflerfish.bundle.frameworkcommands;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.io.Reader;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Dictionary;
import java.util.Enumeration;
import java.util.StringTokenizer;
import java.util.Vector;
import org.knopflerfish.service.console.CommandGroupAdapter;
import org.knopflerfish.service.console.Session;
import org.knopflerfish.service.console.Util;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.BundleException;
import org.osgi.framework.ServiceReference;
import org.osgi.service.packageadmin.ExportedPackage;
import org.osgi.service.packageadmin.PackageAdmin;
import org.osgi.service.packageadmin.RequiredBundle;
import org.osgi.service.permissionadmin.PermissionAdmin;
import org.osgi.service.permissionadmin.PermissionInfo;
import org.osgi.service.startlevel.StartLevel;
// ******************** FrameworkCommandGroup ********************
/**
* * Interface for commands to be handled by the console. * *
*
* @author Gatespace AB *
* @version $Revision: 1.1.1.1 $
*/
public class FrameworkCommandGroup extends CommandGroupAdapter {
BundleContext bc;
private PackageAdmin packageAdmin = null;
private PermissionAdmin permissionAdmin = null;
private StartLevel startLevel = null;
/**
* * The default directories for bundle jar files. *
*
* The system property org.knopflerfish.gosg.jars holds
* a * semicolon separated path of URLs that is used to complete the *
* location when it is given as a partial URL. *
*
*/
private String[] bundleDirs = null;
FrameworkCommandGroup(BundleContext bc) {
super("framework", "Framework commands");
this.bc = bc;
// all of these services are framework singleton internal services
// thus, we take a shortcut and skip the service tracking
ServiceReference sr = bc.getServiceReference(PackageAdmin.class
.getName());
if (sr != null) {
packageAdmin = (PackageAdmin) bc.getService(sr);
}
sr = bc.getServiceReference(PermissionAdmin.class.getName());
if (sr != null) {
permissionAdmin = (PermissionAdmin) bc.getService(sr);
}
sr = bc.getServiceReference(StartLevel.class.getName());
if (sr != null) {
startLevel = (StartLevel) bc.getService(sr);
}
setupJars();
}
void setupJars() {
String jars = System.getProperty("org.knopflerfish.gosg.jars",
"file:./");
StringTokenizer st = new StringTokenizer(jars, ";");
bundleDirs = new String[st.countTokens()];
for (int i = 0; i < bundleDirs.length; i++) {
String path = st.nextToken();
try {
bundleDirs[i] = new URL(path).toString();
} catch (Exception e) {
bundleDirs[i] = path;
}
}
}
/**
* Completes a partial bundle location using the bundles dir path. * The
* result is the first combination of a directory URL (as * returned by
* getBundleDirs()) and the specified * location that
* results in a valid URL with accessible data.
*/
public String completeLocation(String location) {
int ic = location.indexOf(":");
if (ic < 2 || ic > location.indexOf("/")) {
// URL wihtout protocol complete it.
String[] paths = bundleDirs;
for (int i = 0; i < paths.length; i++) {
try {
URL url = new URL(new URL(paths[i]), location);
if ("file".equals(url.getProtocol())) {
File f = new File(url.getFile());
if (!f.exists() || !f.canRead()) {
continue; // Noope; try next.
}
} else if ("http".equals(url.getProtocol())) {
HttpURLConnection uc = (HttpURLConnection) url
.openConnection();
uc.connect();
int rc = uc.getResponseCode();
uc.disconnect();
if (rc != HttpURLConnection.HTTP_OK) {
continue; // Noope; try next.
}
} else {
// Generic case; Check if we can read data from this URL
InputStream is = null;
try {
is = url.openStream();
} finally {
if (is != null)
is.close();
}
}
location = url.toString();
break; // Found.
} catch (Exception _e) {
}
}
}
return location;
}
//
// Addpermission command
//
public final static String USAGE_ADDPERMISSION = "-b #bundle# | -d | -l #location# [ []]";
public final static String[] HELP_ADDPERMISSION = new String[] {
"Add permissions to bundle",
"-d Add default permissions",
"-b #bundle# Add permission for bundle name or id",
"-l #location# Add permission for location",
" Permission type", " Permission name",
" Permission actions" };
public int cmdAddpermission(Dictionary opts, Reader in, PrintWriter out,
Session session) {
if (permissionAdmin == null) {
out.println("Permission Admin service is not available");
return 1;
}
String loc = null;
PermissionInfo[] pi;
String selection = (String) opts.get("-b");
if (selection != null) {
Bundle[] b = bc.getBundles();
Util.selectBundles(b, new String[] { selection });
for (int i = 0; i < b.length; i++) {
if (b[i] != null) {
if (loc == null) {
loc = b[i].getLocation();
} else {
out.println("ERROR! Multiple bundles selected");
return 1;
}
}
}
if (loc == null) {
out.println("ERROR! No matching bundle");
return 1;
}
pi = permissionAdmin.getPermissions(loc);
} else if (opts.get("-d") != null) {
pi = permissionAdmin.getDefaultPermissions();
} else {
loc = (String) opts.get("-l");
pi = permissionAdmin.getPermissions(loc);
}
PermissionInfo pia;
try {
pia = new PermissionInfo((String)opts.get("type"),
(String)opts.get("name"),
(String)opts.get("actions"));
} catch (IllegalArgumentException e) {
out.println("ERROR! " + e.getMessage());
out.println("PermissionInfo type = " + opts.get("type"));
out.println("PermissionInfo name = " + opts.get("name"));
out.println("PermissionInfo actions = " + opts.get("actions"));
return 1;
}
if (pi != null) {
PermissionInfo[] npi = new PermissionInfo[pi.length + 1];
System.arraycopy(pi, 0, npi, 0, pi.length);
pi = npi;
} else {
pi = new PermissionInfo[1];
}
pi[pi.length - 1] = pia;
if (loc != null) {
permissionAdmin.setPermissions(loc, pi);
} else {
permissionAdmin.setDefaultPermissions(pi);
}
return 0;
}
//
// Bundles command
//
public final static String USAGE_BUNDLES = "[-1] [-i] [-l] [-s] [-t] [] ...";
public final static String[] HELP_BUNDLES = new String[] { "List bundles",
"-1 One column output",
"-i Sort on bundle id",
"-s Sort on bundle start level",
"-t Sort on last modified time",
"-l Verbose output",
" Name or id of bundle" };
public int cmdBundles(Dictionary opts, Reader in, PrintWriter out,
Session session) {
Bundle[] b = getBundles((String[]) opts.get("bundle"),
opts.get("-i") != null,
opts.get("-s") != null,
opts.get("-t") != null);
boolean verbose = (opts.get("-l") != null);
boolean oneColumn = (opts.get("-1") != null);
Vector tmp = new Vector();
for (int i = 0; i < b.length; i++) {
if (b[i] != null) {
tmp.add(b[i]);
}
}
if (tmp.size() == 0) {
out.println("ERROR! No matching bundle");
return 1;
} else {
printBundles(out, (Bundle[])tmp.toArray(new Bundle[tmp.size()]), verbose, oneColumn);
return 0;
}
}
private void printBundles(PrintWriter out, Bundle[] b, boolean verbose, boolean oneColumn) {
boolean needNl = false;
// .println("12 5/active CM Commands 2 1/active CM Service");
String[] lastModified = null;
if (verbose) {
lastModified = new String[b.length];
int longestLM = 0;
SimpleDateFormat dateFormat = new SimpleDateFormat();
for (int i = 0; i < b.length; i++) { // Or just look at the first one...
lastModified[i] = dateFormat.format(new Date(b[i].getLastModified()));
if (lastModified[i].length() > longestLM) {
longestLM = lastModified[i].length();
}
}
String lmHeader = "modified";
if (longestLM > lmHeader.length()) {
String blank = " ";
lmHeader += blank.substring(blank.length() - (longestLM - lmHeader.length()));
}
out.println(" id level/state " + lmHeader + " location");
out.println(" ----------------------------------------------");
} else {
out.println(" id level/state name");
out.println(" --------------------");
}
for (int i = 0; i < b.length; i++) {
String level = null;
try {
level = "" + startLevel.getBundleStartLevel(b[i]);
if (level.length() < 2) {
level = " " + level;
}
} catch (Exception e) {
// no start level set.
}
if (b[i] == null) {
break;
}
if (verbose) {
out.println(Util.showId(b[i]) + showState(b[i])
+ " " + lastModified[i]
+ " " + b[i].getLocation()
+ getBundleSpeciality(b[i]));
} else {
String s = Util.showId(b[i]) + showState(b[i])
+ Util.shortName(b[i]) + getBundleSpeciality(b[i]);
if ((i & 1) == 0 && !oneColumn) {
out.print(s);
int l = 40 - s.length();
if (l > 0) {
String blank = " ";
out.print(blank.substring(blank.length() - l));
}
needNl = true;
} else {
out.println(s);
needNl = false;
}
}
}
if (needNl) {
out.println("");
}
}
private String getBundleSpeciality(Bundle bundle) {
if (packageAdmin == null) {
return "";
}
String retVal = "";
Bundle[] fragments = packageAdmin.getFragments(bundle);
if (fragments != null && fragments.length > 0) {
retVal += "h"; // host
}
Bundle[] hosts = packageAdmin.getHosts(bundle);
if (hosts != null && hosts.length > 0) {
retVal += "f"; // fragment
}
if (retVal.length() > 0) {
retVal = " (" + retVal + ")";
}
return retVal;
}
//
// Call command
//
public final static String USAGE_CALL = " [] ...";
public final static String[] HELP_CALL = new String[] {
"Call a method with zero or more java.lang.String",
"arguments in a registered service.",
" Service interface",
" Method in service to call",
" Arguments to method. If arguments",
" are on the form \"value::type\", the value",
" will be attempted to created as the",
" specified type", };
public int cmdCall(Dictionary opts, Reader in, PrintWriter out,
Session session) {
int res = 1;
final String si = (String) opts.get("interface");
final ServiceReference sr = (ServiceReference) AccessController
.doPrivileged(new PrivilegedAction() {
public Object run() {
return bc.getServiceReference(si);
}
});
if (sr == null) {
out.println("No such service reference class: " + si);
return 1;
}
Object s = AccessController.doPrivileged(new PrivilegedAction() {
public Object run() {
return bc.getService(sr);
}
});
if (s == null) {
out.println("No such service: " + si);
return 1;
}
String method = (String) opts.get("method");
Class[] parameterTypes = null;
Object[] methodArgs = null;
String[] args = (String[]) opts.get("args");
if (args == null) {
args = new String[0];
}
methodArgs = new Object[args.length];
try {
Method m = findMethod(s.getClass(), method, args.length);
if (m != null) {
parameterTypes = m.getParameterTypes();
} else {
parameterTypes = new Class[args.length];
}
for (int i = 0; i < args.length; i++) {
String val = args[i];
String className = String.class.getName();
int ix = val.indexOf("::");
if (ix != -1) {
className = val.substring(ix + 2);
val = val.substring(0, ix);
}
if (m == null) {
methodArgs[i] = makeObject(val, className);
parameterTypes[i] = getClass(className);
} else {
methodArgs[i] = makeObject(val, parameterTypes[i].getName());
}
}
if (m == null) {
m = s.getClass().getMethod(method, parameterTypes);
}
out.println("Result: " + Util.showObject(m.invoke(s, methodArgs)));
res = 0;
} catch (InvocationTargetException e) {
out.println("Exception thrown by call");
e.getTargetException().printStackTrace(out);
} catch (IllegalAccessException e) {
out.println("Call method not accessible (must be public)");
} catch (NullPointerException e) {
out.println("Internal error: " + e);
} catch (IllegalArgumentException e) {
out.println("Internal error: " + e);
} catch (NoSuchMethodException e) {
out.println("No method '" + method + "' with matching arguments: "
+ e);
}
bc.ungetService(sr);
return res;
}
Class getClass(String className) {
try {
if ("int".equals(className)) {
return Integer.TYPE;
} else if ("boolean".equals(className)) {
return Boolean.TYPE;
} else if ("long".equals(className)) {
return Long.TYPE;
} else if ("string".equals(className)) {
return String.class;
}
if (-1 == className.indexOf(".")) {
className = "java.lang." + className;
}
return Class.forName(className);
} catch (Exception e) {
throw new IllegalArgumentException("Unknown class " + className);
}
}
Method findMethod(Class clazz, String name, int nArgs) {
Method[] methods = clazz.getDeclaredMethods();
Vector v = new Vector();
for (int i = 0; i < methods.length; i++) {
if (methods[i].getName().equals(name)
&& methods[i].getParameterTypes().length == nArgs) {
v.addElement(methods[i]);
}
}
if (v.size() == 1) {
return (Method) v.elementAt(0);
}
return null;
}
Object makeObject(String val, String className) {
try {
Class clazz = getClass(className);
if (clazz == Integer.TYPE) {
return new Integer(val);
}
if (clazz == Long.TYPE) {
return new Long(val);
}
if (clazz == Boolean.TYPE) {
return "true".equals(val) ? Boolean.TRUE : Boolean.FALSE;
}
if (clazz == String.class) {
return val;
}
Constructor cons = clazz
.getConstructor(new Class[] { String.class });
Object r = cons.newInstance(new Object[] { val });
return r;
} catch (Exception e) {
throw new IllegalArgumentException("makeObject(" + val + ", "
+ className + "): " + e);
}
}
//
// Closure command
//
public final static String USAGE_CLOSURE = "";
public final static String[] HELP_CLOSURE = new String[] {
"Display the closure for a bundle",
" - Name or id of bundle" };
public int cmdClosure(Dictionary opts, Reader in, PrintWriter out,
Session session) {
if (packageAdmin == null) {
out.println("Package Admin service is not available");
return 1;
}
String bname = (String) opts.get("bundle");
Bundle[] bl = getBundles(new String[] { bname }, true);
Bundle bundle = bl[0];
if (bundle == null) {
out.println("ERROR! No matching bundle for '" + bname + "'");
return 1;
}
bl = getBundles(null, false, false, false);
// Package
Vector pkgClosure = new Vector();
// This is O(n2) at least, possibly O(n3). Should be improved
for(int b = 0; b < bl.length; b++) {
ExportedPackage[] pkgs = packageAdmin.getExportedPackages(bl[b]);
if (pkgs == null) continue;
for(int p = 0; p < pkgs.length; p++) {
Bundle[] bl2 = pkgs[p].getImportingBundles();
if (bl2 == null) continue;
for(int ib = 0; ib < bl2.length; ib++) {
if(bl2[ib].getBundleId() == bundle.getBundleId() && !pkgClosure.contains(bl[b])) {
pkgClosure.add(bl[b]);
}
}
}
}
pkgClosure.remove(bundle);
if (pkgClosure.size() == 0) {
out.println("No package dependencies");
} else {
out.println("Static dependencies via packages:");
Bundle[] bundles = (Bundle[]) pkgClosure.toArray(new Bundle[pkgClosure.size()]);
printBundles(out, bundles, false, true);
}
// Service
Vector serviceClosure = new Vector();
ServiceReference[] srl = bundle.getServicesInUse();
for (int i = 0; srl != null && i < srl.length; i++) {
if (!serviceClosure.contains(srl[i].getBundle())) {
serviceClosure.add(srl[i].getBundle());
}
}
serviceClosure.remove(bundle);
if(serviceClosure.size() == 0) {
out.println("No service dependencies");
} else {
out.println("Runtime dependencies via services:");
Bundle[] bundles = (Bundle[]) serviceClosure.toArray(new Bundle[serviceClosure.size()]);
printBundles(out, bundles, false, true);
}
// Fragment
Bundle[] fragmentBundles = packageAdmin.getFragments(bundle);
if (fragmentBundles == null) {
out.println("No fragments");
} else {
out.println("Fragments:");
printBundles(out, fragmentBundles, false, true);
}
// Host
Bundle[] hostBundles = packageAdmin.getHosts(bundle);
if (hostBundles == null) {
out.println("No hosts");
} else {
out.println("Hosts:");
printBundles(out, hostBundles, false, true);
}
// Required
Vector required = new Vector();
Vector requiredBy = new Vector();
try { // untested code
RequiredBundle[] requiredBundles = packageAdmin.getRequiredBundles(null);
if (requiredBundles != null) {
for (int reqd = 0; reqd < requiredBundles.length; reqd++) {
Bundle[] requiringBundles = requiredBundles[reqd].getRequiringBundles();
if (requiringBundles == null) continue;
if (requiredBundles[reqd].getBundle().equals(bundle)) {
for (int ring = 0; ring < requiringBundles.length; ring++) {
requiredBy.add(requiringBundles[ring]);
}
} else {
for (int ring = 0; ring < requiringBundles.length; ring++) {
if (requiringBundles[ring].equals(bundle)) {
required.add(requiredBundles[reqd].getBundle());
}
}
}
}
}
} catch (Throwable ignored) {}
if (required.size() == 0) {
out.println("No required bundles");
} else {
out.println("Required bundles:");
Bundle[] bundles = (Bundle[]) required.toArray(new Bundle[required.size()]);
printBundles(out, bundles, false, true);
}
if (requiredBy.size() == 0) {
out.println("No requiring bundles");
} else {
out.println("Requiring bundles:");
Bundle[] bundles = (Bundle[]) requiredBy.toArray(new Bundle[requiredBy.size()]);
printBundles(out, bundles, false, true);
}
return 0;
}
//
// Deletepermission command
//
public final static String USAGE_DELETEPERMISSION = "[-r] -b #bundle# | -d | -l #location# ";
public final static String[] HELP_DELETEPERMISSION = new String[] {
"Delete permissions from a bundle",
"-b #bundle# Delete permission for bundle name or id",
"-d Delete default permissions",
"-l #location# Delete permission for location",
"-r Remove entry if empty",
" Permission type (*, match all)",
" Permission name (*, match all)",
" Permission actions (*, match all)" };
public int cmdDeletepermission(Dictionary opts, Reader in, PrintWriter out,
Session session) {
if (permissionAdmin == null) {
out.println("Permission Admin service is not available");
return 1;
}
String loc = null;
PermissionInfo[] pi;
String selection = (String) opts.get("-b");
if (selection != null) {
Bundle[] b = bc.getBundles();
Util.selectBundles(b, new String[] { selection });
for (int i = 0; i < b.length; i++) {
if (b[i] != null) {
if (loc == null) {
loc = b[i].getLocation();
} else {
out.println("ERROR! Multiple bundles selected");
return 1;
}
}
}
if (loc == null) {
out.println("ERROR! No matching bundle");
return 1;
}
pi = permissionAdmin.getPermissions(loc);
} else if (opts.get("-d") != null) {
pi = permissionAdmin.getDefaultPermissions();
} else {
loc = (String) opts.get("-l");
pi = permissionAdmin.getPermissions(loc);
}
if (pi != null) {
String type = (String) opts.get("type");
String name = (String) opts.get("name");
String actions = (String) opts.get("actions");
int size = 0;
for (int i = 0; i < pi.length; i++) {
if (("*".equals(type) || pi[i].getType().equals(type))
&& ("*".equals(name) || pi[i].getName().equals(name))
&& ("*".equals(actions) || pi[i].getActions().equals(
actions))) {
pi[i] = null;
} else {
size++;
}
}
if (size == 0) {
if (opts.get("-r") != null) {
pi = null;
} else {
pi = new PermissionInfo[0];
}
} else {
PermissionInfo[] npi = new PermissionInfo[size];
for (int i = pi.length - 1; i >= 0; i--) {
if (pi[i] != null) {
npi[--size] = pi[i];
}
}
pi = npi;
}
if (loc != null) {
permissionAdmin.setPermissions(loc, pi);
} else {
permissionAdmin.setDefaultPermissions(pi);
}
}
return 0;
}
//
// Findbundles command
//
public final static String USAGE_FINDBUNDLES = "";
public final static String[] HELP_FINDBUNDLES = new String[] {
"Find bundles with a given symbolic name",
" Symbolic name" };
public int cmdFindbundles(Dictionary opts, Reader in, PrintWriter out,
Session session) {
if (packageAdmin == null) {
out.println("Package Admin service is not available");
return 1;
}
String symbolicName = (String) opts.get("symbolic name");
Bundle[] bundles = packageAdmin.getBundles(symbolicName, null);
if (bundles == null) {
out.println("No bundles found.");
} else {
printBundles(out, bundles, true, true);
}
return 0;
}
//
// Headers command
//
public final static String USAGE_HEADERS = "[-i] [-l #locale#] ...";
public final static String[] HELP_HEADERS = new String[] {
"Show bundle header values",
"-i Sort on bundle id",
"-l #locale# Get localized headers for a given locale",
" Name or id of bundle" };
public int cmdHeaders(Dictionary opts, Reader in, PrintWriter out,
Session session) {
Bundle[] b = getBundles((String[]) opts.get("bundle"),
opts.get("-i") != null);
String locale = (String) opts.get("-l");
boolean found = false;
for (int i = 0; i < b.length; i++) {
if (b[i] != null) {
out.println("Bundle: " + showBundle(b[i]));
Dictionary d = (locale == null ? b[i].getHeaders()
: b[i].getHeaders(locale));
for (Enumeration e = d.keys(); e.hasMoreElements();) {
String key = (String) e.nextElement();
out.println(" " + key + " = "
+ Util.showObject(d.get(key)));
}
found = true;
}
}
if (!found) {
out.println("ERROR! No matching bundle");
return 1;
}
return 0;
}
//
// Install command
//
public final static String USAGE_INSTALL = "[-s] ...";
public final static String[] HELP_INSTALL = new String[] {
"Install one or more bundles", "-s Start bundle(s)",
" Name or id of bundle" };
public int cmdInstall(Dictionary opts, Reader in, PrintWriter out,
Session session) {
String[] loc = (String[]) opts.get("location");
String url = null;
try {
for (int i = 0; i < loc.length; i++) {
url = completeLocation(loc[i]);
Bundle b = bc.installBundle(url);
out.println("Installed: " + showBundle(b));
if (opts.get("-s") != null) {
b.start();
out.println("Started: " + showBundle(b));
}
}
} catch (BundleException e) {
Throwable t = e;
while (t instanceof BundleException
&& ((BundleException) t).getNestedException() != null)
t = ((BundleException) t).getNestedException();
if (t instanceof FileNotFoundException) {
out.println("Couldn't install/start bundle: URL not found: "
+ url);
} else {
out.println("Couldn't install/start bundle: " + url
+ " (due to: " + t + ")");
t.printStackTrace(out);
}
return 1;
}
return 0;
}
//
// Package command
//
public final static String USAGE_PACKAGE = "[-l] -b | -p [] ...";
public final static String[] HELP_PACKAGE = new String[] {
"Show java package information",
"If no package or bundle is specified show all packages",
"-l Verbose output",
"-b Only look at selected bundles",
"-p Only look at selected packages",
" Package or bundle" };
public int cmdPackage(Dictionary opts, Reader in, PrintWriter out,
Session session) {
if (packageAdmin == null) {
out.println("Package Admin service is not available");
return 1;
}
boolean verbose = opts.get("-l") != null;
ExportedPackage[] epkgs;
String[] selection = (String[]) opts.get("selection");
if (opts.get("-b") != null) {
Bundle[] b = getBundles(selection, false);
epkgs = new ExportedPackage[0];
for (int i = 0; i < b.length; i++) {
if (b[i] != null) {
ExportedPackage[] e = packageAdmin
.getExportedPackages(b[i]);
if (e != null) {
if (verbose) {
ExportedPackage[] ne = new ExportedPackage[e.length
+ epkgs.length];
System.arraycopy(epkgs, 0, ne, 0, epkgs.length);
System.arraycopy(e, 0, ne, epkgs.length, e.length);
epkgs = ne;
} else {
out.println("Exported by " + showBundle(b[i]));
out.println(" Package: " + e[0].getName());
for (int j = 1; j < e.length; j++) {
out.println(" " + e[j].getName());
}
}
}
}
}
if (!verbose) {
return 0;
}
} else {
if (selection != null) {
epkgs = new ExportedPackage[selection.length];
for (int i = 0; i < selection.length; i++) {
epkgs[i] = packageAdmin.getExportedPackage(selection[i]);
}
} else {
epkgs = packageAdmin.getExportedPackages((Bundle)null);
// TODO: We should sort here
}
}
for (int i = 0; i < epkgs.length; i++) {
if (epkgs[i] != null) {
out.print("Package: " + epkgs[i].getName());
Bundle b = epkgs[i].getExportingBundle();
if (verbose) {
out.println();
out.println(" specification version: "
+ epkgs[i].getVersion());
out.println(" removal pending: "
+ epkgs[i].isRemovalPending());
out.println(" exporting bundle: " + showBundle(b));
Bundle[] ib = epkgs[i].getImportingBundles();
if (ib != null && ib.length > 0) {
out.println(" importing bundle: "
+ showBundle(ib[0]));
for (int j = 1; j < ib.length; j++) {
out.println(" "
+ showBundle(ib[j]));
}
}
out.println();
} else {
out.println(" exported by " + showBundle(b));
}
} else {
if (verbose) {
out.println("Package not found: " + selection[i]);
out.println();
}
}
}
return 0;
}
//
// Permissions command
//
public final static String USAGE_PERMISSIONS = "[-d] [] ...";
public final static String[] HELP_PERMISSIONS = new String[] {
"Show permission information",
"If no parameters is given show all entries",
"-d Show default permissions",
" Name or id of bundle or an unknown location" };
public int cmdPermissions(Dictionary opts, Reader in, PrintWriter out,
Session session) {
if (permissionAdmin == null) {
out.println("Permission Admin service is not available");
return 1;
}
String[] loclist = permissionAdmin.getLocations();
String[] selection = (String[]) opts.get("selection");
if (loclist != null && selection != null) {
Bundle[] b = bc.getBundles();
Util.selectBundles(b, selection);
lloop: for (int i = 0; i < loclist.length; i++) {
for (int j = 0; j < selection.length; j++) {
if (loclist[i].equals(selection[j])) {
continue lloop;
}
}
for (int j = 0; j < b.length; j++) {
if (b[j] != null && loclist[i].equals(b[j].getLocation())) {
continue lloop;
}
}
loclist[i] = null;
}
}
if (opts.get("-d") != null) {
out.println("Default permissions");
showPerms(out, permissionAdmin.getDefaultPermissions());
}
if (loclist != null) {
Bundle[] b = bc.getBundles();
for (int i = 0; i < loclist.length; i++) {
if (loclist[i] != null) {
int j = b.length;
while (--j >= 0) {
if (loclist[i].equals(b[j].getLocation())) {
break;
}
}
out.println("Location: "
+ loclist[i]
+ (j >= 0 ? " (Bundle #" + b[j].getBundleId() + ")"
: ""));
showPerms(out, permissionAdmin.getPermissions(loclist[i]));
}
}
}
return 0;
}
//
// Refresh command
//
public final static String USAGE_REFRESH = "[] ...";
public final static String[] HELP_REFRESH = new String[] {
"Refresh all exported java packages belong to specified bundle",
"If no bundle is specified refresh all bundles",
" Name or id of bundle" };
public int cmdRefresh(Dictionary opts, Reader in, PrintWriter out,
Session session) {
if (packageAdmin == null) {
out.println("Package Admin service is not available");
return 1;
}
String[] bs = (String[]) opts.get("bundle");
if (bs != null) {
Bundle[] b = getBundles(bs, true);
for (int i = 0; i < b.length; i++) {
if (b[i] == null) {
Bundle[] nb = new Bundle[i];
System.arraycopy(b, 0, nb, 0, nb.length);
b = nb;
break;
}
}
if (b.length == 0) {
out.println("ERROR! No matching bundle");
return 1;
}
packageAdmin.refreshPackages(b);
} else {
packageAdmin.refreshPackages(null);
}
return 0;
}
//
// Resolve command
//
public final static String USAGE_RESOLVE = "[] ...";
public final static String[] HELP_RESOLVE = new String[] {
"Resolve one or more bundles",
"If no bundle is specified resolve all bundles",
" Name or id of bundle" };
public int cmdResolve(Dictionary opts, Reader in, PrintWriter out,
Session session) {
if (packageAdmin == null) {
out.println("Package Admin service is not available");
return 1;
}
String[] bs = (String[]) opts.get("bundle");
Bundle[] b = null;
if (bs != null) {
b = getBundles(bs, true);
for (int i = 0; i < b.length; i++) {
if (b[i] == null) {
Bundle[] nb = new Bundle[i];
System.arraycopy(b, 0, nb, 0, nb.length);
b = nb;
break;
}
}
if (b.length == 0) {
out.println("ERROR! No matching bundle");
return 1;
}
}
packageAdmin.resolveBundles(b);
return 0;
}
//
// Services command
//
public final static String USAGE_SERVICES = "[-i] [-l] [-r] [-u] [] ...";
public final static String[] HELP_SERVICES = new String[] {
"List registered services", "-i Sort on bundle id",
"-l Verbose output",
"-r Show services registered by named bundles (default)",
"-u Show services used by named bundles",
" Name or id of bundle" };
public int cmdServices(final Dictionary opts, Reader in,
final PrintWriter out, Session session) {
final Bundle[] b = getBundles((String[]) opts.get("bundle"), opts
.get("-i") != null);
AccessController.doPrivileged(new PrivilegedAction() {
public Object run() {
for (int i = 0; i < b.length; i++) {
if (b[i] != null) {
out.println("Bundle: " + showBundle(b[i]));
if (opts.get("-r") != null || opts.get("-u") == null) {
ServiceReference[] s = b[i].getRegisteredServices();
if (s != null && s.length > 0) {
out.print(" registered:");
for (int j = 0; j < s.length; j++) {
if (opts.get("-l") != null) {
out.print("\n ");
showLongService(s[j], " ", out);
} else {
out.print(" "+ Util.showServiceClasses(s[j]));
}
}
out.println("");
}
}
if (opts.get("-u") != null) {
ServiceReference[] s = b[i].getServicesInUse();
if (s != null && s.length > 0) {
out.print(" uses:");
for (int j = 0; j < s.length; j++) {
if (opts.get("-l") != null) {
out.print("\n ");
showLongService(s[j], " ", out);
} else {
out.print(" "+ Util.showServiceClasses(s[j]));
}
}
}
out.println("");
}
}
}
return null;
}
});
return 0;
}
void showLongService(ServiceReference s, String pad, PrintWriter out) {
out.print(Util.showServiceClasses(s));
String[] k = s.getPropertyKeys();
for (int i = 0; i < k.length; i++) {
out.print("\n " + pad + k[i] + " = "
+ Util.showObject(s.getProperty(k[i])));
}
}
//
// Start command
//
public final static String USAGE_START = " ...";
public final static String[] HELP_START = new String[] {
"Start one or more bundles", " Name or id of bundle" };
public int cmdStart(Dictionary opts, Reader in, PrintWriter out,
Session session) {
Bundle[] b = getBundles((String[]) opts.get("bundle"), true);
boolean found = false;
for (int i = 0; i < b.length; i++) {
if (b[i] != null) {
try {
b[i].start();
out.println("Started: " + showBundle(b[i]));
} catch (BundleException e) {
Throwable t = e;
while (t instanceof BundleException
&& ((BundleException) t).getNestedException() != null)
t = ((BundleException) t).getNestedException();
out.println("Couldn't start bundle: " + showBundle(b[i])
+ " (due to: " + t + ")");
t.printStackTrace(out);
}
found = true;
}
}
if (!found) {
out.println("ERROR! No matching bundle");
return 1;
}
return 0;
}
//
// Stop command
//
public final static String USAGE_STOP = " ...";
public final static String[] HELP_STOP = new String[] {
"Stop one or more bundles", " Name or id of bundle" };
public int cmdStop(Dictionary opts, Reader in, PrintWriter out,
Session session) {
Bundle[] b = getBundles((String[]) opts.get("bundle"), true);
boolean found = false;
for (int i = b.length - 1; i >= 0; i--) {
if (b[i] != null) {
try {
b[i].stop();
out.println("Stopped: " + showBundle(b[i]));
} catch (BundleException e) {
Throwable t = e;
while (t instanceof BundleException
&& ((BundleException) t).getNestedException() != null)
t = ((BundleException) t).getNestedException();
out.println("Couldn't stop bundle: " + showBundle(b[i])
+ " (due to: " + t + ")");
}
found = true;
}
}
if (!found) {
out.println("ERROR! No matching bundle");
return 1;
}
return 0;
}
//
// Showstate command
//
public final static String USAGE_SHOWSTATE = "[] ...";
public final static String[] HELP_SHOWSTATE = new String[] {
"Show the state of a service, if the service provides state information",
" The service pid(s) of interest" };
public int cmdShowstate(Dictionary opts, Reader in, PrintWriter out,
Session session) {
String[] pids = (String[]) opts.get("pid");
try {
if (pids != null && pids.length > 0) {
for (int i = 0; i < pids.length; i++) {
showstate(out, bc.getServiceReferences(null, "(service.id="
+ pids[i] + ")"));
}
} else
showstate(out, bc.getServiceReferences(null, "(state=*)"));
} catch (Exception e) {
out.println("Error: " + e);
}
return 0;
}
//
// Shutdown command
//
public final static String USAGE_SHUTDOWN = "[]";
public final static String[] HELP_SHUTDOWN = new String[] {
"Shutdown framework", " Exit code for JVM" };
public int cmdShutdown(Dictionary opts, Reader in, PrintWriter out,
Session session) {
String c = (String) opts.get("exit code");
int ec = 0;
if (c != null) {
try {
ec = Integer.parseInt(c);
}
catch (NumberFormatException e) {
out.println("Illegal exit code: must be an integer");
return 1;
}
}
try {
Bundle sysBundle = bc.getBundle(0);
sysBundle.stop();
} catch (Exception e) {
out.println("Failed to stop using system bundle");
try {
System.exit(0);
} catch (Exception e2) {
out.println("Failed to exit using system exit " + e2);
}
}
return 0;
}
//
// Uninstall command
//
public final static String USAGE_UNINSTALL = " ...";
public final static String[] HELP_UNINSTALL = new String[] {
"Uninstall one or more bundles", " Name or id of bundle" };
public int cmdUninstall(Dictionary opts, Reader in, PrintWriter out,
Session session) {
Bundle[] b = getBundles((String[]) opts.get("bundle"), true);
boolean found = false;
for (int i = 0; i < b.length; i++) {
if (b[i] != null) {
try {
b[i].uninstall();
out.println("Uninstalled: " + showBundle(b[i]));
} catch (BundleException e) {
Throwable t = e;
while (t instanceof BundleException
&& ((BundleException) t).getNestedException() != null)
t = ((BundleException) t).getNestedException();
out.println("Couldn't uninstall: " + showBundle(b[i])
+ " (due to: " + t + ")");
}
found = true;
}
}
if (!found) {
out.println("ERROR! No matching bundle");
return 1;
}
return 0;
}
//
// Update command
//
public final static String USAGE_UPDATE = " ...";
public final static String[] HELP_UPDATE = new String[] {
"Update one or more bundles",
" Name or id of bundle",
"Note: Use refresh command to force the framework to do a package update",
"of exported packages used by running bundles." };
public int cmdUpdate(Dictionary opts, Reader in, PrintWriter out,
Session session) {
Bundle[] b = getBundles((String[]) opts.get("bundle"), true);
boolean found = false;
for (int i = b.length - 1; i >= 0; i--) {
if (b[i] != null) {
try {
b[i].update();
out.println("Updated: " + showBundle(b[i]));
} catch (BundleException e) {
Throwable t = e;
while (t instanceof BundleException
&& ((BundleException) t).getNestedException() != null)
t = ((BundleException) t).getNestedException();
out.println("Couldn't update: " + showBundle(b[i])
+ " (due to: " + t + ")");
}
found = true;
}
}
if (!found) {
out.println("ERROR! No matching bundle");
return 1;
}
out
.println("Note: Use refresh command to update exported packages in running bundles");
return 0;
}
public final static String USAGE_FROMUPDATE = " ";
public final static String[] HELP_FROMUPDATE = new String[] {
"Update a bundle from a specific URL",
" - Name or id of bundle",
" - URL to update from",
"Note: Use refresh command to force the framework to do a package update",
"of exported packages used by running bundles." };
public int cmdFromupdate(Dictionary opts, Reader in, PrintWriter out,
Session session) {
String bname = (String) opts.get("bundle");
Bundle[] bl = getBundles(new String[] { bname }, true);
String fromURL = (String) opts.get("url");
Bundle b = bl[0];
if (b == null) {
out.println("ERROR! No matching bundle for '" + bname + "'");
return 1;
}
try {
URL url = new URL(fromURL);
URLConnection conn = url.openConnection();
InputStream inStream = conn.getInputStream();
b.update(inStream);
out.println("Updated: " + showBundle(b));
} catch (BundleException e) {
Throwable t = e;
while (t instanceof BundleException
&& ((BundleException) t).getNestedException() != null)
t = ((BundleException) t).getNestedException();
out.println("Couldn't update: " + showBundle(b) + " (due to: " + t
+ ")");
} catch (Exception e) {
out.println("Couldn't update: " + showBundle(b) + " (due to: " + e
+ ")");
}
out
.println("Note: Use refresh command to update exported packages in running bundles");
return 0;
}
public final static String USAGE_FROMINSTALL = " []";
public final static String[] HELP_FROMINSTALL = new String[] {
"Install a bundle with a specific location from an URL",
" - URL to bundle jar file",
" - Optional location string to use for installation", };
public int cmdFrominstall(Dictionary opts, Reader in, PrintWriter out,
Session session) {
String fromURL = (String) opts.get("url");
String loc = (String) opts.get("location");
if (loc == null) {
loc = fromURL;
}
try {
URL url = new URL(fromURL);
URLConnection conn = url.openConnection();
InputStream inStream = conn.getInputStream();
Bundle b = bc.installBundle(loc, inStream);
out.println("Installed: " + showBundle(b));
} catch (BundleException e) {
Throwable t = e;
while (t instanceof BundleException
&& ((BundleException) t).getNestedException() != null)
t = ((BundleException) t).getNestedException();
out.println("Couldn't install: url=" + fromURL + ", location="
+ loc + " (due to: " + t + ")");
} catch (Exception e) {
out.println("Couldn't install: url=" + fromURL + ", location="
+ loc + " (due to: " + e + ")");
}
return 0;
}
//
// Private methods
//
private void showstate(PrintWriter out, ServiceReference[] srs) {
if (srs != null) {
for (int i = 0; i < srs.length; i++) {
Object state = srs[i].getProperty("state");
if (state != null) {
out.println("State for " + srs[i].getProperty("service.id")
+ ":");
out.println(state.toString());
}
}
}
}
private Bundle[] getBundles(String[] selection, boolean sortNumeric) {
return getBundles(selection, sortNumeric, false, false);
}
private Bundle[] getBundles(String[] selection,
boolean sortNumeric,
boolean sortStartLevel) {
return getBundles(selection, sortNumeric, sortStartLevel, false);
}
private Bundle[] getBundles(String[] selection,
boolean sortNumeric,
boolean sortStartLevel,
boolean sortTime) {
Bundle[] b = bc.getBundles();
Util.selectBundles(b, selection);
if (sortNumeric) {
Util.sortBundlesId(b);
} else {
Util.sortBundles(b, false);
}
if (sortStartLevel) {
sortBundlesStartLevel(b);
}
if (sortTime) {
Util.sortBundlesTime(b);
}
return b;
}
/**
* Sort an array of bundle objects based on their start level All entries
* with no start level is placed at the end of the array.
*
* @param b
* array of bundles to be sorted, modified with result
*/
protected void sortBundlesStartLevel(Bundle[] b) {
int x = b.length;
for (int l = x; x > 0;) {
x = 0;
int p = Integer.MAX_VALUE;
try {
p = startLevel.getBundleStartLevel(b[0]);
} catch (Exception ignored) {
}
for (int i = 1; i < l; i++) {
int n = Integer.MAX_VALUE;
try {
n = startLevel.getBundleStartLevel(b[i]);
} catch (Exception ignored) {
}
if (p > n) {
x = i - 1;
Bundle t = b[x];
b[x] = b[i];
b[i] = t;
} else {
p = n;
}
}
}
}
public String showState(Bundle bundle) {
StringBuffer sb = new StringBuffer();
try {
StringBuffer s = new StringBuffer(Integer.toString(startLevel
.getBundleStartLevel(bundle)));
while (s.length() < 2) {
s.insert(0, " ");
}
sb.append(s.toString());
} catch (Exception ignored) {
sb.append("--");
}
sb.append("/");
switch (bundle.getState()) {
case Bundle.INSTALLED:
sb.append("installed");
break;
case Bundle.RESOLVED:
sb.append("resolved");
break;
case Bundle.STARTING:
sb.append("starting");
break;
case Bundle.ACTIVE:
sb.append("active");
break;
case Bundle.STOPPING:
sb.append("stopping");
break;
case Bundle.UNINSTALLED:
sb.append("uninstalled");
break;
default:
sb.append("ILLEGAL <" + bundle.getState() + "> ");
break;
}
while (sb.length() < 13) {
sb.append(" ");
}
return sb.toString();
}
String showBundle(Bundle b) {
return Util.shortName(b) + " (#" + b.getBundleId() + ")";
}
private void showPerms(PrintWriter out, PermissionInfo[] pi) {
final String shift = " ";
if (pi == null) {
out.println(shift + "DEFAULT");
} else if (pi.length == 0) {
out.println(shift + "NONE");
} else {
for (int i = 0; i < pi.length; i++) {
out.println(shift + pi[i]);
}
}
}
//
// Set start level command
//
public final static String USAGE_STARTLEVEL = "[]";
public final static String[] HELP_STARTLEVEL = new String[] {
"Shows or sets the global startlevel", "[] new start level",
" if no is provided, show current level", };
public int cmdStartlevel(Dictionary opts, Reader in, PrintWriter out,
Session session) {
String levelStr = (String) opts.get("level");
try {
if (levelStr != null) {
int level = Integer.parseInt(levelStr);
startLevel.setStartLevel(level);
} else {
out.println("current start level: "
+ startLevel.getStartLevel());
out.println("initial bundle start level: "
+ startLevel.getInitialBundleStartLevel());
}
return 0;
} catch (Exception e) {
out.println("Failed to show/set startlevel=" + levelStr);
e.printStackTrace(out);
return -1;
}
}
//
// CD command
//
public final static String USAGE_CD = "[-reset] [] ...";
public final static String[] HELP_CD = new String[] {
"Shows or sets URL prefix",
"[-reset] reset prefix list to value startup value",
"[] ... list of URL prefixes for install command", };
public int cmdCd(Dictionary opts, Reader in, PrintWriter out,
Session session) {
String[] prefixes = (String[]) opts.get("prefix");
try {
if (opts.get("-reset") != null) {
setupJars();
}
if (prefixes == null) {
for (int i = 0; i < bundleDirs.length; i++) {
out.println(" " + bundleDirs[i]);
}
} else {
bundleDirs = prefixes;
}
return 0;
} catch (Exception e) {
out.println("Failed to cd");
e.printStackTrace(out);
return -1;
}
}
//
// Set bundle start level
//
public final static String USAGE_BUNDLELEVEL = " [] ...";
public final static String[] HELP_BUNDLELEVEL = new String[] {
"Set startlevel(s) for bundles", " new start level",
" Name or id of bundles",
" If bundle list is empty, set initial",
" start level for new bundles", };
public int cmdBundlelevel(Dictionary opts, Reader in, PrintWriter out,
Session session) {
int level = -1;
try {
level = Integer.parseInt((String) opts.get("level"));
String[] bls = (String[]) opts.get("bundle");
Bundle[] bl = getBundles(bls, false, false);
if (bls == null || bls.length == 0) {
startLevel.setInitialBundleStartLevel(level);
out.println("initial bundle start level set to " + level);
} else {
for (int i = 0; i < bl.length; i++) {
if (bl[i] != null) {
System.out.println("set " + i + " " + bl[i] + " "
+ level);
startLevel.setBundleStartLevel(bl[i], level);
}
}
}
return 0;
} catch (Exception e) {
out.println("Failed to set bundle startlevel=" + level);
e.printStackTrace(out);
return -1;
}
}
}