/* * 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; } } }