View Javadoc

1   package com.atlassian.plugins.rest.common.error.jersey;
2   
3   import java.io.PrintWriter;
4   import java.io.StringWriter;
5   import java.util.List;
6   
7   import javax.ws.rs.core.MediaType;
8   import javax.ws.rs.core.Request;
9   import javax.ws.rs.core.Response;
10  import javax.ws.rs.core.Variant;
11  import javax.xml.bind.annotation.XmlElement;
12  import javax.xml.bind.annotation.XmlRootElement;
13  
14  import com.atlassian.plugins.rest.common.Status;
15  
16  /**
17   * An analog of {@link Status} specifically for uncaught exceptions. The stack trace is
18   * included.
19   */
20  @XmlRootElement(name="status")
21  public class UncaughtExceptionEntity
22  {
23      private static final Integer INTERNAL_SERVER_ERROR_CODE =
24              Integer.valueOf(Response.Status.INTERNAL_SERVER_ERROR.getStatusCode());
25  
26      /**
27       * This is a redundant duplicate of the HTTP error code but it may be clearer in
28       * a browser.
29       */
30      @XmlElement(name = "status-code")
31      private final Integer code = INTERNAL_SERVER_ERROR_CODE;
32  
33      /**
34       * A humane readable message for the given status.
35       */
36      @XmlElement
37      private final String message;
38  
39      @XmlElement(name = "stack-trace")
40      private final String stackTrace;
41  
42      /**
43       * JAXB requires a default constructor.
44       */
45      public UncaughtExceptionEntity()
46      {
47          this.message = null;
48          this.stackTrace = "";
49      }
50  
51      public UncaughtExceptionEntity(Throwable t)
52      {
53          this.message = t.getMessage();
54  
55          StringWriter sw = new StringWriter();
56  
57          PrintWriter pw = new PrintWriter(sw);
58          t.printStackTrace(pw);
59  
60          this.stackTrace = sw.toString();
61      }
62  
63      public String getMessage()
64      {
65          return message;
66      }
67  
68      public String getStackTrace()
69      {
70          return stackTrace;
71      }
72  
73      private static final MediaType TEXT_PLAIN_UTF8_TYPE = MediaType.valueOf("text/plain; charset=utf-8");
74  
75      /**
76       * These are the media types that an UncaughtExceptionEntity can be represented as.
77       */
78      private static final List<Variant> POSSIBLE_VARIANTS = Variant.mediaTypes(
79              MediaType.APPLICATION_XML_TYPE,
80              MediaType.APPLICATION_JSON_TYPE,
81              MediaType.TEXT_PLAIN_TYPE).add().build();
82  
83      public static MediaType variantFor(Request request)
84      {
85          Variant v = request.selectVariant(POSSIBLE_VARIANTS);
86          if (v == null)
87          {
88              v = POSSIBLE_VARIANTS.get(0);
89          }
90  
91          /* If we include the charset in the variant then it gets prioritised as a default. Select
92           * it as text/plain and then switch in the variant with the charset here.
93           */
94          MediaType t = v.getMediaType();
95  
96          if (t.equals(MediaType.TEXT_PLAIN_TYPE))
97          {
98              return TEXT_PLAIN_UTF8_TYPE;
99          }
100         else
101         {
102             return t;
103         }
104     }
105 }