Waveset’s open architecture enables you to create custom resource adapters to manage external resources that are not already supported by the resource adapters provided with Waveset. These custom adapters define essential characteristics and methods needed to transform requests from Waveset into actions performed on a resource.
This chapter describes how to create, test, and load a custom Waveset resource adapter. This information is organized as follows:
Waveset contains sample adapters or skeleton adapters that are intended to be used as a basis for creating custom adapters. To enhance your understanding of these valuable starter files, this chapter uses them frequently to exemplify particular characteristics of resource adapter files.
Review the information in these sections before you start developing custom adapters:
This chapter provides background information about resource adapter design and operation for:
Developers who need to create custom resource adapters.
Waveset administrators who are learning how the Waveset system works or who need to troubleshoot problems with resource adapters.
This chapter assumes that you are familiar with creating and using the built-in Waveset resources and that you have read the Resources chapter of Business Administrator's Guide.
Be sure to read the following information before trying to write custom resource adapters for Waveset:
Do not create custom adapters in the com.waveset.adapter package. Instead, create custom adapters in a customer-specific package to be sure the adapter uses package-level classes and methods that are included in the supported public API. For example, use com.customer_name.adapter.
Also, all package names must be lowercase.
Do not use import .*. Although Java supports this mechanism, using import .* is generally considered bad practice because this mechanism
Obscures the actual location of referenced classes to readers
Can result in incorrect or ambiguous references (such as compiler errors) in certain situations following internal refactoring
Instead, insert an explicit import statement for every referenced class or interface.
In addition to the information provided in this chapter, see the following publications related to resource adapters.
Table 10–1 Related Documentation
Publication Title |
Description |
---|---|
Resource Reference |
Describes how to load and synchronize account information from a resource into Oracle Waveset. |
Business Administrator's Guide |
Contains additional information about customizing and managing resources supplied by Waveset. |
You can download these publications from http://docs.sun.com.
A resource adapter serves as a proxy between Waveset and an external resource, such as an application or database. The adapter defines the essential characteristics of the resource type, and this information is saved in the Waveset repository as a resource object. Waveset resource adapters are standard or Active Sync-enabled adapters.
This section contains the following topics:
Standard resource adapters provide a generic interface to resource types that are supported by Waveset; such as Web servers, Web applications, databases, and even legacy applications and operating systems. In Java terms, standard resource adapters extend the ResourceAdapterBase class.
These adapters push account information changes from Waveset to their managed, external resources and typically perform the following administrative activities:
Connect to and disconnect from a resource
Create, delete, or modify users
Enable, disable, or get users
Authenticate users
Manage objects such as group membership or directory organization structure
Standard resource adapters generally follow these steps when pushing information from Waveset to the resource managed by Waveset:
Waveset server initializes the resource manager.
All available resource types are registered through the Resource Adapter interface. As part of the registration process, the resource adapter provides a prototype XML definition.
User initiates process of creating a new resource.
When an Waveset administrator creates a new resource, the task that creates the form to display the resource type’s prototype definition is queried for the resource attribute fields. Waveset uses these attributes to display a form in the browser. The user who is creating the new resource fills in the information and clicks Save.
Waveset saves the information provided, along with the other resource fields in the resource object repository under the name of the new resource object.
When the user clicks Save during resource creation, the creation task gathers the entered data, executes any necessary validation, then serializes the data using XML before writing the serialized object to the object repository.
Waveset displays the list of available resources in a multi-selection box when an Waveset user is created or modified.
Selecting a resource causes Waveset to query the resource object for the available account attribute fields. Waveset uses these field descriptions to display a form that contains the attribute fields, which the user can fill in with the appropriate data.
The resource object is queried for the connection information when this form is saved, and a connection is established with the resource.
The adapter sends the command to perform the intended action on the account on the resource over this connection.
If this request is a create request, the adapter updates the Waveset user object with the resource account information.
When user account information is displayed, Waveset requests the list of resources on which the user has accounts from the saved account object. For each resource, Waveset queries the resource object and uses the connection information to establish a connection to the resource.
The adapter sends a command over this connection to retrieve account information for the user, and it uses the retrieved information to fill in the attribute fields that are defined in the resource object. The system creates a form to display these values.
Active Sync-enabled adapters are an extension of a standard resource adapter and they are used to implement the Active Sync interface for some common resources, such as Active Directory. These adapters pull data changes directly from the resource to initiate the following activities in Waveset:
Polling or receiving change event notification
Issuing actions to create, update, or delete resource accounts
Editing or creating users with a custom form
Saving the resource changes
Logging progress information and errors
Active Sync-enabled adapters are particularly suitable for supporting the following resource types:
Applications with audit or notification interfaces
Some applications, such as Microsoft Active Directory and PeopleSoft, have external interfaces. You can configure these application interfaces to add events to an audit log or to notify other applications when certain changes occur.
For example, you can configure the interface to record an transaction in the audit log whenever a user account is modified natively on the Active Directory server. You can configure the Waveset Active Directory resource to review this log every 30 minutes and trigger events in Waveset when any changes occur. You can register other Active Sync-enabled adapters with the resource through an API, and use event messages to notify the adapter when changes occur. These event messages can reference the item that changed, the information that was updated, and frequently the user who made the change.
Databases populated with update information
You can manage database resources by generating a table of deltas and generate this table in several different ways. For example, you can compare a snapshot of the database to current values and create a new table with the differences. The adapter pulls rows from the table of deltas, processes them, and subsequently marks them when completed.
Databases with modification timestamps
You can create Active Sync-enabled queries for database entries that have been modified after a particular time. The adapters run updates and then poll for new queries. By storing the last successfully processed row, Waveset can perform a “starts with” query to minimize the polling impact. Only those changes made to the resource since the previous set of modifications were made are returned for processing.
Resources with change-log entries
Most LDAP servers provide a change-log mechanism that you can use to track changes, optionally constrained to sections of interest in the DIT. By periodically querying the change-log entries, the LDAP resource adapter can update Waveset with detected changes; including creates, deletes, and updates.
Active Sync-enabled adapters generally follow these steps when listening or polling for changes to the resource managed by Waveset. When the adapter detects that a resource has changed, the Active Sync-enabled adapter:
Extracts the changed information from the resource.
Determines which Waveset object is affected.
Builds a map of user attributes to pass to the IAPIFactory.getIAPI method, along with a reference to the adapter and a map of any additional options, which creates an Identity Application Programming Interface (IAPI) object.
Sets the logger on the IAPI event to the adapter’s Active Sync logger.
Active Sync Manager processes the IAPI object and returns a WavesetResult object to the adapter. The WavesetResult object informs the Active Sync-enabled adapter if the operation succeeds.
The WavesetResult object might contain many results from the various steps the Waveset system used to update the identity. Typically, a workflow also handles errors within Waveset, often ending up as an Approval for a managing administrator.
Exceptions are logged in the Active Sync and Waveset tracing logs with the ActiveSyncUtil.logResourceException method.
When Active Sync-enabled adapters detect a change to an account on a resource, the adapter maps the incoming attributes to an Waveset user or, if the adapter cannot match the user account, creates an Waveset user account.
The following rules and parameters determine what happens when a change is detected.
If present, a Process rule determines whether the adapter uses IAPIProcess or attempts to use IAPIUser. If the adapter cannot use IAPIUser because a Correlation or Confirmation rule does not uniquely identify an Waveset user for the event (given the other parameter settings), and a Resolve Process rule is configured, the adapter uses the Resolve Process rule to create an IAPIProcess event. Otherwise, the adapter reports an error condition.
IAPIUser checks out a view and makes this view available to the User form.
For creates and updates, IAPIUser checks out the User view.
For deletes, IAPIUser checks out the Deprovision view.
However, a User view is not checked out or available with IAPIProcess. Either a Process rule has been set or a Resolve Process rule is invoked.
Resource objects define the capabilities and configuration of the resource you are managing in Waveset, including the information described in the following table.
Table 10–2 Information Defined by Resource Objects
You must define a resource object in Waveset for every resource that Waveset communicates with or manages.
You can view resource objects from Waveset’s Debug pages:
http://host:port/idm/debug/
Where:
host is the local server on which Waveset is running.
port is the TCP port number on which the server is listening.
The session.jsp page gives you the option of listing objects of type Resource. See Viewing and Editing a Resource Object for more information.
A resource adapter class implements methods that
Register the resource object in the Waveset repository
Enable you to manage the external resource
Push information from Waveset to the resource
(Optional) Pull information from the resource into Waveset
This optional pull capability is known as Active Sync, and a resource adapter with Active Sync capability is referred to as Active Sync-enabled. See What Are Active Sync-Enabled Resource Adapters? for more information.
Some preparation is necessary before you actually start writing a custom adapter. This section describes how to prepare for adapter development, and the tasks include:
Before you can create a custom adapter, you must become familiar with the components in a resource adapter’s source code. This section describes the following components, which are common to most adapters:
Standard Java header information identifies the parent class of the new adapter class file you are creating, constructors, and imported files.
This header information is representative of the standard Java files (including public class declaration and class constructors). You must edit the sections of the file that list the constructors and public classes, and, if necessary, the imported files.
The prototypeXML string in the adapter Java file is the XML definition of a resource. This string must contain the resource name and all of the resource attributes that you want to display in the Waveset user interface. The prototypeXML string also defines resource objects stored in the Waveset repository.
The following table describes the different prototypeXML information types that you use to define a resource in Waveset.
Some of these information types are specific to Active Sync-enabled adapters.
Type |
Description |
---|---|
Resource |
Defines top-level characteristics of the resource. Keywords include:
|
XML elements that are defined with the <ResourceAttribute> element and used by Waveset to configure the resource. For more information, see Resource Attributes. |
|
Defines the default schema map for basic user attributes. You use the <AccountAttribute> element to define account attributes. You map standard Waveset account attribute types differently than you map custom attributes. For more information about mapping account attributes to resource attributes, see Map the Attributes. |
|
Defines how the account name for the user is built. Use the <Template> tag to define this template. Account names are typically in one of the following forms:
|
|
(Standard resource adapter only) Defines values to support pass-through authentication for the resource. Use the <LoginConfigEntry> element to define this value. For more information about pass-through authentication, see the Resource Reference. |
|
Form |
(Active Sync-enabled adapters only) Designates a form object that processes data from the Active Sync-enabled adapter before the data is integrated into Waveset. A form is optional, but in most cases a form provides flexible changes in the future and can be used to transform incoming data, map data to other user attributes on other resource accounts, and cause other actions in Waveset to occur. |
Only available to Administrators defining the resource.
Resource attributes define the connection information on the resource being managed. Resource attributes typically include the resource host name, resource administrator name and password, and the container information for directory-based resources. Waveset attributes such as the list of resource approvers and the number of times to retry operations on the resource are also considered resource attributes.
When writing custom adapters, you use resource attributes to define:
Resources you want to manage, along with other connection and resource characteristics.
From the perspective of an administrator using the Waveset Administrator interface, these attributes define the field names that are visible in the Waveset interface and prompt the user for values.
For Active Directory resources, attributes can include source name, host name, port number, user, password, and domain. For example, the Create/Edit Resource page for a resource type requires a host field in which administrators creating a resource identify the host on which the resource resides. This field (not the contents of the field) is defined in this adapter file.
Authorized account that has rights to create users on the resource. For an Active Directory resource, this includes the user and password fields.
Source attributes including the form, the Waveset administrator that the adapter will run as, scheduling and logging information, and additional attributes used only in Active Sync methods.
You can modify these values from the Waveset interface when creating a specific instance of this resource type.
You use the <ResourceAttribute> element, as shown in the following example, to define resource attributes in the prototypeXML string of the adapter Java file:
<ResourceAttribute name=’"+RA_HOST+"’ type=’string’ multi=’false’\n"+ description=’<b>host</b><br>Enter the resource host name.’>\n"+ |
Where the description field identifies the item-level help for the RA_HOST field and must not contain the < character. In the preceding example, the < characters are replaced by < and '.
The following table describes the keywords you can use in <ResourceAttribute> element.
Table 10–4 <ResourceAttribute> Element Keywords
The ResourceAttribute> element may also contain a ValidationPolicy element. A validation policy ensures the value a user specifies on the Resource Parameters page meets the requirements defined in a separate policy object.
The following sample causes the adapter to use the Port Policy to ensure the specified value is valid. The default Port Policy checks the value is an integer between 1 and 65536.
<ResourceAttribute name='Port' value='123'> <ValidationPolicy> <ObjectRef type='Policy' id='#ID#PortPolicy' name='Port Policy'/> </ValidationPolicy> </ResourceAttribute>
When you are working with resource adapters and adapter parameters, you can use one of the following strategies to overwrite resource attributes:
Use the adapter’s Attribute page to set a resource attribute value once for all users
Set a default attribute value on the adapter, then subsequently override its value, as needed, within your user form
In the following example, the user form must override the resource attribute value for template during the creation of each user. When implementing similar code in a production environment, you would probably include more detailed logic to calculate this template value within your user form.
<Field name=’template’> <Display class=’Text’> <Property name=’title’ value=’NDS User Template’/> </Display </Field> <!-- Change NDS for the name of your NDS resource --> <!-- Template is the name of the attribute field, as viewed in the resource xml --> <Field name=’accounts[NDS].resourceAttributes.Template’> <Expansion> <ref>template</ref> </Expansion> </Field> |
The following table describes required resource attributes that are supplied in the skeleton adapter files.
Table 10–5 Resource Attributes in Skeleton Adapter Files
Required Resource Attribute |
Description |
---|---|
RA_HOST |
Resource host name. This attribute corresponds to the Host field on the Resource Parameters page. |
RA_PORT |
Port number used to communicate with the resource. This attribute corresponds to the Port field on the Resource Parameters page. |
RA_USER |
Name of a user account that has permission to connect to the resource. The field name varies on the Resource Parameters page. |
RA_PASSWORD |
Password for the account specified by RA_USER. This attribute corresponds to the Host field on the Resource Parameters page. |
The next table describes required Active Sync-specific attributes that are defined in the ACTIVE_SYNC_STD_RES_ATTRS_XML string of the Active Sync class.
Table 10–6 Active Sync-Specific Attributes Defined in ACTIVE_SYNC_STD_RES_ATTRS_XML
This table describes required Active Sync-specific attributes that are defined in the ACTIVE_SYNC_EVENT_RES_ATTRS_XML string of the Active Sync class.
Table 10–7 Active Sync-Specific Attributes Defined in ACTIVE_SYNC_EVENT_RES_ATTRS_XML
Only available to Administrators defining the resource.
Waveset account attributes describe the default user attributes supported for the resource.
With an Active Sync-enabled adapter, account attributes are the attributes that are available to update the Waveset user account. The Active Sync-enabled adapter collects these attributes and stores them in the global area for the input form.
Waveset supports the following types of account attributes:
string
integer
boolean
encrypted
binary
Binary attributes include graphic files, audio files, or certificates. Not all adapters support binary account attributes. Generally, only certain directory, flat file, and database adapters can process binary attributes.
Consult the “Account Attributes” section of the adapter documentation to determine if your adapter supports binary attributes.
Keep the size of any file referenced in a binary attribute as small as possible. For example, loading extremely large graphics files can affect Waveset’s performance.
You define Waveset account attributes in the AttributeDefinition object of the resource’s schema map, and use the prototypeXML string in the adapter file to map incoming resource attributes to account attributes in Waveset. For example, you would map the LDAP sn resource attribute to the lastname attribute in Waveset. Waveset account attributes include
You use the Account Attributes page, or schema map, to map Waveset account attributes to resource account attributes. The list of attributes varies for each resource. You generally remove all unused attributes from the schema map page. If you add attributes, you will probably need to edit user forms or other code.
The attribute mappings specified in the resource schema map determine which account attributes can be requested when you are creating a user. Based on the role selected for a user, you will be prompted for a set of account attributes that are the union of attributes of all resources in the selected role.
To view or edit the Waveset schema for users or roles, you must be a member of the IDM Schema Configuration AdminGroup and you must have the IDM Schema Configuration capability.
The Active Sync resource schema map is an optional utility that enables you to edit inputs to an Active Sync-enabled adapter, which are often database column names or directory attribute names. Using the schema map and an Active Sync form, you can implement Java code to handle a resource type, defining details of the resource configuration in the map and form.
Waveset uses an Active Sync resource’s schema map in the same way that it uses a typical schema map. The schema map specifies which attributes to fetch from the resource and their local names. All attribute names that are listed in the schema map (that is, all attributes that exist on the resource) are made available to the Active Sync form and the user form with the activeSync.name attribute. If the Active Sync resource does not use a form, all attributes are named global to ensure that all attributes automatically propagate to attributes with the same name on all resources. Use a form rather than the global namespace.
Do not put the accountId attribute in the global namespace because this special attribute is used to identify waveset.account.global.
If you are creating the resource account for the first time, the accountId attribute also becomes a resource’s accountId directly and it bypasses the identity template.
For example, if a new Waveset user is created through the Active Sync-enabled adapter and that user has an LDAP account assigned to it, the LDAP accountID will match the global.accountId instead of the correct DN from the DN template.
After creating a resource instance, administrators can subsequently use a schema map to:
Limit resource attributes to only those that are essential for your company.
Map Waveset attributes to resource attributes.
Create common Waveset attribute names to use with multiple resources.
Identify required user attributes and attribute types.
You can view Waveset account attributes from the Edit Schema page in the Waveset user interface by clicking the Edit Schema button located at the bottom of the Edit/Create Residenource page.
For more information about creating a resource or editing a resource schema map, see the Business Administrator's Guide.
An identity template is only available to Administrators who are defining the resource.
To view or edit the Waveset schema for Users or Roles, you must be a member of the IDM Schema Configuration AdminGroup and you must have the IDM Schema Configuration capability.
You use the identity template (or account DN) to define a user’s default account name syntax when creating the account on the resource. The identity template translates the Waveset user account information to account information on the external resource.
You can use any schema map attribute (an attribute listed on the left side of the schema map) in the identity template, and you can overwrite the user identity template from the User form, which is commonly done to substitute organization names.
Waveset users have an identity for each of their accounts, and this identity can be the same for some or for all of these accounts. The system sets the identity for an account when the account is provisioned. The Waveset user object maintains a mapping between a user’s identities and the resources to which they correspond.
The user has a primary accountId in Waveset that is used as a key and as a separate accountId for each of the resources on which that user has an account. The accountId is denoted in the form of accountId:<resource name>, as shown in the following table.
Table 10–8 accountID Examples
Attribute |
Example |
---|---|
accountId |
maurelius |
accountId:NT_Res1 |
marcus_aurelius |
accountId:LDAP_Res1 |
uid=maurelius,ou=marketing,ou=employees,o=abc_company |
accountId:AIX_Res1 |
maurelius |
Account user names are in one of two forms:
Flat namespaces
Hierarchical namespaces
You typically use the accountId attribute for systems with a flat namespace, which include:
UNIX systems
Oracle and Sybase relational databases
For resources with flat namespaces, the identity template can simply specify that the Waveset account name be used.
You use distinguished names (DNs) for systems with a hierarchical namespace. DNs can include the account name, organizational units, and organizations.
Account name syntax is especially important for hierarchical namespaces. For resources with hierarchical namespaces, the identity template can be more complicated than that of a flat namespace, which allows you to build the full, hierarchical name. The following table shows examples of hierarchical namespaces and how they represent DNs.
Table 10–9 Hierarchical Namespace Examples
System |
Distinguished Name String |
---|---|
LDAP |
cn=$accountId,ou=austin,ou=central,ou=sales,o=comp |
Novell NDS |
cn=$accountId.ou=accounting.o=comp |
Microsoft Windows 2000 |
CN=$fullname,CN=Users,DC=mydomain,DC=com |
For example, you can specify the following for a resource identity template with a hierarchical namespace such as LDAP:
uid=$accountID,ou=$department,ou=People,cn=waveset,cn=com
Where:
accountID is the Waveset account name
department is the user’s department name
Login Configuration defines parameters that are used if you are going to use the resource for pass-through authentication. Typically, these parameters are username and password, but some resources use different parameters. For example, SecurId uses user name and passcode.
The Login Configuration information type helps define the resource, but it is not easily modified by administrators.
For more information about pass-through authentication, see Enabling Pass-Through Authentication for Resource Types and the Resource Reference.
Resource methods write information from Waveset into the external resource.
You must be familiar with the resource to write customized methods.
You categorize resource methods by task. When developing your own custom adapters, you must determine which categories your adapter needs to meet the goals of your development. For example,
Is your adapter going to be a standard or an Active Sync-enabled adapter?
Will the first phase of your deployment support password reset only?
How you answer these questions determines which resource methods must be completed.
The following table describes resource methods categories. (Additional information about each functional category is discussed later in this chapter.)
Table 10–10 Resource Methods Categories
In Active Sync-enabled adapters, resource methods
Create a feed from the resource into Waveset. Presents methods that search the resource for changes or receive updates. To write these methods, you must understand how to register or search for changes on the resource, and communicate with the resource.
Run update operations in the Waveset repository by performing the feed from the resource into Waveset.
The following considerations are specific to account attributes in standard resource adapters:
User identity template
Creating an identity template out of multiple user attributes
Login configuration and pass-through authentication
To view or edit the Waveset schema for Users or Roles you must be a member of the IDM Schema Configuration AdminGroup and you must have the IDM Schema Configuration capability.
The user identity template establishes the account name to use when creating the account on the resource. This template translates Waveset user account information to account information on the external resource.
You can use any schema map attribute (an attribute listed on the left side of the schema map) in the identity template.
You can overwrite the user identity template from the User form, which is commonly done to substitute organization names.
You can create an identity template out of a portion of multiple user attributes. For example, a template might consist of the first letter of the first name plus seven characters of the last name. In this case, you can customize the user form to perform the desired logic and then override the identity template that is defined on the resource.
The <LoginConfigEntry> element specifies the name and type of login module as well as the set of authentication properties required by this resource type to complete successful user authentication.
The <LoginConfig> and <SupportedApplications> sections of the adapter file specify whether the resource will be included in the options list on the Login Module configuration pages. Do not change this section of the file if you want the resource to appear in the options list.
Each <AuthnProperty> element contains the following attributes.
Table 10–11 <AuthnProperty> Element Attributes
User management across forests is only possible when multiple gateways, one for each forest, are deployed. In this case, you can configure the adapters to use a predefined domain for authentication per adapter without requiring the user to specify a domain as follows:
Add the following authentication property to the <AuthnProperties> element in the resource object’s XML:
<AuthnProperty name=’w2k_domain’ dataSource=’resource attribute’ value=’MyDomainName’/>
Replace MyDomainName with the domain that authenticates users.
For more information about this property, see the Active Directory resource adapter documentation in Resource Reference.
Most resource login modules support both the Waveset Administrative interface and User interface. The following example shows how SkeletonResourceAdapter.java implements the <LoginConfigEntry> element:
The following example defines the supported LoginModule DATA_SOURCE options. In this example, a LoginConfig entry is taken from the LDAP resource adapter supplied by Waveset. The entry defines two authentication properties whose dataSource value, if not specified, is supplied by the user.
public static final String USER_DATA_SOURCE = "user"; public static final String HTTP_REMOTE_USER_DATA_SOURCE = "http remote user"; public static final String HTTP_ATTRIBUTE_DATA_SOURCE = "http attribute"; public static final String HTTP_REQUEST_DATA_SOURCE = "http request"; public static final String HTTP_HEADER_DATA_SOURCE = "http header"; public static final String HTTPS_X509_CERTIFICATE_DATA_SOURCE = "x509 certificate"; " <LoginConfigEntry name=’"+WS_RESOURCE_LOGIN_MODULE+"’ type=’"+LDAP_RESOURCE_TYPE+"’ displayName=’"+Messages.RES_LOGIN_MOD_LDAP+"’>\n"+ " <AuthnProperties>\n"+ " <AuthnProperty name=’"+LDAP_UID+"’ displayName=’"+Messages.UI_USERID_LABEL+"’ formFieldType=’text’ isId=’true’/>\n"+ " <AuthnProperty name=’"+LDAP_PASSWORD+"’ displayName=’"+Messages.UI_PWD_LABEL+"’ formFieldType=’password’/>\n"+ " </AuthnProperties>\n"+ " </LoginConfigEntry>\n"+ |
The next example shows a Login Config entry where the authentication property’s dataSource value is not supplied by the user. In this case, the value is derived from the HTTP request header.
" <LoginConfigEntry name=’"+Constants.WS_RESOURCE_LOGIN_MODULE+"’ |type=’"+RESOURCE_NAME+"’ displayName=’"+RESOURCE_LOGIN_MODULE+"’>\n"+ " <AuthnProperties>\n"+ " <AuthnProperty name=’"+LOGIN_USER+"’ displayName=’"+DISPLAY_USER+"’ formFieldType=’text’ isId=’true’ dataSource=’http header’/>\n"+ " </AuthnProperties>\n"+| " </LoginConfigEntry>\n"+ |
The following example shows how prototypeXML defines fields displayed on the Create/Edit Resource page.
<ResourceAttributes> <ResourceAttribute name=’Host’ description=’The host name running the resource agent.’ multi=’false’ value=’n’> </ResourceAttribute> <ResourceAttribute name=’TCP Port’ description=’The TCP/IP port used to communicate with the LDAP server.’ multi=’false’ value=’9278’> </ResourceAttribute> <ResourceAttribute name=’user’ description=’The administrator user name with which the system should authenticate.’ multi=’false’ value=’Administrator’> </ResourceAttribute> <ResourceAttribute name=’password’ type=’encrypted’ description=’The password that should be used when authenticating.’ multi=’false’ value=’VhXrkGkfDKw=’> </ResourceAttribute> <ResourceAttribute name=’domain’ description=’The name of the domain in which accounts will be created.’ multi=’false’ value=’AD’> </ResourceAttribute> </ResourceAttributes> |
The Waveset Administrative interface displays the resource attributes for the default resource as specified.
The following sections describe how to profile and define prerequisites for standard resource adapters and Active Sync-enabled adapters.
Use the following information to create a profile and define prerequisites for a standard resource adapter:
Select an Waveset adapter file that most closely resembles the resource type to which you are connecting.
See Table 10–12 for a brief description of the default Waveset resource adapter files supplied with a standard Waveset configuration.
Research user account characteristics and how these tasks are performed on the remote resource:
Authenticate access to the remote resource
Update users
Get details about the changed users
List all users on the system
List other system objects, such as groups, that are used in the listAllObjects method
Identify the minimum attributes needed to perform an action and all supported attributes.
Verify that you have the appropriate tools to support connection to the resource.
Many resources ship with a published set of APIs or a complete toolkit that can be used to integrate outside applications to the resource. Determine whether your resource has a set of APIs or whether the toolkit provides documentation and tools to speed up integration with Waveset. For example, you must connect to a database through JDBC.
Determine who can log in and search for users on the resource
Most resource adapters require and run an administrative account to perform tasks such as searching for users and retrieving attributes. This account is typically a highly privileged or super user account, but can be a delegated administration account with read-only access.
Determine whether you can extend the resource’s built-in attributes.
For example, Active Directory and LDAP both allow you to create extended schema attributes, which are attributes other than the standard Waveset attributes.
Decide which attributes you want to maintain in Waveset, determine what the attribute names are on the resource, and decide what to name the attributes in Waveset. These attribute names go in the schema map and are used as inputs to forms that are used to create a resource of that type.
When profiling an Active Sync-Enabled resource adapter, use the following information in addition to the considerations described in Profiling a Standard Resource Adapter:
When researching user account characteristics and how these tasks are performed on the remote resource, you must also:
Search for changes to users
Identify ways to search for changed users only
Determine which resource attributes or actions create events.
If the resource supports subscribing to notification messages when changes are made, identify which attribute changes you want to trigger the notification and which attributes you want in the message.
Decide which of the following actions Waveset should perform when the adapter detects an event on the source.
Create, update, or delete a user
Disable or enable an account
Update the answers used to authenticate a user
Update a phone number
Decide whether you want the adapter to be driven by events in the external resource or driven by specified polling intervals.
Before making your decision, you must understand how polling works in typical Waveset installations. Although some installations implement or are driven by external events, most Waveset deployment environments use a hybrid method.
Choose one of the following approaches:
Set up polling intervals where an Active Sync Manager thread calls the poll interface at a configurable interval or on a specified schedule. You can set polling parameters, including settings such as faster polling if work was received, thread-per-adapter or common thread, and limits on the amount of concurrent operations.
Set up an event-driven environment where the adapter sets up a listening connection, such as an LDAP listener, and waits for messages from the remote system. You can implement the poll method to do nothing, and set the polling interval to an arbitrary value, such as once a week. If updates are event-driven, the updates must have a guaranteed delivery mechanism, such as MQ Series, or synchronization is lost.
Implement a hybrid solution where external events trigger smart polling and the regular poll routine can recover from missed messages.
Smart polling adapts the poll rate to the change rate and polls infrequently unless changes are being made often. Smart polling balances the performance impact of frequent polling with the update delays of infrequent polling.
In this model, incoming messages are queued and multiple updates for a single object are collapsed into a single update, which increases efficiency. For example, multiple attributes can be updated on a directory, and each attribute triggers a message. The poll routine examines the message queue and removes all duplicates. The routine then fetches the complete object to ensure that the latest data is synchronized and that updates are handled efficiently.
After profiling the resource, identify classes and methods needed in your adapter:
Review the relevant Javadoc to determine which base classes and methods you can use as is and which you must extend. This javadoc is available on your Waveset CD in the REF/javadoc directory.
Create a list of methods that you must write and include in the Java file based on the resource to which you are connecting.
When creating an adapter, the most time-intensive task is writing your own methods to push information from Waveset to the resource or to create a feed from the resource to Waveset.
The Sun Resource Extension Facility Kit (REF Kit) is supplied in the /REF directory on the Waveset CD or install image. You can use the sample files and other tools in this REF Kit to jump-start the process of creating your own custom adapter.
The following table describes the contents of the REF Kit.
Table 10–12 REF Kit Components
This section contains instructions for setting up your build environment.
Prerequisites:
You must install the JDK version required for your Waveset version. See “Supported Software and Environments” in the Waveset Release Notes for information.
After installing the JDK, you must install the REF Kit by copying the entire /REF directory to your system.
If you are working on Microsoft Windows operating system, use the following steps to set up your build environment:
Change directories to a new directory.
Create a file called ws.bat.
Add the following lines to this file:
set WSHOME=<Path where REF Kit is installed> set JAVA_HOME=<Path where JDK is installed> set PATH=%PATH%;%JAVA_HOME%\bin : |
Where you set:
Save and close the file.
If you are working on a UNIX operating system, use the following steps to set up your build environment:
Change directories to a new directory.
Create a file called ws.sh.
Add the following lines to this file:
WSHOME=<path_where_REF_is_installed> JAVA_HOME=<path_where_JDK_is_installed> PATH=$JAVA_HOME/bin:$PATH export WSHOME JAVA_HOME PATH : |
Where you set:
Save and close the file.
After finishing the preparation work described in Preparing for Adapter Development you are ready to start writing your custom adapter.
This section describes how to write a custom adapter, including:
The following sections provide a high-level overview of the steps you perform to create a custom adapter:
This section describes the processes to follow when creating a standard adapter or an Active Sync-enabled adapter.
The steps for writing a standard adapter are slightly different based on which operating system you are using.
Open a command window and go to the following directory:
\waveset\idm\adapter\src
Rename the SkeletonStandardResourceAdapter.java skeleton file to a file name of your choice. See Rename the Skeleton File for more information.
Edit the new adapter’s source file as described in Edit the Source File.
Source the file you created previously to set up your environment:
For Windows: Source the ws.bat file.
For UNIX: Source the ws.sh file.
Type the following command to compile your source files:
For Windows: javac -d . -classpath %CLASSPATH% yourfile.java
For UNIX: javac -d . -classpath $CLASSPATH yourfile.java
This section describes the general steps you follow to create a custom Active Sync-Enabled adapter on the Microsoft Windows operating system.
Open a command window and change to the following directory:
\waveset\idm\adapter\src
Rename (or copy) one of the following skeleton files to a file name of your choice. See Rename the Skeleton File for more information.
SkeletonStandardAndActiveSyncResourceAdapter.java (for standard and Active Sync-enabled resources)
SkeletonActiveSyncResourceAdapter.java (for Active Sync-only resources)
Edit the new adapter’s source file as described in Edit the Source File.
Source the file you created previously to set up your environment:
For Windows: Source the ws.bat file.
For UNIX: Source the ws.sh file.
Type the following command to compile your source files:
For Windows: javac -d . -classpath %CLASSPATH% yourfile.java
For UNIX: javac -d . -classpath $CLASSPATH yourfile.java
You must rename the skeleton adapter to a name that is appropriate for your new adapter. Perform the following actions:
Rename the sample java file to match your new class name.
Edit the source code to replace the sample class name with the new class name.
After renaming the skeleton file, you must edit the new adapter’s source code to replace specific text strings and to define default values you want the adapter to support.
Search for, and replace, the following text strings to determine where you must make adapter-specific modifications in the code.
Name the resource adapter type.
This name displays in the New Resources menu in the Waveset Administrator interface.
Map the incoming resource attributes to Waveset account attributes by replacing default values in the prototypeXML string with your own default values for this adapter type. For example, you might want to delete the RA_GROUPS attribute from your adapter type.
See Map the Attributes for more information.
Add or delete methods from the skeleton file. In particular, you must add Java code to support join, leave, and move operations, which are not supported in this example file.
See Write the Adapter Methods for more information.
After editing the adapter file, you can load it into Waveset.
Generally, you set options for the adapter type by mapping the incoming resource attributes to the standard Waveset account attributes or by creating your own custom attributes (called extended schema attributes).
Your resource must define resource attributes and set default values for resource attributes for which it makes sense to have default. The resource does not have to present the prototypeXML object.
The attributes in SkeletonActiveSyncResourceAdapter are mandatory. Do not delete these attribute definitions when customizing the file.
To map incoming resource attributes to one of the standard Waveset account attributes, use the syntax shown in the following example.
Where:
The <AccountAttributesTypes> element surrounds the prototypeXML string where you map the resource attribute to the Waveset account attribute.
The <AttributeDefinitionRef> element identifies the Waveset account attribute.
The following table describes the <AttributeDefinitionRef> element fields.
Element Field |
Description |
---|---|
name |
Identifies the Waveset account attribute to which the resource attribute is being mapped. (The left column on the resource schema page in the Waveset User Interface.) |
mapName |
Identifies the name of the incoming resource attribute. When editing the skeleton file, replace change-value-here with the resource attribute name. |
mapType |
Identifies the incoming attribute type, which can be string, int, or encrypted. |
For more information on mapping resource attributes to account attributes, see Map the Attributes.
To map incoming resource attributes to attributes other than a standard Waveset attribute, you must create an extended schema attribute. The following example illustrates how to map a resource attribute to an extended schema attribute.
<AccountAttributeType name=’HomeDirectory’ type=’string’ mapName=’HomeDirectory’ mapType=’string’>\n"+ </AccountAttributeType>\n"+ |
You do not have to declare an ObjectRef type. The mapName field identifies the custom account attribute HomeDirectory. You define the mapType field the same as you would when mapping an attribute to a standard account attribute.
You must use an identity template (or an account DN) to uniquely identify every user and group in your enterprise.
DNs display on the following Waveset User interface pages:
Resources
Distinguished Name Template
Edit Schema
For more information about identity templates, see Identity Template.
The Waveset adapter interface provides general methods that you must customize to suit your particular environment. This section briefly describes:
Standard resource adapter-specific methods are specific to the resource you are updating to synchronize with Waveset.
The body of a resource adapter consists of resource-specific methods. Consequently, the resource adapter provides methods that are only generic placeholders for the specific methods that you will write.
This section describes how the methods used to implement operations are categorized. The information is organized into the following sections:
When writing a custom adapter
Call the setdisabled() method on any WSUser object that is returned by a custom method.
If the adapter implements the AsynchronousResourceAdapter class, then note that this adapter might be working with users that are partially initialized. (These users are created outside Waveset, but not fully populated with attributes.) The Provisioner does not automatically convert a Create operation to an Update operation if the WSUser already exists on the resource. Your resource adapter must distinguish this case.
The following table describes the methods used to create a Resource instance.
Table 10–14 Methods Used to Create a Resource Instance
The following methods are responsible for establishing connections and disconnections as an authorized user. All resource adapters must implement these methods.
ResourceAdapterBase provides methods that you can use to check the validity of an operation, such as whether the connection to the resource is working, before the adapter attempts the actual operation.
The following table describes methods you can use to verify that your adapter is communicating with the resource and that the authorized account has access.
Table 10–15 Methods Used to Check Communication
The getFeatures() method specifies which features are supported by an adapter. The features can be categorized as follows:
General features
Account features
Group features
Organizational unit features
The ResourceAdapterBase class defines a base implementation of the getFeatures() method. The Enabled in Base? column in the following tables indicates whether the feature is defined as enabled in the base implementation in ResourceAdapterBase.
Table 10–16 General Features
Feature Name |
Enabled in Base? |
Comments |
---|---|---|
ACTIONS |
No |
Indicates whether before and after actions are supported. To enable, override the supportsActions method with a true value. |
RESOURCE_PASSWORD_CHANGE |
No |
Indicates whether the resource adapter supports password changes. To enable, override the supportsResourceAccount method. |
Table 10–17 Account Features
Table 10–18 Group Features
Feature Name |
Enabled in Base? |
Comments |
---|---|---|
GROUP_CREATE,GROUP_DELETE, GROUP_UPDATE |
No |
Indicates whether groups can be created, deleted, or updated. Use the put operation to if these features are supported on the resource. |
Table 10–19 Organizational Unit Features
Feature Name |
Enabled in Base? |
Comments |
---|---|---|
ORGUNIT_CREATEORGUNIT_DELETEORGUNIT_UPDATE |
No |
Indicates whether organizational units can be created, deleted, or updated. Use the put operation to if these features are supported on the resource. |
If your custom adapter overrides the ResourceAdapterBase implementation of the getFeatures method, add code similar to the following:
public GenericObject getFeatures() { GenericObject genObj = super.getFeatures(); genObj.put(Features.ACCOUNT_RENAME, Features.ACCOUNT_RENAME); genObj.remove(Features.ACCOUNT_UPDATE, Features.ACCOUNT_UPDATE); .. other features supported by this Resource Adapter … return genObj; } |
To disable a feature by overriding a different method (such as supportsActions) add code similar to the following:
public boolean supportsActions() { return true; } |
The following tables describe the methods used to create, delete, and update accounts on Resources.
Table 10–20 Creating Accounts on the Resource
Method |
Description |
---|---|
realCreate() |
Creates the account on the resource. Receives a user object as input, and contains the account attribute information needed to create the user account (such as account name, password, and user name) |
Table 10–21 Deleting Accounts on the Resource
Method |
Description |
---|---|
realDelete() |
Deletes one or more accounts on the resource. Receives a user object or list of user objects as input. By default, this method creates a connection, calls realDelete, closes the connection for each user object in the list. |
Table 10–22 Updating Accounts on the Resource
Method |
Description |
---|---|
realUpdate() |
Updates a subset of the account attributes. By default, this method creates a connection, calls realUpdate, and closes the connection for each user object in the list. NOTE: User account attributes from the resource are merged with any new changes from Waveset. |
Table 10–23 Getting User Information
Method |
Description |
---|---|
getUser() |
Retrieves information from the resource about user attributes. Receives a user object as input (typically with only an account identity set), and returns a new user object with values set for any attribute defined in resource schema map. |
You can use list methods to establish processes that adapters use to retrieve user information from the resource.
Table 10–24 List Methods
Method |
Description |
---|---|
getAccountIterator() |
Used to discover or import all the users from a resource. Implements the Account Iterator interface to iterate over all users of a resource. |
listAllObjects () |
Given a resource object type (such as accountID or group), returns a list of that type from the resource. Implement this method to generate lists that are used by the resource, such as a list of resource groups or distribution lists. This method is called from the user form (not called by provisioning engine). |
Best Practice
When writing an AccountIterator interface implementation for a custom adapter, try to do the following:
Have the AccountIterator.next() method return a user that contains all attributes in the schema map when getAccountIterator() is called. The reconciler will trim the schema (in a cloned resource used for the getAccountIterator() request) to request only those attributes the reconciler needs. Generally, the reconciler needs only the accountId attribute; but there are cases when the reconciler has additional attributes in the schema. Other getAccountIterator() users, such as Load From Resource, potentially need all of the schema attributes.
Try to create a “smart” adapter that does the right thing based on what is in the schema map. If your adapter can just list the accounts and get the requested information, then the adapter should just do those tasks. Otherwise, the adapter might have to fetch an account to get the required attributes. Adapters that are not smart always get all the attributes.
Make your adapter as scalable as possible, which generally means the adapter does not list or fetch all of the accounts at once. Instead, your adapter should iterate over the accounts as the AccountIterator.next() method is called. Avoid having your adapter do much in the AccountIterator constructor.
The following example shows code for retrieving information from a resource and converting that information into information that Waveset can work with.
Resource Adapters: Retrieving Information on a Resource
public WSUser getUser(WSUser user) throws WavesetException { String identity = getIdentity(user); WSUser newUser = null; try { startConnection(); Map attributes = fetchUser(user); if (attributes != null) { newUser = makeWavesetUser(attributes); } } finally { stopConnection(); } return newUser; } |
Method |
Description |
---|---|
supportsAccountDisable() |
Returns true or false depending on whether the resource supports native account disable. |
realEnable() |
Implements native calls that are needed to enable the user account on the resource. |
realDisable() |
Implements native calls that are needed to disable the user account on the resource. |
You can disable an account by using the disable utilities supported by the resource or the account disable utility provided by Waveset.
Use native disable utilities whenever possible.
Native support for disabling an account: Certain resources provide a separate flag that, when set, prevents users from logging in. Example utilities include User Manager for Active Directory Users and Computers for Active Directory, and ConsoleOne or Netware Administrator for NDS/Netware. When an account is enabled, the user’s original password is still valid. You can determine whether native support for account disable is available on your resource by implementing the supportsAccountDisable method.
Waveset disable utility: If the resource does not support disabling an account, or supports disable by means of resetting the user’s password, the Waveset provisioning engine disables the account. You can perform the disable by setting the user account to a randomly generated, non-displayed, non-retained password. When the account is enabled, the system randomly generates a new password, which is displayed in the Waveset Administrative interface or emailed to the user.
Use the following general steps to enable pass-through authentication in a resource type:
Ensure that the adapter’s getFeatures() method returns ResourceAdapter.ACCOUNT_LOGIN as a supported feature.
If your custom adapter overrides the ResourceAdapterBase implementation, add the following code.
public GenericObject getFeatures() { GenericObject genObj = super.getFeatures(); genObj.put(Features.ACCOUNT_RENAME, Features.ACCOUNT_RENAME); .. other features supported by this Resource Adapter … return genObj; } |
If your custom adapter does not override the getFeatures() implementation in the ResourceAdapterBase class, it will inherit the getFeatures() implementation that is exported for ACCOUNT_LOGIN by default.
Add the <LoginConfigEntry> element to the adapter’s prototypeXML.
Implement the adapter’s authenticate() method.
The authenticate() method authenticates the user against the resource by using the authentication property name/value pairs provided in the loginInfo map. If authentication succeeds, be sure that the authenticated unique ID is returned in the WavesetResult by adding a result as follows:
result.addResult(Constants.AUTHENTICATED_IDENTITY, accountID); |
If authentication succeeded, but the user’s password was expired, then in addition to the identity added above, also add the password expired indicator to the result to be returned. This will ensure that the user will be forced to change their password on at least resource upon next login to Waveset.
result.addResult(Constants.RESOURCE_PASSWORD_EXPIRED, new Boolean(true)); |
If authentication fails (because the user name or password is invalid), then:
throw new WavesetException("Authentication failed for " + uid + "."); |
Active Sync-specific methods provide the mechanism for updating Waveset, which is the primary purpose of your Active Sync-enabled adapter adapter. These methods are based on pulling information from the authoritative resource. In addition, you use these methods to start, stop, and schedule the adapter.
The methods you are going to write in this section of the adapter are based on generic methods supplied with the skeleton adapter file. You must edit some of these methods, which are categorized by task.
The following sections describe general guidelines for creating Active Sync-enabled adapter methods:
You initialize and schedule the adapter by implementing the init() and poll() methods.
The init() method is called when the adapter manager loads the adapter. There are two methods for loading the adapter:
The manager can load the adapter at system startup if the adapter startup type is automatic.
An administrator loads the adapter by clicking Start on the Resources page if the adapter startup type is manual.
In the initialization process, the adapter can perform its own initialization. Typically, this involves initializing logging (with the ActiveSyncUtil class), and any adapter-specific initialization such as registering with a resource to receive update events.
If an exception is thrown, the adapter is shut down and unloaded.
All of the adapter’s work is performed by the poll() method. Scheduling the adapter requires setting up a poll() method to search for and retrieve changed information on the resource.
This method is the main method of the Active Sync-enabled adapter. The adapter manager calls the poll() method to poll the remote resource for changes. The call then converts the changes into IAPI calls and posts them back to a server. This method is called on its own thread and can block for as long as needed.
It should call its ActiveSyncUtil instance’s isStopRequested method and return when true. Check isStopRequested as part of the loop condition when looping through changes.
To configure defaults for polling, you can set the polling-related resource attributes in the adapter file. Setting these polling-related attributes provides administrators with a means to later use the Waveset interface to set the start time and date for the poll interval and the length of the interval.
Scheduling Parameters
You use the following scheduling parameters in Active Sync-enabled adapters:
RA_SCHEDULE_INTERVAL
RA_SCHEDULE_INTERVAL_COUNT
RA_SCHEDULE_START_TIME
RA_SCHEDULE_START_DATE
See Table 10–6 for a description of these parameters.
Scheduling Parameters in the prototypeXML
The scheduling parameters are present in the string constant ActiveSync. ACTIVE_SYNC_STD_RES_ATTRS_XML, along with all other general Active Sync-related resource attributes.
The following table describes the usage of scheduling parameters using some sample polling scenarios.
Table 10–26 Sample Polling Scenarios
Polling Scenario |
Parameters |
---|---|
Daily at 2 A.M. |
Interval = day, count =1, start_time=0200 |
Four times daily |
Interval=hour, count=6. |
Poll once every two weeks on Thursday at 5 P.M |
Interval = week, count=2, start date = 20020705 (a Thursday), time = 17:00. |
Most Active Sync-enabled adapters are also standard adapters, where a single Java class both extends ResourceAdapterBase (or AgentResourceAdapter) and implements the Active Sync interface.
The following example shows how to retrieve the attribute and pass the update through to the base.
public Object getAttributeValue(String name) throws WavesetException { return getResource().getResourceAttributeVal(name); } public void setAttributeValue(String name, Object value) throws WavesetException { getResource().setResourceAttributeVal(name,value); |
When an update is received, the adapter uses the IAPI classes, notably IAPIFactory to:
Collect the changed attributes
Map the changes to a unique Waveset object
Update that object with the changed information
Using the Active Sync event parameter configurator for the resource, IAPIFactory.getIAPI constructs an IAPI object, either IAPIUser or IAPIProcess from a map of changed attributes. If an exclusion rule (iapi_create, iapi_delete, or iapi_update) is configured for the resource, IAPIFactory checks if the account is excluded. If a non-null object is created and returned by the Factory, the adapter can modify the IAPI object (for example, by adding a logger), then submits it.
When the object is submitted, the form associated with the resource is expanded with the object view before the view is checked in. For more information about forms and views, see Deployment Reference.
In SkeletonActiveSyncResourceAdapter, this process is handled in the buildEvent and processUpdates methods.
No system requirements are associated with adapter shutdown. Waveset calls the shutdown method, which is an opportunity for your adapter to cleanup any objects still in use from the polling loop.
Waveset uses pass-through authentication to grant users and administrators access through one or more different passwords. Waveset manages pass-through authentication through the implementation of:
Login applications (collection of login module groups)
Login module groups (ordered set of login modules)
Login modules (sets authentication for each assigned resource and specify one of several success requirements for authentication)
You configure a custom adapter to support pass-through authentication by
Implementing the authenticate() method appropriately
Including the account.LOGIN feature in the getFeatures() method map (com.waveset.adapter.ResourceAdapter.ACCOUNT_LOGIN)
Including the <LoginConfigEntry> section in the resource’s prototypeXML
When configuring a custom resource adapter to support an interactive login, you must enable the adapter to request additional information from a user during log in and after that user submits the initial login page.
The adapter authenticate() method controls whether the login becomes interactive. The authenticate() method’s return values trigger the interactive login so the authenticate() is called again with the results of the next login page until the authenticate() method decides the login
Fails by throwing an exception
Succeeds by returning the account ID of the authenticated account in the WavesetResult as usual
To be interactive, the adapter must return a WavesetResult that
Does not contain ResultItems with a Constants.AUTHENTICATED_GUID type or Constants.AUTHENTICATED_IDENTITY type
Does contain ResultItems that are used to dynamically build a form for the next page of the login
Each ResultItem corresponds to a field in the form. ResultItems must have the Constants.CONTINUE_AUTHENTICATION_ATTR type with values in the following format:
label|attrName|displayType|prompt|’isId’
Where
label is a string containing a label or none.
attrName is the login attribute name that is passed into the next authenticate() method call as a key in the loginInfo HashMap.
displayType describes the type of form field to use. displayType values include
text
secret
label
checkbox
prompt corresponds to the title or label of the form field.
isId is an optional string.
If you use the isId string, the value of the form field is added to the loginInfo HashMap with the key Constants.ACCOUNT_ID and the value of the field.
The following ResultItem types are also “round-tripped” and returned in the loginInfo HashMap on the next authenticate() call:
Constants.CONTINUE_AUTHENTICATION_ACCOUNT_HANDLE keep track of which user or account is in the process of being authenticated.
Constants.CONTINUE_AUTHENTICATION_PREVIOUS_ATTR remove previous authentication attributes from the loginInfo, so the loginInfo does not contain an “old” authentication attr.
This section describes how to define the following resource object components:
Object classes are handled differently for LDAP-based resource objects than for other resource objects.
LDAP-based resource objects can consist of more than one LDAP object class, where each object class is an extension of its parent object class. However, within LDAP, the complete set of these object classes is viewed and managed as a single object type within LDAP.
To manage this type of resource object within Waveset, include the XML element <ObjectClasses> within the <ObjectType> definition. The <ObjectClasses> element allows you to define the set of object classes that is associated with this <ObjectType> as well as the relationship of classes to each other.
For non-LDAP-based resource objects, you can use the <ObjectType> to represent information other than the resource object type name.
In the following example, the primary attribute defines the object class to be used when creating and updating an object of this type. In this case, inetorgperson is the object class that is defined as the primary one because it is a subclass of the other listed object classes. The operator attribute specifies whether the list of object classes should be treated as one (logical AND) or treated as unique classes (logical OR) when listing or getting an object of this type. In this case, Waveset performs an AND operation on these object classes prior to any list or get requests for this object type.
<ObjectClasses primary=’inetorgperson’ operator=’AND’>\n"+ <ObjectClass name=’person’/>\n"+ <ObjectClass name=’organizationalPerson’/>\n"+ <ObjectClass name=’inetorgperson’/>\n"+ </ObjectClasses>\n"+ |
In the next example, all requests to create and/or update resource objects of this type are done using the groupOfUniqueNames object class. All list and get requests will query for all objects whose object class is either groupOfNames or groupOfUniqueNames.
<ObjectClasses primary=’groupOfUniqueNames’ operator=’OR’>\n"+ <ObjectClass name=’groupOfNames’/>\n"+ <ObjectClass name=’groupOfUniqueNames’/>\n"+ </ObjectClasses>\n"+ |
In this example, only one object class is defined so all create, get, list, and update operations are performed using object class organizationalUnit.
<ObjectClasses operator=’AND’>\n"+ <ObjectClass name=’organizationalUnit’/>\n"+ </ObjectClasses>\n"+ |
Because there is only one object class, you can exclude the <ObjectClasses> section. If you exclude the <ObjectClasses> section, the object class defaults to the <ObjectType> name attribute value. However, if you want the object type name to differ from the resource object class name, you must include the <ObjectClasses> section with the single <ObjectClass> entry.
Resource Object types uniquely define a specific type of resource, and you define object types in the adapter’s prototypeXML string.
The XML <ObjectTypes> element is a container within the adapter’s prototypeXML string that contains one or more object type definitions to be managed on that resource. This <ObjectTypes> element fully describes the resource-specific object to Waveset, including the following:
A list of specific object classes contained in the object type (required only for LDAP-compliant directories)
A list of supported features
A list of object type-specific attributes that are available within Waveset for editing and searching
The following table describes the supported attributes of the <ObjectType> element.
Table 10–27 Supported <ObjectType> Element Attributes
The following example shows ObjectType definitions:
static final String prototypeXml = "<Resource name=’Skeleton’ class= ’com.waveset.adapter.sample.SkeletonStandardResourceAdapter’ typeString=’Skeleton of a resource adapter’ typeDisplayString=’"+Messages.RESTYPE_SKELETON+"’>\n"+ " <ObjectTypes>\n"+ " <ObjectType name=’Group’ icon=’group’>\n"+ … other content defined below will go here … " </ObjectType>\n"+ " <ObjectType name=’Role’ icon=’ldap_role’>\n"+ … other content defined below will go here … " </ObjectType>\n"+ " <ObjectType name=’Organization’ icon=’folder_with_org’ container=’true’>\n"+ … other content defined below will go here … "</ObjectType>\n"+ " </ObjectTypes>\n”+ |
The <ObjectFeatures> section specifies a list of one or more features supported by this object type, where each object feature is directly tied to the implementation of the associated object type method in the resource adapter.
Each ObjectFeature definition must contain the name attribute, which specifies a feature name. The create and update features can specify a form attribute, which defines the resource form used to process create and update features. If you do not specify a form attribute, Waveset processes the create and update features with the same form used by all resources of a given type.
The following table describes the object feature mappings.
Table 10–28 Object Feature Mappings
Object Feature |
Method |
Supports Form Attribute? |
---|---|---|
create |
createObject |
Yes |
delete |
deleteObject |
No |
find |
listObjects |
No |
list |
listObjects |
No |
rename |
updateObject |
No |
saveas |
createObject |
No |
update |
updateObject |
Yes |
view |
getObject |
No |
In the following example, the <ObjectFeatures> section includes all supported object features. Your resource adapter can support all of these features or just a subset of features. The more object features your adapter supports, the richer the object management function within Waveset.
<ObjectFeatures>\n"+ <ObjectFeature name=’create’ form=’My Create Position Form’/> <ObjectFeature name=’update’ form=’My Update Position Form’/> <ObjectFeature name=’create’/>\n"+ <ObjectFeature name=’delete’/>\n"+ <ObjectFeature name=’rename’/>\n"+ <ObjectFeature name=’saveas’/>\n"+ <ObjectFeature name=’find’/>\n"+ <ObjectFeature name=’list’/>\n"+ <ObjectFeature name=’view’/>\n"+ </ObjectFeatures>\n"+ |
The <ObjectAttributes> section specifies the set of attributes to be managed and queried in Waveset. Each <ObjectAttribute> element name should be the same as the native resource attribute name. Unlike user attributes in Waveset, no attribute mapping is specified. Use only the native attribute names.
The following table describes attributes that are required for <ObjectAttributes>.
Table 10–29 Required Attributes for <ObjectAttributes>
Attribute |
Description |
---|---|
idAttr |
The value of this attribute should be the resource object attribute name that uniquely identifies this object within the resource’s object namespace (for example, dn, uid) |
displayNameAttr |
The value of this attribute should be the resource object attribute name whose value is the name you want displayed when objects of this type are viewed within Waveset (for example, cn, samAccountName). |
descriptionAttr |
(Optional) This value of this attribute should be the resource object attribute name whose value you want displayed in the Description column of the Resources page. |
The following example shows an <ObjectAttributes> section defined in an <ObjectType>.
<ObjectAttributes idAttr=’dn’ displayNameAttr=’cn’ descriptionAttr= ’description’>\n"+ <ObjectAttribute name=’cn’ type=’string’/>\n"+ <ObjectAttribute name=’description’ type=’string’/>\n"+ <ObjectAttribute name=’owner’ type=’distinguishedname’ namingAttr=’cn’/>\n"+ <ObjectAttribute name=’uniqueMember’ type=’dn’ namingAttr=’cn’ />\n"+ </ObjectAttributes>\n"+ |
The following table describes the <ObjectAttribute> attributes.
Table 10–30 <ObjectAttribute> Attributes
Attribute |
Description |
---|---|
name |
Identifies the resource object type attribute name (required) |
type |
Identifies the type of object. Valid types include string or distinguishedname / ”dn’ (defaults to string) |
namingAttr |
If object type is distinguishedname or dn, this value specifies the attribute whose value should be used to display an instance of this object type referred to by the dn within Waveset |
The methods in the resource adapter object type implementation are responsible for coercing all string values into the appropriate type based on the resource attribute name.
You must provide the following resource forms:
A ResourceForm named <resource type> Create <object type> Form for each resource <ObjectType> that supports the Create feature.
For example, AIX Create Group Form or LDAP Create Organizational Unit Form
A ResourceForm named <resource type> Update <object type> Form for each resource <ObjectType> that supports the Update feature.
For example, AIX Update Group Form or LDAP Update Organizational Unit Form
You can also assign an optional form that processes incoming data before storing it in Waveset. This resource form is a mechanism that transforms incoming data from the schema map and applies the transformed data to the User view. The sample form also performs actions, such as enabling and disabling an account, that are based on specific incoming data values such as employee status.
The following table describes attributes contained in the top-level namespace.
All values are strings unless otherwise specified.
Attribute |
Description |
---|---|
<objectType>.resourceType |
Waveset resource type name (for example, LDAP, Active Directory) |
<objectType>.resourceName |
Waveset resource name |
<objectType>.resourceId |
Waveset resource ID |
<objectType>.objectType |
Resource-specific object type (for example, Group) |
<objectType>.objectName |
Name of resource object (for example, cn or samAccountName) |
<objectType>.objectId |
Fully qualified name of resource object (for example, dn) |
<objectType>.requestor |
ID of user requesting view |
<objectType>.attributes |
Resource object attribute name/value pairs (object) |
<objectType>.organization |
Waveset member organization |
<objectType>.attrsToGet |
List of object type specific attributes to return when requesting an object through checkoutView or getView (list) |
<objectType>.searchContex |
Context used to search for non-fully qualified names in form input |
<objectType>.searchAttributes |
List of resource object type-specific attribute names that will be used to search within the specified searchContext for names input to the form (list). |
<objectType>.searchTimeLimit |
Maximum time spent searching where <objectType> is the lowercase name of a resource specific object type. For example, group, organizationalunit, organization. |
<objectType>.attributes<resource attribute name> |
Used to get or set the value of specified resource attribute (for example, <objectType>.attributes.cn, where cn is the resource attribute name). When resource attributes are distinguished names, the name returned when getting the value is the value of the namingAttr specified in the <ObjectAttribute> section of the <ObjectType> description. |
If necessary, create the following directory:
idm/WEB-INF/classes/package_path |
Where package_path is the package where your class is defined. For example,
com/waveset/adapter/sample
Copy your NewResourceAdapter.class file into the directory you just created.
Create a gif image that is 18x18 pixels and 72 DPI in size to represent your adapter. Waveset displays this .gif file image next to the resource name on the List Resources page.
You must use the following format when naming your .gif file:
YourAdapterName.gif
You must replace any spaces in your adapter name with underscores. For example, look at some of the existing adapter names in
\waveset\idm\web\applet\images
Copy the .gif file to idm/applet/images.
Stop and restart the application server. For information about working with application servers, see Installation Guide.
Create an HTML help file for your resource.
The idm.jar in the com/waveset/msgcat/help/resources directory contains example help files.
See Deployment Reference for information about including online help with an application.
From the Managed Resources page of the Administrator interface, click the Custom Adapter button and enter the full class name of your adapter class. For example
com.waveset.adapter.sample.NewResourceAdapter
Create a resource in Waveset using your adapter.
Ensure your native managed system is operational.
Test the connectivity of your new Waveset resource, as described in Checking Connections and Operations.
After writing a custom resource adapter, you must test the validity of that adapter. In particular, you must test the connection to the resource.
Topics covered in this section include:
Use the following steps to unit-test the validity of a custom adapter (in particular, to test the connection to the resource):
Save the adapter.
Run unit tests on that adapter from your own machine.
Load the adapter into Waveset.
Test the adapter in Waveset, as follows:
Writing and maintaining a custom resource adapter can be a very complex process. Developers commonly discover that their custom adapters do not perform as expected, or that the adapters do not perform the functions expected by Waveset. Even well-written resource adapters will sometimes not work well after the external resource has been upgraded.
Waveset provides a compatibility testing mechanism that you can use to verify the quality of a custom resource adapter. This tester
Makes it easier for you to write, publish, and maintain a custom adapter
Makes it easier for you to run the adapter and interpret results
Focuses on testing the adapter’s supported features as fully as possible in an adapter-independent manner
Simplifies troubleshooting an adapter
This section describes how to use Waveset’s Compatibility Test Suite. The information is organized as follows:
Waveset’s Compatibility Test Suite performs a set of standard tests to check the adapter’s supported features. If a particular test requires a feature not provided by the adapter, Waveset skips that test.
The Compatibility Test Suite requires certain information, such as a valid user name and password to run a compatibility test on a resource adapter. You can typically use the standard DataProvider (provided with Waveset) to supply the data required for the test.
For special circumstances, such as when you want to provide information in a class instead of as an expression in XML, you can write a custom DataProvider.
Open a command window.
At the command prompt, type the lh command using the following format:
$WSHOME/bin/lh com.sun.idm.testing.adapter.CompatibilitySuite [Options] [testName] |
Where:
[options] include:
-h: Use to access usage information
For example:
Usage: CompatibilitySuite [arguments]
Valid arguments:
Argument |
Description |
---|---|
-propsFile value |
Path to the properties file |
-formatter value |
Formatter to use for formatting output of tests |
-user value |
Name of user to execute test as |
-pass value |
Plain text password used to log the user on |
-import value |
Comma separated list of files (on server) to import |
-toDir value |
Directory to put test output in |
-v |
Echoes all arguments passed in to the screen |
-h |
Displays the usage message |
-propsFile file: Use to specify a properties file name.
-formatter type,path: Use to specify XML, HTML, or plain text and a path in which to put this file.
[testName] is a comma-separated list of the tests to run.
The following properties control how tests are executed:
Property |
Description |
---|---|
adapter |
Classname of the adapter to test |
dp |
Name of a custom DataProvider |
importScript |
Comma-separated list of paths to the scripts to execute Note: These scripts return a string of imported XML. |
ns |
DataProvider namespace |
includedTests |
Comma-separated list of tests to include |
excludedTests |
Comma-separated list of tests to exclude |
import |
Comma-separated list of files to import |
You can specify these properties directly from the command line, or add them to a properties file specified from the command line. For example,
lh -DpropName=propValue |
Where properties conflict, properties in the property file specified by propsFile are used.
When you use the [testName] command, the Compatibility Test Suite ignores the includedTests and excludedTests options.
In most cases, the framework provided by Waveset is flexible enough to test the resource adapter. However, you can easily extend the functionality in two places if necessary:
You can implement the DataProvider interface to create a custom DataProvider. A custom DataProvider allows data to come from any source.
You can implement the CompatibilityHelper interface to provide a CompatibilityHelper. A CompatibilityHelper provides a way to initialize a resource before running tests.
See the Javadoc for more information about implementing these interfaces and the required naming conventions.
This example illustrates how to run compatibility tests on a SimulatedResourceAdapter using the default DataProvider.
Use the following steps to prepare the compatibility tests.
Set up the following files:
sample/compat/example.1/example.properties
sample/compat/example.1/SimulatedCompatibilityConfig.xml
The default path to the simulated resource in SimulatedCompatibilityConfig is /tmp/mySimulatedResource.xml.
You can edit this path if you want to specify a different location.
Before executing the example, copy ant-junit.jar from Apache ant 1.6.5 to your $WSHOME/WEB-INF/lib directory.
Use the following steps to execute the compatibility tests.
Open a command window.
At the prompt, type
cd $WSHOME
bin/lh com.sun.idm.testing.adapter.CompatibilitySuite -propsFile sample/compat/example.1/example.properties
Your output should look similar to the following example:
TestSuite: com.sun.idm.testing.adapter.CompatibilitySuite Starting internal database server ... DB Server @ jdbc:hsqldb:hsql://127.0.0.1:57022/idm Importing file sample/compat/example.1/SimulatedCompatibilityConfig.xml ’Create(com.sun.idm.testing.adapter.compatibility.Create)’ skipped (unknown) ’Authenticate(com.sun.idm.testing.adapter.compatibility.AuthenticateUser)’ skipped (unknown) ’DeleteExisting(com.sun.idm.testing.adapter.compatibility.DeleteExisting)’ skipped (unknown) ’UpdateExisting(com.sun.idm.testing.adapter.compatibility.UpdateExisting)’ skipped (unknown) ’RenameExisting(com.sun.idm.testing.adapter.compatibility.RenameExisting)’ skipped (unknown) ’EnableExisting(com.sun.idm.testing.adapter.compatibility.EnableExisting)’ skipped (unknown) ’DisableExisting(com.sun.idm.testing.adapter.compatibility.DisableExisting)’ skipped (unknown) ’Iterate(com.sun.idm.testing.adapter.compatibility.Iterate)’ skipped (unknown) ’DeleteMissing(com.sun.idm.testing.adapter.compatibility.DeleteMissing)’ passed (77 ms) Tests run: 9, failures: 0, errors: 0, skipped: 8, Time elapsed: 10864 ms |
In Execute the Test, the lh command runs the compatibility test with the following argument:
-propsFile sample/compat/example.1/example.properties
Both the adapter and ns properties are required to run the test.
The adapter property provides the adapter class name to be tested.
The ns property provides a namespace for the test.
The DataProvider can use the namespace to set up multiple configurations.
Execute the Test also uses the import property, which imports a list of files into the repository. The import property is similar to lh import filename.
When you start the compatibility test, the tester retrieves the adapter and ns properties from the specified properties.
The default DataProvider retrieves data from the extension element of a namespace#TestData configuration object, which in this example was SimulatedCompatibilityConfig#TestData.
If you do not specify a DataProvider when setting up a test, Waveset used the default DataProvider.
The DataProvider retrieves this SimulatedCompatibilityConfig#TestData configuration object from the repository.
To get the configuration object into the repository, you must define the object in the following file, which is specified in the import property:
sample/compat/example.1/SimulatedCompatibilityConfig.xml
To simplify configuration in Execute the Test, only one test was run with the includedTests=DeleteMissing parameter.
See the Javadoc for more information about which parameters are available and which parameters are required for the different tests.
To run the creation tests, and other tests that create users, you must add more data to the configuration object. In this next example, you must use the default DataProvider again and import an XML file.
Use the following steps to prepare the compatibility tests.
Set up the following files:
sample/compat/example.2/example.properties
sample/compat/example.2/SimulatedCompatibilityConfig.xml
The default path to the simulated resource in SimulatedCompatibilityConfig is /tmp/mySimulatedResource.xml.
You can edit this path if you want to specify a different location.
Before executing the example, copy ant-junit.jar from Apache ant 1.6.5 to your $WSHOME/WEB-INF/lib directory.
Use the following steps to execute the compatibility tests.
Open a command window.
At the prompt, type
cd $WSHOME
bin/lh com.sun.idm.testing.adapter.CompatibilitySuite -propsFile sample/compat/example.2/example.properties
Your output should look similar to the following example:
TestSuite: com.sun.idm.testing.adapter.CompatibilitySuite Starting internal database server ... DB Server @ jdbc:hsqldb:hsql://127.0.0.1:57022/idm Importing file ./sample/compat/example.2/SimulatedCompatibilityConfig.xml ’Authenticate(com.sun.idm.testing.adapter.compatibility.AuthenticateUser)’ skipped (unknown) ’UpdateExisting(com.sun.idm.testing.adapter.compatibility.UpdateExisting)’ skipped (unknown) ’RenameExisting(com.sun.idm.testing.adapter.compatibility.RenameExisting)’ skipped (unknown) ’Iterate(com.sun.idm.testing.adapter.compatibility.Iterate)’ skipped (unknown) ’DeleteMissing(com.sun.idm.testing.adapter.compatibility.DeleteMissing)’ passed (15 ms) ’EnableExisting(com.sun.idm.testing.adapter.compatibility.EnableExisting)’ passed (259 ms) ’DisableExisting(com.sun.idm.testing.adapter.compatibility.DisableExisting)’ passed (7 ms) ’DeleteExisting(com.sun.idm.testing.adapter.compatibility.DeleteExisting)’ passed (3 ms) ’Create(com.sun.idm.testing.adapter.compatibility.Create)’ passed (3 ms) Tests run: 9, failures: 0, errors: 0, skipped: 4, Time elapsed: 10178 ms |
You requested additional tests by setting the following property in the properties file:
IncludedTests=DeleteMissing,Create,EnableExisting,DisableExisting,DeleteExisting
These tests required more data from the DataProvider.
To provide this new data, several changes were made to the configuration object specified by SimulatedCompatibilityConfig.xml.
The SimulatedCompatibilityConfig.xml file added a create attribute containing a username, password, and list of user attributes. The default DataProvider uses the create attribute when the compatibility tests ask for the username, password, and attributes required to create a single user.
The SimulatedCompatibilityConfig.xml file also added a schema map.
In this next example, you finish the test configuration.
Use the following steps to prepare the compatibility tests.
Set up the following files:
sample/compat/example.3/example.properties
sample/compat/example.3/SimulatedCompatibilityConfig.xml
The default path to the simulated resource in SimulatedCompatibilityConfig is /tmp/mySimulatedResource.xml.
You can edit this path to specify a different location by changing two lines in the file.
Before executing the example, copy ant-junit.jar from Apache ant 1.6.5 to your $WSHOME/WEB-INF/lib directory.
You must initialize the repository to run the encrypt command.
For example, use the lh import sample/init.xml command to initialize the repository, where the original file looks like the following:
<Attribute name="login_infos"> <List> <Object> <Attribute name="sim_user" value="ctUser" /> <Attribute name="sim_password" value="ctPass" /> <Attribute name="shouldfail" value="no" /> </Object> <Object> <Attribute name="sim_user" value="ctUser" /> <Attribute name="sim_password" value="wrongPass" /> <Attribute name="shouldfail" value="yes" /> </Object> <Object> <Attribute name="sim_user" value="ctUser" /> <Attribute name="sim_password"> <!-- result of ’encrypt ctPass’ from lh console --> <EncryptedData>11D1DEF534EA1BE0:-32DFBF32:1165DC91D73: -7FFA|mDBIkSQB3xg=</EncryptedData> </Attribute> <Attribute name="shouldfail" value="no" /> </Object> <Object> <Attribute name="sim_user" value="ctUser" /> <Attribute name="sim_password"> <!-- result of ’encrypt wrongPass’ from lh console --> <EncryptedData>11D1DEF534EA1BE0:-32DFBF32:1165DC91D73: -7FFA|m0n9bAaMx+sKpqs5PmH3eQ== </EncryptedData> </Attribute> <Attribute name="shouldfail" value="yes" /> </Object> </List> </Attribute> |
In each case, use an encrypt command from the lh console to get an encrypted password that can be decrypted in your environment.
Run lh console and at the console prompt, type the text in single quotes for each of the preceding EncryptedData entries (for example, encrypt ctPass) and replace the text between <EncryptedData> and </EncryptedData> with the result.
See the following example:
<!-- result of ’encrypt ctPass’ from lh console --> <EncryptedData>11D1DEF534EA1BE0:-65F64461:1163AB5A7B2:-7FFA|iMm4Tcqck+M=</EncryptedData> <!-- result of ’encrypt wrongPass’ from lh console --> <EncryptedData>11D1DEF534EA1BE0:-65F64461:1163AB5A7B2:-7FFA|d1/PheqRok+J3uaggtj9Gw== </EncryptedData> |
Alternatively, you can have the DataProvider skip the two login info entries by commenting out the whole block as follows:
<!-- commented out <Attribute name="login_infos"> <List> <Object> <Attribute name="sim_user" value="ctUser" /> <Attribute name="sim_password" value="ctPass" /> <Attribute name="shouldfail" value="no" /> </Object> <Object> <Attribute name="sim_user" value="ctUser" /> <Attribute name="sim_password" value="wrongPass" /> <Attribute name="shouldfail" value="yes" /> </Object> <Object> <Attribute name="sim_user" value="ctUser" /> <Attribute name="sim_password"> <EncryptedData>11D1DEF534EA1BE0:-32DFBF32:1165DC91D73:-7FFA|mDBIkSQB3xg= </EncryptedData> </Attribute> <Attribute name="shouldfail" value="no" /> </Object> <Object> <Attribute name="sim_user" value="ctUser" /> <Attribute name="sim_password"> <EncryptedData>11D1DEF534EA1BE0:-32DFBF32:1165DC91D73: -7FFA|m0n9bAaMx+sKpqs5PmH3eQ== </EncryptedData> </Attribute> <Attribute name="shouldfail" value="yes" /> </Object> </List> </Attribute> --> |
Next, copy the new data and paste it inside the <EncryptedData> tag to replace the old data. Be certain there are no extra spaces or line breaks inside the tag.
Use the following steps to execute the compatibility tests.
Open a command window.
At the prompt, type
cd $WSHOME
bin/lh com.sun.idm.testing.adapter.CompatibilitySuite -propsFile sample/compat/example.3/example.properties
Your output should look similar to the following example:
TestSuite: com.sun.idm.testing.adapter.CompatibilitySuite Starting internal database server ... DB Server @ jdbc:hsqldb:hsql://127.0.0.1:57022/idm Importing file ./sample/compat/example.3/SimulatedCompatibilityConfig.xml ’Create(com.sun.idm.testing.adapter.compatibility.Create)’ passed (31 ms) ’Authenticate(com.sun.idm.testing.adapter.compatibility.AuthenticateUser)’ passed (12 ms) ’DeleteExisting(com.sun.idm.testing.adapter.compatibility.DeleteExisting)’ passed (1 ms) ’DeleteMissing(com.sun.idm.testing.adapter.compatibility.DeleteMissing)’ passed (1 ms) ’UpdateExisting(com.sun.idm.testing.adapter.compatibility.UpdateExisting)’ passed (33 ms) ’RenameExisting(com.sun.idm.testing.adapter.compatibility.RenameExisting)’ passed (5 ms) ’EnableExisting(com.sun.idm.testing.adapter.compatibility.EnableExisting)’ passed (10 ms) ’DisableExisting(com.sun.idm.testing.adapter.compatibility.DisableExisting)’ passed (5 ms) ’Iterate(com.sun.idm.testing.adapter.compatibility.Iterate)’ passed (352 ms) Tests run: 9, failures: 0, errors: 0, skipped: 0, Time elapsed: 10262 ms |
The line specifying the included tests was removed from the example.properties file, which should run the entire suite.
Additional data is required for the remaining tests, so the SimulatedCompatibilityConfig.xml file was modified to include update, rename, and iterate attributes. These attributes modify users, rename users, and create a set of users over which to iterate. In addition, the file added an login_info attribute that specifies a list of items used to authenticate a user if authentication is supported by the resource adapter.
Finally, the shouldfail attribute, provided in the file under the login info entries, allows negative tests. The tests in the suite should now complete with no errors or skipped tests.
The compatibility tests enable you to execute a javascript or beanshell script and then import the script results into the repository. Either script must return a string that contains the XML to be imported.
Waveset provides an example Apache Velocity template and some supporting beanshell script that uses the template. The beanshell script was created just to fill in the required variables, which makes it very easy to work with the default DataProvider.
Prepare the compatibility test to execute with a beanshell script
Set up the following files:
sample/compat/example.4/example.properties
sample/compat/example.4/SimulatedCompatibilityConfig.bsh
The default path to the simulated resource in SimulatedCompatibilityConfig is /tmp/mySimulatedResource.xml.
You can edit this path if you want to specify a different location.
You must change two lines in the file.
Before executing the example, copy ant-junit.jar from Apache ant 1.6.5 to your $WSHOME/WEB-INF/lib directory.
Execute the compatibility tests as follows:
Open a command window.
At the prompt, type
cd $WSHOME
bin/lh com.sun.idm.testing.adapter.CompatibilitySuite -propsFile sample/compat/example.4/example.properties
Your output should look similar to the following example:
TestSuite: com.sun.idm.testing.adapter.CompatibilitySuite Starting internal database server ... DB Server @ jdbc:hsqldb:hsql://127.0.0.1:57022/idm Executing script /opt/build/dv207518/adapterTestsTemp/waveset/export/pipeline/./sample/ compat/example.4/SimulatedCompatibilityConfig.bsh Importing results ’Create(com.sun.idm.testing.adapter.compatibility.Create)’ passed (25 ms) ’Authenticate(com.sun.idm.testing.adapter.compatibility.AuthenticateUser)’ passed (11 ms) ’DeleteExisting(com.sun.idm.testing.adapter.compatibility.DeleteExisting)’ passed (5 ms) ’DeleteMissing(com.sun.idm.testing.adapter.compatibility.DeleteMissing)’ passed (4 ms) ’UpdateExisting(com.sun.idm.testing.adapter.compatibility.UpdateExisting)’ passed (4 ms) ’RenameExisting(com.sun.idm.testing.adapter.compatibility.RenameExisting)’ passed (3 ms) ’EnableExisting(com.sun.idm.testing.adapter.compatibility.EnableExisting)’ passed (11 ms) ’DisableExisting(com.sun.idm.testing.adapter.compatibility.DisableExisting)’ passed (5 ms) ’Iterate(com.sun.idm.testing.adapter.compatibility.Iterate)’ passed (22 ms) Tests run: 9, failures: 0, errors: 0, skipped: 0, Time elapsed: 11354 ms |
The DataProvider supplied an importScript property, which caused the SimulatedCompatibilityConfig.bsh script to run. This script returns an XML string that is imported into the repository as a configuration object. The script specified the necessary items, and the velocity template creates the string.
You can use one of the following methods to debug the import script:
Use lh console to turn on tracing and then check the generated log files for the script’s return value. For example, type:
trace 4 com.sun.idm.testing.adapter.CompatibilitySuite
Use the excludedTests property and exclude each test. No tests run, but the script executes.
This example used beanshell scripting, but you can also use Javascript.
Several beanshell helpers are provided in the sample/compat/beanshell directory to make scripting easier by using the Apache Velocity template engine.
Commented examples are included to help you use the beanshell helpers.
To use the templates, add the following code at the top of your beanshell script:
// import helpers String wavesetHome = Util.getWavesetHome(); if(wavesetHome != null) { if ( wavesetHome.startsWith("file:" ) ) { wavesetHome = wavesetHome.substring("file:".length()); } addClassPath(wavesetHome + "./sample/compat/"); } importCommands("beanshell"); |
Using the helpers is optional.
When using a script, the only requirement is that the script must return a string containing XML. The script can access any of the parameters that were passed into the CompatibilitySuite using _params.
Where _params can contain any of the following properties.
Property |
Description |
---|---|
adapter |
Classname of the adapter to test |
dp |
Name of a custom DataProvider |
importScript |
Comma-separated list of paths to the scripts to execute Note: These scripts return a string of imported XML. |
ns |
DataProvider namespace |
includedTests |
Comma-separated list of tests to include |
excludedTests |
Comma-separated list of tests to exclude |
import |
Comma-separated list of files to import |
These properties are not provided in the _params map unless you set them in the properties file or used the -D command from the command line to add these properties to the _params map.
In beanshell, you can use a call to params.get(“parameter_name”) to retrieve these parameters.
If the beanshell script needs to know how the namespace parameter was set so that the script could form the name of the configuration object, the parameter would be retrieved as follows:
String namespace = _params.get("ns");
Use the following process to run compatibility tests from inside the web container.
Use the following steps to prepare the compatibility tests.
Copy ant-junit.jar from Apache ant 1.6.5 to your $WSHOME/WEB-INF/lib directory.
Enable the com.sun.idm.testing.adapter.compatibility.CTServlet by uncommenting the following in the web.xml file:
Uncomment servlet definition:
<servlet> <servlet-name>CompatibilityTests</servlet-name> <servlet-class>com.sun.idm.testing.adapter.compatibility.CTServlet</servlet-class> <load-on-startup>1</load-on-startup> </servlet> |
Uncomment servlet mapping:
<servlet-mapping> <servlet-name>CompatibilityTests</servlet-name> <url-pattern>/servlet/CTServlet</url-pattern> </servlet-mapping> |
You might have to restart your computer to use the new servlet.
The servlet accepts POST requests with certain parameters. Some parameters, such as imported files, allow you to specify multiples.
You can specify the following parameters to the Compatibility Suite:
Property |
Description |
---|---|
adapter |
Classname of the adapter to test |
dp |
Name of a custom DataProvider |
excludedTests |
Comma-separated list of tests to exclude |
import |
Comma-separated list of files to import |
importScript |
Comma-separated list of paths to the scripts to execute Note: These scripts return a string of imported XML. |
includedTests |
Comma-separated list of tests to include |
ns |
DataProvider namespace |
pass |
Plain Text password used to log user on Note: This password is sent in plain text, which may influence your decision on whether or not to enable the servlet. |
user |
Name of user who executes test |
Additional, remote-only parameters include:
Property |
Description |
---|---|
importXMLText |
String containing XML to import |
importScriptText |
String containing script to run |
importScriptSuffix |
Specify bsh if the script is a beanshell script Specify js if the script is javascript. Note: If you specify multiple scripts to the servlet, the scripts must all be javascript or all beanshell, you cannot specify one of each. |
You can access the servlet through debug/CompatTests.jsp or the command line Java program, CTContainerTest.java.
To prepare for running the tests remotely, copy the file idmtesting.jar and the example folders under sample/compat to the remote system.
Run the tests from the CompatTests.jsp page
Open a browser and navigate to your idm instance/debug/CompatTests.jsp. For example,
http://example.com:8080/idm/debug/CompatTests.jsp
To run the example, you must provide the following values:
Namespace = SimulatedAdapterTests
Adapter = com.waveset.adapter.SimulatedResourceAdapter
User Name to Run Test as = configurator
Password for User to Run Test as = configurator’s password
Script type = Beanshell radio button
Import Result of this Script Text = SimulatedCompatibilityConfig.bsh file contents
Copy the contents of the SimulatedCompatibilityConfig.bsh file from the sample/compat/example.4 directory and paste them into this text field.
This script runs Example 4, but you can run the other examples in the same way. The other parameters are available too, but the names are slightly altered in the jsp file.
You can also run the compatibility test remotely from a command line Java program called CTContainerTest. The usage is as follows:
CTContainerTest -url url [-v] [-parm1_name parm1_value e ... -parmx_name parmx_value] |
Where:
Parameter names are the same as parameters accepted by the servlet.
Parameter values are the same as values accepted by the servlet.
The servlet does not support the following parameters as a command line argument:
importScriptText
You can use the importLocalScriptFile parameter to send the importScriptText parameter to the servlet. The importLocalScriptFile option reads the contents of the file specified by the parameter value, and submits the content of that file to the servlet with the importScriptText parameter name.
importXMLText
You can use the importLocalXMLFile parameter to send the importXMLText parameter to the servlet. The importLocalXMLFile option reads the contents of the file specified by the parameter value, and submits the content of that file to the servlet with the importXMLText parameter name.
For more information about the available parameters and their use, run the CTContainerTest program with no arguments, as follows:
java -cp idmtesting.jar com.sun.idm.testing.adapter.CTContainerTest |
The following examples illustrate different ways to run this command.
To run these examples in a Windows environment, you must adjust the hostname and port, change the classpath separation character from a colon (:) to a semicolon (;), and change the path separator from a backward slash (/) to a forward slash (\).
Running a Compatibility Test Using the Default DataProvider
java -cp idmtesting.jar:idmcommon.jar com.sun.idm.testing.adapter.CTContainerTest -url "http://host:port/idm/servlet/CTServlet" -adapter com.waveset.adapter.SimulatedResourceAdapter -ns SimulatedAdapterTests -importLocalXMLFile ./example.1/SimulatedCompatibilityConfig.xml -includedTests DeleteMissing |
Running a Compatibility Test with Added Tests
java -cp idmtesting.jar:idmcommon.jar com.sun.idm.testing.adapter.CTContainerTest -url "http://host:port/idm/servlet/CTServlet" -adapter com.waveset.adapter.SimulatedResourceAdapter -ns SimulatedAdapterTests -importLocalXMLFile ./example.2/SimulatedCompatibilityConfig.xml -includedTests DeleteMissing,EnableExisting,DisableExisting,DeleteExisting,Create |
Running a Compatibility Test After Finishing the Test Configuration
java -cp idmtesting.jar:idmcommon.jar com.sun.idm.testing.adapter.CTContainerTest -url "http://host:port/idm/servlet/CTServlet" -adapter com.waveset.adapter.SimulatedResourceAdapter -ns SimulatedAdapterTests -importLocalXMLFile ./example.3/SimulatedCompatibilityConfig.xml |
Running a Compatability Test After Executing Beanshell Script
java -cp idmtesting.jar:idmcommon.jar com.sun.idm.testing.adapter.CTContainerTest -url "http://host:port/idm/servlet/CTServlet" -adapter com.waveset.adapter.SimulatedResourceAdapter -ns SimulatedAdapterTests -importLocalScriptFile ./example.4/SimulatedCompatibilityConfig.bsh |
This section describes the following methods for testing the resource object:
You can confirm the configuration of your resource by viewing the raw XML in the repository.
Log into the Administrator user interface.
Open the Waveset Debug pages by entering http://host:port/idm/debug in the browser.
Choose Resource from the pull-down menu located next to the List Objects button.
Click the List Objects button.
The List Objects of Type: Resource page displays with a list of all resource adapters and Active Sync-enabled adapters.
All resource adapter and Active Sync-enabled adapter classes are based on existing Waveset Resource classes.
Find the resource object you want to see.
To view the resource object, click the View link.
To edit the resource object, click the Edit link.
When you are finished, click Back.
You can use the Find Resources and List Resources pages in the Waveset Administrative interface to test your implementation of a resource object.
Select Resource > List Resource to confirm the following performance characteristics.
Table 10–32 List Resource Performance Characteristics
Select Resource > Find Resources to confirm the following performance characteristics.
Table 10–33 Find Resources Performance Characteristics
You can use Waveset Debug pages to trace methods in your custom adapter. You must first enable tracing and identify the methods for which tracing is requested. You must also provide calls to create log entries for new methods in your custom adapter.
To debug your adapter, review the log file that is generated by the adapter. If you enabled tracing and identified the methods you wanted to trace, your adapter will write its resource settings to the log file. Use this information to validate that the adapter was started and that all setting changes were saved.
See System Administrator's Guide for detailed information about tracing and debugging custom adapters.
Any time you install a new Waveset patch or service pack you must test your custom resources with the new idmcommon.jar and idmformui.jar files. You might have to modify or enhance your adapters so they adapt to changes made in the new release. Alternatively, you might just need to rebuild or refresh your resource adapter in your installation.
When you upgrade to a new release, you might have to recompile all of your custom resource adapters, depending on the target Waveset version. All custom Java that uses Waveset APIs (including custom resource adapters) require a recompile during upgrading. Also, consider other Java classes that use the Waveset library.
For more information about upgrading, see Upgrade Guide.
If your current Waveset installation has a large amount of custom work, contact your Sun Account Representative or Sun Customer Support for assistance with your upgrade.