/*
* ====================
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright 2008-2009 Sun Microsystems, Inc. All rights reserved.
*
* The contents of this file are subject to the terms of the Common Development
* and Distribution License("CDDL") (the "License"). You may not use this file
* except in compliance with the License.
*
* You can obtain a copy of the License at
* http://opensource.org/licenses/cddl1.php
* See the License for the specific language governing permissions and limitations
* under the License.
*
* When distributing the Covered Code, include this CDDL Header Notice in each file
* and include the License file at http://opensource.org/licenses/cddl1.php.
* If applicable, add the following below this CDDL Header, with the fields
* enclosed by brackets [] replaced by your own identifying information:
* "Portions Copyrighted [year] [name of copyright owner]"
* ====================
*/
package org.identityconnectors.oracleerp;
import static org.identityconnectors.oracleerp.OracleERPUtil.ACTIVE_PEOPLE_ONLY_WHERE_CLAUSE;
import static org.identityconnectors.oracleerp.OracleERPUtil.DIRECT_RESPS;
import static org.identityconnectors.oracleerp.OracleERPUtil.EMP_ID;
import static org.identityconnectors.oracleerp.OracleERPUtil.EMP_NUM;
import static org.identityconnectors.oracleerp.OracleERPUtil.EXP_PWD;
import static org.identityconnectors.oracleerp.OracleERPUtil.MSG_ACCOUNT_NAME_REQUIRED;
import static org.identityconnectors.oracleerp.OracleERPUtil.MSG_ACCOUNT_NOT_CREATE;
import static org.identityconnectors.oracleerp.OracleERPUtil.MSG_HR_LINKING_ERROR;
import static org.identityconnectors.oracleerp.OracleERPUtil.NPW_NUM;
import static org.identityconnectors.oracleerp.OracleERPUtil.OWNER;
import static org.identityconnectors.oracleerp.OracleERPUtil.PERSON_ID;
import static org.identityconnectors.oracleerp.OracleERPUtil.RESPS;
import static org.identityconnectors.oracleerp.OracleERPUtil.SEC_ATTRS;
import static org.identityconnectors.oracleerp.OracleERPUtil.whereAnd;
import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Set;
import org.identityconnectors.common.logging.Log;
import org.identityconnectors.dbcommon.SQLUtil;
import org.identityconnectors.framework.common.exceptions.ConnectorException;
import org.identityconnectors.framework.common.objects.Attribute;
import org.identityconnectors.framework.common.objects.AttributeBuilder;
import org.identityconnectors.framework.common.objects.AttributeUtil;
import org.identityconnectors.framework.common.objects.Name;
import org.identityconnectors.framework.common.objects.ObjectClass;
import org.identityconnectors.framework.common.objects.OperationOptions;
import org.identityconnectors.framework.common.objects.OperationalAttributes;
import org.identityconnectors.framework.common.objects.Uid;
import org.identityconnectors.framework.spi.operations.CreateOp;
import org.identityconnectors.oracleerp.AccountSQLCall.AccountSQLCallBuilder;
/**
* The Account CreateOp implementation of the SPI
*
* { call {0}fnd_user_pkg.{1} ( {2} ) } // {0} .. "APPS.", {1} .. "CreateUser"
* {2} ... is an array of x_user_name => ?, x_owner => ?, x_unencrypted_password
* => ?, x_session_number => ?, x_start_date => ?, x_end_date => ?,
* x_last_logon_date => ?, x_description => ?, x_password_date => ?,
* x_password_accesses_left => ?, x_password_lifespan_accesses => ?,
* x_password_lifespan_days => ?, x_employee_id => ?, x_email_address => ?,
* x_fax => ?, x_customer_id => ?, x_supplier_id => ? ) };
*
* @author Petr Jung
* @version $Revision 1.0$
* @since 1.0
*/
final class AccountOperationCreate extends Operation implements CreateOp {
private static final Log LOG = Log.getLog(AccountOperationCreate.class);
/** ResOps. */
private ResponsibilitiesOperations respOps;
/** SecuringAttributes Operations. */
private SecuringAttributesOperations secAttrOps;
/**
* @param conn
* @param cfg
*/
AccountOperationCreate(OracleERPConnection conn, OracleERPConfiguration cfg) {
super(conn, cfg);
respOps = new ResponsibilitiesOperations(getConn(), getCfg());
secAttrOps = new SecuringAttributesOperations(getConn(), getCfg());
}
/*
* (non-Javadoc)
*
* @see org.identityconnectors.framework.spi.operations.CreateOp#create(org.
* identityconnectors.framework.common.objects.ObjectClass, java.util.Set,
* org.identityconnectors.framework.common.objects.OperationOptions)
*/
public Uid create(ObjectClass oclass, Set<Attribute> attrs, OperationOptions options) {
final Name nameAttr = AttributeUtil.getNameFromAttributes(attrs);
if (nameAttr == null || nameAttr.getNameValue() == null) {
throw new IllegalArgumentException(getCfg().getMessage(MSG_ACCOUNT_NAME_REQUIRED));
}
final String name = nameAttr.getNameValue().toUpperCase();
LOG.ok("create user ''{0}''", name);
// Get the User values
final AccountSQLCallBuilder asb = new AccountSQLCallBuilder(getCfg(), true);
// Add default owner
asb.setAttribute(oclass, AttributeBuilder.build(OWNER, getCfg().getDefaultOwner()), options);
// Get the person_id and set is it as a employee id
final Integer personId = getPersonId(name, attrs);
if (personId != null) {
// Person Id as a Employee_Id
asb.setAttribute(oclass, AttributeBuilder.build(EMP_ID, personId), options);
}
// Add password not expired in create
if (AttributeUtil.find(EXP_PWD, attrs) == null
&& AttributeUtil.find(OperationalAttributes.PASSWORD_EXPIRED_NAME, attrs) == null) {
asb.setAttribute(oclass, AttributeBuilder.buildPasswordExpired(false), options);
}
for (Attribute attr : attrs) {
asb.setAttribute(oclass, attr, options);
}
// Run the create call, new style is using the defaults
if (!asb.isEmpty()) {
CallableStatement cs = null;
AccountSQLCall aSql = asb.build();
final String msg = "Create user account {0}";
LOG.ok(msg, name);
try {
// Create the user
cs = getConn().prepareCall(aSql.getCallSql(), aSql.getSqlParams());
cs.execute();
} catch (Exception e) {
SQLUtil.rollbackQuietly(getConn());
final String message = getCfg().getMessage(MSG_ACCOUNT_NOT_CREATE, name);
LOG.error(e, message);
throw new ConnectorException(message, e);
} finally {
SQLUtil.closeQuietly(cs);
}
}
// Update responsibilities
final Attribute resp = AttributeUtil.find(RESPS, attrs);
final Attribute directResp = AttributeUtil.find(DIRECT_RESPS, attrs);
if (directResp != null) {
respOps.updateUserResponsibilities(directResp, name);
} else if (resp != null) {
respOps.updateUserResponsibilities(resp, name);
}
// update securing attributes
final Attribute secAttr = AttributeUtil.find(SEC_ATTRS, attrs);
if (secAttr != null) {
secAttrOps.updateUserSecuringAttrs(secAttr, name);
}
getConn().commit();
LOG.ok("create user ''{0}'' done", name);
return new Uid(name);
}
/**
* Get The personId from employeNumber or NPW number.
*
* @param name
* user identity
* @param attrs
* attributes
* @return personid the id of the person
*/
private Integer getPersonId(String name, Set<Attribute> attrs) {
LOG.ok("getPersonId for userId: ''{0}''", name);
Integer ret = null;
int num = 0;
String columnName = null;
final Attribute empAttr = AttributeUtil.find(EMP_NUM, attrs);
final Attribute npwAttr = AttributeUtil.find(NPW_NUM, attrs);
if (empAttr != null) {
num = Integer.valueOf(AttributeUtil.getAsStringValue(empAttr));
columnName = EMP_NUM;
LOG.ok("{0} present with value ''{1}''", columnName, num);
} else if (npwAttr != null) {
num = Integer.valueOf(AttributeUtil.getAsStringValue(npwAttr));
columnName = NPW_NUM;
LOG.ok("{0} present with value ''{1}''", columnName, num);
} else {
LOG.ok("neither {0} not {1} attributes for personId are present", EMP_NUM, NPW_NUM);
return null;
}
LOG.ok("clomunName ''{0}''", columnName);
String sql =
"select " + PERSON_ID + " from " + getCfg().app() + "PER_PEOPLE_F where "
+ columnName + " = ?";
sql = whereAnd(sql, ACTIVE_PEOPLE_ONLY_WHERE_CLAUSE);
ResultSet rs = null; // SQL query on person_id
PreparedStatement ps = null; // statement that generates the query
try {
ps = getConn().prepareStatement(sql);
ps.setInt(1, num);
ps.setQueryTimeout(OracleERPUtil.ORACLE_TIMEOUT);
rs = ps.executeQuery();
if (rs.next()) {
ret = rs.getInt(1);
}
LOG.ok("Oracle ERP: PERSON_ID return from {0} = {1}", sql, ret);
if (ret == null) {
final String msg = getCfg().getMessage(MSG_HR_LINKING_ERROR, num, name);
LOG.error(msg);
throw new ConnectorException(msg);
}
LOG.ok("getPersonId for userId: ''{0}'' -> ''{1}''", name, ret);
return ret;
} catch (SQLException e) {
LOG.error(e, sql);
throw ConnectorException.wrap(e);
} finally {
SQLUtil.closeQuietly(rs);
rs = null;
SQLUtil.closeQuietly(ps);
ps = null;
}
}
}