//
// Licensed 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.
//

==== Naming (JNDI)

The Apache Karaf Naming (JNDI) is an optional enterprise feature.

You have to install the `jndi` feature first:

----
karaf@root()> feature:install jndi
----

Apache Karaf provides a complete JNDI support.

You have two parts in the Apache Karaf JNDI support:

* a fully compliant implementation of the OSGi Alliance JNDI Service specification.
* a more "regular" JNDI context, containing different names that you can administrate.

===== OSGi Services Registry and JNDI

The OSGi Service Registry provides a centralized register/query capabilities for OSGi services.

A common pattern outside of OSGi is to make use of JNDI API to access services from a directory system.
The OSGi service registry can be viewed as an example of such a system.

Apache Karaf supports the `osgi:service` lookup scheme as defined by the JNDI Service Specification.

The schema is:

----
osgi:service/<interface>[/<filter>]
----

For instance, you can directly use JNDI to get a OSGi service:

----
Context ctx = new InitialContext();
Runnable r = (Runnable) ctx.lookup("osgi:service/java.lang.Runnable");
----

===== JNDI service

Apache Karaf also supports regular JNDI, including a directoy system where you can register name bindings, sub-context, etc.

It supports the standard JNDI API:

----
Context ctx = new InitialContext();
Runnable r = (Runnable) ctx.lookup("this/is/the/name");
----

It also allows you to bind some OSGi services as "pure" JNDI name. In that case, you don't have to use the specific
`osgi:service` scheme.

===== Commands

Apache Karaf provides specific commands to manipulate the JNDI service.

====== `jndi:names`

The `jndi:names` command lists all JNDI names. It groups both the JNDI names from the `osgi:service` scheme and the
regular JNDI names:

----
karaf@root()> jndi:names
JNDI Name         | Class Name
------------------------------------------------------------------
osgi:service/jndi | org.apache.karaf.jndi.internal.JndiServiceImpl
jndi/service      | org.apache.karaf.jndi.internal.JndiServiceImpl
----

We can see here the `osgi:service/jndi` name (using the `osgi:service` scheme) and `jndi/service` name (using the
regular JNDI service).

The `jndi:names` command accepts an optional `context` argument to list names on the given context.

For instance, you can list only names in the `jndi` sub-context:

----
karaf@root()> jndi:names jndi
JNDI Name | Class Name
----------------------------------------------------------
service   | org.apache.karaf.jndi.internal.JndiServiceImpl
----

[NOTE]
====
The `jndi:names` lists only names (the full qualified name). It means that the empty JNDI sub-contexts are not displayed.
To display all JNDI sub-contexts (empty or not), you can use the `jndi:contexts` command.
====

====== `jndi:contexts`

The `jndi:contexts` command lists all JNDI sub-contexts:

----
karaf@root()> jndi:contexts
JNDI Sub-Context
----------------
other/context
foo/bar
----

====== `jndi:create`

The `jndi:create` command creates a new JNDI sub-context:

----
karaf@root()> jndi:create my/company
----

====== `jndi:delete`

The `jndi:delete` command deletes a JNDI sub-context:

----
karaf@root()> jndi:delete my/company
----

====== `jndi:alias`

The `jndi:alias` command creates a new JNDI name (alias) with an existing one.

The existing JNDI name can be a regular one:

----
karaf@root()> jndi:alias bean/services/jndi aliases/services/jndi
karaf@root()> jndi:names
JNDI Name             | Class Name
----------------------------------------------------------------------
osgi:service/jndi     | org.apache.karaf.jndi.internal.JndiServiceImpl
bean/services/jndi    | org.apache.karaf.jndi.internal.JndiServiceImpl
aliases/services/jndi | org.apache.karaf.jndi.internal.JndiServiceImpl
----

or a name from the `osgi:service` schema:

----
karaf@root()> jndi:alias osgi:service/jndi alias/jndi/service
karaf@root()> jndi:names
JNDI Name          | Class Name
-------------------------------------------------------------------
osgi:service/jndi  | org.apache.karaf.jndi.internal.JndiServiceImpl
alias/jndi/service | org.apache.karaf.jndi.internal.JndiServiceImpl
----

[NOTE]
====
The `jndi:alias` automatically creates all required JNDI sub-contexts.
====

====== `jndi:bind`

The `jndi:bind` command binds an OSGi service with a JNDI name.

The `jndi:bind` command requires an OSGi service ID and a JNDI name. The OSGi service ID can be found using the `service:list` command.

For instance, we can bind the OSGi service with ID 344 with the JNDI name `services/kar`:

----
karaf@root()> jndi:bind 344 services/kar
karaf@root()> jndi:names
JNDI Name         | Class Name
-------------------------------------------------------------------------------
osgi:service/jndi | org.apache.karaf.jndi.internal.JndiServiceImpl
services/kar      | org.apache.karaf.kar.internal.KarServiceImpl
----

====== `jndi:unbind`

The `jndi:unbind` command unbind a given JNDI name:

----
karaf@root()> jndi:names
JNDI Name         | Class Name
-------------------------------------------------------------------------------
osgi:service/jndi | org.apache.karaf.jndi.internal.JndiServiceImpl
services/kar      | org.apache.karaf.kar.internal.KarServiceImpl
karaf@root()> jndi:unbind services/kar
karaf@root()> jndi:names
JNDI Name         | Class Name
-------------------------------------------------------------------------------
osgi:service/jndi | org.apache.karaf.jndi.internal.JndiServiceImpl
----

[NOTE]
====
It's not possible to unbind a name from the `osgi:service` schema, as it's linked to a OSGi service.
====

===== JMX JndiMBean

The JMX JndiMBean provides the JNDI names, and the operations to manipulate the JNDI service.

The object name to use is `org.apache.karaf:type=jndi,name=*`.

====== 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.

====== Operations

* `getNames(context)` provides a map containing JNDI names and class names in a given JNDI sub-context.
* `create(context)` creates a new JNDI sub-context.
* `delete(context)` deletes a JNDI sub-context.
* `alias(name, alias` creates a JNDI name (alias) for a given one.
* `bind(serviceId, name` binds a JNDI name using an OSGi service (identified by its ID).
* `unbind(name)` unbinds a JNDI name.