17-4 Oracle Fusion Middleware Developers Guide for Oracle Identity Manager
Example 17–2 Implementation of PoolableConnector
package org.identityconnectors.flatfile; import java.util.HashSet;
import java.util.Iterator; import java.util.List;
import java.util.Map; import java.util.Set;
import org.identityconnectors.flatfile.io.FlatFileIOFactory; import org.identityconnectors.flatfile.io.FlatFileMetadata;
import org.identityconnectors.flatfile.io.FlatFileParser; import org.identityconnectors.flatfile.io.FlatFileWriter;
import org.identityconnectors.framework.api.operations.GetApiOp; import org.identityconnectors.framework.common.exceptions.AlreadyExistsException;
import org.identityconnectors.framework.common.exceptions.ConnectorException; import org.identityconnectors.framework.common.objects.Attribute;
import org.identityconnectors.framework.common.objects.AttributeInfo; import org.identityconnectors.framework.common.objects.AttributeInfoBuilder;
import org.identityconnectors.framework.common.objects.ConnectorObject; import org.identityconnectors.framework.common.objects.ConnectorObjectBuilder;
import org.identityconnectors.framework.common.objects.ObjectClass; import org.identityconnectors.framework.common.objects.OperationOptions;
import org.identityconnectors.framework.common.objects.ResultsHandler; import org.identityconnectors.framework.common.objects.Schema;
import org.identityconnectors.framework.common.objects.SchemaBuilder; import org.identityconnectors.framework.common.objects.Uid;
import org.identityconnectors.framework.common.objects.filter.AbstractFilterTranslator;
import org.identityconnectors.framework.common.objects.filter.FilterTranslator; import org.identityconnectors.framework.spi.Configuration;
import org.identityconnectors.framework.spi.ConnectorClass; import org.identityconnectors.framework.spi.PoolableConnector;
import org.identityconnectors.framework.spi.operations.CreateOp; import org.identityconnectors.framework.spi.operations.DeleteOp;
import org.identityconnectors.framework.spi.operations.SchemaOp; import org.identityconnectors.framework.spi.operations.SearchOp;
import org.identityconnectors.framework.spi.operations.UpdateOp; The main connector class
ConnectorClassconfigurationClass = FlatFileConfiguration.class, displayNameKey = FlatFile
public class FlatFileConnector implements SchemaOp, CreateOp, DeleteOp, UpdateOp, SearchOpMapString, String, GetApiOp, PoolableConnector {
private FlatFileConfiguration flatFileConfig; private FlatFileMetadata flatFileMetadata;
private FlatFileParser flatFileParser; private FlatFileWriter flatFileWriter;
private boolean alive = false; Override
public Configuration getConfiguration { return this.flatFileConfig;
} Override
public void initConfiguration config {
Developing Identity Connectors 17-5
this.flatFileConfig = FlatFileConfiguration config; FlatFileIOFactory flatFileIOFactory =
FlatFileIOFactory.getInstanceflatFileConfig; this.flatFileMetadata = flatFileIOFactory.getMetadataInstance;
this.flatFileParser = flatFileIOFactory.getFileParserInstance; this.flatFileWriter = flatFileIOFactory.getFileWriterInstance;
this.alive = true; System.out.printlninit called: Initialization done;
} Override
public void dispose { this.alive = false;
} Override
public Schema schema { SchemaBuilder flatFileSchemaBldr = new SchemaBuilderthis.getClass;
SetAttributeInfo attrInfos = new HashSetAttributeInfo; for String fieldName : flatFileMetadata.getOrderedTextFieldNames {
AttributeInfoBuilder attrBuilder = new AttributeInfoBuilder; attrBuilder.setNamefieldName;
attrBuilder.setCreateabletrue; attrBuilder.setUpdateabletrue;
attrInfos.addattrBuilder.build; }
Supported class and attributes flatFileSchemaBldr.defineObjectClass
ObjectClass.ACCOUNT.getDisplayNameKey,attrInfos; System.out.printlnschema called: Built the schema properly;
return flatFileSchemaBldr.build; }
Override public Uid createObjectClass arg0, SetAttribute attrs,
OperationOptions ops { System.out.printlnCreating user account + attrs;
assertUserObjectClassarg0; try {
FlatFileUserAccount accountRecord = new FlatFileUserAccountattrs; Assert uid is there
assertUidPresenceaccountRecord; Create the user
this.flatFileWriter.addAccountaccountRecord; Return uid
String uniqueAttrField = this.flatFileConfig .getUniqueAttributeName;
String uniqueAttrVal = accountRecord .getAttributeValueuniqueAttrField;
System.out.printlnUser + uniqueAttrVal + created; return new UiduniqueAttrVal;
} catch Exception ex { If account exists
17-6 Oracle Fusion Middleware Developers Guide for Oracle Identity Manager
if ex.getMessage.containsexists throw new AlreadyExistsExceptionex;
For all other causes System.out.printlnError in create + ex.getMessage;
throw ConnectorException.wrapex; }
} Override
public void deleteObjectClass arg0, Uid arg1, OperationOptions arg2 { final String uidVal = arg1.getUidValue;
this.flatFileWriter.deleteAccountuidVal; System.out.printlnAccount + uidVal + deleted;
} Override
public Uid updateObjectClass arg0, Uid arg1, SetAttribute arg2, OperationOptions arg3 {
String accountIdentifier = arg1.getUidValue; Fetch the account
FlatFileUserAccount accountToBeUpdated = this.flatFileParser .getAccountaccountIdentifier;
Update accountToBeUpdated.updateAttributesarg2;
this.flatFileWriter .modifyAccountaccountIdentifier, accountToBeUpdated;
System.out.printlnAccount + accountIdentifier + updated; Return new uid
String newAccountIdentifier = accountToBeUpdated .getAttributeValuethis.flatFileConfig.getUniqueAttributeName;
return new UidnewAccountIdentifier; }
Override public FilterTranslatorMapString, String createFilterTranslator
ObjectClass arg0, OperationOptions arg1 { TODO: Create a fine grained filter translator
Return a dummy object as its not applicable here. All processing happens in the execute query
return new AbstractFilterTranslatorMapString, String { };
} Override
public ConnectorObject getObjectObjectClass arg0, Uid uid, OperationOptions arg2 {
Return matching record String accountIdentifier = uid.getUidValue;
FlatFileUserAccount userAcc = this.flatFileParser .getAccountaccountIdentifier;
ConnectorObject userAccConnObject = convertToConnectorObjectuserAcc; return userAccConnObject;
} non-Javadoc
Developing Identity Connectors 17-7
This is the search implementation. The Map passed as the query here, will map to all the records with
matching attributes. The record will be filtered if any of the matching attributes are not
found see
org.identityconnectors.framework.spi.operations.SearchOpexecuteQuery org.identityconnectors.framework.common.objects.ObjectClass,
java.lang.Object, org.identityconnectors.framework.common.objects.ResultsHandler,
org.identityconnectors.framework.common.objects.OperationOptions Override
public void executeQueryObjectClass objectClass, MapString, String matchSet, ResultsHandler resultHandler,
OperationOptions ops { System.out.printlnInside executeQuery;
Iterate over the records and handle individually IteratorFlatFileUserAccount userAccountIterator = this.flatFileParser
.getAccountIteratormatchSet; while userAccountIterator.hasNext {
FlatFileUserAccount userAcc = userAccountIterator.next; ConnectorObject userAccObject = convertToConnectorObjectuserAcc;
if resultHandler.handleuserAccObject { System.out.printlnNot able to handle + userAcc;
break; }
} }
private void assertUserObjectClassObjectClass arg0 { if arg0.equalsObjectClass.ACCOUNT
throw new UnsupportedOperationException Only user account operations supported.;
} private void assertUidPresenceFlatFileUserAccount accountRecord {
String uniqueAttrField = this.flatFileConfig.getUniqueAttributeName; String uniqueAttrVal = accountRecord.getAttributeValueuniqueAttrField;
if uniqueAttrVal == null { throw new IllegalArgumentExceptionUnique attribute not passed;
} }
private ConnectorObject convertToConnectorObjectFlatFileUserAccount userAcc {
ConnectorObjectBuilder userObjBuilder = new ConnectorObjectBuilder; Add attributes
ListString attributeNames = this.flatFileMetadata .getOrderedTextFieldNames;
for String attributeName : attributeNames { String attributeVal = userAcc.getAttributeValueattributeName;
userObjBuilder.addAttributeattributeName, attributeVal;
17-8 Oracle Fusion Middleware Developers Guide for Oracle Identity Manager
if attributeName.equalsthis.flatFileConfig .getUniqueAttributeName {
userObjBuilder.setUidattributeVal; userObjBuilder.setNameattributeVal;
} }
return userObjBuilder.build; }
Override public void checkAlive {
if alive throw new RuntimeExceptionConnection not alive;
} }
3.
This connector supports only the ContainsAllValuesFilter operation. Implement the ContainsAllValuesFilter operation
Example 17–3 illustrates the sample
implementation of org.identityconnectors.framework.common.objects.filter.AbstractFilterTranslator
T that defines the filter operation.
Example 17–3 Implementation of AbstractFilterTranslatorT
package org.identityconnectors.flatfile.filteroperations; import java.util.HashMap;
import java.util.Map; import org.identityconnectors.framework.common.objects.Attribute;
import org.identityconnectors.framework.common.objects.filter.AbstractFilterTranslator;
import org.identityconnectors.framework.common.objects.filter.ContainsAllValuesFilter;
public class ContainsAllValuesImpl extends AbstractFilterTranslatorMapString, String{
Override protected MapString, String createContainsAllValuesExpression
ContainsAllValuesFilter filter, boolean not { MapString, String containsAllMap = new HashMapString, String;
Attribute attr = filter.getAttribute; containsAllMap.putattr.getName, attr.getValue.get0.toString;
return containsAllMap; }
}
4.
Create the connector bundle JAR. The MANIFEST.MF file must contain the following entries:
■
ConnectorBundle-FrameworkVersion
■
ConnectorBundle-Name
■
ConnectorBundle-Version Example 17–4
shows the contents of the MANIFEST.MF file:
Developing Identity Connectors 17-9
Example 17–4 The MANIFEST.MF File
Manifest-Version: 1.0 Ant-Version: Apache Ant 1.7.0
Created-By: 14.1-b02 Sun Microsystems Inc. ConnectorBundle-FrameworkVersion: 1.0
ConnectorBundle-Name: org.identityconnectors.flatfile ConnectorBundle-Version: 1.0
Build-Number: 609 Subversion-Revision: 4582
5.
Update the connector bundle JAR as created in step 4. To do so:
a.
Extract the connector bundle JAR into any desired location.
b.
Create a lib directory in the directory in which you extracted the JAR.
c.
Add the dependent third-party JARs into the lib directory.
d.
JAR the entire directory.
17.1.1 Supporting Classes for File Input and Output Handling
This section shows the implementation of the following supporting classes for file input and output handling:
■
Example 17–5, FlatFileIOFactory
■
Example 17–6, FlatFileMetadata
■
Example 17–7, FlatFileParser
■
Example 17–8, FlatFileWriter Example 17–5
shows the implementation of the FlatFileIOFactory supporting class:
Example 17–5 FlatFileIOFactory
package org.identityconnectors.flatfile.io; import org.identityconnectors.flatfile.FlatFileConfiguration;
public class FlatFileIOFactory { private FlatFileMetadata flatFileMetadata;
private FlatFileConfiguration flatFileConfig; Provides instance of the factory
param flatfileConfig Configuration bean for the flat file public static FlatFileIOFactory getInstanceFlatFileConfiguration fileConfig
{ return new FlatFileIOFactoryfileConfig;
} Making it private to avoid public instantiation. Encouraging use of
getInstance param fileConfig
Note: The MANIFEST.MF file must contain the entires listed in step
4.
17-10 Oracle Fusion Middleware Developers Guide for Oracle Identity Manager
private FlatFileIOFactoryFlatFileConfiguration fileConfig { this.flatFileConfig = fileConfig;
this.flatFileMetadata = new FlatFileMetadataflatFileConfig; System.out.printlnMetadata set;
} Returns the metadata instance
return public FlatFileMetadata getMetadataInstance {
return this.flatFileMetadata; }
Returns the FlatFileParser instance return
public FlatFileParser getFileParserInstance { return new FlatFileParserthis.flatFileMetadata, this.flatFileConfig;
} Returns the FlatFileWriter instance
return public FlatFileWriter getFileWriterInstance {
return new FlatFileWriterthis.flatFileMetadata, this.flatFileConfig; }
}
Example 17–6 shows the implementation of the FlatFileMetaData supporting class:
Example 17–6 FlatFileMetadata
package org.identityconnectors.flatfile.io; import java.io.BufferedReader;
import java.io.File; import java.io.FileReader;
import java.io.IOException; import java.util.ArrayList;
import java.util.List; import java.util.StringTokenizer;
import org.identityconnectors.flatfile.FlatFileConfiguration; This class contains all the metadata related information Example: Ordering of
columns, Number of columns etc. author harsh
public class FlatFileMetadata { private FlatFileConfiguration fileConfig;
private ListString orderedTextFieldNames;
Developing Identity Connectors 17-11
private String changeLogFieldName; private String uniqueAttributeFiledName;
Instantiates the class with the file configuration. Making it package private to encourage instantiation from Factory class
param fileConfig FlatFileMetadataFlatFileConfiguration fileConfig {
Ideally you should not take connector specific configuration class in flat file resource classes. Change if this has to go to production.
Probably make another configuration class for flat file with same signatures.
this.fileConfig = fileConfig; initializeMetadata;
validateConfigProps; }
Returns the text field names in the order of their storage return
public ListString getOrderedTextFieldNames { return this.orderedTextFieldNames;
} Returns the number of columns
public int getNumberOfFields { int numberOfTextFields = this.orderedTextFieldNames.size;
return numberOfTextFields; }
Specifies if number of tokens are matching with the standard length of metadata
param countTokens return
public boolean isDifferentFromNumberOfFieldsint countTokens { return getNumberOfFields = countTokens;
} Reads the header line and sets the metadata
private void initializeMetadata { Read the file.
File recordsStore = this.fileConfig.getStoreFile; try {
BufferedReader storeFileReader = new BufferedReadernew FileReader recordsStore.getAbsolutePath;
Read the header line
17-12 Oracle Fusion Middleware Developers Guide for Oracle Identity Manager
String headerString = storeFileReader.readLine; Tokenize the headerString
StringTokenizer tokenizer = new StringTokenizerheaderString, fileConfig.getTextFieldDelimeter;
this.orderedTextFieldNames = new ArrayListString; while tokenizer.hasMoreTokens {
String header = tokenizer.nextToken; this.orderedTextFieldNames.addheader;
} System.out.printlnColumns read - + this.orderedTextFieldNames;
} catch IOException e { throw new RuntimeExceptionHow can I read a corrupted file;
} Store the change log and unique attribute field names
this.changeLogFieldName = fileConfig.getChangeLogAttributeName; this.uniqueAttributeFiledName = fileConfig.getUniqueAttributeName;
} Validate if the attribute names in config props object are present in the
column names throws RuntimeException
if validation fails private void validateConfigProps {
Check if unique attribute col name is present if this.orderedTextFieldNames.containsthis.changeLogFieldName
throw new RuntimeExceptionChange log field name + this.changeLogFieldName + not found in the store file ;
Check if change col name is present if this.orderedTextFieldNames.containsthis.uniqueAttributeFiledName
throw new RuntimeExceptionUnique attribute field name + this.uniqueAttributeFiledName
+ not found in the store file; }
}
Example 17–7 shows the implementation of the FlatFileParser supporting class:
Example 17–7 FlatFileParser
package org.identityconnectors.flatfile.io; import java.io.BufferedReader;
import java.io.File; import java.io.FileReader;
import java.io.IOException; import java.util.ArrayList;
import java.util.HashMap; import java.util.Iterator;
import java.util.List; import java.util.Map;
import org.identityconnectors.flatfile.FlatFileConfiguration; import org.identityconnectors.flatfile.FlatFileUserAccount;
Developing Identity Connectors 17-13
import org.identityconnectors.flatfile.utils.AccountConversionHandler; public class FlatFileParser {
private File recordsStore; private FlatFileConfiguration fileConfig;
private FlatFileMetadata metadata; private AccountConversionHandler accountConverter;
Instantiates the parser class. Making it package private to encourage instantiation from Factory class
param metadata param fileConfig
FlatFileParserFlatFileMetadata metadata, FlatFileConfiguration fileConfig { this.fileConfig = fileConfig;
this.recordsStore = fileConfig.getStoreFile; this.accountConverter = new AccountConversionHandlermetadata,
fileConfig; this.metadata = metadata;
} Returns all accounts in the file
return public ListFlatFileUserAccount getAllAccounts {
try { BufferedReader userRecordReader = new BufferedReader
new FileReaderrecordsStore.getAbsolutePath; String recordStr;
Skip headers userRecordReader.readLine;
Loop over records and make list of objects ListFlatFileUserAccount allAccountRecords = new
ArrayListFlatFileUserAccount; while recordStr = userRecordReader.readLine = null {
try { FlatFileUserAccount accountRecord = accountConverter
.convertStringRecordToAccountObjrecordStr; allAccountRecords.addaccountRecord;
} catch RuntimeException e { System.out.printlnInvalid entry + e.getMessage;
} }
userRecordReader.close; return allAccountRecords;
} catch IOException e { throw new RuntimeExceptionHow can I read a corrupted file;
} }
Gets the account of matching account identifier
17-14 Oracle Fusion Middleware Developers Guide for Oracle Identity Manager
param accountIdentifier return
public FlatFileUserAccount getAccountString accountIdentifier { I know its not right to get all account details. Dont want to focus
on efficiency and scalability as this is just a sample. Iterate over all records and check for matching account
MapString, String matchSet = new HashMapString, String; matchSet.putfileConfig.getUniqueAttributeName, accountIdentifier;
for FlatFileUserAccount userRecord : getAllAccounts { if userRecord.hasMatchingAttributesmatchSet
return userRecord; }
Got nothing.. return null;
} Returns all records with matching Attributes If more than attributes are
passed. it will check all the attributes param matchSet
Checks if all provided attributes are matched public ListFlatFileUserAccount getAccountsByMatchedAttrs
MapString, String matchSet { I know its not right to get all account details. Dont want to focus
on efficiency and scalability as this is just a sample. Iterate over all records and check for matching account
ListFlatFileUserAccount matchingRecords = new ArrayListFlatFileUserAccount;
for FlatFileUserAccount userRecord : getAllAccounts { if userRecord.hasMatchingAttributesmatchSet
matchingRecords.adduserRecord; }
return matchingRecords; }
Returns the records that fall after the specified change number This function helps in checking the function of sync
param changeNumber the change number for the last search
public ListFlatFileUserAccount getUpdatedAccountsint changeNumber { I know its not right to get all account details. Dont want to focus
on efficiency and scalability as this is just a sample. Iterate over all records and check for matching account
ListFlatFileUserAccount matchingRecords = new
Developing Identity Connectors 17-15
ArrayListFlatFileUserAccount; String changeLogAttrName = fileConfig.getChangeLogAttributeName;
for FlatFileUserAccount userRecord : getAllAccounts { int recordChangeNumber = userRecord
.getChangeNumberchangeLogAttrName; if recordChangeNumber = changeNumber
matchingRecords.adduserRecord; }
return matchingRecords; }
Returns an iterator that iterates over the records. This is provided for dynamic retrieval of records
param matchSet Filters the records by matching the given attributes. Use null
or empty set to avoid filtering return
public IteratorFlatFileUserAccount getAccountIterator MapString, String matchSet {
IteratorFlatFileUserAccount recordIterator = new FlatFileLineIterator this.metadata, this.fileConfig, matchSet;
return recordIterator; }
Gives the next change number. Logic is max of existing change numbers + 1 return
public int getNextChangeNumber { int maximumChangeNumber = 0;
I know its not right to get all account details. Dont want to focus on efficiency and scalability as this is just a sample.
Iterate over all records and check for matching account String changeLogAttrName = fileConfig.getChangeLogAttributeName;
for FlatFileUserAccount userRecord : getAllAccounts { int changeNumber = userRecord.getChangeNumberchangeLogAttrName;
if changeNumber = maximumChangeNumber { maximumChangeNumber = changeNumber + 1;
} }
return maximumChangeNumber; }
}
Example 17–8 shows the implementation of the FlatFileWriter supporting class:
Example 17–8 FlatFileWriter
package org.identityconnectors.flatfile.io; import java.io.BufferedReader;
17-16 Oracle Fusion Middleware Developers Guide for Oracle Identity Manager
import java.io.BufferedWriter; import java.io.File;
import java.io.FileReader; import java.io.FileWriter;
import java.io.IOException; import org.identityconnectors.flatfile.FlatFileConfiguration;
import org.identityconnectors.flatfile.FlatFileUserAccount; import org.identityconnectors.flatfile.utils.AccountConversionHandler;
Class for searching operations on files author Harsh
public class FlatFileWriter { private File recordsStore;
private FlatFileParser recordParser; private FlatFileConfiguration fileConfig;
private AccountConversionHandler accountConverter; Initializes the writer with the configuration Making it package private
to encourage use of Factory class for global instantiation param metadata
param fileConfig FlatFileWriterFlatFileMetadata metadata, FlatFileConfiguration fileConfig {
this.fileConfig = fileConfig; this.recordsStore = fileConfig.getStoreFile;
recordParser = new FlatFileParsermetadata, fileConfig; accountConverter = new AccountConversionHandlermetadata, fileConfig;
} Appends the user record at the end of
param accountRecord public void addAccountFlatFileUserAccount accountRecord {
try { BufferedWriter userRecordWriter = new BufferedWriter
new FileWriterthis.recordsStore.getAbsolutePath, true; Set the latest changelog number
int latestChangeNumber = recordParser.getNextChangeNumber; accountRecord.setChangeNumberfileConfig
.getChangeLogAttributeName, latestChangeNumber; Validate if same account id doesnt exist
String accountUid = accountRecord.getAttributeValuefileConfig .getUniqueAttributeName;
FlatFileUserAccount accountByAccountId = recordParser .getAccountaccountUid;
if accountByAccountId = null throw new RuntimeExceptionAccount + accountUid
Developing Identity Connectors 17-17
+ already exists; Put the user record in formatted way
String userRecordAsStr = accountConverter .convertAccountObjToStringRecordaccountRecord;
userRecordWriter.write\n + userRecordAsStr; Close the output stream
userRecordWriter.close; } catch IOException e { Catch exception if any
throw new RuntimeExceptionHow can I write on a corrupted file; }
} Removes the entry for respective account identifier
param accountIdentifier public void deleteAccountString accountIdentifier {
String blankRecord = ; this.modifyAccountInStoreaccountIdentifier, blankRecord;
} Updates the entry with respective account identifier
param accountIdentifier param updatedAccountRecord
return new accountIdentifier public String modifyAccountString accountIdentifier,
FlatFileUserAccount updatedAccountRecord { Frame a record string and update back to file
int nextChangeNumber = recordParser.getNextChangeNumber; String changeNumberFieldName = fileConfig.getChangeLogAttributeName;
updatedAccountRecord.setChangeNumberchangeNumberFieldName, nextChangeNumber;
String newRecordAsStr = accountConverter .convertAccountObjToStringRecordupdatedAccountRecord;
Update to the file this.modifyAccountInStoreaccountIdentifier, newRecordAsStr;
Return new UID String uniqueAttrFieldName = fileConfig.getUniqueAttributeName;
String newAccountIdentifier = updatedAccountRecord .getAttributeValueuniqueAttrFieldName;
return newAccountIdentifier; }
Returns the complete flat file as string. return
private String getCompleteFlatFileAsStr { try {
17-18 Oracle Fusion Middleware Developers Guide for Oracle Identity Manager
BufferedReader userRecordReader = new BufferedReader new FileReaderrecordsStore.getAbsolutePath;
String recordStr; Loop over records and make list of objects
StringBuilder flatFileStr = new StringBuilder; while recordStr = userRecordReader.readLine = null {
if recordStr.isEmpty flatFileStr.appendrecordStr + \n;
} userRecordReader.close;
return flatFileStr.toString; } catch IOException e {
throw new RuntimeExceptionHow can I read a corrupted file; }
} Updates the account with the new record. this can also be used for delete
param accountIdentifier param updatedRecord
private void modifyAccountInStoreString accountIdentifier, String updatedRecord {
try { Load the complete flat file
String completeFlatFile = this.getCompleteFlatFileAsStr; Construct the string to be removed and replace it with blank
FlatFileUserAccount accountToBeRemoved = recordParser .getAccountaccountIdentifier;
String updatableString = accountConverter .convertAccountObjToStringRecordaccountToBeRemoved;
String updatedFlatFile = completeFlatFile.replaceAll updatableString, updatedRecord;
Rewrite the file BufferedWriter userRecordWriter = new BufferedWriter
new FileWriterthis.recordsStore.getAbsolutePath, false; userRecordWriter.writeupdatedFlatFile;
debug System.out.printlnOld string + updatableString;
System.out.printlnNew String + updatedRecord; System.out.printlnnew file - + updatedFlatFile;
Close the output stream userRecordWriter.close;
} catch IOException e { Catch exception if any throw new RuntimeExceptionHow can I write on a corrupted file;
} }
}
Developing Identity Connectors 17-19
17.2 Uploading the Identity Connector Bundle to Oracle Identity Manager Database
The identity connector bundle must be available to ICF in Oracle Identity Manager database. Follow the list of sections in order to integrate the ICF identity connector
with Oracle Identity Manager. Some of the procedures include configuration by using the Oracle Identity Manager Design Console.
■
Registering the Connector Bundle with Oracle Identity Manager
■
Creating Basic Identity Connector Metadata
■
Creating Provisioning Metadata
■
Creating Reconciliation Metadata
17.2.1 Registering the Connector Bundle with Oracle Identity Manager
The connector bundle must be available for the Connector Server local to Oracle Identity Manager. Following is the procedure to accomplish this:
1.
Copy the connector bundle JAR to the machine on which Oracle Identity Manager in installed.
2.
Run the following command to upload the JAR. MW_HOMEserverbinUploadJars.sh
3. Select ICFBundle as the JAR type.
4. Enter the location of the connector bundle JAR.
5. Press Enter.
17.2.2 Creating Basic Identity Connector Metadata
This metadata configuration is needed for both provisioning and reconciliation. The set of procedures in this section are completed by using the Oracle Identity Manager
Design Console.
■
Creating the IT Resource Type Definition
■
Creating the Resource Object
■
Creating the Main Configuration Lookup
■
Creating Object Type Configuration Lookup
17.2.2.1 Creating the IT Resource Type Definition
An IT resource type definition is the representation of a resources connection information. The configuration parameters in the IT resource type definition should be
matched with the configuration parameters of the connector bundle. The values of the parameters in the IT resource will be set in the bundle configuration.
Note: In this chapter, DW_HOME represents
MW_HOMEOracle_IDM1.
Note:
You may include parameters the bundle configuration is not using. They produce no negative effects on the bundle operations.
17-20 Oracle Fusion Middleware Developers Guide for Oracle Identity Manager
1.
Log in to the Oracle Identity Manager Design Console.
2.
Click IT Resource Type Definition under Resource Management.
3.
Create a new IT Resource Type Definition with the Server Type defined as Flat File.
4.
Add the following parameters as illustrated in Figure 17–1
.
■
Configuration Lookup is the marker of the main configuration lookup for the
resource. The name of the parameter must be Configuration Lookup. It is a good practice to add a value to Default Field Value.
■
textFieldDelimeter maps to the textFieldDelimeter parameter in the bundle
configuration. The value of this parameter will be passed.
■
storeFile maps to the storeFile parameter in the bundle configuration. The
value of this parameter will be passed.
Figure 17–1 IT Resource Type Definition in Design Console
17.2.2.2 Creating the Resource Object
The resource object is the Oracle Identity Manager representation of a resource. The connector bundle is tied to the resource object.
1.
Log in to the Oracle Identity Manager Design Console.
2.
Click Resource Objects under Resource Management.
3.
Create a new resource object with the name FLATFILERO. As the resource object is a target resource dont check the Trusted Source box as
illustrated in Figure 17–2
.
Developing Identity Connectors 17-21
Figure 17–2 Resource Objects in Design Console
17.2.2.3 Creating Lookups
Separate lookups have to be defined for different objects supported by the connector bundle. This lookup can contain provisioning and reconciliation related information
for those objects. The Main Configuration Lookup is the root for object specific lookups as it contains the pointers to those lookups. The following sections contain
information on how to create lookups.
■
Creating the Main Configuration Lookup
■
Creating Object Type Configuration Lookup
17.2.2.3.1 Creating the Main Configuration Lookup The Configuration Lookup as defined
in Section 17.2.2.1, Creating the IT Resource Type Definition
holds connector bundle configurations that are not counted as connection information. If a configuration
parameter is not found in the IT Resource Type Definition, Oracle Identity Manager will look in the Configuration Lookup. The main Configuration Lookup contains
bundle properties and bundle configurations. Bundle Property parameters are mandatory as they are needed for identifying the correct bundle. Bundle
configurations that are not defined as part of the IT resource type definition discussed in
Section 17.2.2.1, Creating the IT Resource Type Definition can be declared here.
1. Log in to the Oracle Identity Manager Design Console.
2. Click Lookup Definition under Administration.
3. Create a new lookup and add Lookup.FF.Configuration as the value for Code.
4. Add the following Lookup Code Information as illustrated in
Figure 17–3 .
■
Add VERSION as the required Bundle Version.
■
Add org.identityconnectors.flatfile as the required Bundle Name. Note:
The values for Code Key should match exactly as illustrated. The values for Decode are specific to the connector bundle.
17-22 Oracle Fusion Middleware Developers Guide for Oracle Identity Manager
■
Add org.identityconnectors.flatfile.FlatFileConnector as the required Connector Name.
■
Add AccountId as the value of uniqueAttributeName. AccountId is a unique string identifier that represents the account to be provisioned or reconciled. It
is the name of the column in the flat file. AccountId is unique and is used to represent a user account detail uniquely.
■
Add ChangeNumber as the value of changeLogAttributeName. When an account is created, a number is attached to it indicating the total accounts
created. This value is maintained in the variable called ChangeNumber.
■
OBJECT_TYPE_NAME Configuration Lookup is the configuration lookup for the particular object type. In this example, the object type is User as User
Configuration Lookup is defined.
Figure 17–3 Lookup Definition in Design Console
17.2.2.3.2 Creating Object Type Configuration Lookup Object type configuration lookup
contains the parameters specific to the particular object type. Object type is an entity over which an identity connector operates. It is mapped to ICF ObjectClass. In
Section 17.2.2.3.1, Creating the Main Configuration Lookup, User Configuration
Lookup has been referenced so that User is the object type, in this case mapped to ObjectClass.ACCOUNT. Roles and UserJobData are two other object types. The
object type name has to match with ObjectClass name supported by the identity connector bundle. The User object type is mapped to predefined
ObjectClass.ACCOUNT, the Group object type is mapped to predefined ObjectClass.GROUP. If the identity connector supports multiple objects, then this step
must be repeated for each.
1. Log in to the Oracle Identity Manager Design Console.
2. Click Lookup Definition under Administration.
Note: Because these use cases cover only the basic functionality, the
configuration is kept to the mandatory attribute.