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      private static final Integer INTERNAL_SERVER_ERROR_CODE =
23              Integer.valueOf(Response.Status.INTERNAL_SERVER_ERROR.getStatusCode());
24  
25      /**
26       * This is a redundant duplicate of the HTTP error code but it may be clearer in
27       * a browser.
28       */
29      @XmlElement(name = "status-code")
30      private final Integer code = INTERNAL_SERVER_ERROR_CODE;
31  
32      /**
33       * A humane readable message for the given status.
34       */
35      @XmlElement
36      private final String message;
37  
38      @XmlElement(name = "stack-trace")
39      private final String stackTrace;
40  
41      /**
42       * JAXB requires a default constructor.
43       */
44      public UncaughtExceptionEntity() {
45          this.message = null;
46          this.stackTrace = "";
47      }
48  
49      public UncaughtExceptionEntity(Throwable t) {
50          this.message = t.getMessage();
51  
52          StringWriter sw = new StringWriter();
53  
54          PrintWriter pw = new PrintWriter(sw);
55          t.printStackTrace(pw);
56  
57          this.stackTrace = sw.toString();
58      }
59  
60      public String getMessage() {
61          return message;
62      }
63  
64      public String getStackTrace() {
65          return stackTrace;
66      }
67  
68      private static final MediaType TEXT_PLAIN_UTF8_TYPE = MediaType.valueOf("text/plain; charset=utf-8");
69  
70      /**
71       * These are the media types that an UncaughtExceptionEntity can be represented as.
72       */
73      private static final List<Variant> POSSIBLE_VARIANTS = Variant.mediaTypes(
74              MediaType.APPLICATION_XML_TYPE,
75              MediaType.APPLICATION_JSON_TYPE,
76              MediaType.TEXT_PLAIN_TYPE).add().build();
77  
78      public static MediaType variantFor(Request request) {
79          Variant v = request.selectVariant(POSSIBLE_VARIANTS);
80          if (v == null) {
81              v = POSSIBLE_VARIANTS.get(0);
82          }
83  
84          /* If we include the charset in the variant then it gets prioritised as a default. Select
85           * it as text/plain and then switch in the variant with the charset here.
86           */
87          MediaType t = v.getMediaType();
88  
89          if (t.equals(MediaType.TEXT_PLAIN_TYPE)) {
90              return TEXT_PLAIN_UTF8_TYPE;
91          } else {
92              return t;
93          }
94      }
95  }