/* * ==================== * 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.solaris.operation; import java.util.Collections; import java.util.LinkedHashMap; import java.util.Map; import org.identityconnectors.framework.common.exceptions.ConnectorException; import org.identityconnectors.framework.common.exceptions.UnknownUidException; import org.identityconnectors.solaris.SolarisConnection; import org.identityconnectors.solaris.SolarisConnection.ErrorHandler; final class DeleteNativeUser { private DeleteNativeUser() { } /** * implementation of the Native Delete operation. * * Compare with NIS implementation: {@see * OpDeleteImpl#invokeNISDelete(String)} */ static void delete(final String accountId, SolarisConnection conn) { // USERDEL accountId final String command = conn.buildCommand(true, "userdel", ((conn.getConfiguration() .isDeleteHomeDirectory()) ? "-r" : ""), accountId); Map<String, ErrorHandler> rejectMap = initRejectsMap(accountId); conn.executeCommand(command, rejectMap, Collections.<String> emptySet()); final String output = conn.executeCommand("echo $?"); if (!output.equals("0")) { throw new UnknownUidException("Error deleting user: " + accountId); } } private static Map<String, ErrorHandler> initRejectsMap(final String accountId) { // initialize error handler final String messageErrorDelete = "Error deleting user: "; final ErrorHandler unknownUidHandler = new ErrorHandler() { public void handle(String buffer) { throw new UnknownUidException(messageErrorDelete + accountId); } }; // initialize rejects map final Map<String, ErrorHandler> result = new LinkedHashMap<String, ErrorHandler>(); final String rejectDoesNotExist = "does not exist"; result.put(rejectDoesNotExist, unknownUidHandler); final String rejectUnknownUser = "nknown user"; result.put(rejectUnknownUser, unknownUidHandler); result.put("ERROR", new ErrorHandler() { public void handle(String buffer) { /* * contract tests workaround: (issue is not right type of * exception) * * Initial state: originally we were throwing just * ConnectorException here, because we assumed that if Expect4j * matches, "ERROR", this means that none of other more specific * messages have been in the response. This assumption turned * out to be wrong, thus we introduced the following change: * * Change description: we need to do an extra check of the * buffer, if the buffer doesn't contain reject strings for more * specific exceptions, that deserve UnknownUidException to be * thrown. * * Original motivation of this extra check: Random errors in * contract tests can occur because the wrong exception type is * thrown. * * How the error happens: Expect4J reads the response from the * resource partially (for instance just the start of the error * message, containing "ERROR"), so will invoke the Closure for * generic error message, instead of the specific one. After * Expect invokes the closure, the SolarisConnection marks, * which error message was matched. If an error messages is * matched, SolarisConnection will try to read as much of the * response, as it can. This is were the connection comes to * know the remaining part of the error message, which can * contain the specific information we miss. So even though * Expect4j matched the generic message, based on full buffer * content we need to throw a specific error message. */ String msg = messageErrorDelete + "'" + accountId + "', buffer: <" + buffer + ">"; if (buffer.contains(rejectDoesNotExist) || buffer.contains(rejectUnknownUser)) { throw new UnknownUidException(msg); } else { throw new ConnectorException(msg); } } }); return result; } }