/*******************************************************************************
$Source: /cvs/repositories/openii3/project/java/examples/org/any_openeai_enterprise/gateways/directoryservice/BasicPersonSyncCommand.java,v $
$Revision: 1.8 $
*******************************************************************************/
/**********************************************************************
This file is part of the OpenEAI sample, reference implementation,
and deployment management suite created by Tod Jackson
(tod@openeai.org) and Steve Wheat (steve@openeai.org) at
the University of Illinois Urbana-Champaign.
Copyright (C) 2004 The OpenEAI Software Foundation
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
For specific licensing details and examples of how this software
can be used to implement integrations for your enterprise, visit
http://www.OpenEai.org/licensing.
*/
package org.any_openeai_enterprise.gateways.directoryservice;
// Core Java
import java.util.ArrayList;
import java.util.ListIterator;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.naming.directory.Attribute;
import javax.naming.directory.DirContext;
import javax.naming.directory.SearchControls;
import javax.naming.directory.SearchResult;
import org.jdom.Document;
import org.jdom.Element;
import org.openeai.config.CommandConfig;
import org.openeai.config.EnterpriseConfigurationObjectException;
import org.openeai.layouts.EnterpriseLayoutException;
import org.openeai.moa.objects.resources.Error;
import com.any_erp_vendor.moa.jmsobjects.person.v1_0.BasicPerson;
/**
* This command handles BasicPerson.Update-Sync messages to apply changes to
* person data to the LDAP directory server.
* <P>
*
*/
public class BasicPersonSyncCommand extends DirectoryServiceBase {
/**
* Constructor
*/
public BasicPersonSyncCommand(CommandConfig cConfig) throws InstantiationException {
super(cConfig);
// Get the value of the publishErrorsForMissingEntries property.
if (getProperties().getProperty("publishErrorsForMissingEntries", "false").equalsIgnoreCase("true")) {
setPublishErrorsForMissingEntries(true);
}
logger.info("[" + getServiceName() + "] The value of " + "publishErrorsForMissingEntries is: " +
getPublishErrorsForMissingEntries());
// Verify that all message objects required are in AppConfig.
try {
BasicPerson person = (BasicPerson)getAppConfig().getObject("BasicPerson");
}
catch (EnterpriseConfigurationObjectException eoce) {
// An error occurred retrieving a required object from AppConfig. Log it
// and throw an exception.
String errMsg = "An error occurred retrieving a required object from " +
"AppConfig. The exception is: " + eoce.getMessage();
logger.fatal("[" + getServiceName() + "] " + errMsg);
throw new InstantiationException(errMsg);
}
// Get an initial context to the directory server.
try {
DirContext dirCtx = getInitialContext(getProperties());
setDirContext(dirCtx);
}
catch (NamingException ne) {
String errMsg = "Error creating initial context. The exception is: " +
ne.getMessage();
logger.fatal("[" + getServiceName() + "] " + errMsg);
throw new InstantiationException(errMsg);
}
logger.info("[" + getServiceName() + "] instantiated successfully.");
}
public void execute(int messageNumber, Message aMessage) {
ArrayList errors = new ArrayList();
// Create the input document from the JMS message passed in.
Document inDoc = null;
try { inDoc = initializeInput(messageNumber, aMessage); }
catch (JMSException jmse) {
// An error occurred creating the input document from the JMS message
// passed in. Log it and publish a sync error.
publishError ("system", "OpenEAI-2101", "An error occurred creating the input " +
"document from the JMS message passed in. The exception is: " +
jmse.getMessage(), "[" + getServiceName() + ".execute]", jmse);
return;
}
// Get the message metadata.
eControlArea = getControlArea(inDoc.getRootElement());
String messageCategory = eControlArea.getAttribute("messageCategory").getValue();
String messageObject = eControlArea.getAttribute("messageObject").getValue();
String messageRelease = eControlArea.getAttribute("messageRelease").getValue();
String messageAction = eControlArea.getAttribute("messageAction").getValue();
String messageType = eControlArea.getAttribute("messageType").getValue();
logger.info("[" + getServiceName() + ".execute] Received a(n) " +
messageCategory + "." + messageObject + "." + messageAction + "-" +
messageType + " (release " + messageRelease + ") message.");
// Verify that this is a message we support.
if (messageObject.equalsIgnoreCase("BasicPerson") == false) {
Error error = new Error();
error.setType("application");
error.setErrorNumber("OpenEAI-1002");
error.setErrorDescription("Message object '" + messageObject +
"' is not supported.");
errors.add(error);
}
if (messageType.equalsIgnoreCase("Sync") == false) {
Error error = new Error();
error.setType("application");
error.setErrorNumber("OpenEAI-1002");
error.setErrorDescription("Message type '" + messageType + "' is not " +
"supported.");
errors.add(error);
}
if (errors.size() > 0) {
ListIterator iterator = errors.listIterator();
while (iterator.hasNext()) {
Error error = (Error)iterator.next();
logger.fatal("[" + getServiceName() + ".execute] " +
error.getErrorDescription());
}
publishSyncError(eControlArea, errors);
return;
}
// Get two configured BasicPerson objects from AppConfig.
BasicPerson currentBasicPerson = null;
BasicPerson newBasicPerson = null;
try {
currentBasicPerson = (BasicPerson)getAppConfig().getObject("BasicPerson");
newBasicPerson = (BasicPerson)getAppConfig().getObject("BasicPerson");
}
catch (EnterpriseConfigurationObjectException ecoe) {
// An error occurred getting an object from AppConfig. Log it and
// publish a sync error message.
publishError ("application", "OpenEAI-3001", "An error occurred getting an object from " +
"AppConfig. the exception is: " + ecoe.getMessage(), "[" + getServiceName() + ".execute] ", ecoe);
return;
}
// Handle a BasicPerson.Update-Sync
if (messageAction.equalsIgnoreCase("Update")) {
// Get the baseline state of the BasicPerson and build a BasicPerson
// object.
Element eBaselinePerson = inDoc.getRootElement().getChild("DataArea")
.getChild("BaselineData").getChild("BasicPerson");
try {
currentBasicPerson.buildObjectFromInput(eBaselinePerson);
}
catch (EnterpriseLayoutException ele) {
// An error occurred building the BasicPerson object from the
// BasicPerson element contained in the BaselineData element of the
// message. Log it and publish a sync error message.
publishError ("system", "DirectoryServiceGateway-1001", "An error occurred building the BasicPerson "
+ "object from the BasicPerson element contained in the " +
"BaselineData element of the message. The exception is: " +
ele.getMessage(), "[" + getServiceName() + ".execute] ", ele);
return;
}
String institutionalID = currentBasicPerson.getInstitutionalId();
// Find out of the person exists in the directory. Update can only
// work on existing persons
if (!personExists ("employeeNumber", institutionalID))
{
publishError ("system", "DirectoryServiceGateway-1008", "Person with InstitutionalID \"" +
institutionalID + "\" does not exist in the directory. Update only possible with " +
"existing persons.", "[" + getServiceName() + ".execute] ");
return;
}
// Get the new state of the BasicPerson and build a BasicPerson
// object.
Element eNewPerson = inDoc.getRootElement().getChild("DataArea").getChild("NewData").getChild("BasicPerson");
try {
newBasicPerson.buildObjectFromInput(eNewPerson);
}
catch (EnterpriseLayoutException ele) {
// An error occurred building the BasicPerson object from thw
// BasicPerson element contained in the NewData element of
// the message. Log it and publish a sync error message.
publishError ("system", "DirectoryServiceGateway-1002", "An error occurred building the " +
"BasicPerson object from the BasicPerson element contained in " +
"the NewData element of the message. The exception is: " +
ele.getMessage(), "[" + getServiceName() + ".execute] ", ele);
return;
}
// Determine whether the user exists is the directory server.
String userName = "";
if (currentBasicPerson.getName() != null)
userName = currentBasicPerson.getName().getFirstName() + " " + currentBasicPerson.getName().getLastName();
logger.debug("[" + getServiceName() + ".execute] Querying the directory to "
+ "see if this person already exists in the directory.");
// Specify the search filter for the directory service query using
// the uniqueMember and the uniquePermission built above.
String filter = "employeeNumber=" + institutionalID;
logger.debug("[" + getServiceName() + ".execute] Search filter is: " + filter);
// Specify the providerUrl.
String providerUrl = getUserDirectoryTreeBase();
logger.debug("[" + getServiceName() + ".execute] providerUrl is: " + providerUrl);
// Specify search controls that set the scope of the search.
SearchControls cons = new SearchControls();
cons.setSearchScope(SearchControls.ONELEVEL_SCOPE);
String[] attrs = new String[7];
attrs[0] = "uid";
attrs[1] = "cn";
attrs[2] = "telephoneNumber";
attrs[3] = "mail";
attrs[4] = "homePhone";
attrs[5] = "mobile";
attrs[6] = "displayName";
cons.setReturningAttributes(attrs);
// Search for user entries that match the employeeNumber, retrieving
// the uid.
try {
logger.debug("[" + getServiceName() + ".execute] Querying the directory "
+ "server.");
NamingEnumeration results = getDirContext().search(providerUrl, filter,
cons);
// If there are no matching entries and the
// publishErrorsForMissingEntries property is true, publish a error
// message indicating that the user does not exist. Otherwise, log the
// fact that the user does not exist and return.
if (results == null || results.hasMore() == false) {
if (getPublishErrorsForMissingEntries() == true) {
// --- Publish the sync error.
publishError ("application", "DirectoryServiceGateway-1003", "No user " + userName + "(" +
currentBasicPerson.getInstitutionalId() + ") exists in the " +
"directory. Cannot modify attributes for this user.", "[" + getServiceName() + ".execute] ");
return;
}
else {
// --- Just log it.
logger.info("[" + getServiceName() + ".execute] No user " + userName +
"(" + currentBasicPerson.getInstitutionalId() + ") exists in " +
"the directory. Cannot modify attributes for this user.");
return;
}
}
// Otherwise, the user already exists in the directory.
else {
// Get the uid and cn for the user.
SearchResult sr = (SearchResult)results.next();
String uid = (String)sr.getAttributes().get("uid").get();
String currentName = (String)sr.getAttributes().get("cn").get();
Attribute dispName = sr.getAttributes().get("displayName");
String currentDisplayName = "";
if (dispName != null)
currentDisplayName = (String)dispName.get();
// Determine whether the user's name has changed.
boolean isNameChanged = false;
String newName = newBasicPerson.getName().getLastName();
String newDisplayName = newName;
if (newBasicPerson.getName().getFirstName() != null)
{
newName = newBasicPerson.getName().getFirstName() + " " + newName;
String newMiddleName = newBasicPerson.getName().getMiddleName();
if (newMiddleName != null && newMiddleName.length() > 0)
{
newDisplayName = newBasicPerson.getName().getFirstName() + " " + newBasicPerson.getName().getMiddleName().charAt(0) + ". " + newBasicPerson.getName().getLastName();
}
else
newDisplayName = newName;
}
if (currentName.equals(newName) == false || currentDisplayName.equals(newDisplayName) == false)
isNameChanged = true;
// If the name has changed, update the given name, surname, and
// common name in the user's directory entry. Otherwise, log the
// fact that the names are the same and no change is required and
// return.
if (isNameChanged == true) {
logger.info("[" + getServiceName() + ".execute] The current name " +
"of the user ('" + currentName + "') and the new name ('" + newName +
"') are not the same.");
updateName (uid, newBasicPerson.getName().getFirstName(), newBasicPerson.getName().getLastName(), newBasicPerson.getName().getMiddleName());
}
// (As mentioned above...otherwise, log the fact that the names are
// the same and no change is required and return.)
else {
logger.info("[" + getServiceName() + ".execute] The current name " +
"of the user ('" + currentName + "') and the new name ('" +
newName + "') are the same, so no update of the name in the " +
"directory is required.");
}
// Determine whether any of the user's phone numbers have changed.
// boolean isPhoneChanged = false;
boolean hasHome = false;
boolean isHomeChanged = false;
boolean hasOffice = false;
boolean isOfficeChanged = false;
boolean hasMobile = false;
boolean isMobileChanged = false;
String currentPhone = null;
String newPhone = null;
String type = null;
//check to see if data area contains a phone number
//else delete all phone numbers from directory if none found
if(newBasicPerson.getPhone().isEmpty() == false){
//Determine what phone types are present in newBasicPerson
for (int i =0; i < newBasicPerson.getPhone().size(); i++){
newPhone = newBasicPerson.getPhone(i).getPhoneNumber();
newPhone = newBasicPerson.getPhone(i).getPhoneArea() + "-" + newPhone;
if(newBasicPerson.getPhone(i).getType().equalsIgnoreCase("home"))
hasHome = true;
if(newBasicPerson.getPhone(i).getType().equalsIgnoreCase("office"))
hasOffice = true;
if(newBasicPerson.getPhone(i).getType().equalsIgnoreCase("mobile"))
hasMobile = true;
}
//Check each phone type for changes
for (int i =0; i < newBasicPerson.getPhone().size(); i++){
currentPhone = null;
// isPhoneChanged = false;
newPhone = newBasicPerson.getPhone(i).getPhoneNumber();
newPhone = newBasicPerson.getPhone(i).getPhoneArea() + "-" + newPhone;
if(hasHome == true && newBasicPerson.getPhone(i).getType().equalsIgnoreCase("home")){
type = "homePhone";
if(sr.getAttributes().get(type) != null)
currentPhone = (String) sr.getAttributes().get(type).get();
if(newPhone.equals(currentPhone) == false){
isHomeChanged = true;
updatePhone(uid, newPhone, type);
}
}
else {
type = "homePhone";
if(hasHome == false && (sr.getAttributes().get(type) != null) && isHomeChanged != true){
deletePhone(uid, type);
isHomeChanged = true;
}
}
if(hasOffice == true && newBasicPerson.getPhone(i).getType().equalsIgnoreCase("office")){
//compare newPhone to currentPhone
type = "telephoneNumber";
if(sr.getAttributes().get(type) != null)
currentPhone = (String) sr.getAttributes().get(type).get();
if(newPhone.equals(currentPhone) == false){
isOfficeChanged = true;
updatePhone(uid, newPhone, type);
}
}
else {
type = "telephoneNumber";
if(hasOffice == false && (sr.getAttributes().get(type) != null) && isOfficeChanged != true){
deletePhone(uid, type);
isOfficeChanged = true;
}
}
if(hasMobile == true && newBasicPerson.getPhone(i).getType().equalsIgnoreCase("mobile")){
//compare newPhone to currentPhone
type = "mobile";
if(sr.getAttributes().get(type) != null)
currentPhone = (String) sr.getAttributes().get(type).get();
if(newPhone.equals(currentPhone) == false){
isMobileChanged = true;
updatePhone(uid, newPhone, type);
}
}
else {
type = "mobile";
if(hasMobile == false && (sr.getAttributes().get(type) != null) && isMobileChanged != true){
deletePhone(uid, type);
isMobileChanged = true;
}
}
// create an info message stating which phone number have not changed.
String outputType = " ";
if(newBasicPerson.getPhone(i).getType().equalsIgnoreCase("office") && isOfficeChanged == false){
outputType = "office";
logger.info("[" + getServiceName() + ".execute] The current " + outputType + " phone " +
"has not changed, so no update of the " + outputType + " phone in the directory is required.");
}
if(newBasicPerson.getPhone(i).getType().equalsIgnoreCase("home") && isHomeChanged == false){
outputType = "home";
logger.info("[" + getServiceName() + ".execute] The current " + outputType + " phone " +
"has not changed, so no update of the " + outputType + " phone in the directory is required.");
}
if(newBasicPerson.getPhone(i).getType().equalsIgnoreCase("mobile") && isMobileChanged == false){
outputType = "mobile";
logger.info("[" + getServiceName() + ".execute] The current " + outputType + " phone " +
"has not changed, so no update of the " + outputType + " phone in the directory is required.");
}
}
}
else{
// newBasicPerson has no phone numbers
// if search returns any phone numbers,
// delete phone number in DSG repository.
// Assume user intends to delete phone numbers
String[] checkType = { "homePhone", "telephoneNumber", "mobile" };
for (int i = 0; i < checkType.length; i++){
if (sr.getAttributes().get(checkType[i]) != null){
deletePhone(uid, checkType[i]);
}
}
}
/************************************************************************************************************/
// Determine whether any of the user's email addresses have changed.
boolean isPerferred = false;
String currentEmail = null;
String newEmail = null;
//check to see if data area contains an email address
//else delete email address from directory if found
if(newBasicPerson.getEmail().isEmpty() == false){
//Determine if any of the emails is a perferred email to use to check if update is required
//directory should store the preferred email if available
for (int i =0; i < newBasicPerson.getEmail().size(); i++){
if(newBasicPerson.getEmail(i).getPreferred().equalsIgnoreCase("yes")){
isPerferred = true;
newEmail = newBasicPerson.getEmail(i).getEmailAddress();
}
}
if(isPerferred == true){
//get currentEmail and compare to perferred newEmail
//if not the same perform updateEmail()
if(sr.getAttributes().get("mail") != null) currentEmail = (String) sr.getAttributes().get("mail").get();
if(newEmail.equals(currentEmail) == false) updateEmail(uid, newEmail);
else {
logger.info("[" + getServiceName() + ".execute] The current email address " +
"of the user ('" + currentEmail + "') and the new email address ('" + newEmail +
"') are the same, so no update of the email in the directory is required.");
}
}
if(isPerferred == false){
newEmail = newBasicPerson.getEmail(0).getEmailAddress();
if (sr.getAttributes().get("mail") != null) currentEmail = (String)sr.getAttributes().get("mail").get();
if(newEmail.equals(currentEmail) == false) updateEmail(uid, newEmail);
else {
logger.info("[" + getServiceName() + ".execute] The current email address " +
"of the user ('" + currentEmail + "') and the new email address ('" + newEmail +
"') are the same, so no update of the email in the directory is required.");
}
}
}
else{
// newBasicPerson has no email addresses
// if search returns an email address,
// update email address in DSG by deleteing
// the email address in the DSG repository.
// Assume user intends to delete email address
if(sr.getAttributes().get("mail") != null)
deleteEmail(uid);
}
//***************************************************************************************************************
}
}
catch (NamingException ne) {
// An error occurred determining whether the user exists in the
// directory. Log it and publish a sync error message.
publishError ("system", "DirectoryServiceGateway-1005", "An error occurred determining whether the " +
"user exists in the directory. The exception is: " + ne.getMessage(),
"[" + getServiceName() + ".execute] ", ne);
return;
}
}
// Otherwise, the message is unsupported. Log it and publish a sync error.
else {
publishError ("application", "OpenEAI-1002", "Unsupported message action. This command only "
+ "supports an action of 'update'", "[" + getServiceName() + ".execute] ");
return;
}
}
@Override
protected String getServiceName()
{
return "BasicPersonSyncCommand";
}
}