6 Developing Plug-ins

The Service Framework in Oracle Identity Manager enables you to extend the platform by adding new services. Sometimes, the existing services can be extended or modified to suit new requirements. Oracle Identity Manager supports this requirement by means of the Plug-in Framework.

This chapter explains basic features of the plug-in framework and how to perform common tasks to customize your environment using plug-ins. The topics include:

6.1 Background of the Plug-in Framework

A plug-in is software that extends the functionality of features provided by Oracle Identity Manager. The plug-in framework enables you to define, register, and configure plug-ins, which extend the functionality provided by features. Plug-ins can be predefined or custom-developed, and they are utilized at plug-in points.

A plug-in point is a specific point in the business logic where extensibility can be provided. An interface definition called the plug-in interface accompanies such a point. Users can extend the plug-in interface based on the business requirements and register them as plug-ins.

6.1.1 About the Plug-in Framework

The plug-in framework provides Oracle Identity Manager with a number of added capabilities. For example:

  • Services can define plug-in points where functionality can be extended. For example, the notification engine uses a default provider to send e-mail notifications. This provider is set up as a plug-in point so that a custom e-mail provider can be implemented.

  • Services can discover all the plug-ins defined for a particular plug-in point.

  • Plug-ins can be loaded from multiple sources. Feature developers do not need to be concerned about where the plug-ins are stored or with how they are loaded.

  • Developers can change the plug-in code without needing to re-register the plug-in. Note: This is possible only when the plug-in is stored on the filesystem.

6.1.2 About Plug-in Stores

The plug-in framework can store plug-ins in two types of stores:

  • file system

  • the Oracle Identity Manager database

When looking for plug-ins, the framework first examines plug-ins registered in the database, and looks in the file system.

6.1.2.1 File Store

The File Store consists of one or more directories on the Oracle Identity Manager host and is primarily used in development environments. File storage is convenient for the developer since there is no need to explicitly register the developed plug-ins with a file store. Users can just drop in the plug-in zips or exploded plug-in directory to the designated location(s).

By default, Plug-in framework looks for the plug-ins under the OIM_HOME/plugins directory. Additional plug-in directories can also be specified.

The plug-in framework monitors all the additions, modification, and deletions of plug-in zip files under the registered plug-in directories in the file system, and automatically reloads the plug-ins. Plug-in metadata such as name, version, and ID is read from the plug-in zip and is maintained in memory. This metadata is updated based on any file changes. The latest plug-in zip file is considered to be the current version of the plug-in.

For details about how to configure the file store, see Section 6.2, "Configuring Plug-ins".

6.1.2.2 Database Store

Plug-ins can be stored in the Oracle Identity Manager database, so that they are accessible from any node in a cluster. The Plug-in Framework uses Operation DB as the database store. This type of store is appropriate for a production environment.

You must explicitly register any plug-ins that are stored in the database. You can use the Plugin Registration Utility, which is a command-line tool, to register and deregister plug-ins. You can also use the registerPlugin API for this purpose. See Section 6.4, "Registering Plug-ins" for more information about registering plug-ins.

6.1.3 Steps for Developing Plug-ins

The basic aspects of developing and implementing plug-ins are as follows:

  • Declare a plug-in instance where you may specify the type of value mapping for the plug-in point.

  • Specify the properties that will comprise the plug-in metadata.

  • Develop the plug-in code and distribute the plug-in.

For details, see Section 6.3, "Defining and Using Plug-ins".

6.2 Configuring Plug-ins

You use the oim-config.xml file to configure the following:

  • the directory or directories in which the files store will look for plug-ins

  • whether to activate a thread that monitors the file store for any changes; the thread checks the zip files or exploded files in all the plug-in directories

    The monitoring thread is typically activated in a dynamic development environment since plug-ins are being added or modified in such an environment; it can be inactive in a production system which contains a well-defined set of plug-ins . This is tracked by the reloadingEnabled attribute.

  • the time interval at which the monitoring thread wakes up and looks for any changes.

The following is a code snippet from the oim-config.xml file:

