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