Using Connectors

How do I access the connector API?

It's available through the ConnectorFacade class. An application should do all its interaction with a Connector via an instance of ConnectorFacade.

How do I create a ConnectorFacade?

  1. Create a ConnectorInfoManager and a ConnectorKey for the connector.
  2. Using the manager and the key, create a ConnectorInfo instance.
  3. From the ConnectorInfo object, create the default !APIConfiguration.
  4. From the default !APIConfiguration, retrieve the ConfigurationProperties.
  5. Set all of the ConfigurationProperties needed by the connector using !setPropertyValue().
  6. Use the ConnectorFacadeFactory's !newInstance() method to create a new instance of the connector.

Here is an example:

    // Use the ConnectorInfoManager to retrieve a ConnectorInfo object for the connector 
   
ConnectorInfoManagerFactory fact = ConnectorInfoManagerFactory.getInstance();
   
File bundleDirectory = new File("/connectorDir/bundles/foobar");      
    URL url
= IOUtil.makeURL(bundleDirectory, "/dist/org.identityconnectors.foobar-1.0.jar");        
   
ConnectorInfoManager manager = fact.getLocalManager(url);
   
ConnectorKey key = new ConnectorKey("org.identityconnectors.foobar", "1.0", "FooBarConnector");      
   
ConnectorInfo info = manager.findConnectorInfo(key);

   
// From the ConnectorInfo object, create the default APIConfiguration.
   
APIConfiguration apiConfig = info.createDefaultAPIConfiguration();

   
// From the default APIConfiguration, retrieve the ConfigurationProperties.
   
ConfigurationProperties properties = apiConfig.getConfigurationProperties();
       
   
// Print out what the properties are (not necessary)
   
List propertyNames = properties.getPropertyNames();
   
for(String propName : propertyNames) {
       
ConfigurationProperty prop = properties.getProperty(propName);
       
System.out.println("Property Name: " + prop.getName() + "\tProperty Type: " + prop.getType());
   
}

   
// Set all of the ConfigurationProperties needed by the connector.
    properties
.setPropertyValue("host", FOOBAR_HOST);
    properties
.setPropertyValue("adminName", FOOBAR_ADMIN);
    properties
.setPropertyValue("adminPassword", FOOBAR_PASSWORD);
    properties
.setPropertyValue("useSSL", false);

   
// Use the ConnectorFacadeFactory's newInstance() method to get a new connector.
   
ConnectorFacade conn = ConnectorFacadeFactory.getInstance().newInstance(apiConfig);

   
// Make sure we have set up the Configuration properly
    conn
.validate();

   
// Start using the Connector
    conn
.[authenticate|create|update|delete|search|...]

How do I determine if the connector supports an operation?

Check the set returned by ConnectorFacade.getSupportedOperations(). For example:

    Set<Class< ? extends APIOperation>> ops = conn.getSupportedOperations();
   
// check to see if the set contains the operation you care about (e.g. CreateApiOp)
   
return ops.contains(CreateApiOp.class);

However, a connector may support an operation for only certain object classes. Therefore, it is more correct to check the schema to determine if the desired operation is supported for the specific ObjectClass you're specifying:

    Schema schema = conn.schema();
   
Set<ObjectClassInfo> objectClasses = schema.getObjectClassInfo();      
   
Set<ObjectClassInfo> ocinfos = schema.getSupportedObjectClassesByOperation(CreateApiOp.class);

   
for(ObjectClassInfo oci : objectClasses) {
       
// check the object class is supported for the operation
       
if (ocinfos.contains(ocinfo)) {
           
// object class is supported
       
}
   
}    

How do I determine what attributes are supported or required for a particular ObjectClass?

Get the schema from the connector facade. From the schema, get the set of object class infos. From there, look for the ObjectClassInfo belonging to the ObjectClass of the object you want the attributes from. From that ObjectClassInfo, get the set of AttributeInfos. Each AttributeInfo can be used to get the attribute name, attribute type, if it's required, if it's readable, writeable, etc.

    Schema schema = conn.schema();
   
Set objectClasses = schema.getObjectClassInfo();
   
for(ObjectClassInfo oci : objectClasses) {
       
Set attributeInfos = oci.getAttributeInfo();
       
String type = oci.getType();
       
if(ObjectClass.ACCOUNT_NAME.equals(type)) {
           
for(AttributeInfo info : attributeInfos) {
               
System.out.println(info.toString());
           
}
       
}......
       
........                
   
}