<pluginConfig storeType="common">
 
    <storeConfig reloadingEnabled="true"
 
      reloadingInterval="20">
 
      <!--
 
        Plugins present in the OIM_HOME/plugins directory are added by default.
 
        For adding more plugins, specify the plugin directory as below:
 
        <registeredDirs>/scratch/oimplugins</registeredDirs>
 
        <registeredDirs>/scratch/custom</registeredDirs>
 
      -->
 
    </storeConfig>
 
  </pluginConfig>

In this example:

  • common store designation tells the framework to monitor both database and file stores

    Note:

    Do not modify the Store value; common is appropriate in all environments.
  • one directory is configured; additional directories can be configured by simply adding more <registeredDirs> tags.

  • the monitoring thread is active and looks for plug-in changes every 20 seconds by default.

    Monitoring is typically active in development environments only. If you switch between active and inactive, you must restart the application server for the change to take effect.

    Note:

    Restarting the application server is required for any changes made to plug-in data in the oim-config.xml file.

6.3 Defining and Using Plug-ins

This section provides details about the key aspects of defining and setting up plug-ins:

Note:

Although these topics are presented in separate sections, they are not necessarily sequential steps. Tasks such as declaring plug-in points, their plug-ins and the plug-in metadata can be performed together in a single step.

6.3.1 Declaring Plug-ins

To extend the functionality provided by Oracle Identity Manager, you can declare the plug-ins for the application. The declaration can be explicit or implicit.

Be sure to assign unique names to all the plug-ins associated with a specific plug-in point. If the plug-in names are non-unique, an exception will be thrown during plug-in registration.

Declare the plug-ins in the plugin.xml file. For example:

<?xml version="1.0" encoding="UTF-8"?>
<oimplugins>
....
<plugins pluginpoint="oracle.iam.sample.passwdmgmt.service.PasswordElement">
<plugin pluginclass= "oracle.iam.sample.passwdmgmt.custom.NumCustomPasswordElement"
            version="1.0.1" name="num pwd element"/>
<plugin pluginclass= "oracle.iam.sample.passwdmgmt.custom.DictionaryPasswordElement" version="1.0.1" name="Dictionary password element" />        
    </plugins>
....
</oimplugins>

The XML shows two plug-in declarations. Both the plug-ins extend from the same plug-in point.

6.3.2 Specifying Plug-in Metadata

Along with each plug-in that is defined in plugin.xml, you can specify a list of properties that comprise the plug-in metadata.

In this example, the metadata consists of a single property known as PasswordElementNum, with the value 1:

<?xml version="1.0" encoding="UTF-8"?>
<oimplugins>
    ....
  <plugins pluginpoint="oracle.iam.sample.passwdmgmt.service.PasswordElement">
    <plugin pluginclass= "oracle.iam.sample.passwdmgmt.custom.NumCustomPasswordElement"
            version="1.0.1" name="num pwd element">
      <metadata name="PasswordElementNum"><value>1</value></metadata>
    </plugin>
    <plugin pluginclass= "oracle.iam.sample.passwdmgmt.custom.DictionaryPasswordElement"
          version="1.0.1" name="Dictionary password element" >
      <metadata name="PasswordElementNum"><value>2"</value></metadata>
    </plugin>
  </plugins>
    ....
</oimplugins>

6.3.3 Developing Plug-ins

An Oracle Identity Manager plug-in is distributed as a ZIP file with a specified directory structure. The directory structure is as follows:

  • The plugin.xml file: The XML file contains the metadata associated with all the plug-ins such as the plug-in point it extends, the class implementing the plug-in, name, and the version number. All the fields in the XML are mandatory except the name. If the name is not given, then plugin class name is used as the name.

  • The lib/ directory: The lib/ directory consists of JAR files that contains the classes implementing the plug-in logic and the dependent library JAR files. In most instances, this directory consists of a single JAR file with the implementation of all the plug-ins that are specified in plugin.xml.

  • The resources/ directory: Contains resource files required by the plug-in, such as property files, resource bundles, and image files.

Multiple plug-ins implementing same plug-in point can be part of a same ZIP.

