src/share/jaxws_classes/com/sun/xml/internal/ws/fault/ExceptionBean.java

changeset 286
f50545b5e2f1
child 368
0989ad8c0860
equal deleted inserted replaced
284:88b85470e72c 286:f50545b5e2f1
1 /*
2 * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26 package com.sun.xml.internal.ws.fault;
27
28 import com.sun.xml.internal.bind.marshaller.NamespacePrefixMapper;
29 import com.sun.xml.internal.ws.developer.ServerSideException;
30 import org.w3c.dom.Element;
31 import org.w3c.dom.Node;
32
33 import javax.xml.bind.JAXBContext;
34 import javax.xml.bind.JAXBException;
35 import javax.xml.bind.Marshaller;
36 import javax.xml.bind.PropertyException;
37 import javax.xml.bind.annotation.XmlAttribute;
38 import javax.xml.bind.annotation.XmlElement;
39 import javax.xml.bind.annotation.XmlElementWrapper;
40 import javax.xml.bind.annotation.XmlRootElement;
41 import java.util.ArrayList;
42 import java.util.List;
43
44 /**
45 * JAXB-bound bean that captures the exception and its call stack.
46 *
47 * <p>
48 * This is used to capture the stack trace of the server side error and
49 * send that over to the client.
50 *
51 * @author Kohsuke Kawaguchi
52 */
53 @XmlRootElement(namespace=ExceptionBean.NS,name=ExceptionBean.LOCAL_NAME)
54 final class ExceptionBean {
55 /**
56 * Converts the given {@link Throwable} into an XML representation
57 * and put that as a DOM tree under the given node.
58 */
59 public static void marshal( Throwable t, Node parent ) throws JAXBException {
60 Marshaller m = JAXB_CONTEXT.createMarshaller();
61 try {
62 m.setProperty("com.sun.xml.internal.bind.namespacePrefixMapper",nsp);
63 } catch (PropertyException pe) {}
64 m.marshal(new ExceptionBean(t), parent );
65 }
66
67 /**
68 * Does the reverse operation of {@link #marshal(Throwable, Node)}. Constructs an
69 * {@link Exception} object from the XML.
70 */
71 public static ServerSideException unmarshal( Node xml ) throws JAXBException {
72 ExceptionBean e = (ExceptionBean) JAXB_CONTEXT.createUnmarshaller().unmarshal(xml);
73 return e.toException();
74 }
75
76 @XmlAttribute(name="class")
77 public String className;
78 @XmlElement
79 public String message;
80 @XmlElementWrapper(namespace=NS,name="stackTrace")
81 @XmlElement(namespace=NS,name="frame")
82 public List<StackFrame> stackTrace = new ArrayList<StackFrame>();
83 @XmlElement(namespace=NS,name="cause")
84 public ExceptionBean cause;
85
86 // so that people noticed this fragment can turn it off
87 @XmlAttribute
88 public String note = "To disable this feature, set "+SOAPFaultBuilder.CAPTURE_STACK_TRACE_PROPERTY+" system property to false";
89
90 ExceptionBean() {// for JAXB
91 }
92
93 /**
94 * Creates an {@link ExceptionBean} tree that represents the given {@link Throwable}.
95 */
96 private ExceptionBean(Throwable t) {
97 this.className = t.getClass().getName();
98 this.message = t.getMessage();
99
100 for (StackTraceElement f : t.getStackTrace()) {
101 stackTrace.add(new StackFrame(f));
102 }
103
104 Throwable cause = t.getCause();
105 if(t!=cause && cause!=null)
106 this.cause = new ExceptionBean(cause);
107 }
108
109 private ServerSideException toException() {
110 ServerSideException e = new ServerSideException(className,message);
111 if(stackTrace!=null) {
112 StackTraceElement[] ste = new StackTraceElement[stackTrace.size()];
113 for( int i=0; i<stackTrace.size(); i++ )
114 ste[i] = stackTrace.get(i).toStackTraceElement();
115 e.setStackTrace(ste);
116 }
117 if(cause!=null)
118 e.initCause(cause.toException());
119 return e;
120 }
121
122 /**
123 * Captures one stack frame.
124 */
125 static final class StackFrame {
126 @XmlAttribute(name="class")
127 public String declaringClass;
128 @XmlAttribute(name="method")
129 public String methodName;
130 @XmlAttribute(name="file")
131 public String fileName;
132 @XmlAttribute(name="line")
133 public String lineNumber;
134
135 StackFrame() {// for JAXB
136 }
137
138 public StackFrame(StackTraceElement ste) {
139 this.declaringClass = ste.getClassName();
140 this.methodName = ste.getMethodName();
141 this.fileName = ste.getFileName();
142 this.lineNumber = box(ste.getLineNumber());
143 }
144
145 private String box(int i) {
146 if(i>=0) return String.valueOf(i);
147 if(i==-2) return "native";
148 return "unknown";
149 }
150
151 private int unbox(String v) {
152 try {
153 return Integer.parseInt(v);
154 } catch (NumberFormatException e) {
155 if(v.equals("native")) return -2;
156 return -1;
157 }
158 }
159
160 private StackTraceElement toStackTraceElement() {
161 return new StackTraceElement(declaringClass,methodName,fileName,unbox(lineNumber));
162 }
163 }
164
165 /**
166 * Checks if the given element is the XML representation of {@link ExceptionBean}.
167 */
168 public static boolean isStackTraceXml(Element n) {
169 return n.getLocalName().equals(LOCAL_NAME) && n.getNamespaceURI().equals(NS);
170 }
171
172 private static final JAXBContext JAXB_CONTEXT;
173
174 /**
175 * Namespace URI.
176 */
177 /*package*/ static final String NS = "http://jax-ws.dev.java.net/";
178
179 /*package*/ static final String LOCAL_NAME = "exception";
180
181 static {
182 try {
183 JAXB_CONTEXT = JAXBContext.newInstance(ExceptionBean.class);
184 } catch (JAXBException e) {
185 // this must be a bug in our code
186 throw new Error(e);
187 }
188 }
189
190 private static final NamespacePrefixMapper nsp = new NamespacePrefixMapper() {
191 public String getPreferredPrefix(String namespaceUri, String suggestion, boolean requirePrefix) {
192 if(namespaceUri.equals(NS)) return "";
193 return suggestion;
194 }
195 };
196 }

mercurial