You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@karaf.apache.org by jb...@apache.org on 2013/12/14 16:21:11 UTC

svn commit: r1550937 - in /karaf/trunk: jndi/command/ jndi/command/src/main/java/org/apache/karaf/jndi/command/ jndi/command/src/main/java/org/apache/karaf/jndi/command/completers/ jndi/command/src/main/resources/OSGI-INF/ jndi/command/src/main/resourc...

Author: jbonofre
Date: Sat Dec 14 15:21:11 2013
New Revision: 1550937

URL: http://svn.apache.org/r1550937
Log:
[KARAF-2511] Add JNDI contexts operation and completers

Added:
    karaf/trunk/jndi/command/src/main/java/org/apache/karaf/jndi/command/ContextsCommand.java
    karaf/trunk/jndi/command/src/main/java/org/apache/karaf/jndi/command/completers/
    karaf/trunk/jndi/command/src/main/java/org/apache/karaf/jndi/command/completers/ContextsCompleter.java
    karaf/trunk/jndi/command/src/main/java/org/apache/karaf/jndi/command/completers/NamesCompleter.java
    karaf/trunk/jndi/command/src/main/java/org/apache/karaf/jndi/command/completers/ServicesIdCompleter.java
Modified:
    karaf/trunk/jndi/command/pom.xml
    karaf/trunk/jndi/command/src/main/resources/OSGI-INF/blueprint/jndi-command.xml
    karaf/trunk/jndi/command/src/main/resources/OSGI-INF/bundle.info
    karaf/trunk/jndi/core/src/main/java/org/apache/karaf/jndi/JndiMBean.java
    karaf/trunk/jndi/core/src/main/java/org/apache/karaf/jndi/JndiService.java
    karaf/trunk/jndi/core/src/main/java/org/apache/karaf/jndi/internal/JndiMBeanImpl.java
    karaf/trunk/jndi/core/src/main/java/org/apache/karaf/jndi/internal/JndiServiceImpl.java
    karaf/trunk/manual/src/main/webapp/users-guide/jndi.conf

Modified: karaf/trunk/jndi/command/pom.xml
URL: http://svn.apache.org/viewvc/karaf/trunk/jndi/command/pom.xml?rev=1550937&r1=1550936&r2=1550937&view=diff
==============================================================================
--- karaf/trunk/jndi/command/pom.xml (original)
+++ karaf/trunk/jndi/command/pom.xml Sat Dec 14 15:21:11 2013
@@ -1,4 +1,4 @@
-<?xml version="1.0" encoding="UTF-8"?>
+ <?xml version="1.0" encoding="UTF-8"?>
 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
 
     <!--
@@ -44,6 +44,11 @@
         </dependency>
 
         <dependency>
+            <groupId>org.osgi</groupId>
+            <artifactId>org.osgi.core</artifactId>
+        </dependency>
+
+        <dependency>
             <groupId>org.apache.karaf.shell</groupId>
             <artifactId>org.apache.karaf.shell.console</artifactId>
         </dependency>