A plug-in is Java class implementing the plug-in point interface. The plug-in library (JAR) can contain other classes as well, but the class implementing the plug-in is the only one that is exposed to the feature. This class must be specified in plugin.xml.

The plug-in can also use any resources files. These resources given in the resources directory of the plug-in zip can be accessed as follows:

this.getClass().getClassLoader().getResourceAsStream(<resource_name>);

6.4 Registering Plug-ins

You can register the plug-ins by using APIs and Plugin Registration Utility.

6.4.1 Registering and Unregistering Plug-ins By Using APIs

You can use the following APIs for registration-related tasks:

  • PlatformService.registerPlugin

  • PlatformService.unRegisterPlugin

Here is an example:

ClientPlatform platform = OIMClient.getInstance();
platform.login("username", "password");
PlatformService service = platform.getService(PlatformService.class);
File zipFile = new File(fileName);
FileInputStream fis = new FileInputStream(zipFile);
int size = (int) zipFile.length();
byte[] b = new byte[size];
int bytesRead = fis.read(b, 0, size);
while (bytesRead < size) {
bytesRead += fis.read(b, bytesRead, size - bytesRead);
}
fis.close();
service.registerPlugin(b);
service.unRegisterPlugin(pluginID, version);

6.4.2 Registering and Unregistering Plug-ins By Using the Plugin Registration Utility

You can use the Plugin Registration Utility for registration-related tasks. The utility uses the following files:

  • pluginregistration.xml

  • ant.properties

These files are located in the OIM_HOME/plugin_utility/ directory.

Note:

Plug-in registration utilities require Apache Ant version 1.7 or later.

Before using the utility, perform the following:

  1. Set the values for WLS_HOME and OIM_HOME in ant.properties.

    For example:

    WLS_HOME =.../middleware/wlserver_10.3
    OIM_HOME =..../middleware/Oracle_IDM1/server
    
  2. Build the wlfullclient.jar in Oracle WebLogic server:

    1. Change directories to WLS_HOME/server/lib.

    2. Run the following command:

      java -jar ../../../modules/com.bea.core.jarbuilder_1.3.0.0.jar
      

      Note:

      The exact jar file version can be different based on the WLS. Use the corresponding file with the name as com.bea.core.jarbuilder.

Registering a Plug-in

To register a plug-in:

  1. Execute the ant target "register":

    ant -f  pluginregistration.xml register
    
  2. This will prompt for the Oracle Identity Manager username and password along with the server information and the location of the plugin zip file. Enter the complete path of the zip file location.

Unregister a Plug-in

To unregister a plug-in:

  1. Execute the ant target "unregister":

    ant -f  pluginregistration.xml unregister
    
  2. This will prompt for the Oracle Identity Manager username and password along with the server information and the classname of the plug-in class. Enter the classname with the complete package.

6.5 About Mapped Values

With simple mapped values, a hashed table is built in which you can store a one-to-one mapping of values.

The plug-in framework uses the following logic to determine a simple mapped value:

  • If the attribute has a mapping specified for a given method, that mapping is used.

  • If the attribute uses the same mapping for all methods, that mapping is always used.

  • Otherwise, if no mapping is specified, a NoSuchMappingException is thrown.

  • If the mapping's attribute is declared, it is used as the key to look up the value in the provided HashMap.

  • If the mapping's attribute is not declared but the mapping's value is declared, that value is returned.

Here is an example that shows how the hash map is built and used:

