FELIX-2113: Add obr:find and obr:resolve to find matching resources and show resolution output
git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@912219 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/karaf/pom.xml b/karaf/pom.xml
index d7735fa..890593c 100644
--- a/karaf/pom.xml
+++ b/karaf/pom.xml
@@ -72,7 +72,7 @@
<depends.maven.plugin.version>1.0</depends.maven.plugin.version>
<easymock.version>2.4</easymock.version>
<equinox.version>3.5.1.v20090827</equinox.version>
- <felix.bundlerepository.version>1.4.0</felix.bundlerepository.version>
+ <felix.bundlerepository.version>1.5.0-SNAPSHOT</felix.bundlerepository.version>
<felix.compendium.version>1.2.0</felix.compendium.version>
<felix.configadmin.version>1.2.4</felix.configadmin.version>
<felix.fileinstall.version>2.0.8</felix.fileinstall.version>
diff --git a/karaf/shell/obr/src/main/java/org/apache/felix/karaf/shell/obr/FindCommand.java b/karaf/shell/obr/src/main/java/org/apache/felix/karaf/shell/obr/FindCommand.java
new file mode 100644
index 0000000..51368e2
--- /dev/null
+++ b/karaf/shell/obr/src/main/java/org/apache/felix/karaf/shell/obr/FindCommand.java
@@ -0,0 +1,90 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.felix.karaf.shell.obr;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.felix.gogo.commands.Argument;
+import org.apache.felix.gogo.commands.Command;
+import org.apache.felix.karaf.shell.obr.util.RequirementImpl;
+import org.osgi.framework.Filter;
+import org.osgi.framework.FrameworkUtil;
+import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.framework.Version;
+import org.osgi.service.obr.Capability;
+import org.osgi.service.obr.Repository;
+import org.osgi.service.obr.RepositoryAdmin;
+import org.osgi.service.obr.Requirement;
+import org.osgi.service.obr.Resource;
+
+@Command(scope = "obr", name = "find", description = "Find OBR bundles for a given filter")
+public class FindCommand extends ObrCommandSupport {
+
+ @Argument(index = 0, name = "requirement", description = "Requirement", required = true, multiValued = false)
+ String requirement;
+
+ protected void doExecute(RepositoryAdmin admin) throws Exception {
+ List<Resource> matching = new ArrayList<Resource>();
+ Repository[] repos = admin.listRepositories();
+ Requirement req = parseRequirement(requirement);
+ for (int repoIdx = 0; (repos != null) && (repoIdx < repos.length); repoIdx++) {
+ Resource[] resources = repos[repoIdx].getResources();
+ for (int resIdx = 0; (resources != null) && (resIdx < resources.length); resIdx++) {
+ Capability[] caps = resources[resIdx].getCapabilities();
+ for (int capIdx = 0; (caps != null) && (capIdx < caps.length); capIdx++) {
+ if (req.isSatisfied(caps[capIdx])) {
+ matching.add(resources[resIdx]);
+ break;
+ }
+ }
+ }
+ }
+ if (matching.isEmpty()) {
+ System.out.println("No matching resources.");
+ } else {
+ for (Resource resource : matching) {
+ String name = resource.getPresentationName();
+ Version version = resource.getVersion();
+ System.out.println(version != null ? name + " (" + version + ")" : name);
+ }
+ }
+ }
+
+ private Requirement parseRequirement(String req) throws InvalidSyntaxException {
+ int p = req.indexOf(':');
+ String name;
+ String filter;
+ if (p > 0) {
+ name = req.substring(0, p);
+ filter = req.substring(p + 1);
+ } else {
+ if (req.contains("package")) {
+ name = "package";
+ } else {
+ name = "bundle";
+ }
+ filter = req;
+ }
+ if (!filter.startsWith("(")) {
+ filter = "(" + filter + ")";
+ }
+ Filter flt = FrameworkUtil.createFilter(filter);
+ return new RequirementImpl(name, flt);
+ }
+
+}
\ No newline at end of file
diff --git a/karaf/shell/obr/src/main/java/org/apache/felix/karaf/shell/obr/InfoCommand.java b/karaf/shell/obr/src/main/java/org/apache/felix/karaf/shell/obr/InfoCommand.java
index 493460c..e66a65f 100644
--- a/karaf/shell/obr/src/main/java/org/apache/felix/karaf/shell/obr/InfoCommand.java
+++ b/karaf/shell/obr/src/main/java/org/apache/felix/karaf/shell/obr/InfoCommand.java
@@ -88,7 +88,7 @@
out.println("Requires:");
for (int i = 0; i < reqs.length; i++)
{
- out.println(" " + reqs[i].getFilter());
+ out.println(" " + reqs[i].getName() + ":" + reqs[i].getFilter());
}
}
@@ -98,7 +98,7 @@
out.println("Capabilities:");
for (int i = 0; i < caps.length; i++)
{
- out.println(" " + caps[i].getProperties());
+ out.println(" " + caps[i].getName() + ":" + caps[i].getProperties());
}
}
}
diff --git a/karaf/shell/obr/src/main/java/org/apache/felix/karaf/shell/obr/ObrCommandSupport.java b/karaf/shell/obr/src/main/java/org/apache/felix/karaf/shell/obr/ObrCommandSupport.java
index 94b16c1..80ec89e 100644
--- a/karaf/shell/obr/src/main/java/org/apache/felix/karaf/shell/obr/ObrCommandSupport.java
+++ b/karaf/shell/obr/src/main/java/org/apache/felix/karaf/shell/obr/ObrCommandSupport.java
@@ -114,7 +114,7 @@
String[] target;
int idx = bundle.indexOf(VERSION_DELIM);
if (idx > 0) {
- target = new String[] { bundle.substring(0, idx), bundle.substring(idx) };
+ target = new String[] { bundle.substring(0, idx), bundle.substring(idx+1) };
}
else
{
diff --git a/karaf/shell/obr/src/main/java/org/apache/felix/karaf/shell/obr/ResolveCommand.java b/karaf/shell/obr/src/main/java/org/apache/felix/karaf/shell/obr/ResolveCommand.java
new file mode 100644
index 0000000..a64a6f7
--- /dev/null
+++ b/karaf/shell/obr/src/main/java/org/apache/felix/karaf/shell/obr/ResolveCommand.java
@@ -0,0 +1,128 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.felix.karaf.shell.obr;
+
+import java.util.List;
+
+import org.apache.felix.gogo.commands.Argument;
+import org.apache.felix.gogo.commands.Command;
+import org.apache.felix.gogo.commands.Option;
+import org.apache.felix.karaf.shell.obr.util.RequirementImpl;
+import org.apache.felix.karaf.shell.obr.util.ResourceImpl;
+import org.osgi.framework.Filter;
+import org.osgi.framework.FrameworkUtil;
+import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.service.obr.RepositoryAdmin;
+import org.osgi.service.obr.Requirement;
+import org.osgi.service.obr.Resolver;
+import org.osgi.service.obr.Resource;
+
+@Command(scope = "obr", name = "resolve", description = "Show the resolution output for a given set of requirements")
+public class ResolveCommand extends ObrCommandSupport {
+
+ @Option(name = "-w", aliases = "--why", description = "Display the reason if the inclusion of the resource")
+ boolean why;
+
+ @Argument(index = 0, name = "requirements", description = "Requirements", required = true, multiValued = true)
+ List<String> requirements;
+
+ protected void doExecute(RepositoryAdmin admin) throws Exception {
+ Resource resource = new ResourceImpl(null, null, null, null, null, null, getRequirements(), null, null, null);
+ Resolver resolver = admin.resolver();
+ resolver.add(resource);
+ if (resolver.resolve()) {
+ Resource[] resources;
+ resources = resolver.getRequiredResources();
+ if ((resources != null) && (resources.length > 0)) {
+ System.out.println("Required resource(s):");
+ printUnderline(System.out, 21);
+ for (int resIdx = 0; resIdx < resources.length; resIdx++) {
+ System.out.println(" " + resources[resIdx].getPresentationName()
+ + " (" + resources[resIdx].getVersion() + ")");
+ if (why) {
+ Requirement[] r = resolver.getReason(resources[resIdx]);
+ for (int reqIdx = 0; r != null && reqIdx < r.length; reqIdx++) {
+ System.out.println(" - " + r[reqIdx].getName() + ":" + r[reqIdx].getFilter());
+ }
+ }
+ }
+ }
+ resources = resolver.getOptionalResources();
+ if ((resources != null) && (resources.length > 0)) {
+ System.out.println();
+ System.out.println("Optional resource(s):");
+ printUnderline(System.out, 21);
+ for (int resIdx = 0; resIdx < resources.length; resIdx++) {
+ System.out.println(" " + resources[resIdx].getPresentationName()
+ + " (" + resources[resIdx].getVersion() + ")");
+ if (why) {
+ Requirement[] r = resolver.getReason(resources[resIdx]);
+ for (int reqIdx = 0; r != null && reqIdx < r.length; reqIdx++) {
+ System.out.println(" - " + r[reqIdx].getName() + ":" + r[reqIdx].getFilter());
+ }
+ }
+ }
+ }
+ } else {
+ Requirement[] reqs = resolver.getUnsatisfiedRequirements();
+ if ((reqs != null) && (reqs.length > 0)) {
+ System.out.println("Unsatisfied requirement(s):");
+ printUnderline(System.out, 27);
+ for (int reqIdx = 0; reqIdx < reqs.length; reqIdx++) {
+ System.out.println(" " + reqs[reqIdx].getName() + ":" + reqs[reqIdx].getFilter());
+ Resource[] resources = resolver.getResources(reqs[reqIdx]);
+ for (int resIdx = 0; resIdx < resources.length; resIdx++) {
+ System.out.println(" " + resources[resIdx].getPresentationName());
+ }
+ }
+ } else {
+ System.out.println("Could not resolve targets.");
+ }
+ }
+ }
+
+ private Requirement[] getRequirements() throws InvalidSyntaxException {
+ Requirement[] reqs = new Requirement[requirements.size()];
+ for (int i = 0; i < reqs.length; i++) {
+ reqs[i] = parseRequirement(requirements.get(i));
+ }
+ return reqs;
+ }
+
+ private Requirement parseRequirement(String req) throws InvalidSyntaxException {
+ int p = req.indexOf(':');
+ String name;
+ String filter;
+ if (p > 0) {
+ name = req.substring(0, p);
+ filter = req.substring(p + 1);
+ } else {
+ if (req.contains("package")) {
+ name = "package";
+ } else {
+ name = "bundle";
+ }
+ filter = req;
+ }
+ if (!filter.startsWith("(")) {
+ filter = "(" + filter + ")";
+ }
+ Filter flt = FrameworkUtil.createFilter(filter);
+ return new RequirementImpl(name, flt);
+ }
+
+}
\ No newline at end of file
diff --git a/karaf/shell/obr/src/main/java/org/apache/felix/karaf/shell/obr/SourceCommand.java b/karaf/shell/obr/src/main/java/org/apache/felix/karaf/shell/obr/SourceCommand.java
index 0c81967..3e8dcfd 100644
--- a/karaf/shell/obr/src/main/java/org/apache/felix/karaf/shell/obr/SourceCommand.java
+++ b/karaf/shell/obr/src/main/java/org/apache/felix/karaf/shell/obr/SourceCommand.java
@@ -22,6 +22,7 @@
import org.apache.felix.gogo.commands.Option;
import org.apache.felix.gogo.commands.Argument;
import org.apache.felix.gogo.commands.Command;
+import org.apache.felix.karaf.shell.obr.util.FileUtil;
import org.osgi.service.obr.RepositoryAdmin;
import org.osgi.service.obr.Resource;
diff --git a/karaf/shell/obr/src/main/java/org/apache/felix/karaf/shell/obr/FileUtil.java b/karaf/shell/obr/src/main/java/org/apache/felix/karaf/shell/obr/util/FileUtil.java
similarity index 98%
rename from karaf/shell/obr/src/main/java/org/apache/felix/karaf/shell/obr/FileUtil.java
rename to karaf/shell/obr/src/main/java/org/apache/felix/karaf/shell/obr/util/FileUtil.java
index b70e15a..7ebfbb4 100644
--- a/karaf/shell/obr/src/main/java/org/apache/felix/karaf/shell/obr/FileUtil.java
+++ b/karaf/shell/obr/src/main/java/org/apache/felix/karaf/shell/obr/util/FileUtil.java
@@ -16,7 +16,7 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.apache.felix.karaf.shell.obr;
+package org.apache.felix.karaf.shell.obr.util;
import java.io.BufferedOutputStream;
import java.io.File;
diff --git a/karaf/shell/obr/src/main/java/org/apache/felix/karaf/shell/obr/util/IteratorToEnumeration.java b/karaf/shell/obr/src/main/java/org/apache/felix/karaf/shell/obr/util/IteratorToEnumeration.java
new file mode 100644
index 0000000..fc29ca9
--- /dev/null
+++ b/karaf/shell/obr/src/main/java/org/apache/felix/karaf/shell/obr/util/IteratorToEnumeration.java
@@ -0,0 +1,44 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.felix.karaf.shell.obr.util;
+
+import java.util.Enumeration;
+import java.util.Iterator;
+
+public class IteratorToEnumeration implements Enumeration
+{
+ private Iterator m_iter = null;
+
+ public IteratorToEnumeration(Iterator iter)
+ {
+ m_iter = iter;
+ }
+
+ public boolean hasMoreElements()
+ {
+ if (m_iter == null)
+ return false;
+ return m_iter.hasNext();
+ }
+
+ public Object nextElement()
+ {
+ if (m_iter == null)
+ return null;
+ return m_iter.next();
+ }
+}
diff --git a/karaf/shell/obr/src/main/java/org/apache/felix/karaf/shell/obr/util/MapToDictionary.java b/karaf/shell/obr/src/main/java/org/apache/felix/karaf/shell/obr/util/MapToDictionary.java
new file mode 100644
index 0000000..15283fa
--- /dev/null
+++ b/karaf/shell/obr/src/main/java/org/apache/felix/karaf/shell/obr/util/MapToDictionary.java
@@ -0,0 +1,98 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.felix.karaf.shell.obr.util;
+
+import java.util.Dictionary;
+import java.util.Enumeration;
+import java.util.Map;
+
+/**
+ * This is a simple class that implements a <tt>Dictionary</tt>
+ * from a <tt>Map</tt>. The resulting dictionary is immutatable.
+**/
+public class MapToDictionary extends Dictionary
+{
+ /**
+ * Map source.
+ **/
+ private Map m_map = null;
+
+ public MapToDictionary(Map map)
+ {
+ m_map = map;
+ }
+
+ public void setSourceMap(Map map)
+ {
+ m_map = map;
+ }
+
+ public Enumeration elements()
+ {
+ if (m_map == null)
+ {
+ return null;
+ }
+ return new IteratorToEnumeration(m_map.values().iterator());
+ }
+
+ public Object get(Object key)
+ {
+ if (m_map == null)
+ {
+ return null;
+ }
+ return m_map.get(key);
+ }
+
+ public boolean isEmpty()
+ {
+ if (m_map == null)
+ {
+ return true;
+ }
+ return m_map.isEmpty();
+ }
+
+ public Enumeration keys()
+ {
+ if (m_map == null)
+ {
+ return null;
+ }
+ return new IteratorToEnumeration(m_map.keySet().iterator());
+ }
+
+ public Object put(Object key, Object value)
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ public Object remove(Object key)
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ public int size()
+ {
+ if (m_map == null)
+ {
+ return 0;
+ }
+ return m_map.size();
+ }
+}
\ No newline at end of file
diff --git a/karaf/shell/obr/src/main/java/org/apache/felix/karaf/shell/obr/util/RequirementImpl.java b/karaf/shell/obr/src/main/java/org/apache/felix/karaf/shell/obr/util/RequirementImpl.java
new file mode 100644
index 0000000..7ccf6e8
--- /dev/null
+++ b/karaf/shell/obr/src/main/java/org/apache/felix/karaf/shell/obr/util/RequirementImpl.java
@@ -0,0 +1,76 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.karaf.shell.obr.util;
+
+import org.osgi.framework.Filter;
+import org.osgi.service.obr.Capability;
+import org.osgi.service.obr.Requirement;
+
+/**
+ * @version $Rev$ $Date$
+ */
+public class RequirementImpl implements Requirement {
+ private final String name;
+ private final Filter filter;
+ private final boolean multiple;
+ private final boolean optional;
+ private final boolean extend;
+ private final String comment;
+
+ public RequirementImpl(String name, Filter filter) {
+ this(name, filter, false, false, false, null);
+ }
+
+ public RequirementImpl(String name, Filter filter, boolean multiple, boolean optional, boolean extend, String comment) {
+ this.name = name;
+ this.filter = filter;
+ this.multiple = multiple;
+ this.optional = optional;
+ this.extend = extend;
+ this.comment = comment;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public String getFilter() {
+ return filter.toString();
+ }
+
+ public boolean isMultiple() {
+ return multiple;
+ }
+
+ public boolean isOptional() {
+ return optional;
+ }
+
+ public boolean isExtend() {
+ return extend;
+ }
+
+ public String getComment() {
+ return comment;
+ }
+
+ public boolean isSatisfied(Capability capability) {
+ return filter.match(new MapToDictionary(capability.getProperties()));
+ }
+}
diff --git a/karaf/shell/obr/src/main/java/org/apache/felix/karaf/shell/obr/util/ResourceImpl.java b/karaf/shell/obr/src/main/java/org/apache/felix/karaf/shell/obr/util/ResourceImpl.java
new file mode 100644
index 0000000..cdb7f45
--- /dev/null
+++ b/karaf/shell/obr/src/main/java/org/apache/felix/karaf/shell/obr/util/ResourceImpl.java
@@ -0,0 +1,111 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.karaf.shell.obr.util;
+
+import org.osgi.framework.Version;
+import org.osgi.service.obr.Capability;
+import org.osgi.service.obr.Repository;
+import org.osgi.service.obr.Requirement;
+import org.osgi.service.obr.Resource;
+
+import java.net.URL;
+import java.util.Map;
+
+/**
+ * @version $Rev$ $Date$
+ */
+public class ResourceImpl implements Resource
+{
+
+ private final Map properties;
+ private final String symbolicName;
+ private final String presentationName;
+ private final Version version;
+ private final String id;
+ private final URL url;
+ private final Requirement[] requirements;
+ private final Capability[] capabilities;
+ private final String[] categories;
+ private final Repository repository;
+
+
+ public ResourceImpl(Map properties, String symbolicName, String presentationName, Version version, String id, URL url, Requirement[] requirements, Capability[] capabilities, String[] categories, Repository repository)
+ {
+ this.properties = properties;
+ this.symbolicName = symbolicName;
+ this.presentationName = presentationName;
+ this.version = version;
+ this.id = id;
+ this.url = url;
+ this.requirements = requirements;
+ this.capabilities = capabilities;
+ this.categories = categories;
+ this.repository = repository;
+ }
+
+ public Map getProperties()
+ {
+ return properties;
+ }
+
+ public String getSymbolicName()
+ {
+ return symbolicName;
+ }
+
+ public String getPresentationName()
+ {
+ return presentationName;
+ }
+
+ public Version getVersion()
+ {
+ return version;
+ }
+
+ public String getId()
+ {
+ return id;
+ }
+
+ public URL getURL()
+ {
+ return url;
+ }
+
+ public Requirement[] getRequirements()
+ {
+ return requirements;
+ }
+
+ public Capability[] getCapabilities()
+ {
+ return capabilities;
+ }
+
+ public String[] getCategories()
+ {
+ return categories;
+ }
+
+ public Repository getRepository()
+ {
+ return repository;
+ }
+}
diff --git a/karaf/shell/obr/src/main/resources/OSGI-INF/blueprint/shell-obr.xml b/karaf/shell/obr/src/main/resources/OSGI-INF/blueprint/shell-obr.xml
index 096cc00..b56ed03 100644
--- a/karaf/shell/obr/src/main/resources/OSGI-INF/blueprint/shell-obr.xml
+++ b/karaf/shell/obr/src/main/resources/OSGI-INF/blueprint/shell-obr.xml
@@ -26,6 +26,9 @@
<command name="obr/deploy">
<action class="org.apache.felix.karaf.shell.obr.DeployCommand"/>
</command>
+ <command name="obr/find">
+ <action class="org.apache.felix.karaf.shell.obr.FindCommand"/>
+ </command>
<command name="obr/info">
<action class="org.apache.felix.karaf.shell.obr.InfoCommand"/>
</command>
@@ -35,11 +38,14 @@
<command name="obr/listUrl">
<action class="org.apache.felix.karaf.shell.obr.ListUrlCommand"/>
</command>
+ <command name="obr/refreshUrl">
+ <action class="org.apache.felix.karaf.shell.obr.RefreshUrlCommand"/>
+ </command>
<command name="obr/removeUrl">
<action class="org.apache.felix.karaf.shell.obr.RemoveUrlCommand"/>
</command>
- <command name="obr/refreshUrl">
- <action class="org.apache.felix.karaf.shell.obr.RefreshUrlCommand"/>
+ <command name="obr/resolve">
+ <action class="org.apache.felix.karaf.shell.obr.ResolveCommand"/>
</command>
<command name="obr/source">
<action class="org.apache.felix.karaf.shell.obr.SourceCommand"/>