How do I create a new ConnectorObject (account, group, record, etc.)?

To create a connector object, you must call the create() method of the connector facade. You should probably check to make sure that Create() is supported for the ObjectClass you would like to create. The Create method takes two parameters: an ObjectClass and a set of Attributes. The ObjectClass specifies what type of ConnectorObject to create on the target resource. The attributes describe the ConnectorObject (things such as username, password, address, etc.) These must be attributes that the connector supports for this type of ObjectClass. This can be checked via the schema. For example:

    // .......
   
// set up ConnectorFacade
   
// .......

   
//create an account
   
Set attrs = new HashSet();
    attrs
.add(new Name("TESTUSER"));
    attrs
.add(AttributeBuilder.buildPassword("TESTPASSWORD"));
    attrs
.add(AttributeBuilder.build("Company", "Tirasa"));
   
Uid userUid = conn.create(ObjectClass.ACCOUNT, attrs);

How do I update an account's password using a Connector?

Password is one of several special Attributes called OperationalAttributes. In the same way you create an account, to change a password (or perform any kind of update) you need to set up a bag of Attributes using AttributeBuilder and add the new password to it. OperationalAttributes such as Password and Enabled are created via static methods in AttributeBuilder (see the example below). Then invoke the Update() method on the ConnectorFacade.

    // .......
   
// set up ConnectorFacade
   
// .......

   
//create an account
   
Set attrs = new HashSet();
    attrs
.add(new Name("TESTUSER"));
    attrs
.add(AttributeBuilder.buildPassword("NEWPASSWORD"));
   
Uid userUid = conn.update(ObjectClass.ACCOUNT, attrs);

How do I delete a ConnectorObject?

To delete a connector object, you need to know the ObjectClass of the object you want to delete, as well as its Uid. If you don't have the Uid, you can search for it (if the connector supports SearchOp) using what you do know, such as the username. Here's an example:

    // .......
   
// set up ConnectorFacade
   
// .......
   
Uid userUid = findUid(userName);
    conn
.delete(ObjectClass.ACCOUNT, userUid);

How do I search for ConnectorObjects?

You must first create a search Filter and a ResultsHandler. Then use the ConnectorFacade's Search() method (if SearchOp is supported) to search. The results will be returned to the handler. You can build the filter using regular or "special" attributes, but they must be valid according to the schema for that Connector. Here is an example using a compound filter:

    // .......
   
// set up ConnectorFacade
   
// .......

   
Filter leftFilter = FilterBuilder.equalTo(AttributeBuilder.build("FIRSTNAME", "John"));
   
Filter rightFilter = FilterBuilder.equalTo(AttributeBuilder.build("DEPARTMENT", "Marketing"));
   
Filter filter = FilterBuilder.and(leftFilter, rightFilter);
   
final List results = new ArrayList();
   
ResultsHandler handler = new ResultsHandler() {
       
public boolean handle(ConnectorObject obj) {
            results
.add(obj);
           
return true;
       
}
   
};

    conn
.search(ObjectClass.ACCOUNT, filter, handler);      
   
for(ConnectorObject obj : results ) {
       
System.out.println("Name: " + obj.getName() + "\tUID: " + obj.getUid());
   
}

Here is an example with special attributes:

    Filter nameFilter = FilterBuilder.startsWith(new Name("Josh")); //same as AttributeBuilder.build(Name.NAME, "Josh")
   
Filter enabledFilter = FilterBuilder.equalTo(AttributeBuilder.buildEnabled(false)); //find accounts that are disabled
   
Filter filter = FilterBuilder.or(nameFilter, enabledFilter); //compound OR filter
   
final List results = new ArrayList();
   
ResultsHandler handler = new ResultsHandler() {
       
public boolean handle(ConnectorObject obj) {
            results
.add(obj);
           
return true;
       
}
   
};
   
    conn
.search(ObjectClass.ACCOUNT, filter, handler);      
   
for(ConnectorObject obj : results ) {
       
System.out.println("Name: " + obj.getName() + "\tUID: " + obj.getUid());
   
} 

How do I get an ObjectClass when I have an ObjectClassInfo?

Just pass the ObjectClassInfo type to the ObjectClass constructor, as follows:

    ObjectClass objectClass = new ObjectClass(objectClassInfo.getType());