Added: karaf/trunk/jndi/command/src/main/java/org/apache/karaf/jndi/command/ContextsCommand.java
URL: http://svn.apache.org/viewvc/karaf/trunk/jndi/command/src/main/java/org/apache/karaf/jndi/command/ContextsCommand.java?rev=1550937&view=auto
==============================================================================
--- karaf/trunk/jndi/command/src/main/java/org/apache/karaf/jndi/command/ContextsCommand.java (added)
+++ karaf/trunk/jndi/command/src/main/java/org/apache/karaf/jndi/command/ContextsCommand.java Sat Dec 14 15:21:11 2013
@@ -0,0 +1,52 @@
+/*
+ * 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.jndi.command;
+
+import org.apache.karaf.shell.commands.Argument;
+import org.apache.karaf.shell.commands.Command;
+import org.apache.karaf.shell.table.ShellTable;
+
+import java.util.List;
+
+@Command(scope = "jndi", name = "contexts", description = "List the JNDI sub-contexts.")
+public class ContextsCommand extends JndiCommandSupport {
+
+    @Argument(index = 0, name = "context", description = "The base JNDI context", required = false, multiValued = false)
+    String context;
+
+    public Object doExecute() throws Exception {
+        ShellTable table = new ShellTable();
+
+        table.column("JNDI Sub-Context");
+
+        List<String> contexts;
+        if (context == null) {
+            contexts = this.getJndiService().contexts();
+        } else {
+            contexts = this.getJndiService().contexts(context);
+        }
+
+        for (String c : contexts) {
+            table.addRow().addContent(c);
+        }
+
+        table.print(System.out);
+
+        return null;
+    }
+
+}

Added: karaf/trunk/jndi/command/src/main/java/org/apache/karaf/jndi/command/completers/ContextsCompleter.java
URL: http://svn.apache.org/viewvc/karaf/trunk/jndi/command/src/main/java/org/apache/karaf/jndi/command/completers/ContextsCompleter.java?rev=1550937&view=auto
==============================================================================
--- karaf/trunk/jndi/command/src/main/java/org/apache/karaf/jndi/command/completers/ContextsCompleter.java (added)
+++ karaf/trunk/jndi/command/src/main/java/org/apache/karaf/jndi/command/completers/ContextsCompleter.java Sat Dec 14 15:21:11 2013
@@ -0,0 +1,53 @@
+/*
+ * 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.jndi.command.completers;
+
+import org.apache.karaf.jndi.JndiService;
+import org.apache.karaf.shell.console.Completer;
+import org.apache.karaf.shell.console.completer.StringsCompleter;
+
+import java.util.List;
+
+/**
+ * Completers on the JNDI contexts.
+ */
+public class ContextsCompleter implements Completer {
+
+    private JndiService jndiService;
+
+    public int complete(String buffer, int cursor, List candidates) {
+        StringsCompleter delegate = new StringsCompleter();
+        try {
+            List<String> contexts = jndiService.contexts();
+            for (String context : contexts) {
+                delegate.getStrings().add(context);
+            }
+        } catch (Exception e) {
+            // nothing to do
+        }
+        return delegate.complete(buffer, cursor, candidates);
+    }
+
+    public JndiService getJndiService() {
+        return jndiService;
+    }
+
+    public void setJndiService(JndiService jndiService) {
+        this.jndiService = jndiService;
+    }
+
+}

Added: karaf/trunk/jndi/command/src/main/java/org/apache/karaf/jndi/command/completers/NamesCompleter.java
URL: http://svn.apache.org/viewvc/karaf/trunk/jndi/command/src/main/java/org/apache/karaf/jndi/command/completers/NamesCompleter.java?rev=1550937&view=auto
==============================================================================
--- karaf/trunk/jndi/command/src/main/java/org/apache/karaf/jndi/command/completers/NamesCompleter.java (added)
+++ karaf/trunk/jndi/command/src/main/java/org/apache/karaf/jndi/command/completers/NamesCompleter.java Sat Dec 14 15:21:11 2013
@@ -0,0 +1,52 @@
+/*
+ * 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.jndi.command.completers;
+
+import org.apache.karaf.jndi.JndiService;
+import org.apache.karaf.shell.console.Completer;
+import org.apache.karaf.shell.console.completer.StringsCompleter;
+
+import java.util.List;
+
+/**
+ * Completer to the JNDI names.
+ */
+public class NamesCompleter implements Completer {
+
+    private JndiService jndiService;
+
+    public int complete(String buffer, int cursor, List candidates) {
+        StringsCompleter delegate = new StringsCompleter();
+        try {
+            for (String name : jndiService.names().keySet()) {
+                delegate.getStrings().add(name);
+            }
+        } catch (Exception e) {
+            // nothing to do
+        }
+        return delegate.complete(buffer, cursor, candidates);
+    }
+
+    public JndiService getJndiService() {
+        return jndiService;
+    }
+
+    public void setJndiService(JndiService jndiService) {
+        this.jndiService = jndiService;
+    }
+
+}

Added: karaf/trunk/jndi/command/src/main/java/org/apache/karaf/jndi/command/completers/ServicesIdCompleter.java
URL: http://svn.apache.org/viewvc/karaf/trunk/jndi/command/src/main/java/org/apache/karaf/jndi/command/completers/ServicesIdCompleter.java?rev=1550937&view=auto
==============================================================================
--- karaf/trunk/jndi/command/src/main/java/org/apache/karaf/jndi/command/completers/ServicesIdCompleter.java (added)
+++ karaf/trunk/jndi/command/src/main/java/org/apache/karaf/jndi/command/completers/ServicesIdCompleter.java Sat Dec 14 15:21:11 2013
@@ -0,0 +1,59 @@
+/*
+ * 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.jndi.command.completers;
+
+import org.apache.karaf.shell.console.Completer;
+import org.apache.karaf.shell.console.completer.StringsCompleter;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.Constants;
+import org.osgi.framework.ServiceReference;
+
+import java.util.List;
+
+/**
+ * Completer on the OSGi services ID.
+ */
+public class ServicesIdCompleter implements Completer {
+
+    private BundleContext bundleContext;
+
+    public int complete(String buffer, int cursor, List candidates) {
+        StringsCompleter delegate = new StringsCompleter();
+        Bundle[] bundles = bundleContext.getBundles();
+        for (Bundle bundle : bundles) {
+            ServiceReference[] references = bundle.getRegisteredServices();
+            if (references != null) {
+                for (ServiceReference reference : references) {
+                    if (reference.getProperty(Constants.SERVICE_ID) != null) {
+                        delegate.getStrings().add(reference.getProperty(Constants.SERVICE_ID).toString());
+                    }
+                }
+            }
+        }
+        return delegate.complete(buffer, cursor, candidates);
+    }
+
+    public BundleContext getBundleContext() {
+        return bundleContext;
+    }
+
+    public void setBundleContext(BundleContext bundleContext) {
+        this.bundleContext = bundleContext;
+    }
+
+}

