Developing the Connector using the ICF framework.
I am demonstrating the ICF connector development using the Oracle Database eclipse link jpa framework.
2. Setting the JAVA_HOME and GRADLE_HOME environment variables.
mkdir databaseconnector-demo
mkdir databaseconnector-demo/src
mkdir databaseconnector-demo/src/main
mkdir databaseconnector-demo/src/main/java
mkdir databaseconnector-demo/src/main/resources
connector-framework-internal.jar
connector-framework.jar
groovy-all.jar
ojdbc6.jar
apply plugin: 'eclipse'
version="1.0"
configurations{
includeInJar
}
repositories{
mavenCentral()
}
dependencies{
compile fileTree (dir: '<Replace with your ICF jar files and oracle jdbc driver>',include: '*.jar')
includeInJar 'com.sun.messaging.mq:fscontext:4.4.2'
configurations.compile.extendsFrom(configurations.includeInJar)
}
jar.doFirst{
manifest {
attributes("Manifest-Version" : "1.0",
"Created-By" : "Data Base Demo",
"ConnectorBundle-FrameworkVersion" : "1.4.0",
"ConnectorBundle-Name" : project.name,
"ConnectorBundle-Version" : version,
"Build-Number": "609",
"Subversion-Revision" : "4582"
)
}
into('lib') {
println "includeInJar: " + configurations.includeInJar.collect { File file -> file }
from configurations.includeInJar
}
}
Define the configuration properties to capture the config data from OIM to Connector to establish the connectivity to the oracle database. For demo i have used 5 config properties are driver, url,userName, password, and environment. The driver property holds the jdbc driver, url holds the jdbc url, username holds the jdbc user name, password holds the jdbc password, and environment to get the data source from local or remote. If you specify the environment is local it will create the data source pro grammatically in connector. If you specify remote and it will fetch the data source from the application server. The sample code is given below.
package identity.dbconnector;
import identity.dbconnector.util.DataBaseIdentityUtil;
import org.identityconnectors.framework.common.exceptions.ConnectorException;
import org.identityconnectors.framework.spi.AbstractConfiguration;
import org.identityconnectors.framework.spi.ConfigurationProperty;
public class DataBaseIdentityConfig extends AbstractConfiguration {
private String driver;
private String url;
private String userName;
private String password;
private String environment;
public String getDriver() {
return driver;
}
@ConfigurationProperty(order=1,displayMessageKey="driver_display",helpMessageKey="driver_help",required=true)
public void setDriver(String driver) {
this.driver = driver;
}
public String getUrl() {
return url;
}
@ConfigurationProperty(order=2,displayMessageKey="url_display",helpMessageKey="url_help",required=true)
public void setUrl(String url) {
this.url = url;
}
public String getUserName() {
return userName;
}
@ConfigurationProperty(order=3,displayMessageKey="userName_display",helpMessageKey="userName_help",required=true)
public void setUserName(String userName) {
this.userName = userName;
}
public String getPassword() {
return password;
}
@ConfigurationProperty(order=4,displayMessageKey="password_display",helpMessageKey="password_help",required=true,confidential=true)
public void setPassword(String password) {
this.password = password;
}
public String getEnvironment() {
return environment;
}
@ConfigurationProperty(order=5,displayMessageKey="environment_display",helpMessageKey="environment_help",required=true,confidential=true)
public void setEnvironment(String environment) {
this.environment = environment;
}
@Override
public void validate()
{
if(DataBaseIdentityUtil.isEmpty(driver))
{
throw new ConnectorException(String.format(DataBaseIdentityConstants.CONFIG_PARAM,"jdbc driver"));
}
if(DataBaseIdentityUtil.isEmpty(url))
{
throw new ConnectorException(String.format(DataBaseIdentityConstants.CONFIG_PARAM,"jdbc url"));
}
if(DataBaseIdentityUtil.isEmpty(userName))
{
throw new ConnectorException(String.format(DataBaseIdentityConstants.CONFIG_PARAM,"jdbc userName"));
}
if(DataBaseIdentityUtil.isEmpty(password))
{
throw new ConnectorException(String.format(DataBaseIdentityConstants.CONFIG_PARAM,"jdbc password"));
}
}
}
The following interfaces needs to be implemented to develop the custom ICF Connector. They are
The interface is required to get the user based on the uid.
The interface is required to build the metadata in the OIM.
1. public void init(Configuration config)
In my example I am establishing the Connectivity from Connector to Database.
2. public Schema schema()
I am initializing the schema to persist the data in database and also btuild the OIM metadata.
3. public Uid create(ObjectClass objectClass, Set<Attribute> attributes, OperationOptions operations)
provisioning the users to the database.
4. public Uid update(ObjectClass objectClass, Uid uid, Set<Attribute> attributes, OperationOptions operations)
6.public void sync(ObjectClass objectClass, SyncToken syncToken, SyncResultsHandler handler, OperationOptions operations)
Incremental Reconciliation based on time stamp to sync with OIM.
7. public void delete(ObjectClass objectClass, Uid uid, OperationOptions operations)
De-provision the user in oim and also delete entry in database.
8.public void dispose()
Closing the database connection
9.public ConnectorObject getObject(ObjectClass objectClass, Uid uid, OperationOptions operations)
Getting the Connector object from the database.
10 public void checkAlive()
Verifying the connection is alive or not.
package identity.dbconnector;
import identity.dbconnector.dao.UserProfileDao;
import identity.dbconnector.dao.UserProfileDaoImpl;
import identity.dbconnector.domain.UserProfile;
import identity.dbconnector.util.DataBaseIdentityUtil;
import java.sql.SQLException;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import oracle.jdbc.pool.OracleConnectionPoolDataSource;
import org.identityconnectors.common.logging.Log;
import org.identityconnectors.framework.api.operations.GetApiOp;
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.SyncDeltaBuilder;
import org.identityconnectors.framework.common.objects.SyncDeltaType;
import org.identityconnectors.framework.common.objects.SyncResultsHandler;
import org.identityconnectors.framework.common.objects.SyncToken;
import org.identityconnectors.framework.common.objects.Uid;
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.SyncOp;
import org.identityconnectors.framework.spi.operations.UpdateOp;
@ConnectorClass(configurationClass=DataBaseIdentityConfig.class,displayNameKey="displayName",messageCatalogPaths="identity.dbconnector.Messages")
public class DataBaseIdentityConnector implements PoolableConnector,
SearchOp<String>, UpdateOp, DeleteOp, CreateOp, SyncOp,GetApiOp,SchemaOp {
private DataBaseIdentityConfig config;
private EntityManagerFactory factory=null;
private UserProfileDao userProfileDao=null;
private Context context=null;
private static Log logger=null;
@Override
public void dispose()
{
logger.ok("dispose started");
if(factory != null)
{
logger.ok("dispose factory");
factory.close();
}
if(context != null)
{
try {
logger.ok("dispose context");
context.close();
} catch (NamingException e)
{
logger.error(e, "dispose context");
}
}
logger.ok("dispose ended");
}
@Override
public Configuration getConfiguration() {
// TODO Auto-generated method stub
return config;
}
@Override
public void init(Configuration config)
{
logger=Log.getLog(this.getClass());
logger.ok("Invoking the Init Method Start");
this.config=(DataBaseIdentityConfig)config;
initDataSource(this.config);
factory= Persistence.createEntityManagerFactory(DataBaseIdentityConstants.PERSISTENCE_UNIT);
userProfileDao= new UserProfileDaoImpl(factory);
logger.ok("Invoking the Init Method End ");
}
private void initDataSource(DataBaseIdentityConfig config)
{
logger.ok(" initDataSource - started");
if(!DataBaseIdentityUtil.isEmpty(config.getEnvironment()) && config.getEnvironment().equalsIgnoreCase(DataBaseIdentityConstants.DATASOURCE_LOCAL))
{
System.setProperty(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.fscontext.RefFSContextFactory");
System.setProperty(Context.PROVIDER_URL, "file:///tmp");
try
{
//Properties prop= new Properties();
//prop.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.fscontext.RefFSContextFactory");
//prop.put(Context.PROVIDER_URL, "file:///tmp");
context = new InitialContext();
logger.ok("INitialize the Local Context Successfully");
OracleConnectionPoolDataSource ds= new OracleConnectionPoolDataSource();
ds.setURL(config.getUrl());
ds.setUser(config.getUserName());
ds.setPassword(config.getPassword());
context.rebind("mydatasource", ds);
logger.ok("Data Source created successfully");
} catch (NamingException e) {
logger.error(e, "initializing the data source error");
throw new ConnectorException(DataBaseIdentityConstants.CONNECTOR_CON_EXP);
} catch (SQLException e) {
logger.error(e, "initializing the data source error");
throw new ConnectorException(DataBaseIdentityConstants.CONNECTOR_CON_EXP);
}
}
logger.ok(" initDataSource - Ended");
}
@Override
public Uid create(ObjectClass objectClass, Set<Attribute> attributes,
OperationOptions operations) {
logger.ok("create Started");
Map<String, Object> row=DataBaseIdentityUtil.convertSetToMap(attributes);
logger.ok("Create Request Attributes : "+attributes);
if(row != null && row.isEmpty())
{
throw new ConnectorException(DataBaseIdentityConstants.USER_ATTR_MISSING);
}
String userLogin=DataBaseIdentityUtil.getString(row, DataBaseIdentityConstants.USER_LOGIN);
logger.ok("Create Request Login : "+userLogin);
if(DataBaseIdentityUtil.isEmpty(userLogin))
{
logger.error(String.format(DataBaseIdentityConstants.USER_ATTR_REQUIRED,DataBaseIdentityConstants.USER_LOGIN));
throw new ConnectorException(String.format(DataBaseIdentityConstants.USER_ATTR_REQUIRED,DataBaseIdentityConstants.USER_LOGIN));
}
UserProfile profile= userProfileDao.findByLogin(userLogin);
if(profile != null)
{
logger.error(String.format(DataBaseIdentityConstants.USER_ALREADY_EXISTS,row.get(DataBaseIdentityConstants.USER_LOGIN).toString()));
throw new ConnectorException(String.format(DataBaseIdentityConstants.USER_ALREADY_EXISTS,row.get(DataBaseIdentityConstants.USER_LOGIN).toString()));
}
profile=DataBaseIdentityUtil.convertToUserProfile(row);
profile.setCreateDate(new Date());
profile.setPassword(DataBaseIdentityUtil.getString(row, DataBaseIdentityConstants.PASSWORD));
profile.setStatus(DataBaseIdentityConstants.STATUS_ENABLED);
logger.ok("User Creation Process Started");
profile=userProfileDao.createUser(profile);
logger.ok("User Creation Process Ended");
Uid uid= new Uid(profile.getId().toString());
logger.ok("User Created Successfully and Id :"+uid);
logger.ok("create Ended");
return uid;
}
@Override
public void delete(ObjectClass objectClass, Uid uid, OperationOptions operations)
{
logger.ok("delete Started");
logger.ok("delete User Uid "+uid);
userProfileDao.deleteUser(new Long(uid.getUidValue()));
logger.ok("delete Ended");
}
@Override
public void checkAlive()
{
userProfileDao.test();
}
@Override
public ConnectorObject getObject(ObjectClass objectClass, Uid uid,
OperationOptions operations)
{
logger.ok("getObject Started");
logger.ok("The Requested getObject uid "+uid);
UserProfile profile= userProfileDao.findById(new Long(uid.getUidValue()));
if(profile==null)
{
logger.error(String.format(DataBaseIdentityConstants.USER_NOT_FOUND,"Uid",uid.getUidValue()));
throw new ConnectorException(String.format(DataBaseIdentityConstants.USER_NOT_FOUND,"Uid",uid.getUidValue()));
}
logger.ok("getObject Ended");
return DataBaseIdentityUtil.convertMapToConnectorObject(profile);
}
@Override
public Schema schema() {
logger.ok("schema Started.");
Set<AttributeInfo> attributes= new HashSet<AttributeInfo>();
SchemaBuilder builder= new SchemaBuilder(this.getClass());
AttributeInfoBuilder userLogin = new AttributeInfoBuilder();
userLogin.setName(DataBaseIdentityConstants.USER_LOGIN);
userLogin.setCreateable(true);
userLogin.setUpdateable(true);
userLogin.setReadable(true);
userLogin.setRequired(true);
userLogin.setMultiValued(false);
attributes.add(userLogin.build());
AttributeInfoBuilder password = new AttributeInfoBuilder();
password.setName(DataBaseIdentityConstants.PASSWORD);
password.setCreateable(true);
password.setUpdateable(true);
password.setReadable(true);
password.setRequired(true);
password.setMultiValued(false);
attributes.add(password.build());
AttributeInfoBuilder firstName = new AttributeInfoBuilder();
firstName.setName(DataBaseIdentityConstants.FIRST_NAME);
firstName.setCreateable(true);
firstName.setUpdateable(true);
firstName.setReadable(true);
firstName.setRequired(true);
firstName.setMultiValued(false);
attributes.add(firstName.build());
AttributeInfoBuilder lastName = new AttributeInfoBuilder();
lastName.setName(DataBaseIdentityConstants.LAST_NAME);
lastName.setCreateable(true);
lastName.setUpdateable(true);
lastName.setReadable(true);
lastName.setRequired(true);
lastName.setMultiValued(false);
attributes.add(lastName.build());
AttributeInfoBuilder middleName = new AttributeInfoBuilder();
middleName.setName(DataBaseIdentityConstants.MIDDLE_NAME);
middleName.setCreateable(true);
middleName.setUpdateable(true);
middleName.setReadable(true);
middleName.setRequired(true);
middleName.setMultiValued(false);
attributes.add(middleName.build());
builder.defineObjectClass(ObjectClass.ACCOUNT.getDisplayNameKey(),attributes);
logger.ok("Schema Attributes "+attributes);
logger.ok("schema Started.");
return builder.build();
}
@Override
public Uid update(ObjectClass objectClass, Uid uid, Set<Attribute> attributes,
OperationOptions operations)
{
logger.ok("update Started");
logger.ok("update Operation Request Attributes: "+attributes);
Map<String, Object> row=DataBaseIdentityUtil.convertSetToMap(attributes);
logger.ok("update Operation Request Attributes: "+row);
if(row != null && row.isEmpty())
{
logger.error(DataBaseIdentityConstants.USER_ATTR_MISSING);
throw new ConnectorException(DataBaseIdentityConstants.USER_ATTR_MISSING);
}
UserProfile profile= userProfileDao.findById(Long.parseLong(uid.getUidValue()));
if(profile==null)
{
logger.error(String.format(DataBaseIdentityConstants.USER_NOT_FOUND,"Uid",uid.getUidValue()));
throw new ConnectorException(String.format(DataBaseIdentityConstants.USER_NOT_FOUND,"Uid",uid.getUidValue()));
}
logger.error("The User "+uid.getUidValue()+" found Successfully ");
profile.setUpdateDate(new Date());
if(row.containsKey(DataBaseIdentityConstants.USER_LOGIN))
{
String userName=DataBaseIdentityUtil.getString(row, DataBaseIdentityConstants.USER_LOGIN);
if(DataBaseIdentityUtil.isEmpty(userName))
{
logger.error(String.format(DataBaseIdentityConstants.USER_ATTR_REQUIRED,DataBaseIdentityConstants.USER_LOGIN));
throw new ConnectorException(String.format(DataBaseIdentityConstants.USER_ATTR_REQUIRED,DataBaseIdentityConstants.USER_LOGIN));
}
profile.setUserName(userName);
}
if(row.containsKey(DataBaseIdentityConstants.PASSWORD))
{
profile.setPassword(DataBaseIdentityUtil.getString(row, DataBaseIdentityConstants.PASSWORD));
}
if(row.containsKey(DataBaseIdentityConstants.FIRST_NAME))
{
profile.setFirstName(DataBaseIdentityUtil.getString(row, DataBaseIdentityConstants.FIRST_NAME));
}
if(row.containsKey(DataBaseIdentityConstants.LAST_NAME))
{
profile.setLastName(DataBaseIdentityUtil.getString(row, DataBaseIdentityConstants.LAST_NAME));
}
if(row.containsKey(DataBaseIdentityConstants.MIDDLE_NAME))
{
profile.setMiddleName(DataBaseIdentityUtil.getString(row, DataBaseIdentityConstants.MIDDLE_NAME));
}
if(row.containsKey(DataBaseIdentityConstants.ATTR_ENABLE))
{
String enable=DataBaseIdentityUtil.getString(row, DataBaseIdentityConstants.ATTR_ENABLE);
if(!DataBaseIdentityUtil.isEmpty(enable))
{
if(enable.equalsIgnoreCase("true"))
{
enable=DataBaseIdentityConstants.STATUS_ENABLED;
}
else
{
enable=DataBaseIdentityConstants.STATUS_DISABLED;
}
}
else
{
enable=DataBaseIdentityConstants.STATUS_DISABLED;
}
profile.setStatus(enable);
}
userProfileDao.updateUser(profile);
logger.ok("update Ended");
return uid;
}
@Override
public FilterTranslator<String> createFilterTranslator(ObjectClass objectClass,
OperationOptions operations) {
return new DataBaseIdentityFilter();
}
@Override public void executeQuery(ObjectClass objectClass, String filter, ResultsHandler handler, OperationOptions operations) { logger.ok("executeQuery Started"); logger.ok("executeQuery filter "+filter); List<String> returnAttrs= new ArrayList<String>(); if(operations != null) { for (String attr: operations.getAttributesToGet()) { logger.ok("executeQuery Attributes "+attr); returnAttrs.add(attr); } } List<UserProfile> profiles=userProfileDao.findByUsersCriteria(filter); logger.error("executeQuery Result "+profiles); if(profiles != null && !profiles.isEmpty()) { for (UserProfile userProfile : profiles) { ConnectorObject conobj=DataBaseIdentityUtil.convertMapToConnectorObject(userProfile); if(returnAttrs.contains(DataBaseIdentityConstants.LAST_UPDATE)) { conobj=DataBaseIdentityUtil.convertMapToConnectorObject(userProfile,DataBaseIdentityConstants.LAST_UPDATE); } else if(returnAttrs.contains(DataBaseIdentityConstants.CREATE_DATE)) { conobj=DataBaseIdentityUtil.convertMapToConnectorObject(userProfile,DataBaseIdentityConstants.CREATE_DATE); } else { conobj=DataBaseIdentityUtil.convertMapToConnectorObject(userProfile); } logger.ok("executeQuery Attributes Objects "+conobj.getAttributes()); handler.handle(conobj); logger.ok("executeQuery Attributes Objects After "+conobj.getAttributes()); } } logger.ok("executeQuery Ended"); }
@Override
public SyncToken getLatestSyncToken(ObjectClass objectClass) {
// TODO Auto-generated method stub
SyncToken token= new SyncToken(DataBaseIdentityUtil.convertDateToString(new Date()));
return token;
}
@Override
public void sync(ObjectClass objectClass, SyncToken syncToken, SyncResultsHandler handler,
OperationOptions operations)
{
logger.ok("sync Started");
logger.ok("syncToken "+syncToken);
List<UserProfile> profiles=userProfileDao.getUsersByChange(syncToken==null ? null : DataBaseIdentityUtil.convertSringToDate(""+syncToken.getValue()));
logger.ok("sync Result "+profiles);
if(profiles != null && !profiles.isEmpty())
{
for (UserProfile userProfile : profiles)
{
SyncDeltaBuilder builder= new SyncDeltaBuilder();
builder.setObject(DataBaseIdentityUtil.convertMapToConnectorObject(userProfile));
builder.setDeltaType(SyncDeltaType.CREATE_OR_UPDATE);
builder.setUid(new Uid(""+userProfile.getId()));
builder.setToken(new SyncToken(userProfile.getUpdateDate() != null ? DataBaseIdentityUtil.convertDateToString(userProfile.getUpdateDate()) : userProfile.getCreateDate() != null ? DataBaseIdentityUtil.convertDateToString(userProfile.getCreateDate()): DataBaseIdentityUtil.convertDateToString(new Date())));
handler.handle(builder.build());
}
}
}
}
}
1. Messages.properties
This property file storing the config property labels and also connector display name key.
create a file Messages.properties in the identity.dbconnector directory and add the following content in the file.
driver_display=Jdbc Driver Name
driver_help=Jdbc Driver Name
url_display=Jdbc URL
url_help=Jdbc URL Format
userName_display=Jdbc User Name
userName_help=Jdbc User Name
password_display=Jdbc User Password
password_help=Jdbc User Password
environment_display=Data Source Environment
environment_help=Data Source Environment
displayName=Database Identity Connector
2. persistence.xml
create a file persistence.xml in the META-INF directory.
<?xml version="1.0" encoding="UTF-8" ?>
<persistence xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_1.xsd"
version="2.1" xmlns="http://java.sun.com/xml/ns/persistence">
<persistence-unit name="databaseconnector" transaction-type="RESOURCE_LOCAL">
<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
<non-jta-data-source>mydatasource</non-jta-data-source>
<jta-data-source>mydatasource</jta-data-source>
<class>identity.dbconnector.domain.UserProfile</class>
<properties>
<property name="eclipselink.ddl-generation.output-mode" value="database"/>
</properties>
</persistence-unit>
</persistence>
Pre-Requisite
1. Install and download the gradle2. Setting the JAVA_HOME and GRADLE_HOME environment variables.
Creating the Eclipse Project
Directory Structure
mkdir databaseconnector-demo
mkdir databaseconnector-demo/src
mkdir databaseconnector-demo/src/main
mkdir databaseconnector-demo/src/main/java
mkdir databaseconnector-demo/src/main/resources
ICF Jar and odbc Jar Files
The following jar files in the classpath. They areconnector-framework-internal.jar
connector-framework.jar
groovy-all.jar
ojdbc6.jar
Creating the build.gradle File
pply plugin: 'java'apply plugin: 'eclipse'
version="1.0"
configurations{
includeInJar
}
repositories{
mavenCentral()
}
dependencies{
compile fileTree (dir: '<Replace with your ICF jar files and oracle jdbc driver>',include: '*.jar')
includeInJar 'com.sun.messaging.mq:fscontext:4.4.2'
configurations.compile.extendsFrom(configurations.includeInJar)
}
jar.doFirst{
manifest {
attributes("Manifest-Version" : "1.0",
"Created-By" : "Data Base Demo",
"ConnectorBundle-FrameworkVersion" : "1.4.0",
"ConnectorBundle-Name" : project.name,
"ConnectorBundle-Version" : version,
"Build-Number": "609",
"Subversion-Revision" : "4582"
)
}
into('lib') {
println "includeInJar: " + configurations.includeInJar.collect { File file -> file }
from configurations.includeInJar
}
}
Create the Eclipse Project
gradle cleanEclipse eclipseImport the Project into the Eclipse
Click File --> Import --> Existing Project into workspace --> Next --> Select Root Directory --> Browse --> OK --> FinishDeveloping the ICF Connector
1. Defining the Configuration properties
Define the configuration properties to capture the config data from OIM to Connector to establish the connectivity to the oracle database. For demo i have used 5 config properties are driver, url,userName, password, and environment. The driver property holds the jdbc driver, url holds the jdbc url, username holds the jdbc user name, password holds the jdbc password, and environment to get the data source from local or remote. If you specify the environment is local it will create the data source pro grammatically in connector. If you specify remote and it will fetch the data source from the application server. The sample code is given below.
package identity.dbconnector;
import identity.dbconnector.util.DataBaseIdentityUtil;
import org.identityconnectors.framework.common.exceptions.ConnectorException;
import org.identityconnectors.framework.spi.AbstractConfiguration;
import org.identityconnectors.framework.spi.ConfigurationProperty;
public class DataBaseIdentityConfig extends AbstractConfiguration {
private String driver;
private String url;
private String userName;
private String password;
private String environment;
public String getDriver() {
return driver;
}
@ConfigurationProperty(order=1,displayMessageKey="driver_display",helpMessageKey="driver_help",required=true)
public void setDriver(String driver) {
this.driver = driver;
}
public String getUrl() {
return url;
}
@ConfigurationProperty(order=2,displayMessageKey="url_display",helpMessageKey="url_help",required=true)
public void setUrl(String url) {
this.url = url;
}
public String getUserName() {
return userName;
}
@ConfigurationProperty(order=3,displayMessageKey="userName_display",helpMessageKey="userName_help",required=true)
public void setUserName(String userName) {
this.userName = userName;
}
public String getPassword() {
return password;
}
@ConfigurationProperty(order=4,displayMessageKey="password_display",helpMessageKey="password_help",required=true,confidential=true)
public void setPassword(String password) {
this.password = password;
}
public String getEnvironment() {
return environment;
}
@ConfigurationProperty(order=5,displayMessageKey="environment_display",helpMessageKey="environment_help",required=true,confidential=true)
public void setEnvironment(String environment) {
this.environment = environment;
}
@Override
public void validate()
{
if(DataBaseIdentityUtil.isEmpty(driver))
{
throw new ConnectorException(String.format(DataBaseIdentityConstants.CONFIG_PARAM,"jdbc driver"));
}
if(DataBaseIdentityUtil.isEmpty(url))
{
throw new ConnectorException(String.format(DataBaseIdentityConstants.CONFIG_PARAM,"jdbc url"));
}
if(DataBaseIdentityUtil.isEmpty(userName))
{
throw new ConnectorException(String.format(DataBaseIdentityConstants.CONFIG_PARAM,"jdbc userName"));
}
if(DataBaseIdentityUtil.isEmpty(password))
{
throw new ConnectorException(String.format(DataBaseIdentityConstants.CONFIG_PARAM,"jdbc password"));
}
}
}
2. Connector operation interfaces
The following interfaces needs to be implemented to develop the custom ICF Connector. They are
2.1 PoolableConnector
This interface is required to implement the Pooled the connector instance.
2.2 SearchOp<String>
This interface is required to reconcile the users from the target system.
2.3 UpdateOp
The interface is required to implement the attribute changes from oim to target system. The attribute changes are updating the user attribute, enable and disable the user.
2.4 DeleteOp
The interface is required to De-provision the user from target system
2.5 CreateOp
The interface is required to provisioning to the user to the target system.
2.6 SyncOp
The interface is required to fetch the changes from the target system and synchronize with OIM.
2.7 GetApiOp
2.8 SchemaOp
The interface is required to build the metadata in the OIM.
3. Defining the Connector Operations
The following operations going to demonstrate in connector.1. public void init(Configuration config)
In my example I am establishing the Connectivity from Connector to Database.
2. public Schema schema()
I am initializing the schema to persist the data in database and also btuild the OIM metadata.
3. public Uid create(ObjectClass objectClass, Set<Attribute> attributes, OperationOptions operations)
provisioning the users to the database.
4. public Uid update(ObjectClass objectClass, Uid uid, Set<Attribute> attributes, OperationOptions operations)
Updating the User attributes in database and also enable and disable the user in database.
In enable operation OIM send the attribute value __ENABLE__= true and also __CURRENT_ATTRIBUTES__ contains the current data in OIM. The disable operation also same as enable operation attribute, except __ENABLE__ = false
5. public void executeQuery(ObjectClass objectClass, String filter,ResultsHandler handler, OperationOptions operations)
Reconciliation operation being used to link the data from database to oim. For reconciliation I am using the two kinds of filters to link the data. They are equal and contains filter. If you want to retrieve the single user use the equal filter . If you want to link all users use the contains filter.
Incremental Reconciliation based on time stamp to sync with OIM.
7. public void delete(ObjectClass objectClass, Uid uid, OperationOptions operations)
De-provision the user in oim and also delete entry in database.
8.public void dispose()
Closing the database connection
9.public ConnectorObject getObject(ObjectClass objectClass, Uid uid, OperationOptions operations)
Getting the Connector object from the database.
10 public void checkAlive()
Verifying the connection is alive or not.
Sample Code:
Connector Class:
package identity.dbconnector;
import identity.dbconnector.dao.UserProfileDao;
import identity.dbconnector.dao.UserProfileDaoImpl;
import identity.dbconnector.domain.UserProfile;
import identity.dbconnector.util.DataBaseIdentityUtil;
import java.sql.SQLException;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import oracle.jdbc.pool.OracleConnectionPoolDataSource;
import org.identityconnectors.common.logging.Log;
import org.identityconnectors.framework.api.operations.GetApiOp;
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.SyncDeltaBuilder;
import org.identityconnectors.framework.common.objects.SyncDeltaType;
import org.identityconnectors.framework.common.objects.SyncResultsHandler;
import org.identityconnectors.framework.common.objects.SyncToken;
import org.identityconnectors.framework.common.objects.Uid;
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.SyncOp;
import org.identityconnectors.framework.spi.operations.UpdateOp;
@ConnectorClass(configurationClass=DataBaseIdentityConfig.class,displayNameKey="displayName",messageCatalogPaths="identity.dbconnector.Messages")
public class DataBaseIdentityConnector implements PoolableConnector,
SearchOp<String>, UpdateOp, DeleteOp, CreateOp, SyncOp,GetApiOp,SchemaOp {
private DataBaseIdentityConfig config;
private EntityManagerFactory factory=null;
private UserProfileDao userProfileDao=null;
private Context context=null;
private static Log logger=null;
@Override
public void dispose()
{
logger.ok("dispose started");
if(factory != null)
{
logger.ok("dispose factory");
factory.close();
}
if(context != null)
{
try {
logger.ok("dispose context");
context.close();
} catch (NamingException e)
{
logger.error(e, "dispose context");
}
}
logger.ok("dispose ended");
}
@Override
public Configuration getConfiguration() {
// TODO Auto-generated method stub
return config;
}
@Override
public void init(Configuration config)
{
logger=Log.getLog(this.getClass());
logger.ok("Invoking the Init Method Start");
this.config=(DataBaseIdentityConfig)config;
initDataSource(this.config);
factory= Persistence.createEntityManagerFactory(DataBaseIdentityConstants.PERSISTENCE_UNIT);
userProfileDao= new UserProfileDaoImpl(factory);
logger.ok("Invoking the Init Method End ");
}
private void initDataSource(DataBaseIdentityConfig config)
{
logger.ok(" initDataSource - started");
if(!DataBaseIdentityUtil.isEmpty(config.getEnvironment()) && config.getEnvironment().equalsIgnoreCase(DataBaseIdentityConstants.DATASOURCE_LOCAL))
{
System.setProperty(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.fscontext.RefFSContextFactory");
System.setProperty(Context.PROVIDER_URL, "file:///tmp");
try
{
//Properties prop= new Properties();
//prop.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.fscontext.RefFSContextFactory");
//prop.put(Context.PROVIDER_URL, "file:///tmp");
context = new InitialContext();
logger.ok("INitialize the Local Context Successfully");
OracleConnectionPoolDataSource ds= new OracleConnectionPoolDataSource();
ds.setURL(config.getUrl());
ds.setUser(config.getUserName());
ds.setPassword(config.getPassword());
context.rebind("mydatasource", ds);
logger.ok("Data Source created successfully");
} catch (NamingException e) {
logger.error(e, "initializing the data source error");
throw new ConnectorException(DataBaseIdentityConstants.CONNECTOR_CON_EXP);
} catch (SQLException e) {
logger.error(e, "initializing the data source error");
throw new ConnectorException(DataBaseIdentityConstants.CONNECTOR_CON_EXP);
}
}
logger.ok(" initDataSource - Ended");
}
@Override
public Uid create(ObjectClass objectClass, Set<Attribute> attributes,
OperationOptions operations) {
logger.ok("create Started");
Map<String, Object> row=DataBaseIdentityUtil.convertSetToMap(attributes);
logger.ok("Create Request Attributes : "+attributes);
if(row != null && row.isEmpty())
{
throw new ConnectorException(DataBaseIdentityConstants.USER_ATTR_MISSING);
}
String userLogin=DataBaseIdentityUtil.getString(row, DataBaseIdentityConstants.USER_LOGIN);
logger.ok("Create Request Login : "+userLogin);
if(DataBaseIdentityUtil.isEmpty(userLogin))
{
logger.error(String.format(DataBaseIdentityConstants.USER_ATTR_REQUIRED,DataBaseIdentityConstants.USER_LOGIN));
throw new ConnectorException(String.format(DataBaseIdentityConstants.USER_ATTR_REQUIRED,DataBaseIdentityConstants.USER_LOGIN));
}
UserProfile profile= userProfileDao.findByLogin(userLogin);
if(profile != null)
{
logger.error(String.format(DataBaseIdentityConstants.USER_ALREADY_EXISTS,row.get(DataBaseIdentityConstants.USER_LOGIN).toString()));
throw new ConnectorException(String.format(DataBaseIdentityConstants.USER_ALREADY_EXISTS,row.get(DataBaseIdentityConstants.USER_LOGIN).toString()));
}
profile=DataBaseIdentityUtil.convertToUserProfile(row);
profile.setCreateDate(new Date());
profile.setPassword(DataBaseIdentityUtil.getString(row, DataBaseIdentityConstants.PASSWORD));
profile.setStatus(DataBaseIdentityConstants.STATUS_ENABLED);
logger.ok("User Creation Process Started");
profile=userProfileDao.createUser(profile);
logger.ok("User Creation Process Ended");
Uid uid= new Uid(profile.getId().toString());
logger.ok("User Created Successfully and Id :"+uid);
logger.ok("create Ended");
return uid;
}
@Override
public void delete(ObjectClass objectClass, Uid uid, OperationOptions operations)
{
logger.ok("delete Started");
logger.ok("delete User Uid "+uid);
userProfileDao.deleteUser(new Long(uid.getUidValue()));
logger.ok("delete Ended");
}
@Override
public void checkAlive()
{
userProfileDao.test();
}
@Override
public ConnectorObject getObject(ObjectClass objectClass, Uid uid,
OperationOptions operations)
{
logger.ok("getObject Started");
logger.ok("The Requested getObject uid "+uid);
UserProfile profile= userProfileDao.findById(new Long(uid.getUidValue()));
if(profile==null)
{
logger.error(String.format(DataBaseIdentityConstants.USER_NOT_FOUND,"Uid",uid.getUidValue()));
throw new ConnectorException(String.format(DataBaseIdentityConstants.USER_NOT_FOUND,"Uid",uid.getUidValue()));
}
logger.ok("getObject Ended");
return DataBaseIdentityUtil.convertMapToConnectorObject(profile);
}
@Override
public Schema schema() {
logger.ok("schema Started.");
Set<AttributeInfo> attributes= new HashSet<AttributeInfo>();
SchemaBuilder builder= new SchemaBuilder(this.getClass());
AttributeInfoBuilder userLogin = new AttributeInfoBuilder();
userLogin.setName(DataBaseIdentityConstants.USER_LOGIN);
userLogin.setCreateable(true);
userLogin.setUpdateable(true);
userLogin.setReadable(true);
userLogin.setRequired(true);
userLogin.setMultiValued(false);
attributes.add(userLogin.build());
AttributeInfoBuilder password = new AttributeInfoBuilder();
password.setName(DataBaseIdentityConstants.PASSWORD);
password.setCreateable(true);
password.setUpdateable(true);
password.setReadable(true);
password.setRequired(true);
password.setMultiValued(false);
attributes.add(password.build());
AttributeInfoBuilder firstName = new AttributeInfoBuilder();
firstName.setName(DataBaseIdentityConstants.FIRST_NAME);
firstName.setCreateable(true);
firstName.setUpdateable(true);
firstName.setReadable(true);
firstName.setRequired(true);
firstName.setMultiValued(false);
attributes.add(firstName.build());
AttributeInfoBuilder lastName = new AttributeInfoBuilder();
lastName.setName(DataBaseIdentityConstants.LAST_NAME);
lastName.setCreateable(true);
lastName.setUpdateable(true);
lastName.setReadable(true);
lastName.setRequired(true);
lastName.setMultiValued(false);
attributes.add(lastName.build());
AttributeInfoBuilder middleName = new AttributeInfoBuilder();
middleName.setName(DataBaseIdentityConstants.MIDDLE_NAME);
middleName.setCreateable(true);
middleName.setUpdateable(true);
middleName.setReadable(true);
middleName.setRequired(true);
middleName.setMultiValued(false);
attributes.add(middleName.build());
builder.defineObjectClass(ObjectClass.ACCOUNT.getDisplayNameKey(),attributes);
logger.ok("Schema Attributes "+attributes);
logger.ok("schema Started.");
return builder.build();
}
@Override
public Uid update(ObjectClass objectClass, Uid uid, Set<Attribute> attributes,
OperationOptions operations)
{
logger.ok("update Started");
logger.ok("update Operation Request Attributes: "+attributes);
Map<String, Object> row=DataBaseIdentityUtil.convertSetToMap(attributes);
logger.ok("update Operation Request Attributes: "+row);
if(row != null && row.isEmpty())
{
logger.error(DataBaseIdentityConstants.USER_ATTR_MISSING);
throw new ConnectorException(DataBaseIdentityConstants.USER_ATTR_MISSING);
}
UserProfile profile= userProfileDao.findById(Long.parseLong(uid.getUidValue()));
if(profile==null)
{
logger.error(String.format(DataBaseIdentityConstants.USER_NOT_FOUND,"Uid",uid.getUidValue()));
throw new ConnectorException(String.format(DataBaseIdentityConstants.USER_NOT_FOUND,"Uid",uid.getUidValue()));
}
logger.error("The User "+uid.getUidValue()+" found Successfully ");
profile.setUpdateDate(new Date());
if(row.containsKey(DataBaseIdentityConstants.USER_LOGIN))
{
String userName=DataBaseIdentityUtil.getString(row, DataBaseIdentityConstants.USER_LOGIN);
if(DataBaseIdentityUtil.isEmpty(userName))
{
logger.error(String.format(DataBaseIdentityConstants.USER_ATTR_REQUIRED,DataBaseIdentityConstants.USER_LOGIN));
throw new ConnectorException(String.format(DataBaseIdentityConstants.USER_ATTR_REQUIRED,DataBaseIdentityConstants.USER_LOGIN));
}
profile.setUserName(userName);
}
if(row.containsKey(DataBaseIdentityConstants.PASSWORD))
{
profile.setPassword(DataBaseIdentityUtil.getString(row, DataBaseIdentityConstants.PASSWORD));
}
if(row.containsKey(DataBaseIdentityConstants.FIRST_NAME))
{
profile.setFirstName(DataBaseIdentityUtil.getString(row, DataBaseIdentityConstants.FIRST_NAME));
}
if(row.containsKey(DataBaseIdentityConstants.LAST_NAME))
{
profile.setLastName(DataBaseIdentityUtil.getString(row, DataBaseIdentityConstants.LAST_NAME));
}
if(row.containsKey(DataBaseIdentityConstants.MIDDLE_NAME))
{
profile.setMiddleName(DataBaseIdentityUtil.getString(row, DataBaseIdentityConstants.MIDDLE_NAME));
}
if(row.containsKey(DataBaseIdentityConstants.ATTR_ENABLE))
{
String enable=DataBaseIdentityUtil.getString(row, DataBaseIdentityConstants.ATTR_ENABLE);
if(!DataBaseIdentityUtil.isEmpty(enable))
{
if(enable.equalsIgnoreCase("true"))
{
enable=DataBaseIdentityConstants.STATUS_ENABLED;
}
else
{
enable=DataBaseIdentityConstants.STATUS_DISABLED;
}
}
else
{
enable=DataBaseIdentityConstants.STATUS_DISABLED;
}
profile.setStatus(enable);
}
userProfileDao.updateUser(profile);
logger.ok("update Ended");
return uid;
}
@Override
public FilterTranslator<String> createFilterTranslator(ObjectClass objectClass,
OperationOptions operations) {
return new DataBaseIdentityFilter();
}
@Override public void executeQuery(ObjectClass objectClass, String filter, ResultsHandler handler, OperationOptions operations) { logger.ok("executeQuery Started"); logger.ok("executeQuery filter "+filter); List<String> returnAttrs= new ArrayList<String>(); if(operations != null) { for (String attr: operations.getAttributesToGet()) { logger.ok("executeQuery Attributes "+attr); returnAttrs.add(attr); } } List<UserProfile> profiles=userProfileDao.findByUsersCriteria(filter); logger.error("executeQuery Result "+profiles); if(profiles != null && !profiles.isEmpty()) { for (UserProfile userProfile : profiles) { ConnectorObject conobj=DataBaseIdentityUtil.convertMapToConnectorObject(userProfile); if(returnAttrs.contains(DataBaseIdentityConstants.LAST_UPDATE)) { conobj=DataBaseIdentityUtil.convertMapToConnectorObject(userProfile,DataBaseIdentityConstants.LAST_UPDATE); } else if(returnAttrs.contains(DataBaseIdentityConstants.CREATE_DATE)) { conobj=DataBaseIdentityUtil.convertMapToConnectorObject(userProfile,DataBaseIdentityConstants.CREATE_DATE); } else { conobj=DataBaseIdentityUtil.convertMapToConnectorObject(userProfile); } logger.ok("executeQuery Attributes Objects "+conobj.getAttributes()); handler.handle(conobj); logger.ok("executeQuery Attributes Objects After "+conobj.getAttributes()); } } logger.ok("executeQuery Ended"); }
@Override
public SyncToken getLatestSyncToken(ObjectClass objectClass) {
// TODO Auto-generated method stub
SyncToken token= new SyncToken(DataBaseIdentityUtil.convertDateToString(new Date()));
return token;
}
@Override
public void sync(ObjectClass objectClass, SyncToken syncToken, SyncResultsHandler handler,
OperationOptions operations)
{
logger.ok("sync Started");
logger.ok("syncToken "+syncToken);
List<UserProfile> profiles=userProfileDao.getUsersByChange(syncToken==null ? null : DataBaseIdentityUtil.convertSringToDate(""+syncToken.getValue()));
logger.ok("sync Result "+profiles);
if(profiles != null && !profiles.isEmpty())
{
for (UserProfile userProfile : profiles)
{
SyncDeltaBuilder builder= new SyncDeltaBuilder();
builder.setObject(DataBaseIdentityUtil.convertMapToConnectorObject(userProfile));
builder.setDeltaType(SyncDeltaType.CREATE_OR_UPDATE);
builder.setUid(new Uid(""+userProfile.getId()));
builder.setToken(new SyncToken(userProfile.getUpdateDate() != null ? DataBaseIdentityUtil.convertDateToString(userProfile.getUpdateDate()) : userProfile.getCreateDate() != null ? DataBaseIdentityUtil.convertDateToString(userProfile.getCreateDate()): DataBaseIdentityUtil.convertDateToString(new Date())));
handler.handle(builder.build());
}
}
}
}
}
Connector Constants
package identity.dbconnector;
public interface DataBaseIdentityConstants {
public String PERSISTENCE_UNIT="databaseconnector";
public String USER_NOT_FOUND="The User %s %s Not found.";
public String USER_LOGIN="userLogin";
public String PASSWORD="password";
public String FIRST_NAME="firstName";
public String LAST_NAME="lastName";
public String MIDDLE_NAME="middleName";
public String STATUS="Status";
public String USER_ATTR_MISSING="The User required attributes are missing in the request.";
public String USER_ATTR_REQUIRED="The %s attribute is missing.";
public String USER_ALREADY_EXISTS="The User %s already exists.";
public String DATASOURCE_LOCAL="local";
public String CONFIG_PARAM="The config parameter %s is empty";
public String STATUS_ENABLED="Enabled";
public String STATUS_DISABLED="Disabled";
public String CONNECTOR_CON_EXP="The Connector SQL Connection Error Exception";
public String ATTR_ENABLE="__ENABLE__";
public String DATE_FORMAT="yyyy/MM/dd HH:mm:ss";
public String DB_DATE_FORMAT="YYYY/MM/DD HH24:MI:SS";
public String LAST_UPDATE="updateDate";
public String CREATE_DATE="createDate";
}
Connector Filter:
public String PERSISTENCE_UNIT="databaseconnector";
public String USER_NOT_FOUND="The User %s %s Not found.";
public String USER_LOGIN="userLogin";
public String PASSWORD="password";
public String FIRST_NAME="firstName";
public String LAST_NAME="lastName";
public String MIDDLE_NAME="middleName";
public String STATUS="Status";
public String USER_ATTR_MISSING="The User required attributes are missing in the request.";
public String USER_ATTR_REQUIRED="The %s attribute is missing.";
public String USER_ALREADY_EXISTS="The User %s already exists.";
public String DATASOURCE_LOCAL="local";
public String CONFIG_PARAM="The config parameter %s is empty";
public String STATUS_ENABLED="Enabled";
public String STATUS_DISABLED="Disabled";
public String CONNECTOR_CON_EXP="The Connector SQL Connection Error Exception";
public String ATTR_ENABLE="__ENABLE__";
public String DATE_FORMAT="yyyy/MM/dd HH:mm:ss";
public String DB_DATE_FORMAT="YYYY/MM/DD HH24:MI:SS";
public String LAST_UPDATE="updateDate";
public String CREATE_DATE="createDate";
}
Connector Filter:
package identity.dbconnector;
import identity.dbconnector.util.DataBaseIdentityUtil;
import org.identityconnectors.common.logging.Log;
import org.identityconnectors.framework.common.exceptions.ConnectorException;
import org.identityconnectors.framework.common.objects.Attribute;
import org.identityconnectors.framework.common.objects.filter.AbstractFilterTranslator;
import org.identityconnectors.framework.common.objects.filter.ContainsFilter;
import org.identityconnectors.framework.common.objects.filter.EqualsFilter;
public class DataBaseIdentityFilter extends AbstractFilterTranslator<String>
{
private Log logger= Log.getLog(this.getClass());
public String createEqualsExpression(EqualsFilter filter,boolean not)
{
String operation="createEqualsExpression - ";
logger.ok(operation+" Started");
logger.ok(operation+" filter "+filter);
String query=null;
if(not)
{
return query;
}
Attribute attr= filter.getAttribute();
if(attr==null || attr.getValue()==null || (attr.getValue()!=null && attr.getValue().isEmpty()))
{
return query;
}
String name=filter.getName();
Object val=attr.getValue().get(0);
if(DataBaseIdentityUtil.isEmpty(val))
{
throw new ConnectorException("The filter value can not be empty");
}
String strValue=DataBaseIdentityUtil.getString(val);
query="T."+name + "='"+val+"'";
logger.ok(operation+" Final Filter "+query);
logger.ok(operation+" Ended");
return query;
}
@Override
// TODO Auto-generated method stub
protected String createContainsExpression(ContainsFilter filter, boolean not)
{
String operation="createContainsExpression - ";
logger.ok(operation + " Started");
String query= null;
if(not)
{
return query;
}
Attribute attr= filter.getAttribute();
if(attr==null || attr.getValue()==null || (attr.getValue()!=null && attr.getValue().isEmpty()))
{
return query;
}
String name=filter.getName();
Object val=attr.getValue().get(0);
if(DataBaseIdentityUtil.isEmpty(val))
{
throw new ConnectorException("The filter value can not be empty");
}
String strValue=DataBaseIdentityUtil.getString(val);
if(strValue.equalsIgnoreCase("*"))
{
query= "*";
}
else
{
String tempVal="";
if(strValue.startsWith("*"))
{
tempVal=strValue.substring(1)+"%";
}
if(strValue.endsWith("*"))
{
if(!DataBaseIdentityUtil.isEmpty(tempVal))
{
tempVal=strValue;
}
else
{
tempVal=strValue.substring(0, strValue.length()-1)+"%";
}
}
else
{
tempVal=strValue;
}
query="T."+name + " LIKE '"+tempVal+"'";
}
logger.ok(operation + " Final Filter "+query);
logger.ok(operation + " Ended ");
return query;
}
@Override
protected String createGreaterThanExpression(
GreaterThanFilter filter, boolean not) {
String operation="createGreaterThanOrEqualExpression - ";
logger.ok(operation + " Started");
String query= null;
if(not)
{
return query;
}
Attribute attr= filter.getAttribute();
if(attr==null || attr.getValue()==null || (attr.getValue()!=null && attr.getValue().isEmpty()))
{
return query;
}
String name=filter.getName();
Object val=attr.getValue().get(0);
if(DataBaseIdentityUtil.isEmpty(val))
{
throw new ConnectorException("The filter value can not be empty");
}
String strValue=DataBaseIdentityUtil.getString(val);
if(name.equalsIgnoreCase("updateDate"))
{
query="T."+name + " > FUNC('TO_DATE','"+DataBaseIdentityUtil.convertDateToString(new Date(new Long(strValue).longValue()))+"','"+DataBaseIdentityConstants.DB_DATE_FORMAT+"')";
}
else
{
query="T."+name + " > '"+strValue+"'";
}
logger.ok(operation + " Final Filter "+query);
logger.ok(operation + " Ended ");
return query;
}
@Override
protected String createAndExpression(String leftExpression,
String rightExpression) {
return leftExpression + " AND "+ rightExpression;
}
@Override
protected String createGreaterThanExpression(
GreaterThanFilter filter, boolean not) {
String operation="createGreaterThanOrEqualExpression - ";
logger.ok(operation + " Started");
String query= null;
if(not)
{
return query;
}
Attribute attr= filter.getAttribute();
if(attr==null || attr.getValue()==null || (attr.getValue()!=null && attr.getValue().isEmpty()))
{
return query;
}
String name=filter.getName();
Object val=attr.getValue().get(0);
if(DataBaseIdentityUtil.isEmpty(val))
{
throw new ConnectorException("The filter value can not be empty");
}
String strValue=DataBaseIdentityUtil.getString(val);
if(name.equalsIgnoreCase("updateDate"))
{
query="T."+name + " > FUNC('TO_DATE','"+DataBaseIdentityUtil.convertDateToString(new Date(new Long(strValue).longValue()))+"','"+DataBaseIdentityConstants.DB_DATE_FORMAT+"')";
}
else
{
query="T."+name + " > '"+strValue+"'";
}
logger.ok(operation + " Final Filter "+query);
logger.ok(operation + " Ended ");
return query;
}
@Override
protected String createAndExpression(String leftExpression,
String rightExpression) {
return leftExpression + " AND "+ rightExpression;
}
}
Connector Config Class:
package identity.dbconnector;
import identity.dbconnector.util.DataBaseIdentityUtil;
import org.identityconnectors.framework.common.exceptions.ConnectorException;
import org.identityconnectors.framework.spi.AbstractConfiguration;
import org.identityconnectors.framework.spi.ConfigurationProperty;
public class DataBaseIdentityConfig extends AbstractConfiguration {
private String driver;
private String url;
private String userName;
private String password;
private String environment;
public String getDriver() {
return driver;
}
@ConfigurationProperty(order=1,displayMessageKey="driver_display",helpMessageKey="driver_help",required=true)
public void setDriver(String driver) {
this.driver = driver;
}
public String getUrl() {
return url;
}
@ConfigurationProperty(order=2,displayMessageKey="url_display",helpMessageKey="url_help",required=true)
public void setUrl(String url) {
this.url = url;
}
public String getUserName() {
return userName;
}
@ConfigurationProperty(order=3,displayMessageKey="userName_display",helpMessageKey="userName_help",required=true)
public void setUserName(String userName) {
this.userName = userName;
}
public String getPassword() {
return password;
}
@ConfigurationProperty(order=4,displayMessageKey="password_display",helpMessageKey="password_help",required=true,confidential=true)
public void setPassword(String password) {
this.password = password;
}
public String getEnvironment() {
return environment;
}
@ConfigurationProperty(order=5,displayMessageKey="environment_display",helpMessageKey="environment_help",required=true,confidential=true)
public void setEnvironment(String environment) {
this.environment = environment;
}
@Override
public void validate()
{
if(DataBaseIdentityUtil.isEmpty(driver))
{
throw new ConnectorException(String.format(DataBaseIdentityConstants.CONFIG_PARAM,"jdbc driver"));
}
if(DataBaseIdentityUtil.isEmpty(url))
{
throw new ConnectorException(String.format(DataBaseIdentityConstants.CONFIG_PARAM,"jdbc url"));
}
if(DataBaseIdentityUtil.isEmpty(userName))
{
throw new ConnectorException(String.format(DataBaseIdentityConstants.CONFIG_PARAM,"jdbc userName"));
}
if(DataBaseIdentityUtil.isEmpty(password))
{
throw new ConnectorException(String.format(DataBaseIdentityConstants.CONFIG_PARAM,"jdbc password"));
}
}
}
Connector DAO
package identity.dbconnector.dao;
import identity.dbconnector.domain.UserProfile;
import java.util.Date;
import java.util.List;
import java.util.Map;
public interface UserProfileDao
{
public UserProfile findByLogin(String loginId);
public UserProfile findById(long id);
public UserProfile createUser(UserProfile userProfile);
public UserProfile updateUser(UserProfile userProfile);
public UserProfile deleteUser(long id);
public List<UserProfile> getAllUser();
public List<UserProfile> getUsersByChange(Date date);
public List<UserProfile> findByUsersCriteria(String criteria);
public void test();
}
package identity.dbconnector.dao;
import identity.dbconnector.DataBaseIdentityConstants;
import identity.dbconnector.domain.UserProfile;
import java.util.Date;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import javax.persistence.Query;
import javax.persistence.TemporalType;
import oracle.net.aso.q;
import org.identityconnectors.common.logging.Log;
import org.identityconnectors.framework.common.exceptions.ConnectorException;
public class UserProfileDaoImpl implements UserProfileDao {
private EntityManagerFactory factory;
private Log logger= Log.getLog(this.getClass());
public UserProfileDaoImpl(EntityManagerFactory factory)
{
this.factory=factory;
}
@Override
public UserProfile findByLogin(String loginId)
{
String operation="findByLogin - ";
logger.ok(operation+" Started");
EntityManager em=null;
UserProfile profile=null;
try
{
em= factory.createEntityManager();
Query query= em.createQuery("Select T FROM UserProfile T WHERE T.userLogin = :userLogin");
logger.ok(operation+" SQL" +query);
query.setParameter("userLogin", loginId);
List<UserProfile> profiles= query.getResultList();
logger.ok(operation+" Result " +profiles);
if(profiles != null && !profiles.isEmpty())
{
profile=profiles.get(0);
}
}
catch(Exception e)
{
logger.error(e,operation);
throw new ConnectorException(e);
}
finally
{
if(em != null)
{
em.close();
}
}
logger.ok(operation+" Ended");
return profile;
}
@Override
public UserProfile findById(long id) {
String operation="findById - ";
logger.ok(operation+" Started");
logger.ok(operation+" Requested Search ID "+id);
EntityManager em=null;
UserProfile profile=null;
try
{
em= factory.createEntityManager();
profile=em.find(UserProfile.class, id);
logger.ok(operation+" Requested Search Result "+profile);
}
catch(Exception e)
{
logger.error(e,operation);
throw new ConnectorException(e);
}
finally
{
if(em != null)
{
em.close();
}
}
logger.ok(operation+" Ended");
return profile;
}
@Override
public UserProfile createUser(UserProfile userProfile) {
// TODO Auto-generated method stub
String operation="createUser - ";
logger.ok(operation+" Started");
EntityManager em=null;
try
{
em= factory.createEntityManager();
em.getTransaction().begin();
em.persist(userProfile);
em.getTransaction().commit();
}
catch(Exception e)
{
logger.error(e, operation);
if( em != null)
{
em.getTransaction().rollback();
}
throw new ConnectorException(e);
}
finally
{
if(em != null)
{
em.close();
}
}
logger.ok(operation+" Ended");
return userProfile;
}
@Override
public UserProfile updateUser(UserProfile userProfile) {
String operation="updateUser - ";
logger.ok(operation+" Started");
EntityManager em=null;
UserProfile profile=null;
try
{
em= factory.createEntityManager();
em.getTransaction().begin();
profile=em.merge(userProfile);
em.getTransaction().commit();
}
catch(Exception e)
{
logger.error(e, operation);
if( em != null)
{
em.getTransaction().rollback();
}
throw new ConnectorException(e);
}
finally
{
if(em != null)
{
em.close();
}
}
logger.ok(operation+" Ended");
return profile;
}
@Override
public UserProfile deleteUser(long id) {
EntityManager em=null;
UserProfile profile=null;
String operation="deleteUser - ";
logger.ok(operation+" Started");
try
{
em= factory.createEntityManager();
em.getTransaction().begin();
profile = em.getReference(UserProfile.class, id);
em.remove(profile);
em.getTransaction().commit();
}
catch(Exception e)
{
logger.error(e,operation);
if( em != null)
{
em.getTransaction().rollback();
}
throw new ConnectorException(e);
}
finally
{
if(em != null)
{
em.close();
}
}
logger.ok(operation+" Ended");
return null;
}
@Override
public List<UserProfile> getAllUser() {
EntityManager em=null;
List<UserProfile> profiles=null;
String operation="getAllUser - ";
logger.ok(operation+" Started");
try
{
em= factory.createEntityManager();
Query query= em.createQuery("Select T FROM UserProfile T ");
logger.ok(operation+" SQl "+query);
profiles= query.getResultList();
}
catch(Exception e)
{
logger.error(e,operation);
throw new ConnectorException(e);
}
finally
{
if(em != null)
{
em.close();
}
}
logger.ok(operation+" Ended ");
return profiles;
}
@Override
public List<UserProfile> getUsersByChange(Date date)
{
String operation="getUsersByChange - ";
logger.ok(operation+" Started");
EntityManager em=null;
List<UserProfile> profiles=null;
try
{
em= factory.createEntityManager();
Query query= em.createQuery("Select T FROM UserProfile T WHERE T.updateDate >= :changeDate OR T.createDate>= :createDate");
query.setParameter("changeDate", date, TemporalType.DATE);
query.setParameter("createDate", date, TemporalType.DATE);
logger.ok(operation+" Sql "+query);
profiles= query.getResultList();
}
catch(Exception e)
{
logger.error(e, operation);
throw new ConnectorException(e);
}
finally
{
if(em != null)
{
em.close();
}
}
logger.ok(operation+" Ended");
return profiles;
}
@Override
public void test()
{
if(!factory.isOpen())
{
factory=Persistence.createEntityManagerFactory(DataBaseIdentityConstants.PERSISTENCE_UNIT);
if(!factory.isOpen())
{
throw new ConnectorException("The Data Base Connection Error");
}
}
}
@Override
public List<UserProfile> findByUsersCriteria(String criteria) {
String operation="findByUsersCriteria - ";
logger.ok(operation+" Started");
EntityManager em=null;
List<UserProfile> profiles=null;
try
{
em= factory.createEntityManager();
String sql="Select T FROM UserProfile T ";
if(!criteria.equalsIgnoreCase("*"))
{
sql= sql+ " WHERE "+criteria;
}
logger.ok(operation+" sql "+sql);
Query query= em.createQuery(sql);
profiles= query.getResultList();
}
catch(Exception e)
{
logger.error(e, operation);
throw new ConnectorException(e);
}
finally
{
if(em != null)
{
em.close();
}
}
logger.ok(operation+" Ended");
return profiles;
}
}
Connector Entity
package identity.dbconnector.domain;
import java.io.Serializable;
import java.util.Date;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
@Entity
@Table(name="USR_PROF")
public class UserProfile implements Serializable {
/**
*
*/
private static final long serialVersionUID = 3582501004813497788L;
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
private Long id;
@Column(name="USR_LOGIN")
private String userLogin;
@Column(name="USR_PWD")
private String password;
@Column(name="USR_FIRST_NAME")
private String firstName;
@Column(name="USR_LAST_NAME")
private String lastName;
@Column(name="USR_MIDDLE_NAME")
private String middleName;
@Column(name="USR_STATUS")
private String status;
@Column(name="USR_CREATE_DATE")
@Temporal(TemporalType.DATE)
private Date createDate;
@Column(name="USR_LASTUPDATE")
@Temporal(TemporalType.DATE)
private Date updateDate;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getUserLogin() {
return userLogin;
}
public void setUserLogin(String userLogin) {
this.userLogin = userLogin;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public String getMiddleName() {
return middleName;
}
public void setMiddleName(String middleName) {
this.middleName = middleName;
}
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
public Date getUpdateDate() {
return updateDate;
}
public void setUpdateDate(Date updateDate) {
this.updateDate = updateDate;
}
public Date getCreateDate() {
return createDate;
}
public void setCreateDate(Date createDate) {
this.createDate = createDate;
}
}
Connector Utility
package identity.dbconnector.util;
import identity.dbconnector.DataBaseIdentityConstants;
import identity.dbconnector.domain.UserProfile;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.identityconnectors.framework.common.objects.Attribute;
import org.identityconnectors.framework.common.objects.ConnectorObject;
import org.identityconnectors.framework.common.objects.ConnectorObjectBuilder;
import sun.java2d.pipe.SpanShapeRenderer.Simple;
public class DataBaseIdentityUtil {
private static Log logger= Log.getLog(DataBaseIdentityUtil.class);
public static ConnectorObject convertMapToConnectorObject(UserProfile userProfile)
{
ConnectorObjectBuilder userObjBuilder = new ConnectorObjectBuilder();
String status=userProfile.getStatus();
if(!isEmpty(status) && status.equalsIgnoreCase(DataBaseIdentityConstants.STATUS_ENABLED))
{
userObjBuilder.addAttribute(DataBaseIdentityConstants.STATUS,DataBaseIdentityConstants.STATUS_ENABLED);
}
else
{
userObjBuilder.addAttribute(DataBaseIdentityConstants.STATUS,DataBaseIdentityConstants.STATUS_DISABLED );
}
userObjBuilder.addAttribute(DataBaseIdentityConstants.FIRST_NAME,userProfile.getFirstName());
userObjBuilder.addAttribute(DataBaseIdentityConstants.LAST_NAME,userProfile.getLastName());
userObjBuilder.addAttribute(DataBaseIdentityConstants.MIDDLE_NAME,userProfile.getMiddleName());
userObjBuilder.addAttribute(DataBaseIdentityConstants.USER_LOGIN,userProfile.getUserLogin());
userObjBuilder.setUid(Long.toString(userProfile.getId()));
userObjBuilder.setName(Long.toString(userProfile.getId()));
logger.error("Final Object Data "+userObjBuilder.toString());
ConnectorObject conobj=userObjBuilder.build();
logger.error("Final Object Data "+conobj.getAttributes());
return conobj;
}
public static ConnectorObject convertMapToConnectorObject(UserProfile userProfile,String updateFieldName)
{
ConnectorObjectBuilder userObjBuilder = new ConnectorObjectBuilder();
String status=userProfile.getStatus();
if(!isEmpty(status) && status.equalsIgnoreCase(DataBaseIdentityConstants.STATUS_ENABLED))
{
userObjBuilder.addAttribute(DataBaseIdentityConstants.STATUS,DataBaseIdentityConstants.STATUS_ENABLED);
}
else
{
userObjBuilder.addAttribute(DataBaseIdentityConstants.STATUS,DataBaseIdentityConstants.STATUS_DISABLED );
}
userObjBuilder.addAttribute(DataBaseIdentityConstants.FIRST_NAME,userProfile.getFirstName());
userObjBuilder.addAttribute(DataBaseIdentityConstants.LAST_NAME,userProfile.getLastName());
userObjBuilder.addAttribute(DataBaseIdentityConstants.MIDDLE_NAME,userProfile.getMiddleName());
userObjBuilder.addAttribute(DataBaseIdentityConstants.USER_LOGIN,userProfile.getUserLogin());
userObjBuilder.setUid(Long.toString(userProfile.getId()));
userObjBuilder.setName(Long.toString(userProfile.getId()));
if(updateFieldName != null)
{
if(updateFieldName.equalsIgnoreCase("updateDate"))
{
if(userProfile.getUpdateDate() != null)
{
userObjBuilder.addAttribute(updateFieldName,userProfile.getUpdateDate().getTime());
}
}
if (updateFieldName.equalsIgnoreCase("createDate"))
{
if(userProfile.getCreateDate() != null)
{
userObjBuilder.addAttribute(updateFieldName,userProfile.getCreateDate().getTime());
}
}
}
logger.error("Final Object Data "+userObjBuilder.toString());
ConnectorObject conobj=userObjBuilder.build();
logger.error("Final Object Data "+conobj.getAttributes());
return conobj;
}
public static boolean isEmpty(Object data)
{
boolean result= data==null;
if(!result)
{
if (data instanceof String) {
String strData = (String) data;
result=strData.trim().isEmpty();
}
}
return result;
}
public static Map<String, Object> convertSetToMap(Set<Attribute> attributes)
{
Map<String, Object> row= null;
if(attributes != null && !attributes.isEmpty())
{
row= new HashMap<String, Object>();
for (Attribute attribute : attributes)
{
List<Object> value= attribute.getValue();
if(attribute.getName().equalsIgnoreCase("__CURRENT_ATTRIBUTES__"))
{
}
/*
else if(attribute.getName().equalsIgnoreCase("__ENABLE__"))
{
addValueToMap(row, value, attribute);
String enableValue=row.get("__ENABLE__").toString();
if(enableValue.equalsIgnoreCase("true"))
{
row.put("status", "active");
}
else
{
row.put("status", "inactive");
}
row.remove("__ENABLE__");
}*/
else
{
addValueToMap(row, value, attribute);
}
}
}
return row;
}
public static UserProfile convertToUserProfile(Map<String, Object> row)
{
UserProfile profile= new UserProfile();
profile.setUserLogin(getString(row, DataBaseIdentityConstants.USER_LOGIN));
profile.setFirstName(getString(row, DataBaseIdentityConstants.FIRST_NAME));
profile.setLastName(getString(row, DataBaseIdentityConstants.LAST_NAME));
profile.setMiddleName(getString(row, DataBaseIdentityConstants.MIDDLE_NAME));
return profile;
}
public static void addValueToMap(Map<String, Object> row,List<Object> value,Attribute attribute)
{
if(isMultiValued(attribute.getValue()))
{
row.put(attribute.getName(),attribute.getValue());
}
else
{ if(isEmpty(value))
{
row.put(attribute.getName(),"");
}
else
{
row.put(attribute.getName(),value.get(0));
}
}
}
public static boolean isMultiValued(List<Object> data)
{
boolean result=false;
if(data!=null && !data.isEmpty())
{
result=data.size() >1;
}
return result;
}
public static String getString(Map<String, Object> row,String key)
{
String result="";
if(row.containsKey(key))
{
Object data=row.get(key);
if (data instanceof String)
{
result=(String)data;
}
}
return result;
}
public static String getString(Object data)
{
return data != null ? data.toString() : "";
}
public static String convertDateToString(Date date)
{
System.out.println("Requested Date "+date);
String result="";
SimpleDateFormat format= new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
result=format.format(date);
return result;
}
public static Date convertSringToDate(String date)
{
System.out.println("Conversion Requested Date "+date);
Date result=null;
SimpleDateFormat format= new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
try {
result=format.parse(date);
} catch (ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return result;
}
}
private static Log logger= Log.getLog(DataBaseIdentityUtil.class);
public static ConnectorObject convertMapToConnectorObject(UserProfile userProfile)
{
ConnectorObjectBuilder userObjBuilder = new ConnectorObjectBuilder();
String status=userProfile.getStatus();
if(!isEmpty(status) && status.equalsIgnoreCase(DataBaseIdentityConstants.STATUS_ENABLED))
{
userObjBuilder.addAttribute(DataBaseIdentityConstants.STATUS,DataBaseIdentityConstants.STATUS_ENABLED);
}
else
{
userObjBuilder.addAttribute(DataBaseIdentityConstants.STATUS,DataBaseIdentityConstants.STATUS_DISABLED );
}
userObjBuilder.addAttribute(DataBaseIdentityConstants.FIRST_NAME,userProfile.getFirstName());
userObjBuilder.addAttribute(DataBaseIdentityConstants.LAST_NAME,userProfile.getLastName());
userObjBuilder.addAttribute(DataBaseIdentityConstants.MIDDLE_NAME,userProfile.getMiddleName());
userObjBuilder.addAttribute(DataBaseIdentityConstants.USER_LOGIN,userProfile.getUserLogin());
userObjBuilder.setUid(Long.toString(userProfile.getId()));
userObjBuilder.setName(Long.toString(userProfile.getId()));
logger.error("Final Object Data "+userObjBuilder.toString());
ConnectorObject conobj=userObjBuilder.build();
logger.error("Final Object Data "+conobj.getAttributes());
return conobj;
}
public static ConnectorObject convertMapToConnectorObject(UserProfile userProfile,String updateFieldName)
{
ConnectorObjectBuilder userObjBuilder = new ConnectorObjectBuilder();
String status=userProfile.getStatus();
if(!isEmpty(status) && status.equalsIgnoreCase(DataBaseIdentityConstants.STATUS_ENABLED))
{
userObjBuilder.addAttribute(DataBaseIdentityConstants.STATUS,DataBaseIdentityConstants.STATUS_ENABLED);
}
else
{
userObjBuilder.addAttribute(DataBaseIdentityConstants.STATUS,DataBaseIdentityConstants.STATUS_DISABLED );
}
userObjBuilder.addAttribute(DataBaseIdentityConstants.FIRST_NAME,userProfile.getFirstName());
userObjBuilder.addAttribute(DataBaseIdentityConstants.LAST_NAME,userProfile.getLastName());
userObjBuilder.addAttribute(DataBaseIdentityConstants.MIDDLE_NAME,userProfile.getMiddleName());
userObjBuilder.addAttribute(DataBaseIdentityConstants.USER_LOGIN,userProfile.getUserLogin());
userObjBuilder.setUid(Long.toString(userProfile.getId()));
userObjBuilder.setName(Long.toString(userProfile.getId()));
if(updateFieldName != null)
{
if(updateFieldName.equalsIgnoreCase("updateDate"))
{
if(userProfile.getUpdateDate() != null)
{
userObjBuilder.addAttribute(updateFieldName,userProfile.getUpdateDate().getTime());
}
}
if (updateFieldName.equalsIgnoreCase("createDate"))
{
if(userProfile.getCreateDate() != null)
{
userObjBuilder.addAttribute(updateFieldName,userProfile.getCreateDate().getTime());
}
}
}
logger.error("Final Object Data "+userObjBuilder.toString());
ConnectorObject conobj=userObjBuilder.build();
logger.error("Final Object Data "+conobj.getAttributes());
return conobj;
}
public static boolean isEmpty(Object data)
{
boolean result= data==null;
if(!result)
{
if (data instanceof String) {
String strData = (String) data;
result=strData.trim().isEmpty();
}
}
return result;
}
public static Map<String, Object> convertSetToMap(Set<Attribute> attributes)
{
Map<String, Object> row= null;
if(attributes != null && !attributes.isEmpty())
{
row= new HashMap<String, Object>();
for (Attribute attribute : attributes)
{
List<Object> value= attribute.getValue();
if(attribute.getName().equalsIgnoreCase("__CURRENT_ATTRIBUTES__"))
{
}
/*
else if(attribute.getName().equalsIgnoreCase("__ENABLE__"))
{
addValueToMap(row, value, attribute);
String enableValue=row.get("__ENABLE__").toString();
if(enableValue.equalsIgnoreCase("true"))
{
row.put("status", "active");
}
else
{
row.put("status", "inactive");
}
row.remove("__ENABLE__");
}*/
else
{
addValueToMap(row, value, attribute);
}
}
}
return row;
}
public static UserProfile convertToUserProfile(Map<String, Object> row)
{
UserProfile profile= new UserProfile();
profile.setUserLogin(getString(row, DataBaseIdentityConstants.USER_LOGIN));
profile.setFirstName(getString(row, DataBaseIdentityConstants.FIRST_NAME));
profile.setLastName(getString(row, DataBaseIdentityConstants.LAST_NAME));
profile.setMiddleName(getString(row, DataBaseIdentityConstants.MIDDLE_NAME));
return profile;
}
public static void addValueToMap(Map<String, Object> row,List<Object> value,Attribute attribute)
{
if(isMultiValued(attribute.getValue()))
{
row.put(attribute.getName(),attribute.getValue());
}
else
{ if(isEmpty(value))
{
row.put(attribute.getName(),"");
}
else
{
row.put(attribute.getName(),value.get(0));
}
}
}
public static boolean isMultiValued(List<Object> data)
{
boolean result=false;
if(data!=null && !data.isEmpty())
{
result=data.size() >1;
}
return result;
}
public static String getString(Map<String, Object> row,String key)
{
String result="";
if(row.containsKey(key))
{
Object data=row.get(key);
if (data instanceof String)
{
result=(String)data;
}
}
return result;
}
public static String getString(Object data)
{
return data != null ? data.toString() : "";
}
public static String convertDateToString(Date date)
{
System.out.println("Requested Date "+date);
String result="";
SimpleDateFormat format= new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
result=format.format(date);
return result;
}
public static Date convertSringToDate(String date)
{
System.out.println("Conversion Requested Date "+date);
Date result=null;
SimpleDateFormat format= new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
try {
result=format.parse(date);
} catch (ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return result;
}
}
Connector Resources
Create the following files in the src/main/resources directory.1. Messages.properties
This property file storing the config property labels and also connector display name key.
create a file Messages.properties in the identity.dbconnector directory and add the following content in the file.
driver_display=Jdbc Driver Name
driver_help=Jdbc Driver Name
url_display=Jdbc URL
url_help=Jdbc URL Format
userName_display=Jdbc User Name
userName_help=Jdbc User Name
password_display=Jdbc User Password
password_help=Jdbc User Password
environment_display=Data Source Environment
environment_help=Data Source Environment
displayName=Database Identity Connector
2. persistence.xml
create a file persistence.xml in the META-INF directory.
<?xml version="1.0" encoding="UTF-8" ?>
<persistence xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_1.xsd"
version="2.1" xmlns="http://java.sun.com/xml/ns/persistence">
<persistence-unit name="databaseconnector" transaction-type="RESOURCE_LOCAL">
<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
<non-jta-data-source>mydatasource</non-jta-data-source>
<jta-data-source>mydatasource</jta-data-source>
<class>identity.dbconnector.domain.UserProfile</class>
<properties>
<property name="eclipselink.ddl-generation.output-mode" value="database"/>
</properties>
</persistence-unit>
</persistence>
Deploying the ICF connector in OIM
Build the Jar File
Execute the following command to build and generate the dbconnector-demo-1.0.jar.
gradle build
Deploy the Jar File
1. Login to the OIM Server.
2. Go to the DOMAIN_HOME/bin directory and execute source ./setDomainEnv.sh file. After executing the file , it will set the classpath.
3. Go to the OIM_HOME/server/bin directory an execute the
UploadJars.sh [-username <username>] [-password <password>] [-serverURL <t3://oimhostname:oimportno>] [-ctxFactory <weblogic.jndi.WLInitialContextFactory>] [- [-ICFBundle <Location of the ICF Bundle Jar>]
It will deploy the ICFBundle into the OIM repository.
Nice article with a good example, bookmarked! Thank you very much.
ReplyDeleteIt would be great if you use some add-on to show better the code.
ReplyDeleteHi
ReplyDeleteThanks for your comment.
What kind of add-on are you looking?. Please let me know in detail and I can provide what you need in this blog and it will be useful to every one.
Thanks
IDMOIM
Hello, I can see that the init DataSource method, only ask for a environment when is set to "local" what about if I want to use "remote" for use a jndi context in the server, How can I configure it for this case.
ReplyDeleteThanks for your help.
Regards.
Hi,
DeleteThe following ways you can initialize the remote data source for weblogic:
1. Create the Hashtable Object
Hashtable environment= new Hashtable();
2. Setting the System Properties in the Hash Table Object:
environment.put(InitialContext.INITIAL_CONTEXT_FACTORY, "weblogic.jndi.WLInitialContextFactory");
environment.put(InitialContext.PROVIDER_URL, "t3s://:Port");
3. Initialize the InitialContext Object
InitialContext context = new InitialContext(environment);
4. Accessing the Data Source
DataSource ds = (DataSource)context.lookup("")
Note: the weblogic.jar file should be exist in the class path to execute initialcontext object.
Please let me know if you need more help
Ok thanks again.
DeleteWhen you call handle method in the "executeQuery()" you print the Attribute Objects before and after call "handle()" method.
ReplyDeleteDid you expect that those Attribute Objects change with "handle()" method ?
And if yes this change triggers the ReconEvent ?
Many thanks.
Regards.
Accordingly to this its true that I ask
Deletehttp://www.gliffy.com/publish/2762204/
Hi
DeleteYour right.
Reconciliation events are triggered by OIM ICF Framework. If you don't want to trigger ICF framework reconciliation, you can write custom code to invoke the OIM Connector executeQuery method and Create the Reconciliation Events.
Please let me know if you need more help.
Hi again, can I use the same code that you put in this blog for trusted reconciliation ? And what change in the OIM metadata or SchedullerTask when the resource is trusted.
ReplyDeleteThanks and regards.
Hi,
ReplyDeleteYou need to build the OIM metadata for Trusted Reconciliation as follows:
1. IT Resource Object
2. Connector Lookup Configuration
3. User Configuration Lookup
4. Reconciliation Lookup Field Mapping
5. Resource Object with Trusted Source Option
6. Process Definition
7. Reconciliation Rules
Please let me know if you need more assistance.
Ok but the source code is the same ? and Do I need to put a new Lookup like "Default LookUp" 12.3.5 Optional Defaults Lookup: http://docs.oracle.com/cd/E27559_01/dev.1112/e27150/icf_integration.htm#BABICECE
ReplyDeleteRegards.
HI,
ReplyDeleteYou can assign a default value as follows:
1. Create a Default value lookup and add the lookup entry in the Configuration Lookup to assign the value.
2. Create a Pre-Process Event Handler and assign the default values programmatically to the OIM User
Please let me know if you need more assistance.
I have another question if I want to execute another task (write the user ID in a file or something else) after the user is provisioned by OOTB OUD Connector, I think that need a Post Process Event Handler for do that, but how can we integrate it with the OOTB OUD Connector ?
ReplyDeleteHi Hiroshige,
ReplyDeleteYou can achieve storing the user names after provisioning the user into the target system as follows:
1. Create a Java Task and incorporate your logic store the user names into a file or data base.
2. Create the Task definition in Connector Process Task Definition.
3. Map the newly created task definition in Create User Success Response.
4. After mapping the newly created task into the create user response, it will invoke the newly created task and store the user names into data base or file based on your logic.
Please let me know if you need more info.
Thanks
Ameer Basha
Hi,
ReplyDeleteFirst of all a lot of thanks for posting this much detail information.
In your blog the last task was :
Deploy the Jar File
1. Login to the OIM Server.
2. Go to the DOMAIN_HOME/bin directory and execute source ./setDomainEnv.sh file. After executing the file , it will set the classpath.
3. Go to the OIM_HOME/server/bin directory an execute the
UploadJars.sh [-username ] [-password ] [-serverURL ] [-ctxFactory ] [- [-ICFBundle ]
It will deploy the ICFBundle into the OIM repository.
My Question is where this jar/class get deployed? in OIM database or any location on the server?
Thanks
Shant
Hi,
ReplyDeleteFirst of all a lot of thanks for posting this much detail information.
In your blog the last task was :
Deploy the Jar File
1. Login to the OIM Server.
2. Go to the DOMAIN_HOME/bin directory and execute source ./setDomainEnv.sh file. After executing the file , it will set the classpath.
3. Go to the OIM_HOME/server/bin directory an execute the
UploadJars.sh [-username ] [-password ] [-serverURL ] [-ctxFactory ] [- [-ICFBundle ]
It will deploy the ICFBundle into the OIM repository.
My Question is where this jar/class get deployed? in OIM database or any location on the server?
Thanks
Shant
Hi Shant,
DeleteThe uploaded jar files are stored in the database OIM Schema and the table name is OIMHOME_JARS.
Please let me know if you need any help.
Can you please explain when do we need to use this custom ICF implementation rather than Database Application Tables(DBAT) Connector?
ReplyDeleteCan we use ICF conenctor to run powershell script to create shared mailbox in Exchange 2010?
ReplyDeleteHi,thanks for posting this much detail information.if possible, please post the detail information for MongoDB ICF connector.
ReplyDeleteHello,
ReplyDeleteThanks for the detailed post.
How do we implement the child table insert/update,which API gets triggered on insert/update/delete? Is it addAttriuteValues()/removeAttributeValues of UpdateAttriuteVlauesOP interface?
thanks for this usefull article, waiting for this article like this again. ICF Materials
ReplyDelete