Author: cschneider Date: Tue Dec 6 10:58:30 2011 New Revision: 1210856 URL: http://svn.apache.org/viewvc?rev=1210856&view=rev Log: KARAF-1077 Moving old service:list to bundle:services. Adding new service:list and completer for objectClass
Added: karaf/trunk/shell/bundles/src/main/java/org/apache/karaf/shell/bundles/ListBundleServices.java (contents, props changed) - copied, changed from r1210508, karaf/trunk/shell/services/src/main/java/org/apache/karaf/shell/services/ListServices.java karaf/trunk/shell/bundles/src/test/java/org/apache/karaf/shell/bundles/ListServicesTest.java (contents, props changed) - copied, changed from r1210413, karaf/trunk/shell/services/src/test/java/org/apache/karaf/shell/services/ListServicesTest.java karaf/trunk/shell/bundles/src/test/java/org/apache/karaf/shell/bundles/TestBundleFactory.java karaf/trunk/shell/services/src/main/java/org/apache/karaf/shell/services/ObjectClassCompleter.java karaf/trunk/shell/services/src/main/java/org/apache/karaf/shell/services/ObjectClassMatcher.java karaf/trunk/shell/services/src/test/java/org/apache/karaf/shell/services/ListServiceNamesTest.java karaf/trunk/shell/services/src/test/java/org/apache/karaf/shell/services/ObjectClassMatcherTest.java karaf/trunk/shell/services/src/test/java/org/apache/karaf/shell/services/TestBundleFactory.java Modified: karaf/trunk/shell/bundles/pom.xml karaf/trunk/shell/bundles/src/main/resources/OSGI-INF/blueprint/shell-bundles.xml karaf/trunk/shell/services/src/main/java/org/apache/karaf/shell/services/ListServices.java karaf/trunk/shell/services/src/main/resources/OSGI-INF/blueprint/shell-services.xml karaf/trunk/shell/services/src/main/resources/OSGI-INF/bundle.info karaf/trunk/shell/services/src/test/java/org/apache/karaf/shell/services/ListServicesTest.java Modified: karaf/trunk/shell/bundles/pom.xml URL: http://svn.apache.org/viewvc/karaf/trunk/shell/bundles/pom.xml?rev=1210856&r1=1210855&r2=1210856&view=diff ============================================================================== --- karaf/trunk/shell/bundles/pom.xml (original) +++ karaf/trunk/shell/bundles/pom.xml Tue Dec 6 10:58:30 2011 @@ -65,6 +65,11 @@ <scope>provided</scope> </dependency> <dependency> + <groupId>org.slf4j</groupId> + <artifactId>slf4j-jdk14</artifactId> + <scope>test</scope> + </dependency> + <dependency> <groupId>org.apache.felix</groupId> <artifactId>org.apache.felix.utils</artifactId> <scope>provided</scope> Copied: karaf/trunk/shell/bundles/src/main/java/org/apache/karaf/shell/bundles/ListBundleServices.java (from r1210508, karaf/trunk/shell/services/src/main/java/org/apache/karaf/shell/services/ListServices.java) URL: http://svn.apache.org/viewvc/karaf/trunk/shell/bundles/src/main/java/org/apache/karaf/shell/bundles/ListBundleServices.java?p2=karaf/trunk/shell/bundles/src/main/java/org/apache/karaf/shell/bundles/ListBundleServices.java&p1=karaf/trunk/shell/services/src/main/java/org/apache/karaf/shell/services/ListServices.java&r1=1210508&r2=1210856&rev=1210856&view=diff ============================================================================== --- karaf/trunk/shell/services/src/main/java/org/apache/karaf/shell/services/ListServices.java (original) +++ karaf/trunk/shell/bundles/src/main/java/org/apache/karaf/shell/bundles/ListBundleServices.java Tue Dec 6 10:58:30 2011 @@ -14,7 +14,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.karaf.shell.services; +package org.apache.karaf.shell.bundles; import java.util.List; @@ -23,15 +23,14 @@ import org.apache.karaf.shell.commands.C import org.apache.karaf.shell.commands.Option; import org.apache.karaf.shell.console.OsgiCommandSupport; import org.apache.felix.service.command.Function; -import org.apache.karaf.shell.bundles.BundleSelector; import org.apache.karaf.util.ShellUtil; import org.osgi.framework.Bundle; import org.osgi.framework.Constants; import org.osgi.framework.BundleContext; import org.osgi.framework.ServiceReference; -@Command(scope = "service", name = "list", description = "Lists OSGi services.") -public class ListServices extends OsgiCommandSupport { +@Command(scope = "bundle", name = "services", description = "Lists OSGi services per Bundle") +public class ListBundleServices extends OsgiCommandSupport { @Argument(index = 0, name = "ids", description = "The list of bundle (identified by IDs or name or name/version) separated by whitespaces", required = false, multiValued = true) List<String> ids; Propchange: karaf/trunk/shell/bundles/src/main/java/org/apache/karaf/shell/bundles/ListBundleServices.java ------------------------------------------------------------------------------ svn:eol-style = native Modified: karaf/trunk/shell/bundles/src/main/resources/OSGI-INF/blueprint/shell-bundles.xml URL: http://svn.apache.org/viewvc/karaf/trunk/shell/bundles/src/main/resources/OSGI-INF/blueprint/shell-bundles.xml?rev=1210856&r1=1210855&r2=1210856&view=diff ============================================================================== --- karaf/trunk/shell/bundles/src/main/resources/OSGI-INF/blueprint/shell-bundles.xml (original) +++ karaf/trunk/shell/bundles/src/main/resources/OSGI-INF/blueprint/shell-bundles.xml Tue Dec 6 10:58:30 2011 @@ -43,6 +43,9 @@ </action> </command> <command> + <action class="org.apache.karaf.shell.bundles.ListBundleServices"/> + </command> + <command> <action class="org.apache.karaf.shell.bundles.Refresh"/> </command> <command> Copied: karaf/trunk/shell/bundles/src/test/java/org/apache/karaf/shell/bundles/ListServicesTest.java (from r1210413, karaf/trunk/shell/services/src/test/java/org/apache/karaf/shell/services/ListServicesTest.java) URL: http://svn.apache.org/viewvc/karaf/trunk/shell/bundles/src/test/java/org/apache/karaf/shell/bundles/ListServicesTest.java?p2=karaf/trunk/shell/bundles/src/test/java/org/apache/karaf/shell/bundles/ListServicesTest.java&p1=karaf/trunk/shell/services/src/test/java/org/apache/karaf/shell/services/ListServicesTest.java&r1=1210413&r2=1210856&rev=1210856&view=diff ============================================================================== --- karaf/trunk/shell/services/src/test/java/org/apache/karaf/shell/services/ListServicesTest.java (original) +++ karaf/trunk/shell/bundles/src/test/java/org/apache/karaf/shell/bundles/ListServicesTest.java Tue Dec 6 10:58:30 2011 @@ -1,17 +1,7 @@ -package org.apache.karaf.shell.services; -import static org.easymock.EasyMock.createMock; -import static org.easymock.EasyMock.expect; -import static org.easymock.EasyMock.replay; - +package org.apache.karaf.shell.bundles; import java.util.Arrays; -import java.util.Dictionary; -import java.util.Hashtable; import org.junit.Test; -import org.osgi.framework.Bundle; -import org.osgi.framework.BundleContext; -import org.osgi.framework.Constants; -import org.osgi.framework.ServiceReference; public class ListServicesTest { @@ -19,66 +9,31 @@ public class ListServicesTest { } - ServiceReference<?> createServiceRef(String ... objectClass) { - ServiceReference<?> serviceRef = createMock(ServiceReference.class); - expect(serviceRef.getProperty("objectClass")).andReturn(objectClass).atLeastOnce(); - expect(serviceRef.getPropertyKeys()).andReturn(new String[]{"objectClass"}); - replay(serviceRef); - return serviceRef; - } - - Bundle createBundle(long id, String name, ServiceReference<?>[] providedServices, ServiceReference<?>[] usedServices) { - Bundle bundle = createMock(Bundle.class); - expect(bundle.getRegisteredServices()).andReturn(providedServices); - expect(bundle.getServicesInUse()).andReturn(usedServices); - expect(bundle.getBundleId()).andReturn(id); - Dictionary<String, String> headers = new Hashtable<String, String>(); - headers.put(Constants.BUNDLE_NAME, name); - expect(bundle.getHeaders()).andReturn(headers).atLeastOnce(); - replay(bundle); - return bundle; - } - - private Bundle[] createBundles() { - Bundle bundle1 = createBundle(1, "ABundle", new ServiceReference<?>[]{createServiceRef("org.example.MyService")}, new ServiceReference<?>[]{}); - Bundle bundle2 = createBundle(2, "AnotherBundle", new ServiceReference<?>[]{}, new ServiceReference<?>[]{createServiceRef("org.example.MyService")}); - return new Bundle[] { bundle1, bundle2 }; - } - - private BundleContext createBundleContext() { - BundleContext bundleContext = createMock(BundleContext.class); - Bundle[] bundles = createBundles(); - expect(bundleContext.getBundle(0)).andReturn(null); - expect(bundleContext.getBundles()).andReturn(bundles); - expect(bundleContext.getBundle(1)).andReturn(bundles[0]); - expect(bundleContext.getBundle(2)).andReturn(bundles[1]); - replay(bundleContext); - return bundleContext; - } - - @Test public void listAllShort() throws Exception { - ListServices listServices = new ListServices(); - listServices.setBundleContext(createBundleContext()); + System.out.println("listAllShort"); + ListBundleServices listServices = new ListBundleServices(); + listServices.setBundleContext(new TestBundleFactory().createBundleContext()); listServices.doExecute(); } @Test public void listAllLong() throws Exception { - ListServices listServices = new ListServices(); + System.out.println("listAllLong"); + ListBundleServices listServices = new ListBundleServices(); listServices.ids = Arrays.asList(new String[]{"1", "2"}); - listServices.setBundleContext(createBundleContext()); + listServices.setBundleContext(new TestBundleFactory().createBundleContext()); listServices.doExecute(); } - + @Test public void listAllLongServiceUse() throws Exception { - ListServices listServices = new ListServices(); + System.out.println("listAllLongServicesUse"); + ListBundleServices listServices = new ListBundleServices(); listServices.ids = Arrays.asList(new String[]{"1", "2"}); listServices.inUse = true; - listServices.setBundleContext(createBundleContext()); + listServices.setBundleContext(new TestBundleFactory().createBundleContext()); listServices.doExecute(); } Propchange: karaf/trunk/shell/bundles/src/test/java/org/apache/karaf/shell/bundles/ListServicesTest.java ------------------------------------------------------------------------------ svn:mime-type = text/plain Added: karaf/trunk/shell/bundles/src/test/java/org/apache/karaf/shell/bundles/TestBundleFactory.java URL: http://svn.apache.org/viewvc/karaf/trunk/shell/bundles/src/test/java/org/apache/karaf/shell/bundles/TestBundleFactory.java?rev=1210856&view=auto ============================================================================== --- karaf/trunk/shell/bundles/src/test/java/org/apache/karaf/shell/bundles/TestBundleFactory.java (added) +++ karaf/trunk/shell/bundles/src/test/java/org/apache/karaf/shell/bundles/TestBundleFactory.java Tue Dec 6 10:58:30 2011 @@ -0,0 +1,88 @@ +package org.apache.karaf.shell.bundles; + +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.replay; + +import java.util.Collections; +import java.util.Dictionary; +import java.util.Hashtable; + +import org.osgi.framework.Bundle; +import org.osgi.framework.BundleContext; +import org.osgi.framework.Constants; +import org.osgi.framework.ServiceReference; + +public class TestBundleFactory { + ServiceReference<?> createServiceRef(Object ... keyProp) { + ServiceReference<?> serviceRef = createMock(ServiceReference.class); + if (keyProp.length % 2 != 0) { + throw new IllegalArgumentException(""); + } + Hashtable<String, Object> keyPropMap = new Hashtable<String, Object>(); + int c = 0; + while (c < keyProp.length) { + String key = (String)keyProp[c++]; + Object value = (Object)keyProp[c++]; + keyPropMap.put(key, value); + expect(serviceRef.getProperty(key)).andReturn(value).anyTimes(); + } + expect(serviceRef.getPropertyKeys()).andReturn(Collections.list(keyPropMap.keys()).toArray(new String[]{})).anyTimes(); + return serviceRef; + } + + Bundle createBundle(long id, String name) { + Bundle bundle = createMock(Bundle.class); + expect(bundle.getBundleId()).andReturn(id).anyTimes(); + Dictionary<String, String> headers = new Hashtable<String, String>(); + headers.put(Constants.BUNDLE_NAME, name); + expect(bundle.getHeaders()).andReturn(headers).anyTimes(); + return bundle; + } + + private Bundle[] createBundles() { + Bundle bundle1 = createBundle(1, "Bundle A"); + Bundle bundle2 = createBundle(2, "Bundle B"); + Bundle bundle3 = createBundle(3, "Bundle C"); + + ServiceReference<?> ref1 = createServiceRef(Constants.OBJECTCLASS, new String[]{"org.example.MyService"}, + "key1", "value1"); + ServiceReference<?> ref2 = createServiceRef(Constants.OBJECTCLASS, new String[]{"org.example.OtherService"}, "key2", 1); + + addRegisteredServices(bundle1, ref1, ref2); + addRegisteredServices(bundle2, ref2); + expect(bundle3.getRegisteredServices()).andReturn(null).anyTimes(); + + expect(bundle1.getServicesInUse()).andReturn(null).anyTimes(); + addUsedServices(bundle2, ref1); + addUsedServices(bundle3, ref1, ref2); + + expect(ref1.getUsingBundles()).andReturn(new Bundle[]{bundle2, bundle3}).anyTimes(); + expect(ref2.getUsingBundles()).andReturn(new Bundle[]{bundle3}).anyTimes(); + + replay(bundle1, bundle2, bundle3, ref1, ref2); + return new Bundle[] { bundle1, bundle2, bundle3 }; + } + + private void addUsedServices(Bundle bundle, ServiceReference<?> ... refs) { + expect(bundle.getServicesInUse()).andReturn(refs).anyTimes(); + } + + private void addRegisteredServices(Bundle bundle, ServiceReference<?> ... refs) { + expect(bundle.getRegisteredServices()).andReturn(refs).anyTimes(); + for (ServiceReference<?> ref : refs) { + expect(ref.getBundle()).andReturn(bundle); + } + } + + public BundleContext createBundleContext() { + BundleContext bundleContext = createMock(BundleContext.class); + Bundle[] bundles = createBundles(); + expect(bundleContext.getBundles()).andReturn(bundles).anyTimes(); + expect(bundleContext.getBundle(0)).andReturn(null).anyTimes(); + expect(bundleContext.getBundle(1)).andReturn(bundles[0]).anyTimes(); + expect(bundleContext.getBundle(2)).andReturn(bundles[1]).anyTimes(); + replay(bundleContext); + return bundleContext; + } +} Modified: karaf/trunk/shell/services/src/main/java/org/apache/karaf/shell/services/ListServices.java URL: http://svn.apache.org/viewvc/karaf/trunk/shell/services/src/main/java/org/apache/karaf/shell/services/ListServices.java?rev=1210856&r1=1210855&r2=1210856&view=diff ============================================================================== --- karaf/trunk/shell/services/src/main/java/org/apache/karaf/shell/services/ListServices.java (original) +++ karaf/trunk/shell/services/src/main/java/org/apache/karaf/shell/services/ListServices.java Tue Dec 6 10:58:30 2011 @@ -16,88 +16,110 @@ */ package org.apache.karaf.shell.services; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.HashMap; import java.util.List; +import java.util.Map; +import org.apache.felix.service.command.Function; import org.apache.karaf.shell.commands.Argument; import org.apache.karaf.shell.commands.Command; import org.apache.karaf.shell.commands.Option; import org.apache.karaf.shell.console.OsgiCommandSupport; -import org.apache.felix.service.command.Function; -import org.apache.karaf.shell.bundles.BundleSelector; import org.apache.karaf.util.ShellUtil; import org.osgi.framework.Bundle; -import org.osgi.framework.Constants; import org.osgi.framework.BundleContext; +import org.osgi.framework.Constants; import org.osgi.framework.ServiceReference; @Command(scope = "service", name = "list", description = "Lists OSGi services.") public class ListServices extends OsgiCommandSupport { - @Argument(index = 0, name = "ids", description = "The list of bundle (identified by IDs or name or name/version) separated by whitespaces", required = false, multiValued = true) - List<String> ids; - + @Argument(index = 0, name = "objectClass", description = "Name of service objectClass to filter for", required = false, + multiValued = false) + String objectClass; + @Option(name = "-a", aliases = {}, description = "Shows all services. (By default Karaf commands are hidden)", required = false, multiValued = false) boolean showAll; - - @Option(name = "-u", aliases = {}, description = "Shows the services each bundle uses. (By default the provided services are shown)", required = false, multiValued = false) - boolean inUse; + + @Option(name = "-n", aliases = {}, description = "Shows only service class names", required = false, multiValued = false) + boolean onlyNames; protected Object doExecute() throws Exception { - BundleContext bundleContext = getBundleContext(); - BundleSelector selector = new BundleSelector(bundleContext, session); - List<Bundle> bundles = selector.selectBundles(ids, true); - if (bundles == null || bundles.isEmpty()) { - Bundle[] allBundles = bundleContext.getBundles(); - printBundles(allBundles, false); - } else { - printBundles(bundles.toArray(new Bundle[]{}), true); + if (onlyNames) { + listNames(); + return null; } - return null; - } - - private void printBundles(Bundle[] bundles, boolean showProperties) { + List<ServiceReference<?>> serviceRefs = new ArrayList<ServiceReference<?>>(); + Bundle[] bundles = getBundleContext().getBundles(); for (Bundle bundle : bundles) { - ServiceReference<?>[] refs = (inUse) ? bundle.getServicesInUse() : bundle.getRegisteredServices(); - printServices(bundle, refs, showProperties); + ServiceReference<?>[] services = bundle.getRegisteredServices(); + if (services != null) { + for (ServiceReference<?> ref : services) { + String[] objectClasses = (String[])ref.getProperty(Constants.OBJECTCLASS); + if (objectClass == null || ObjectClassMatcher.matchesAtLeastOneName(objectClasses, objectClass)) { + serviceRefs.add(ref); + } + } + } } + + Collections.sort(serviceRefs, new ServiceClassComparator()); + + for (ServiceReference<?> serviceRef : serviceRefs) { + if (!isCommand((String[])serviceRef.getProperty(Constants.OBJECTCLASS))) { + printServiceRef(serviceRef); + } + } + return null; } - private void printServices(Bundle bundle, ServiceReference<?>[] refs, boolean showProperties) { - boolean headerPrinted = false; - boolean needSeparator = false; - - if (refs == null) { - return; + private void listNames() { + Map<String, Integer> serviceNames = getServiceNamesMap(getBundleContext()); + ArrayList<String> serviceNamesList = new ArrayList<String>(serviceNames.keySet()); + Collections.sort(serviceNamesList); + for (String name : serviceNamesList) { + System.out.println(name + " (" + serviceNames.get(name) + ")"); } - - for (ServiceReference<?> serviceRef : refs) { - String[] objectClass = (String[]) serviceRef.getProperty(Constants.OBJECTCLASS); - - boolean print = showAll || !isCommand(objectClass); - - // Print header if we have not already done so. - if (!headerPrinted) { - headerPrinted = true; - System.out.println(""); - String title = ShellUtil.getBundleName(bundle) + ((inUse) ? " uses:" : " provides:"); - System.out.println(title); - System.out.println(ShellUtil.getUnderlineString(title)); - } - - if (print) { - // Print service separator if necessary. - if (needSeparator && showProperties) { - System.out.println("----"); - } - - if (showProperties) { - printProperties(serviceRef); - } else { - System.out.println(ShellUtil.getValueString(objectClass)); + } + + public static Map<String, Integer> getServiceNamesMap(BundleContext bundleContext) { + Map<String, Integer> serviceNames = new HashMap<String, Integer>(); + Bundle[] bundles = bundleContext.getBundles(); + for (Bundle bundle : bundles) { + ServiceReference<?>[] services = bundle.getRegisteredServices(); + if (services != null) { + for (ServiceReference<?> serviceReference : services) { + String[] names = (String[])serviceReference.getProperty(Constants.OBJECTCLASS); + for (String name : names) { + int curCount = (serviceNames.containsKey(name)) ? serviceNames.get(name) : 0; + serviceNames.put(name, curCount + 1); + } } + } + } + return serviceNames; + } - needSeparator = true; + private void printServiceRef(ServiceReference<?> serviceRef) { + String[] objectClass = (String[]) serviceRef.getProperty(Constants.OBJECTCLASS); + String serviceClasses = ShellUtil.getValueString(objectClass); + System.out.println(serviceClasses); + System.out.println(ShellUtil.getUnderlineString(serviceClasses)); + + printProperties(serviceRef); + + String bundleName = ShellUtil.getBundleName(serviceRef.getBundle()); + System.out.println("Provided by : "); + System.out.println(" " + bundleName); + if (serviceRef.getUsingBundles() != null) { + System.out.println("Used by: "); + for (Bundle bundle : serviceRef.getUsingBundles()) { + System.out.println(" " + ShellUtil.getBundleName(bundle)); } } + System.out.println(); } private boolean isCommand(String[] objectClasses) { @@ -111,8 +133,19 @@ public class ListServices extends OsgiCo private void printProperties(ServiceReference<?> serviceRef) { for (String key : serviceRef.getPropertyKeys()) { - System.out.println(key + " = " + ShellUtil.getValueString(serviceRef.getProperty(key))); + if (!Constants.OBJECTCLASS.equals(key)) { + System.out.println(" " + key + " = " + ShellUtil.getValueString(serviceRef.getProperty(key))); + } } } + public final class ServiceClassComparator implements Comparator<ServiceReference<?>> { + @Override + public int compare(ServiceReference<?> o1, ServiceReference<?> o2) { + String[] classes1 = (String[])o1.getProperty(Constants.OBJECTCLASS); + String[] classes2 = (String[])o2.getProperty(Constants.OBJECTCLASS); + return classes1[0].compareTo(classes2[0]); + } + } + } Added: karaf/trunk/shell/services/src/main/java/org/apache/karaf/shell/services/ObjectClassCompleter.java URL: http://svn.apache.org/viewvc/karaf/trunk/shell/services/src/main/java/org/apache/karaf/shell/services/ObjectClassCompleter.java?rev=1210856&view=auto ============================================================================== --- karaf/trunk/shell/services/src/main/java/org/apache/karaf/shell/services/ObjectClassCompleter.java (added) +++ karaf/trunk/shell/services/src/main/java/org/apache/karaf/shell/services/ObjectClassCompleter.java Tue Dec 6 10:58:30 2011 @@ -0,0 +1,54 @@ +/* + * 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.karaf.shell.services; + +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.apache.karaf.shell.console.Completer; +import org.apache.karaf.shell.console.completer.StringsCompleter; +import org.osgi.framework.BundleContext; + +public class ObjectClassCompleter implements Completer { + + private final StringsCompleter delegate = new StringsCompleter(); + + private BundleContext context; + + public void setContext(BundleContext context) { + this.context = context; + } + + @SuppressWarnings("rawtypes") + public int complete(final String buffer, final int cursor, final List candidates) { + delegate.getStrings().clear(); + Map<String, Integer> serviceNamesMap = ListServices.getServiceNamesMap(context); + Set<String> serviceNames = serviceNamesMap.keySet(); + for (String name : serviceNames) { + delegate.getStrings().add(ObjectClassMatcher.getShortName(name)); + } + delegate.getStrings().addAll(serviceNames); + return delegate.complete(buffer, cursor, candidates); + } + + + +} Added: karaf/trunk/shell/services/src/main/java/org/apache/karaf/shell/services/ObjectClassMatcher.java URL: http://svn.apache.org/viewvc/karaf/trunk/shell/services/src/main/java/org/apache/karaf/shell/services/ObjectClassMatcher.java?rev=1210856&view=auto ============================================================================== --- karaf/trunk/shell/services/src/main/java/org/apache/karaf/shell/services/ObjectClassMatcher.java (added) +++ karaf/trunk/shell/services/src/main/java/org/apache/karaf/shell/services/ObjectClassMatcher.java Tue Dec 6 10:58:30 2011 @@ -0,0 +1,43 @@ +/* + * 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.karaf.shell.services; + +public class ObjectClassMatcher { + private ObjectClassMatcher() { + } + + static boolean matchesAtLeastOneName(String[] names, String pattern) { + for (String objectClass : names) { + if (matchesName(objectClass, pattern)) { + return true; + } + } + return false; + } + + static boolean matchesName(String name, String pattern) { + return name.equals(pattern) || getShortName(name).equals(pattern); + } + + static String getShortName(String name) { + int idx = name.lastIndexOf("."); + if (idx + 1 > name.length()) { + idx = 0; + } + return name.substring(idx + 1); + } +} Modified: karaf/trunk/shell/services/src/main/resources/OSGI-INF/blueprint/shell-services.xml URL: http://svn.apache.org/viewvc/karaf/trunk/shell/services/src/main/resources/OSGI-INF/blueprint/shell-services.xml?rev=1210856&r1=1210855&r2=1210856&view=diff ============================================================================== --- karaf/trunk/shell/services/src/main/resources/OSGI-INF/blueprint/shell-services.xml (original) +++ karaf/trunk/shell/services/src/main/resources/OSGI-INF/blueprint/shell-services.xml Tue Dec 6 10:58:30 2011 @@ -17,15 +17,23 @@ limitations under the License. --> -<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"> +<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0" + default-activation="lazy"> <command-bundle xmlns="http://karaf.apache.org/xmlns/shell/v1.1.0"> <command> <action class="org.apache.karaf.shell.services.ListServices"/> + <completers> + <ref component-id="objectClassCompleter" /> + <null/> + </completers> </command> <command> <action class="org.apache.karaf.shell.services.Wait"/> </command> </command-bundle> + <bean id="objectClassCompleter" class="org.apache.karaf.shell.services.ObjectClassCompleter"> + <property name="context" ref="blueprintBundleContext"/> + </bean> </blueprint> \ No newline at end of file Modified: karaf/trunk/shell/services/src/main/resources/OSGI-INF/bundle.info URL: http://svn.apache.org/viewvc/karaf/trunk/shell/services/src/main/resources/OSGI-INF/bundle.info?rev=1210856&r1=1210855&r2=1210856&view=diff ============================================================================== --- karaf/trunk/shell/services/src/main/resources/OSGI-INF/bundle.info (original) +++ karaf/trunk/shell/services/src/main/resources/OSGI-INF/bundle.info Tue Dec 6 10:58:30 2011 @@ -12,7 +12,7 @@ h1. Description This bundle provides the shell commands to manipulate OSGi services. The following commands are available: -* services:list - Gets the list of OSGi services available. +* services:list - Gets the list of OSGi services available * service:wait - Wait for a given OSGi service h1. See also Added: karaf/trunk/shell/services/src/test/java/org/apache/karaf/shell/services/ListServiceNamesTest.java URL: http://svn.apache.org/viewvc/karaf/trunk/shell/services/src/test/java/org/apache/karaf/shell/services/ListServiceNamesTest.java?rev=1210856&view=auto ============================================================================== --- karaf/trunk/shell/services/src/test/java/org/apache/karaf/shell/services/ListServiceNamesTest.java (added) +++ karaf/trunk/shell/services/src/test/java/org/apache/karaf/shell/services/ListServiceNamesTest.java Tue Dec 6 10:58:30 2011 @@ -0,0 +1,34 @@ +/* + * 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.karaf.shell.services; +import org.junit.Test; + +public class ListServiceNamesTest { + + public ListServiceNamesTest() { + + } + + @Test + public void listAll() throws Exception { + ListServices listServices = new ListServices(); + listServices.setBundleContext(new TestBundleFactory().createBundleContext()); + listServices.onlyNames = true; + listServices.doExecute(); + } + +} Modified: karaf/trunk/shell/services/src/test/java/org/apache/karaf/shell/services/ListServicesTest.java URL: http://svn.apache.org/viewvc/karaf/trunk/shell/services/src/test/java/org/apache/karaf/shell/services/ListServicesTest.java?rev=1210856&r1=1210855&r2=1210856&view=diff ============================================================================== --- karaf/trunk/shell/services/src/test/java/org/apache/karaf/shell/services/ListServicesTest.java (original) +++ karaf/trunk/shell/services/src/test/java/org/apache/karaf/shell/services/ListServicesTest.java Tue Dec 6 10:58:30 2011 @@ -1,86 +1,35 @@ -package org.apache.karaf.shell.services; -import static org.easymock.EasyMock.createMock; -import static org.easymock.EasyMock.expect; -import static org.easymock.EasyMock.replay; - -import java.util.Arrays; -import java.util.Dictionary; -import java.util.Hashtable; - -import org.junit.Test; -import org.osgi.framework.Bundle; -import org.osgi.framework.BundleContext; -import org.osgi.framework.Constants; -import org.osgi.framework.ServiceReference; - -public class ListServicesTest { - - public ListServicesTest() { - - } - - ServiceReference<?> createServiceRef(String ... objectClass) { - ServiceReference<?> serviceRef = createMock(ServiceReference.class); - expect(serviceRef.getProperty("objectClass")).andReturn(objectClass).atLeastOnce(); - expect(serviceRef.getPropertyKeys()).andReturn(new String[]{"objectClass"}); - replay(serviceRef); - return serviceRef; - } - - Bundle createBundle(long id, String name, ServiceReference<?>[] providedServices, ServiceReference<?>[] usedServices) { - Bundle bundle = createMock(Bundle.class); - expect(bundle.getRegisteredServices()).andReturn(providedServices); - expect(bundle.getServicesInUse()).andReturn(usedServices); - expect(bundle.getBundleId()).andReturn(id); - Dictionary<String, String> headers = new Hashtable<String, String>(); - headers.put(Constants.BUNDLE_NAME, name); - expect(bundle.getHeaders()).andReturn(headers).atLeastOnce(); - replay(bundle); - return bundle; - } - - private Bundle[] createBundles() { - Bundle bundle1 = createBundle(1, "ABundle", new ServiceReference<?>[]{createServiceRef("org.example.MyService")}, new ServiceReference<?>[]{}); - Bundle bundle2 = createBundle(2, "AnotherBundle", new ServiceReference<?>[]{}, new ServiceReference<?>[]{createServiceRef("org.example.MyService")}); - return new Bundle[] { bundle1, bundle2 }; - } - - private BundleContext createBundleContext() { - BundleContext bundleContext = createMock(BundleContext.class); - Bundle[] bundles = createBundles(); - expect(bundleContext.getBundle(0)).andReturn(null); - expect(bundleContext.getBundles()).andReturn(bundles); - expect(bundleContext.getBundle(1)).andReturn(bundles[0]); - expect(bundleContext.getBundle(2)).andReturn(bundles[1]); - replay(bundleContext); - return bundleContext; - } - - - @Test - public void listAllShort() throws Exception { - ListServices listServices = new ListServices(); - listServices.setBundleContext(createBundleContext()); - listServices.doExecute(); - } - - - @Test - public void listAllLong() throws Exception { - ListServices listServices = new ListServices(); - listServices.ids = Arrays.asList(new String[]{"1", "2"}); - listServices.setBundleContext(createBundleContext()); - listServices.doExecute(); - } - - @Test - public void listAllLongServiceUse() throws Exception { - ListServices listServices = new ListServices(); - listServices.ids = Arrays.asList(new String[]{"1", "2"}); - listServices.inUse = true; - listServices.setBundleContext(createBundleContext()); - listServices.doExecute(); - } - - -} +/* + * 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.karaf.shell.services; + +import org.junit.Test; + +public class ListServicesTest { + + public ListServicesTest() { + + } + + @Test + public void listAll() throws Exception { + ListServices listServices = new ListServices(); + listServices.setBundleContext(new TestBundleFactory().createBundleContext()); + listServices.doExecute(); + } + + +} Added: karaf/trunk/shell/services/src/test/java/org/apache/karaf/shell/services/ObjectClassMatcherTest.java URL: http://svn.apache.org/viewvc/karaf/trunk/shell/services/src/test/java/org/apache/karaf/shell/services/ObjectClassMatcherTest.java?rev=1210856&view=auto ============================================================================== --- karaf/trunk/shell/services/src/test/java/org/apache/karaf/shell/services/ObjectClassMatcherTest.java (added) +++ karaf/trunk/shell/services/src/test/java/org/apache/karaf/shell/services/ObjectClassMatcherTest.java Tue Dec 6 10:58:30 2011 @@ -0,0 +1,45 @@ +/* + * 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.karaf.shell.services; + +import junit.framework.Assert; + +import org.junit.Test; + +public class ObjectClassMatcherTest { + + @Test + public void testGetShortName() { + Assert.assertEquals("TestClass", ObjectClassMatcher.getShortName("org.apache.TestClass")); + Assert.assertEquals("", ObjectClassMatcher.getShortName("test.")); + Assert.assertEquals("TestClass", ObjectClassMatcher.getShortName("TestClass")); + } + + @Test + public void testMatchesName() { + Assert.assertTrue(ObjectClassMatcher.matchesName("org.apache.TestClass", "TestClass")); + Assert.assertTrue(ObjectClassMatcher.matchesName("TestClass", "TestClass")); + } + + @Test + public void testMatchesAtLeastOneName() { + Assert.assertTrue(ObjectClassMatcher.matchesAtLeastOneName(new String[]{"other", "org.apache.TestClass"}, "TestClass")); + Assert.assertFalse(ObjectClassMatcher.matchesAtLeastOneName(new String[]{"TestClass2"}, "TestClass")); + } + + +} Added: karaf/trunk/shell/services/src/test/java/org/apache/karaf/shell/services/TestBundleFactory.java URL: http://svn.apache.org/viewvc/karaf/trunk/shell/services/src/test/java/org/apache/karaf/shell/services/TestBundleFactory.java?rev=1210856&view=auto ============================================================================== --- karaf/trunk/shell/services/src/test/java/org/apache/karaf/shell/services/TestBundleFactory.java (added) +++ karaf/trunk/shell/services/src/test/java/org/apache/karaf/shell/services/TestBundleFactory.java Tue Dec 6 10:58:30 2011 @@ -0,0 +1,104 @@ +/* + * 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.karaf.shell.services; + +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.replay; + +import java.util.Collections; +import java.util.Dictionary; +import java.util.Hashtable; + +import org.osgi.framework.Bundle; +import org.osgi.framework.BundleContext; +import org.osgi.framework.Constants; +import org.osgi.framework.ServiceReference; + +public class TestBundleFactory { + ServiceReference<?> createServiceRef(Object ... keyProp) { + ServiceReference<?> serviceRef = createMock(ServiceReference.class); + if (keyProp.length % 2 != 0) { + throw new IllegalArgumentException(""); + } + Hashtable<String, Object> keyPropMap = new Hashtable<String, Object>(); + int c = 0; + while (c < keyProp.length) { + String key = (String)keyProp[c++]; + Object value = (Object)keyProp[c++]; + keyPropMap.put(key, value); + expect(serviceRef.getProperty(key)).andReturn(value).anyTimes(); + } + expect(serviceRef.getPropertyKeys()).andReturn(Collections.list(keyPropMap.keys()).toArray(new String[]{})).anyTimes(); + return serviceRef; + } + + Bundle createBundle(long id, String name) { + Bundle bundle = createMock(Bundle.class); + expect(bundle.getBundleId()).andReturn(id).anyTimes(); + Dictionary<String, String> headers = new Hashtable<String, String>(); + headers.put(Constants.BUNDLE_NAME, name); + expect(bundle.getHeaders()).andReturn(headers).anyTimes(); + return bundle; + } + + private Bundle[] createBundles() { + Bundle bundle1 = createBundle(1, "Bundle A"); + Bundle bundle2 = createBundle(2, "Bundle B"); + Bundle bundle3 = createBundle(3, "Bundle C"); + + ServiceReference<?> ref1 = createServiceRef(Constants.OBJECTCLASS, new String[]{"org.example.MyService"}, + "key1", "value1"); + ServiceReference<?> ref2 = createServiceRef(Constants.OBJECTCLASS, new String[]{"org.example.OtherService"}, "key2", 1); + + addRegisteredServices(bundle1, ref1, ref2); + addRegisteredServices(bundle2, ref2); + expect(bundle3.getRegisteredServices()).andReturn(null).anyTimes(); + + expect(bundle1.getServicesInUse()).andReturn(null).anyTimes(); + addUsedServices(bundle2, ref1); + addUsedServices(bundle3, ref1, ref2); + + expect(ref1.getUsingBundles()).andReturn(new Bundle[]{bundle2, bundle3}).anyTimes(); + expect(ref2.getUsingBundles()).andReturn(new Bundle[]{bundle3}).anyTimes(); + + replay(bundle1, bundle2, bundle3, ref1, ref2); + return new Bundle[] { bundle1, bundle2, bundle3 }; + } + + private void addUsedServices(Bundle bundle, ServiceReference<?> ... refs) { + expect(bundle.getServicesInUse()).andReturn(refs).anyTimes(); + } + + private void addRegisteredServices(Bundle bundle, ServiceReference<?> ... refs) { + expect(bundle.getRegisteredServices()).andReturn(refs).anyTimes(); + for (ServiceReference<?> ref : refs) { + expect(ref.getBundle()).andReturn(bundle); + } + } + + public BundleContext createBundleContext() { + BundleContext bundleContext = createMock(BundleContext.class); + Bundle[] bundles = createBundles(); + expect(bundleContext.getBundles()).andReturn(bundles).anyTimes(); + expect(bundleContext.getBundle(0)).andReturn(null).anyTimes(); + expect(bundleContext.getBundle(1)).andReturn(bundles[0]).anyTimes(); + expect(bundleContext.getBundle(2)).andReturn(bundles[1]).anyTimes(); + replay(bundleContext); + return bundleContext; + } +}