001    /**
002     *   GRANITE DATA SERVICES
003     *   Copyright (C) 2006-2013 GRANITE DATA SERVICES S.A.S.
004     *
005     *   This file is part of Granite Data Services.
006     *
007     *   Granite Data Services is free software; you can redistribute it and/or modify
008     *   it under the terms of the GNU Library General Public License as published by
009     *   the Free Software Foundation; either version 2 of the License, or (at your
010     *   option) any later version.
011     *
012     *   Granite Data Services is distributed in the hope that it will be useful, but
013     *   WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
014     *   FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License
015     *   for more details.
016     *
017     *   You should have received a copy of the GNU Library General Public License
018     *   along with this library; if not, see <http://www.gnu.org/licenses/>.
019     */
020    package org.granite.client.messaging.messages.responses;
021    
022    import java.io.IOException;
023    import java.io.ObjectInput;
024    import java.io.ObjectOutput;
025    import java.util.Map;
026    
027    /**
028     * @author Franck WOLFF
029     */
030    public final class FaultMessage extends AbstractResponseMessage {
031    
032            public static enum Code {
033                    UNKNOWN,
034                    
035                    CLIENT_CALL_FAILED,
036                    CLIENT_CALL_TIMED_OUT,
037                    CLIENT_CALL_CANCELLED,
038                    
039                    SERVER_CALL_FAILED,
040                    
041                INVALID_CREDENTIALS,
042                AUTHENTICATION_FAILED,
043                NOT_LOGGED_IN,
044                SESSION_EXPIRED,
045                ACCESS_DENIED,
046                
047                VALIDATION_FAILED,
048                OPTIMISTIC_LOCK
049            }
050            
051        private Code code;
052        private String description;
053        private String details;
054        private Object cause;
055        private Map<String, Object> extended;
056        
057        private String unknownCode;
058            
059            public FaultMessage() {
060            }
061    
062            public FaultMessage(
063                    String clientId,
064                    String correlationId,
065                    Code code,
066                    String description,
067                    String details,
068                    Object cause,
069                    Map<String, Object> extended) {
070                    
071                    super(clientId, correlationId);
072                    
073                    this.code = code;
074                    this.description = description;
075                    this.details = details;
076                    this.cause = cause;
077                    this.extended = extended;
078            }
079    
080            public FaultMessage(
081                    String id,
082                    String clientId,
083                    long timestamp,
084                    long timeToLive,
085                    Map<String, Object> headers,
086                    String correlationId,
087                    Code code,
088                    String description,
089                    String details,
090                    Object cause,
091                    Map<String, Object> extended) {
092                    
093                    super(id, clientId, timestamp, timeToLive, headers, correlationId);
094                    
095                    this.code = code;
096                    this.description = description;
097                    this.details = details;
098                    this.cause = cause;
099                    this.extended = extended;
100            }
101    
102            @Override
103            public Type getType() {
104                    return Type.FAULT;
105            }
106            
107            public boolean isSecurityFault() {
108                    switch (code) {
109                            case UNKNOWN:
110                                    return unknownCode != null && unknownCode.startsWith("Server.Security.");
111                                    
112                            case INVALID_CREDENTIALS:
113                            case AUTHENTICATION_FAILED:
114                            case NOT_LOGGED_IN:
115                            case SESSION_EXPIRED:
116                            case ACCESS_DENIED:
117                                    return true;
118            
119                            default:
120                                    return false;
121                    }
122            }
123    
124            @Override
125            public Object getData() {
126                    return toString();
127            }
128    
129            public Code getCode() {
130                    return code;
131            }
132    
133            public void setCode(Code code) {
134                    this.code = code;
135            }
136    
137            public String getDescription() {
138                    return description;
139            }
140    
141            public void setDescription(String description) {
142                    this.description = description;
143            }
144    
145            public String getDetails() {
146                    return details;
147            }
148    
149            public void setDetails(String details) {
150                    this.details = details;
151            }
152    
153            public Object getCause() {
154                    return cause;
155            }
156    
157            public void setCause(Object cause) {
158                    this.cause = cause;
159            }
160    
161            public Map<String, Object> getExtended() {
162                    return extended;
163            }
164    
165            public void setExtended(Map<String, Object> extended) {
166                    this.extended = extended;
167            }
168    
169            public String getUnknownCode() {
170                    return unknownCode;
171            }
172    
173            public void setUnknownCode(String unknownCode) {
174                    this.unknownCode = unknownCode;
175            }
176    
177            @Override
178            public FaultMessage copy() {
179                    FaultMessage message = new FaultMessage();
180    
181                    super.copy(message);
182                    
183                    message.code = code;
184                    message.description = description;
185                    message.details = details;
186                    message.cause = cause;
187                    message.extended = extended;
188                    
189                    return message;
190            }
191    
192            @Override
193            @SuppressWarnings("unchecked")
194            public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
195                    super.readExternal(in);
196                    
197                    code = (Code)in.readObject();
198                    description = in.readUTF();
199                    details = in.readUTF();
200                    cause = in.readObject();
201                    extended = (Map<String, Object>)in.readObject();
202            }
203    
204            @Override
205            public void writeExternal(ObjectOutput out) throws IOException {
206                    super.writeExternal(out);
207                    
208                    out.writeObject(code);
209                    if (description != null)
210                            out.writeUTF(description);
211                    else
212                            out.writeObject(null);
213                    if (details != null)
214                            out.writeUTF(details);
215                    else
216                            out.writeObject(null);
217                    out.writeObject(cause);
218                    out.writeObject(extended);
219            }
220    
221            @Override
222            public StringBuilder toString(StringBuilder sb) {
223                    return super.toString(sb)
224                            .append("\n    code=").append(code)
225                            .append("\n    description=").append(description)
226                            .append("\n    details=").append(details)
227                            .append("\n    cause=").append(cause)
228                            .append("\n    extended=").append(extended);
229            }
230    }