Modified: karaf/trunk/jndi/command/src/main/resources/OSGI-INF/blueprint/jndi-command.xml
URL: http://svn.apache.org/viewvc/karaf/trunk/jndi/command/src/main/resources/OSGI-INF/blueprint/jndi-command.xml?rev=1550937&r1=1550936&r2=1550937&view=diff
==============================================================================
--- karaf/trunk/jndi/command/src/main/resources/OSGI-INF/blueprint/jndi-command.xml (original)
+++ karaf/trunk/jndi/command/src/main/resources/OSGI-INF/blueprint/jndi-command.xml Sat Dec 14 15:21:11 2013
@@ -24,32 +24,76 @@
             <action class="org.apache.karaf.jndi.command.AliasCommand">
                 <property name="jndiService" ref="jndiService" />
             </action>
+            <completers>
+                <ref component-id="namesCompleter" />
+                <ref component-id="contextsCompleter" />
+                <null />
+            </completers>
+        </command>
+        <command>
+            <action class="org.apache.karaf.jndi.command.ContextsCommand">
+                <property name="jndiService" ref="jndiService" />
+            </action>
+            <completers>
+                <ref component-id="contextsCompleter" />
+                <null />
+            </completers>
         </command>
         <command>
             <action class="org.apache.karaf.jndi.command.NamesCommand">
                 <property name="jndiService" ref="jndiService" />
             </action>
+            <completers>
+                <ref component-id="contextsCompleter" />
+                <null />
+            </completers>
         </command>
         <command>
             <action class="org.apache.karaf.jndi.command.CreateCommand">
                 <property name="jndiService" ref="jndiService"/>
             </action>
+            <completers>
+                <ref component-id="contextsCompleter" />
+                <null />
+            </completers>
         </command>
         <command>
             <action class="org.apache.karaf.jndi.command.DeleteCommand">
                 <property name="jndiService" ref="jndiService"/>
             </action>
+            <completers>
+                <ref component-id="contextsCompleter" />
+                <null />
+            </completers>
         </command>
         <command>
             <action class="org.apache.karaf.jndi.command.BindCommand">
                 <property name="jndiService" ref="jndiService"/>
             </action>
+            <completers>
+                <ref component-id="servicesIdCompleter" />
+                <ref component-id="contextsCompleter" />
+                <null />
+            </completers>
         </command>
         <command>
             <action class="org.apache.karaf.jndi.command.UnbindCommand">
                 <property name="jndiService" ref="jndiService" />
             </action>
+            <completers>
+                <ref component-id="namesCompleter" />
+            </completers>
         </command>
     </command-bundle>
 
+    <bean id="namesCompleter" class="org.apache.karaf.jndi.command.completers.NamesCompleter">
+        <property name="jndiService" ref="jndiService" />
+    </bean>
+    <bean id="contextsCompleter" class="org.apache.karaf.jndi.command.completers.ContextsCompleter">
+        <property name="jndiService" ref="jndiService" />
+    </bean>
+    <bean id="servicesIdCompleter" class="org.apache.karaf.jndi.command.completers.ServicesIdCompleter">
+        <property name="bundleContext" ref="blueprintBundleContext" />
+    </bean>
+
 </blueprint>
\ No newline at end of file

Modified: karaf/trunk/jndi/command/src/main/resources/OSGI-INF/bundle.info
URL: http://svn.apache.org/viewvc/karaf/trunk/jndi/command/src/main/resources/OSGI-INF/bundle.info?rev=1550937&r1=1550936&r2=1550937&view=diff
==============================================================================
--- karaf/trunk/jndi/command/src/main/resources/OSGI-INF/bundle.info (original)
+++ karaf/trunk/jndi/command/src/main/resources/OSGI-INF/bundle.info Sat Dec 14 15:21:11 2013
@@ -16,6 +16,7 @@ The following commands are available:
 * jndi:alias
 * jndi:bind
 * jndi:create
