/*
* ====================
* 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]"
* ====================
*
* Portions Copyrighted 2012 Evolveum, Radovan Semancik
*/
package org.identityconnectors.solaris.operation;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import org.identityconnectors.common.StringUtil;
import org.identityconnectors.common.logging.Log;
import org.identityconnectors.common.security.GuardedString;
import org.identityconnectors.framework.common.exceptions.AlreadyExistsException;
import org.identityconnectors.framework.common.objects.Attribute;
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.solaris.SolarisConfiguration;
import org.identityconnectors.solaris.SolarisConnection;
import org.identityconnectors.solaris.SolarisConnector;
import org.identityconnectors.solaris.SolarisUtil;
import org.identityconnectors.solaris.attr.NativeAttribute;
import org.identityconnectors.solaris.operation.nis.AbstractNISOp;
import org.identityconnectors.solaris.operation.nis.UpdateNISGroup;
import org.identityconnectors.solaris.operation.nis.UpdateNISUser;
import org.identityconnectors.solaris.operation.search.SolarisEntry;
/**
* Implementation of update SPI operation.
*
* @author David Adam
*/
public class SolarisUpdate extends AbstractOp {
private static final Log logger = Log.getLog(SolarisUpdate.class);
private SolarisConnection connection;
/** These objectclasses are valid for update operation. */
final ObjectClass[] acceptOC = { ObjectClass.ACCOUNT, ObjectClass.GROUP };
public SolarisUpdate(SolarisConnector connector) {
super(connector);
connection = connector.getConnection();
}
/** main update method. */
public Uid update(ObjectClass objclass, Uid uid, Set<Attribute> replaceAttributes,
OperationOptions options) {
logger.info("update ('{0}', name: '{1}'", objclass.toString(), uid.getUidValue());
SolarisUtil.controlObjectClassValidity(objclass, acceptOC, getClass(), connection
.getConfiguration());
// Read only list of attributes
final Map<String, Attribute> attrMap =
new HashMap<String, Attribute>(AttributeUtil.toMap(replaceAttributes));
final SolarisEntry entry =
SolarisUtil.convertIcfAttributesToSolarisEntry(uid.getUidValue(), objclass,
replaceAttributes, connection.getConfiguration());
final String newName = fetchName(entry);
if (objclass.is(ObjectClass.ACCOUNT_NAME)) {
GuardedString passwd = null;
Attribute attrPasswd = attrMap.get(OperationalAttributes.PASSWORD_NAME);
if (attrPasswd != null) {
passwd = AttributeUtil.getGuardedStringValue(attrPasswd);
}
if (connection.isNis()) {
// NIS doesn't control duplicate account names so we need to do
// it in advance
if (StringUtil.isNotBlank(newName)
&& SolarisUtil.exists(objclass, new SolarisEntry.Builder(newName).build(),
connection) && !newName.equals(entry.getName())) {
throw new AlreadyExistsException("Account already exits: " + entry.getName());
}
invokeNISUserUpdate(entry, passwd);
} else {
UpdateNativeUser.updateUser(entry, passwd, connection);
}
} else if (objclass.is(ObjectClass.GROUP_NAME)) {
if (connection.isNis()) {
// NIS doesn't control duplicate account names so we need to do
// it in advance
if (StringUtil.isNotBlank(newName)
&& SolarisUtil.exists(objclass, new SolarisEntry.Builder(newName).build(),
connection) && !newName.equals(entry.getName())) {
throw new AlreadyExistsException("Group already exits: " + entry.getName());
}
invokeNISGroupUpdate(entry);
} else {
UpdateNativeGroup.updateGroup(entry, connection);
}
// Rename was separate operation in Adapter
RenameGroup.renameGroup(entry, connection);
} else {
throw new UnsupportedOperationException();
}
logger.info("update successful ('{0}', name: '{1}')", objclass.toString(), uid
.getUidValue());
Uid newUid = uid; // uid is the uid before update.
// if new uid is in replaceAttributes, return the updated uid
if (attrMap.get(Name.NAME) != null) {
String name = ((Name) attrMap.get(Name.NAME)).getNameValue();
newUid = new Uid(name);
}
return newUid;
}
private String fetchName(SolarisEntry entry) {
String newName = null;
Attribute newNameAttr = entry.searchForAttribute(NativeAttribute.NAME);
if (newNameAttr != null) {
newName = AttributeUtil.getStringValue(newNameAttr);
}
return newName;
}
/**
* Compare with Native update operation. {@see
* OpUpdateImpl#invokeNativeGroupUpdate(SolarisEntry)}
*/
private void invokeNISGroupUpdate(SolarisEntry groupEntry) {
if (connection.isDefaultNisPwdDir()) {
UpdateNativeGroup.updateGroup(groupEntry, connection);
connection.doSudoStart();
try {
AbstractNISOp.addNISMake("group", connection);
} finally {
connection.doSudoReset();
}
} else {
UpdateNISGroup.updateGroup(groupEntry, connection);
}
}
/**
* Compare with Native update operation. {@see
* OpUpdateImpl#invokeNativeUserUpdate(SolarisEntry, GuardedString)}
*/
private void invokeNISUserUpdate(final SolarisEntry userEntry, final GuardedString passwd) {
if (connection.isDefaultNisPwdDir()) {
UpdateNativeUser.updateUser(userEntry, passwd, connection);
connection.doSudoStart();
try {
// The user has to be added to the NIS database
AbstractNISOp.addNISMake("passwd", connection);
} finally {
connection.doSudoReset();
}
} else {
UpdateNISUser.updateUser(userEntry, passwd, connection);
}
}
}