001/*
002  GRANITE DATA SERVICES
003  Copyright (C) 2011 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
021package flex.messaging.messages;
022
023import org.granite.logging.Logger;
024import org.granite.messaging.service.ServiceException;
025import org.granite.messaging.service.security.SecurityServiceException;
026
027import java.io.PrintWriter;
028import java.io.StringWriter;
029import java.util.HashMap;
030import java.util.Map;
031
032/**
033 * @author Franck WOLFF
034 */
035public class ErrorMessage extends AcknowledgeMessage {
036
037    private static final long serialVersionUID = 1L;
038    
039    private static final Logger log = Logger.getLogger("org.granite.logging.ExceptionStackTrace");
040    
041    public static final String CODE_SERVER_CALL_FAILED = "Server.Call.Failed";
042
043    private String faultCode = CODE_SERVER_CALL_FAILED;
044    private String faultDetail;
045    private String faultString;
046    private Object rootCause;
047    private Map<String, Object> extendedData;
048
049    private transient boolean loginError = false;
050
051    public ErrorMessage() {
052        super();
053    }
054
055    public ErrorMessage(Throwable t) {
056        super();
057        init(t);
058    }
059
060    public ErrorMessage(Message request) {
061        this(request, false);
062    }
063
064    public ErrorMessage(Message request, Throwable t) {
065        this(request, t, false);
066    }
067
068    public ErrorMessage(Message request, boolean keepClientId) {
069        super(request, keepClientId);
070    }
071
072    public ErrorMessage(Message request, Throwable t, boolean keepClientId) {
073        super(request, keepClientId);
074        if (request instanceof CommandMessage) {
075            loginError = (
076                ((CommandMessage)request).isLoginOperation() &&
077                (t instanceof SecurityServiceException)
078            );
079        }
080        init(t);
081    }
082
083    private void init(Throwable t) {
084        if (t instanceof ServiceException) {
085            ServiceException se = (ServiceException)t;
086
087            this.faultCode = se.getCode();
088            this.faultString = se.getMessage();
089
090            if (t instanceof SecurityServiceException)
091                this.faultDetail = se.getDetail();
092            else
093                this.faultDetail = se.getDetail() + getStackTrace(t);
094            
095            this.extendedData = se.getExtendedData();
096        }
097        else if (t != null) {
098            this.faultString = t.getMessage();
099            this.faultDetail = t.getMessage();
100        }
101
102        if (!(t instanceof SecurityServiceException)) {
103            for (Throwable root = t; root != null; root = root.getCause())
104                rootCause = root;
105        }
106        if (rootCause != null && !log.isDebugEnabled())
107            rootCause = ((Throwable)rootCause).getMessage();
108    }
109
110    private String getStackTrace(Throwable t) {
111        if (!log.isDebugEnabled())
112                return "";
113        StringWriter sw = new StringWriter();
114        t.printStackTrace(new PrintWriter(sw));
115        return sw.toString().replace("\r\n", "\n").replace('\r', '\n');
116    }
117
118    public String getFaultCode() {
119        return faultCode;
120    }
121    public void setFaultCode(String faultCode) {
122        this.faultCode = faultCode;
123    }
124
125    public String getFaultDetail() {
126        return faultDetail;
127    }
128    public void setFaultDetail(String faultDetail) {
129        this.faultDetail = faultDetail;
130    }
131
132    public String getFaultString() {
133        return faultString;
134    }
135    public void setFaultString(String faultString) {
136        this.faultString = faultString;
137    }
138
139    public Map<String, Object> getExtendedData() {
140        return extendedData;
141    }
142    public void setExtendedData(Map<String, Object> extendedData) {
143        this.extendedData = extendedData;
144    }
145
146    public Object getRootCause() {
147        return rootCause;
148    }
149    public void setRootCause(Object rootCause) {
150        this.rootCause = rootCause;
151    }
152
153    public boolean loginError() {
154        return loginError;
155    }
156
157    public ErrorMessage copy(Message request) {
158        ErrorMessage copy = new ErrorMessage(request, null);
159        copy.faultCode = faultCode;
160        copy.faultDetail = faultDetail;
161        copy.faultString = faultString;
162        copy.loginError = loginError;
163        copy.rootCause = rootCause;
164        copy.extendedData = new HashMap<String, Object>(extendedData);
165        return copy;
166    }
167
168    @Override
169    public String toString() {
170        return toString("");
171    }
172
173    @Override
174    public String toString(String indent) {
175        StringBuilder sb = new StringBuilder(512);
176        sb.append(getClass().getName()).append(" {");
177        sb.append('\n').append(indent).append("  faultCode = ").append(faultCode);
178        sb.append('\n').append(indent).append("  faultDetail = ").append(faultDetail);
179        sb.append('\n').append(indent).append("  faultString = ").append(faultString);
180        sb.append('\n').append(indent).append("  rootCause = ").append(rootCause);
181        sb.append('\n').append(indent).append("  extendedData = ").append(extendedData);
182        super.toString(sb, indent, null);
183        sb.append('\n').append(indent).append('}');
184        return sb.toString();
185    }
186}