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