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.granite.logging.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        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    }