+* jndi:contexts
 * jndi:delete
 * jndi:names
 * jndi:unbind

Modified: karaf/trunk/jndi/core/src/main/java/org/apache/karaf/jndi/JndiMBean.java
URL: http://svn.apache.org/viewvc/karaf/trunk/jndi/core/src/main/java/org/apache/karaf/jndi/JndiMBean.java?rev=1550937&r1=1550936&r2=1550937&view=diff
==============================================================================
--- karaf/trunk/jndi/core/src/main/java/org/apache/karaf/jndi/JndiMBean.java (original)
+++ karaf/trunk/jndi/core/src/main/java/org/apache/karaf/jndi/JndiMBean.java Sat Dec 14 15:21:11 2013
@@ -17,6 +17,7 @@
 package org.apache.karaf.jndi;
 
 import javax.management.MBeanException;
+import java.util.List;
 import java.util.Map;
 
 /**
@@ -42,6 +43,23 @@ public interface JndiMBean {
     public Map<String, String> getNames(String context) throws MBeanException;
 
     /**
+     * Get a list of JNDI sub-contexts (as attribute).
+     *
+     * @return the MBean attribute containing the list of sub-contexts.
+     * @throws MBeanException
+     */
+    public List<String> getContexts() throws MBeanException;
+
+    /**
+     * Get a list of JNDI sub-contexts children of a given base context.
+     *
+     * @param context the base context.
+     * @return the list of sub-contexts.
+     * @throws MBeanException
+     */
+    public List<String> getContexts(String context) throws MBeanException;
+
+    /**
      * Create a JNDI sub-context.
      *
      * @param context the JNDI sub-context name.

Modified: karaf/trunk/jndi/core/src/main/java/org/apache/karaf/jndi/JndiService.java
URL: http://svn.apache.org/viewvc/karaf/trunk/jndi/core/src/main/java/org/apache/karaf/jndi/JndiService.java?rev=1550937&r1=1550936&r2=1550937&view=diff
==============================================================================
--- karaf/trunk/jndi/core/src/main/java/org/apache/karaf/jndi/JndiService.java (original)
+++ karaf/trunk/jndi/core/src/main/java/org/apache/karaf/jndi/JndiService.java Sat Dec 14 15:21:11 2013
@@ -16,6 +16,7 @@
  */
 package org.apache.karaf.jndi;
 
