001/**
002 *   GRANITE DATA SERVICES
003 *   Copyright (C) 2006-2013 GRANITE DATA SERVICES S.A.S.
004 *
005 *   This file is part of the Granite Data Services Platform.
006 *
007 *   Granite Data Services is free software; you can redistribute it and/or
008 *   modify it under the terms of the GNU Lesser General Public
009 *   License as published by the Free Software Foundation; either
010 *   version 2.1 of the License, or (at your option) any later version.
011 *
012 *   Granite Data Services is distributed in the hope that it will be useful,
013 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
014 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
015 *   General Public License for more details.
016 *
017 *   You should have received a copy of the GNU Lesser General Public
018 *   License along with this library; if not, write to the Free Software
019 *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
020 *   USA, or see <http://www.gnu.org/licenses/>.
021 */
022package flex.messaging.messages;
023
024import org.granite.logging.Logger;
025import org.granite.messaging.service.ServiceException;
026import org.granite.messaging.service.security.SecurityServiceException;
027
028import java.io.PrintWriter;
029import java.io.StringWriter;
030import java.util.HashMap;
031import java.util.Map;
032
033/**
034 * @author Franck WOLFF
035 */
036public class ErrorMessage extends AcknowledgeMessage {
037
038    private static final long serialVersionUID = 1L;
039    
040    private static final Logger log = Logger.getLogger("org.granite.logging.ExceptionStackTrace");
041    
042    public static final String CODE_SERVER_CALL_FAILED = "Server.Call.Failed";
043
044    private String faultCode = CODE_SERVER_CALL_FAILED;
045    private String faultDetail;
046    private String faultString;
047    private Object rootCause;
048    private Map<String, Object> extendedData;
049
050    private transient boolean loginError = false;
051
052    public ErrorMessage() {
053        super();
054    }
055
056    public ErrorMessage(Throwable t) {
057        super();
058        init(t);
059    }
060
061    public ErrorMessage(Message request) {
062        this(request, false);
063    }
064
065    public ErrorMessage(Message request, Throwable t) {
066        this(request, t, false);
067    }
068
069    public ErrorMessage(Message request, boolean keepClientId) {
070        super(request, keepClientId);
071    }
072
073    public ErrorMessage(Message request, Throwable t, boolean keepClientId) {
074        super(request, keepClientId);
075        if (request instanceof CommandMessage) {
076            loginError = (
077                ((CommandMessage)request).isLoginOperation() &&
078                (t instanceof SecurityServiceException)
079            );
080        }
081        init(t);
082    }
083
084    private void init(Throwable t) {
085        if (t instanceof ServiceException) {
086            ServiceException se = (ServiceException)t;
087
088            this.faultCode = se.getCode();
089            this.faultString = se.getMessage();
090
091            if (t instanceof SecurityServiceException)
092                this.faultDetail = se.getDetail();
093            else
094                this.faultDetail = se.getDetail() + getStackTrace(t);
095            
096            this.extendedData = se.getExtendedData();
097        }
098        else if (t != null) {
099            this.faultString = t.getMessage();
100            this.faultDetail = t.getMessage();
101        }
102
103        if (!(t instanceof SecurityServiceException)) {
104            for (Throwable root = t; root != null; root = root.getCause())
105                rootCause = root;
106        }
107        if (rootCause != null && !log.isDebugEnabled())
108            rootCause = ((Throwable)rootCause).getMessage();
109    }
110
111    private String getStackTrace(Throwable t) {
112        if (!log.isDebugEnabled())
113                return "";
114        StringWriter sw = new StringWriter();
115        t.printStackTrace(new PrintWriter(sw));
116        return sw.toString().replace("\r\n", "\n").replace('\r', '\n');
117    }
118
119    public String getFaultCode() {
120        return faultCode;
121    }
122    public void setFaultCode(String faultCode) {
123        this.faultCode = faultCode;
124    }
125
126    public String getFaultDetail() {
127        return faultDetail;
128    }
129    public void setFaultDetail(String faultDetail) {
130        this.faultDetail = faultDetail;
131    }
132
133    public String getFaultString() {
134        return faultString;
135    }
136    public void setFaultString(String faultString) {
137        this.faultString = faultString;
138    }
139
140    public Map<String, Object> getExtendedData() {
141        return extendedData;
142    }
143    public void setExtendedData(Map<String, Object> extendedData) {
144        this.extendedData = extendedData;
145    }
146
147    public Object getRootCause() {
148        return rootCause;
149    }
150    public void setRootCause(Object rootCause) {
151        this.rootCause = rootCause;
152    }
153
154    public boolean loginError() {
155        return loginError;
156    }
157
158    public ErrorMessage copy(Message request) {
159        ErrorMessage copy = new ErrorMessage(request, null);
160        copy.faultCode = faultCode;
161        copy.faultDetail = faultDetail;
162        copy.faultString = faultString;
163        copy.loginError = loginError;
164        copy.rootCause = rootCause;
165        copy.extendedData = new HashMap<String, Object>(extendedData);
166        return copy;
167    }
168
169    @Override
170    public String toString() {
171        return toString("");
172    }
173
174    @Override
175    public String toString(String indent) {
176        StringBuilder sb = new StringBuilder(512);
177        sb.append(getClass().getName()).append(" {");
178        sb.append('\n').append(indent).append("  faultCode = ").append(faultCode);
179        sb.append('\n').append(indent).append("  faultDetail = ").append(faultDetail);
180        sb.append('\n').append(indent).append("  faultString = ").append(faultString);
181        sb.append('\n').append(indent).append("  rootCause = ").append(rootCause);
182        sb.append('\n').append(indent).append("  extendedData = ").append(extendedData);
183        super.toString(sb, indent, null);
184        sb.append('\n').append(indent).append('}');
185        return sb.toString();
186    }
187}