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 /** The type of operation that caused this exception. */ 043 public enum OperationType { 044 /** A managed object could not be created. */ 045 CREATE, 046 /** A managed object could not be deleted. */ 047 DELETE, 048 /** A managed object could not be modified. */ 049 MODIFY; 050 } 051 052 /** Serialization ID. */ 053 private static final long serialVersionUID = 8547688890613079044L; 054 055 /** Gets the default message. */ 056 private static LocalizableMessage getDefaultMessage(Collection<LocalizableMessage> messages) { 057 Reject.ifNull(messages); 058 Reject.ifFalse(!messages.isEmpty(), "Messages should not be empty"); 059 060 if (messages.size() == 1) { 061 return ERR_OPERATION_REJECTED_EXCEPTION_SINGLE.get(messages.iterator().next()); 062 } else { 063 return ERR_OPERATION_REJECTED_EXCEPTION_PLURAL.get(getSingleMessage(messages)); 064 } 065 } 066 067 /** Merge the messages into a single message. */ 068 private static LocalizableMessage getSingleMessage(Collection<LocalizableMessage> messages) { 069 if (messages.size() == 1) { 070 return messages.iterator().next(); 071 } else { 072 LocalizableMessageBuilder builder = new LocalizableMessageBuilder(); 073 074 boolean isFirst = true; 075 for (LocalizableMessage m : messages) { 076 if (!isFirst) { 077 builder.append("; "); 078 } 079 builder.append(m); 080 isFirst = false; 081 } 082 083 return builder.toMessage(); 084 } 085 } 086 087 /** The messages describing the constraint violations that occurred. */ 088 private final Collection<LocalizableMessage> messages; 089 090 /** The type of operation that caused this exception. */ 091 private final OperationType type; 092 093 /** The user friendly name of the component that caused this exception. */ 094 private final LocalizableMessage ufn; 095 096 /** 097 * Creates a new operation rejected exception with a default message. 098 * 099 * @param type 100 * The type of operation that caused this exception. 101 * @param ufn 102 * The user friendly name of the component that caused this 103 * exception. 104 */ 105 public OperationRejectedException(OperationType type, LocalizableMessage ufn) { 106 this(type, ufn, ERR_OPERATION_REJECTED_DEFAULT.get()); 107 } 108 109 /** 110 * Creates a new operation rejected exception with the provided messages. 111 * 112 * @param type 113 * The type of operation that caused this exception. 114 * @param ufn 115 * The user friendly name of the component that caused this 116 * exception. 117 * @param messages 118 * The messages describing the constraint violations that 119 * occurred (must be non-<code>null</code> and non-empty). 120 */ 121 public OperationRejectedException(OperationType type, LocalizableMessage ufn, 122 Collection<LocalizableMessage> messages) { 123 super(getDefaultMessage(messages)); 124 125 this.messages = new ArrayList<>(messages); 126 this.type = type; 127 this.ufn = ufn; 128 } 129 130 /** 131 * Creates a new operation rejected exception with the provided message. 132 * 133 * @param type 134 * The type of operation that caused this exception. 135 * @param ufn 136 * The user friendly name of the component that caused this 137 * exception. 138 * @param message 139 * The message describing the constraint violation that occurred. 140 */ 141 public OperationRejectedException(OperationType type, LocalizableMessage ufn, LocalizableMessage message) { 142 this(type, ufn, Collections.singleton(message)); 143 } 144 145 /** 146 * Gets an unmodifiable collection view of the messages describing the 147 * constraint violations that occurred. 148 * 149 * @return Returns an unmodifiable collection view of the messages 150 * describing the constraint violations that occurred. 151 */ 152 public Collection<LocalizableMessage> getMessages() { 153 return Collections.unmodifiableCollection(messages); 154 } 155 156 /** 157 * Creates a single message listing all the messages combined into a single 158 * list separated by semi-colons. 159 * 160 * @return Returns a single message listing all the messages combined into a 161 * single list separated by semi-colons. 162 */ 163 public LocalizableMessage getMessagesAsSingleMessage() { 164 return getSingleMessage(messages); 165 } 166 167 /** 168 * Gets the type of operation that caused this exception. 169 * 170 * @return Returns the type of operation that caused this exception. 171 */ 172 public OperationType getOperationType() { 173 return type; 174 } 175 176 /** 177 * Gets the user friendly name of the component that caused this exception. 178 * 179 * @return Returns the user friendly name of the component that caused this 180 * exception. 181 */ 182 public LocalizableMessage getUserFriendlyName() { 183 return ufn; 184 } 185 186}