+import java.util.List;
 import java.util.Map;
 
 /**
@@ -41,6 +42,23 @@ public interface JndiService {
     Map<String, String> names(String context) throws Exception;
 
     /**
+     * List all JNDI sub-contexts.
+     *
+     * @return a list containing the sub-context names.
+     * @throws Exception
+     */
+    List<String> contexts() throws Exception;
+
+    /**
+     * List the JNDI sub-context from a given context.
+     *
+     * @param context the base JNDI context.
+     * @return a list containing the sub-context names.
+     * @throws Exception
+     */
+    List<String> contexts(String context) throws Exception;
+
+    /**
      * Create a sub-context.
      *
      * @param context the new sub-context name to create.

Modified: karaf/trunk/jndi/core/src/main/java/org/apache/karaf/jndi/internal/JndiMBeanImpl.java
URL: http://svn.apache.org/viewvc/karaf/trunk/jndi/core/src/main/java/org/apache/karaf/jndi/internal/JndiMBeanImpl.java?rev=1550937&r1=1550936&r2=1550937&view=diff
==============================================================================
--- karaf/trunk/jndi/core/src/main/java/org/apache/karaf/jndi/internal/JndiMBeanImpl.java (original)
+++ karaf/trunk/jndi/core/src/main/java/org/apache/karaf/jndi/internal/JndiMBeanImpl.java Sat Dec 14 15:21:11 2013
@@ -20,6 +20,7 @@ import org.apache.karaf.jndi.JndiService
 import org.apache.karaf.jndi.JndiMBean;
 
 import javax.management.MBeanException;
+import java.util.List;
 import java.util.Map;
 
 /**
@@ -48,6 +49,24 @@ public class JndiMBeanImpl implements Jn
     }
 
     @Override
+    public List<String> getContexts() throws MBeanException {
+        try {
+            return this.jndiService.contexts();
+        } catch (Throwable t) {
+            throw new MBeanException(null, t.getMessage());
+        }
+    }
+
+    @Override
+    public List<String> getContexts(String context) throws MBeanException {
+        try {
+            return this.jndiService.contexts(context);
+        } catch (Throwable t) {
+            throw new MBeanException(null, t.getMessage());
+        }
+    }
+
+    @Override
     public void alias(String name, String alias) throws MBeanException {
         try {
             this.jndiService.alias(name, alias);

Modified: karaf/trunk/jndi/core/src/main/java/org/apache/karaf/jndi/internal/JndiServiceImpl.java
URL: http://svn.apache.org/viewvc/karaf/trunk/jndi/core/src/main/java/org/apache/karaf/jndi/internal/JndiServiceImpl.java?rev=1550937&r1=1550936&r2=1550937&view=diff
==============================================================================
--- karaf/trunk/jndi/core/src/main/java/org/apache/karaf/jndi/internal/JndiServiceImpl.java (original)
+++ karaf/trunk/jndi/core/src/main/java/org/apache/karaf/jndi/internal/JndiServiceImpl.java Sat Dec 14 15:21:11 2013
@@ -24,7 +24,9 @@ import org.osgi.framework.Constants;
 import org.osgi.framework.ServiceReference;
 
 import javax.naming.*;
+import java.util.ArrayList;
 import java.util.HashMap;
+import java.util.List;
 import java.util.Map;
 
 /**
@@ -91,8 +93,47 @@ public class JndiServiceImpl implements 
         return map;
     }
 
+    public List<String> contexts() throws Exception {
+        return contexts("/");
+    }
+
+    public List<String> contexts(String name) throws Exception {
+        List<String> contexts = new ArrayList<String>();
+        Context context = new InitialContext();
+        NamingEnumeration<NameClassPair> pairs = context.list(name);
+        while (pairs.hasMoreElements()) {
+            NameClassPair pair = pairs.nextElement();
+            Object o;
+            if (name != null) {
+                o = context.lookup(name + "/" + pair.getName());
+            } else {
+                o = context.lookup(pair.getName());
+            }
+            if (o instanceof Context) {
+                StringBuilder sb = new StringBuilder();
+                sb.append(pair.getName());
+                contexts((Context) o, sb);
+                contexts.add(sb.toString());
+            }
+        }
+        return contexts;
+    }
+
+    private void contexts(Context context, StringBuilder sb) throws Exception {
+        NamingEnumeration list = context.listBindings("");
+        while (list.hasMore()) {
+            Binding item = (Binding) list.next();
+            String name = item.getName();
+            Object o = item.getObject();
+            if (o instanceof Context) {
+                sb.append("/").append(name);
+                contexts((Context) o, sb);
+            }
+        }
+    }
+
     /**
-     * Recursively list a context
+     * Recursively list a context/names
      *
      * @param ctx the startup context.
      * @param sb the string builder where to construct the full qualified name.

Modified: karaf/trunk/manual/src/main/webapp/users-guide/jndi.conf
URL: http://svn.apache.org/viewvc/karaf/trunk/manual/src/main/webapp/users-guide/jndi.conf?rev=1550937&r1=1550936&r2=1550937&view=diff
==============================================================================
--- karaf/trunk/manual/src/main/webapp/users-guide/jndi.conf (original)
+++ karaf/trunk/manual/src/main/webapp/users-guide/jndi.conf Sat Dec 14 15:21:11 2013
@@ -86,6 +86,18 @@ service   | org.apache.karaf.jndi.intern
 The {{jndi:names}} lists only names (the full qualified name). It means that the empty JNDI sub-contexts are not displayed.
 {warning}
 
+h3. {{jndi:contexts}}
+
+The {{jndi:contexts}} command lists all JNDI sub-contexts:
+
+{code}
+karaf@root()> jndi:contexts
+JNDI Sub-Context
+----------------
+other/context
+foo/bar
+{code}
+
 h3. {{jndi:create}}
 
 The {{jndi:create}} command creates a new JNDI sub-context:
@@ -175,11 +187,13 @@ The JMX JndiMBean provides the JNDI name
 
 The object name to use is {{org.apache.karaf:type=jndi,name=*}}.
 
-h3. Attribute
+h3. Attributes
 
 The {{Names}} attribute provides a map containing all JNDI names and class names from both {{osgi:service}} scheme
 and the regular JNDI service.
 
+The {{Contexts}} attribute provides a list containing all JNDI sub-contexts.
+
 h3. Operations
 
 * {{getNames(context)}} provides a map containing JNDI names and class names in a given JNDI sub-context.