001/* 002 * CDDL HEADER START 003 * 004 * The contents of this file are subject to the terms of the 005 * Common Development and Distribution License, Version 1.0 only 006 * (the "License"). You may not use this file except in compliance 007 * with the License. 008 * 009 * You can obtain a copy of the license at legal-notices/CDDLv1_0.txt 010 * or http://forgerock.org/license/CDDLv1.0.html. 011 * See the License for the specific language governing permissions 012 * and limitations under the License. 013 * 014 * When distributing Covered Code, include this CDDL HEADER in each 015 * file and include the License file at legal-notices/CDDLv1_0.txt. 016 * If applicable, add the following below this CDDL HEADER, with the 017 * fields enclosed by brackets "[]" replaced with your own identifying 018 * information: 019 * Portions Copyright [yyyy] [name of copyright owner] 020 * 021 * CDDL HEADER END 022 * 023 * 024 * Copyright 2008 Sun Microsystems, Inc. 025 * Portions Copyright 2015 ForgeRock AS. 026 */ 027package org.forgerock.opendj.config.client; 028 029import static com.forgerock.opendj.ldap.AdminMessages.*; 030 031import java.util.ArrayList; 032import java.util.Collection; 033import java.util.Collections; 034 035import org.forgerock.i18n.LocalizableMessage; 036import org.forgerock.i18n.LocalizableMessageBuilder; 037import org.forgerock.util.Reject; 038 039/** 040 * This exception is thrown when the client or server refuses to create, delete, 041 * or modify a managed object due to one or more constraints that cannot be 042 * satisfied. 043 * <p> 044 * Operations can be rejected either by a client-side constraint violation 045 * triggered by {@link ClientConstraintHandler}, or by a server-side error. 046 * <p> 047 * For example, the Directory Server might not be able perform an operation due 048 * to some OS related problem, such as lack of disk space, or missing files. 049 */ 050public class OperationRejectedException extends AdminClientException { 051 052 /** 053 * The type of operation that caused this exception. 054 */ 055 public enum OperationType { 056 /** 057 * A managed object could not be created. 058 */ 059 CREATE, 060 061 /** 062 * A managed object could not be deleted. 063 */ 064 DELETE, 065 066 /** 067 * A managed object could not be modified. 068 */ 069 MODIFY; 070 } 071 072 /** 073 * Serialization ID. 074 */ 075 private static final long serialVersionUID = 8547688890613079044L; 076 077 /** Gets the default message. */ 078 private static LocalizableMessage getDefaultMessage(Collection<LocalizableMessage> messages) { 079 Reject.ifNull(messages); 080 Reject.ifFalse(!messages.isEmpty(), "Messages should not be empty"); 081 082 if (messages.size() == 1) { 083 return ERR_OPERATION_REJECTED_EXCEPTION_SINGLE.get(messages.iterator().next()); 084 } else { 085 return ERR_OPERATION_REJECTED_EXCEPTION_PLURAL.get(getSingleMessage(messages)); 086 } 087 } 088 089 /** Merge the messages into a single message. */ 090 private static LocalizableMessage getSingleMessage(Collection<LocalizableMessage> messages) { 091 if (messages.size() == 1) { 092 return messages.iterator().next(); 093 } else { 094 LocalizableMessageBuilder builder = new LocalizableMessageBuilder(); 095 096 boolean isFirst = true; 097 for (LocalizableMessage m : messages) { 098 if (!isFirst) { 099 builder.append("; "); 100 } 101 builder.append(m); 102 isFirst = false; 103 } 104 105 return builder.toMessage(); 106 } 107 } 108 109 /** The messages describing the constraint violations that occurred. */ 110 private final Collection<LocalizableMessage> messages; 111 112 /** The type of operation that caused this exception. */ 113 private final OperationType type; 114 115 /** The user friendly name of the component that caused this exception. */ 116 private final LocalizableMessage ufn; 117 118 /** 119 * Creates a new operation rejected exception with a default message. 120 * 121 * @param type 122 * The type of operation that caused this exception. 123 * @param ufn 124 * The user friendly name of the component that caused this 125 * exception. 126 */ 127 public OperationRejectedException(OperationType type, LocalizableMessage ufn) { 128 this(type, ufn, ERR_OPERATION_REJECTED_DEFAULT.get()); 129 } 130 131 /** 132 * Creates a new operation rejected exception with the provided messages. 133 * 134 * @param type 135 * The type of operation that caused this exception. 136 * @param ufn 137 * The user friendly name of the component that caused this 138 * exception. 139 * @param messages 140 * The messages describing the constraint violations that 141 * occurred (must be non-<code>null</code> and non-empty). 142 */ 143 public OperationRejectedException(OperationType type, LocalizableMessage ufn, 144 Collection<LocalizableMessage> messages) { 145 super(getDefaultMessage(messages)); 146 147 this.messages = new ArrayList<>(messages); 148 this.type = type; 149 this.ufn = ufn; 150 } 151 152 /** 153 * Creates a new operation rejected exception with the provided message. 154 * 155 * @param type 156 * The type of operation that caused this exception. 157 * @param ufn 158 * The user friendly name of the component that caused this 159 * exception. 160 * @param message 161 * The message describing the constraint violation that occurred. 162 */ 163 public OperationRejectedException(OperationType type, LocalizableMessage ufn, LocalizableMessage message) { 164 this(type, ufn, Collections.singleton(message)); 165 } 166 167 /** 168 * Gets an unmodifiable collection view of the messages describing the 169 * constraint violations that occurred. 170 * 171 * @return Returns an unmodifiable collection view of the messages 172 * describing the constraint violations that occurred. 173 */ 174 public Collection<LocalizableMessage> getMessages() { 175 return Collections.unmodifiableCollection(messages); 176 } 177 178 /** 179 * Creates a single message listing all the messages combined into a single 180 * list separated by semi-colons. 181 * 182 * @return Returns a single message listing all the messages combined into a 183 * single list separated by semi-colons. 184 */ 185 public LocalizableMessage getMessagesAsSingleMessage() { 186 return getSingleMessage(messages); 187 } 188 189 /** 190 * Gets the type of operation that caused this exception. 191 * 192 * @return Returns the type of operation that caused this exception. 193 */ 194 public OperationType getOperationType() { 195 return type; 196 } 197 198 /** 199 * Gets the user friendly name of the component that caused this exception. 200 * 201 * @return Returns the user friendly name of the component that caused this 202 * exception. 203 */ 204 public LocalizableMessage getUserFriendlyName() { 205 return ufn; 206 } 207 208}