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