public boolean evaluate(String password) {
Map<String, Object> ro = new HashMap<String, Object>();
ro.put("smvalue1", "value");
ro.put("smattr2", "value2");
// Using the mappings declared in Example 22-1, attr1 would 
// have the value of "smvalue1".
String attr1 = PluginFramework.getMappedValue(this, ro,                      "attr1", "evaluate");
// Using the mappings declared in Example 22-1, attr1 would 
// have the value of "value2"
String attr2 = PluginFramework.getMappedValue(this, ro, "attr2", "evaluate");

Here, Example 22-1 refers to an example plugin.xml, as shown in Example 6-1:

Example 6-1 Example Plugin.xml

<?xml version="1.0" encoding="UTF-8"?>
<oimplugininstances>
  <plugininstances name="CustomPasswordElementInstance" plugin="num pwd element" pluginpoint="oracle.iam.sample.passwdmgmt.service.PasswordElement" version="1.0.1">    <metadata name="meta1">
      <value>1</value>
    </metadata>
    <mapping method="evaluate">
      <simple-mapping name="attr1" entity-type="User" value="smvalue1" />
      <runtime-mapping name="phone" entity-type="User" attribute="phonenumber" value="N/A" />
    </mapping>
    <mapping>
      <simple-mapping name="attr1" entity-type="User" value="value1" />
      <simple-mapping name="attr2" entity-type="User" attribute="smattr2" />
      <runtime-mapping name="fname" entity-type="User" attribute="firstname" />
      <runtime-mapping name="lname" entity-type="User" attribute="lastname" />
    </mapping>
    <description>Test class for plugin mapped value</description>
  </plugininstances>
</oimplugininstances>

6.5.1 Accessing Mapped Values

The plug-in framework uses the following logic to determine a simple mapped value:

  • If the given attribute name has a mapping specified for the given method, then that mapping is used. Otherwise, if the given attribute name has a mapping specified for all methods, then that mapping is used. Otherwise, NoSuchMappingException is generated.

  • If the attribute for the mapping is declared, then the attribute is used as the key to lookup the value in the provided HashMap.

  • If the attribute for the mapping is not declared but the value of the mapping is declared, then that value is returned. For example:

    Map<String, Object> ro = new HashMap<String, Object>();
    ro.put("smvalue1", "value");
    ro.put("smattr2", "value2");
    String attr1 = PluginFramework.getMappedValue(this, ro, "attr1", "evaluate");
    String attr2 = PluginFramework.getMappedValue(this, ro, "attr2", "evaluate");
    

6.6 Plug-in Points

Table 6-1 lists the plug-in points in Oracle Identity Manager:

Table 6-1 Plug-in Points

Plug-in Point Description

oracle.iam.ldapsync.LDAPContainerMapper

This is used by LDAP synchronization to determine which user/role container should be used to create the user/role in LDAP.

EventHandler

This is the kernel event handler.

oracle.iam.platform.auth.api.LoginMapper

This is an implementation of a LoginMapper maps the JAAS user principal name to the corresponding Oracle Identity Manager username. This plug-in point is used to override the default mapping of JAAS user principal name to Oracle Identity Manager username for SSO scenarios. The default implementation returns the same value as the JAAS user principal name.This plug-in point is typically used in SSO scenarios where the JAAS user principal name and the Oracle Identity Manager username might be different. For example, the SSO system might set the email as the JAAS username but no user with that username exist in Oracle Identity Manager. For Oracle Identity Manager to recognize that user, the JAAS user principal name must be mapped to the Oracle Identity Manager username. This can be done by implementing a plug-in for LoginMapper, as shown:

public class CustomLoginMapper implements LoginMapper{
                public String getOIMUserID(String jaasPrincipal) throws MappingException {
                       return getUserName(jassPrincipal);
        }

                private String getUserName(String emailID){
               String userName = null;

               //Use usermgmt APIs to get the username corresponding to this email id
               return userName;
                 }
        }

oracle.iam.identity.usermgmt.api.PasswordVerifier

This is used for verification of old password while changing the user's password. The class that is to be used for this validation is configured in the OIM.OldPasswordValidator system property. By default, use the container based authentication for verifying old password.

oracle.iam.request.plugins.StatusChangeEvent

This allows running of custom code during request status change.

oracle.iam.request.plugins.RequestDataValidator

This is used for custom validation of request data after submission.

oracle.iam.request.plugins.PrePopulationAdapter

This is used to prepopulate an attribute value by running custom code during request creation.

oracle.iam.scheduler.vo.Task

This is used to run the job in context. Execute method of the task is retrieved through the plug-in and is loaded.

oracle.iam.identity.usermgmt.api.UserNamePolicy

This is an implementation of username policies that are used to generate/validate username.

oracle.iam.identity.usermgmt.api.ReservationInLDAP

This is an implementation for reservation of user attributes in LDAP.