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}