Clover Coverage Report - Atlassian Trusted Apps(Aggregated)
Coverage timestamp: Tue Jun 9 2009 19:34:44 CDT
46   308   29   1.77
8   198   0.63   2
26     1.12  
13    
 
 
  TransportErrorMessage       Line # 24 16 10 100% 1.0
  TransportErrorMessage.System       Line # 109 1 1 100% 1.0
  TransportErrorMessage.BadMagicNumber       Line # 117 1 1 100% 1.0
  TransportErrorMessage.BadProtocolVersion       Line # 125 1 1 100% 1.0
  TransportErrorMessage.ApplicationIdNotFoundInRequest       Line # 136 1 1 100% 1.0
  TransportErrorMessage.SecretKeyNotFoundInRequest       Line # 144 1 1 100% 1.0
  TransportErrorMessage.MagicNumberNotFoundInRequest       Line # 152 1 1 100% 1.0
  TransportErrorMessage.ApplicationUnknown       Line # 160 1 1 100% 1.0
  TransportErrorMessage.UserUnknown       Line # 168 1 1 100% 1.0
  TransportErrorMessage.PermissionDenied       Line # 176 1 1 100% 1.0
  TransportErrorMessage.Parser       Line # 199 8 3 100% 1.0
  TransportErrorMessage.Code       Line # 236 11 5 89.5% 0.8947368
  TransportErrorMessage.Code.Severity       Line # 290 2 2 100% 1.0
 
  (41)
 
1    package com.atlassian.security.auth.trustedapps;
2   
3    import java.text.MessageFormat;
4    import java.util.HashMap;
5    import java.util.Map;
6   
7    /**
8    * TransportErrorMessages are reported when a client makes a TrustedApplication request.
9    * <p>
10    * The String format of these is important. They basically consist of three elements:
11    * <ol>
12    * <li>Error Code (one of the {@link Code} constants)
13    * <li>Message (a MessageFormat formatted message)
14    * <li>Parameters (encoded as a JSON array)
15    * </ol>
16    * These are separated by a semi-colon tab.
17    * <p>
18    * To parse a String into a {@link TransportErrorMessage} use a {@link Parser}. If the String is not in the correct
19    * format, exceptions will be thrown. The format to the {@link #toString()} method and the format the {@link Parser}
20    * accepts must be symmetric and constant.
21    *
22    * @TODO replace inner classes with enum in JDK5
23    */
 
24    public class TransportErrorMessage
25    {
26    static final Parser PARSER = new Parser();
27   
28    // --------------------------------------------------------------------------------------------------------- members
29   
30    private final Code code;
31    private final String message;
32    private final String[] params;
33   
34    // ----------------------------------------------------------------------------------------------------------- ctors
35   
 
36  38 toggle TransportErrorMessage(Code code, String message, String[] params)
37    {
38  38 Null.not("code", code);
39  37 Null.not("params", params);
40  36 Null.not("message", message);
41  78 for (int i = 0; i < params.length; i++)
42    {
43  47 Null.not(String.valueOf(i), params[i]);
44    }
45   
46  31 this.code = code;
47  31 this.message = message;
48  31 this.params = params;
49    }
50   
 
51  4 toggle TransportErrorMessage(Code code, String message)
52    {
53  4 this(code, message, new String[0]);
54    }
55   
 
56  14 toggle TransportErrorMessage(Code code, String message, String param)
57    {
58  14 this(code, message, new String[] { param });
59    }
60   
 
61  10 toggle TransportErrorMessage(Code code, String message, String one, String two)
62    {
63  10 this(code, message, new String[] { one, two });
64    }
65   
 
66  1 toggle TransportErrorMessage(Code code, String message, String one, String two, String three)
67    {
68  1 this(code, message, new String[] { one, two, three });
69    }
70   
71    // ------------------------------------------------------------------------------------------------------- accessors
72   
 
73  4 toggle public Code getCode()
74    {
75  4 return code;
76    }
77   
 
78  3 toggle public String[] getParameters()
79    {
80  3 return (String[]) params.clone();
81    }
82   
 
83  3 toggle public String getFormattedMessage()
84    {
85  3 return MessageFormat.format(message, params);
86    }
87   
88    /**
89    * String representation of a {@link TransportErrorMessage}. Of the form:
90    *
91    * <pre>
92    * code {@link Parser#SEPARATOR} message {@link Parser#SEPARATOR} params
93    * </pre>
94    *
95    * where the params are encoded as a JSON array.
96    * <p>
97    * Note: The String representation of a {@link TransportErrorMessage} is sent across the wire as an error to the
98    * client. Therefore this format is static and must not change.
99    *
100    * @see Parser#parse(String)
101    */
 
102  60 toggle public String toString()
103    {
104  60 return PARSER.toString(this);
105    }
106   
107    // ------------------------------------------------------------------------------------------------- specializations
108   
 
109    static class System extends TransportErrorMessage
110    {
 
111  2 toggle System(Throwable cause, String appId)
112    {
113  2 super(Code.SYSTEM, "Exception: {0} occurred serving request for application: {1}", cause.toString(), appId);
114    }
115    }
116   
 
117    static class BadMagicNumber extends TransportErrorMessage
118    {
 
119  8 toggle public BadMagicNumber(String keyName, String appId)
120    {
121  8 super(Code.BAD_MAGIC, "Unable to decrypt certificate {0} for application {1}", keyName, appId);
122    }
123    }
124   
 
125    public static class BadProtocolVersion extends TransportErrorMessage
126    {
 
127  1 toggle public BadProtocolVersion(String versionString)
128    {
129  1 super(Code.BAD_PROTOCOL_VERSION, "Bad protocol version: {0}", versionString);
130    }
131    }
132   
133    /**
134    * AppId not found in request
135    */
 
136    public static class ApplicationIdNotFoundInRequest extends TransportErrorMessage
137    {
 
138  1 toggle public ApplicationIdNotFoundInRequest()
139    {
140  1 super(Code.APP_ID_NOT_FOUND, "Application ID not found in request");
141    }
142    }
143   
 
144    public static class SecretKeyNotFoundInRequest extends TransportErrorMessage
145    {
 
146  1 toggle public SecretKeyNotFoundInRequest()
147    {
148  1 super(Code.SECRET_KEY_NOT_FOUND, "Secret Key not found in request");
149    }
150    }
151   
 
152    public static class MagicNumberNotFoundInRequest extends TransportErrorMessage
153    {
 
154  1 toggle public MagicNumberNotFoundInRequest()
155    {
156  1 super(Code.MAGIC_NUMBER_NOT_FOUND, "Magic Number not found in request");
157    }
158    }
159   
 
160    public static class ApplicationUnknown extends TransportErrorMessage
161    {
 
162  2 toggle public ApplicationUnknown(String appId)
163    {
164  2 super(Code.APP_UNKNOWN, "Unknown Application: {0}", appId);
165    }
166    }
167   
 
168    public static class UserUnknown extends TransportErrorMessage
169    {
 
170  2 toggle public UserUnknown(String userName)
171    {
172  2 super(Code.USER_UNKNOWN, "Unknown User: {0}", userName);
173    }
174    }
175   
 
176    public static class PermissionDenied extends TransportErrorMessage
177    {
 
178  1 toggle public PermissionDenied()
179    {
180  1 super(Code.PERMISSION_DENIED, "Permission Denied");
181    }
182    }
183   
184    // --------------------------------------------------------------------------------------------------- inner classes
185   
186    /**
187    * Used to convert an error message String from the server at the client to a TransportErrorMessage.
188    * <p>
189    * String format is:
190    *
191    * <pre>
192    * code SEPARATOR message SEPARATOR args
193    * </pre>
194    *
195    * args are JSON array formatted.
196    *
197    * @see TransportErrorMessage#toString()
198    */
 
199    static class Parser
200    {
201    static final String SEPARATOR = ";\t";
202   
 
203  2 toggle TransportErrorMessage parse(String inputItring) throws IllegalArgumentException
204    {
205  2 Null.not("inputString", inputItring);
206  2 String[] args = inputItring.split(SEPARATOR);
207  2 if (args.length != 3)
208    {
209  1 throw new IllegalArgumentException("Cannot split message into Code, Message, Parameters:" + inputItring);
210    }
211  1 Code code = Code.get(args[0]);
212  1 String[] params = StringUtil.split(args[2]);
213  1 return new TransportErrorMessage(code, args[1], params);
214    }
215   
216    /**
217    * Format a String representation of a {@link TransportErrorMessage} in such a way as the {@link #parse(String)}
218    * method can parse it.
219    *
220    * @param msg
221    * the message to turn into a String
222    * @return the String representation of the message
223    */
 
224  60 toggle String toString(TransportErrorMessage msg)
225    {
226  60 return new StringBuffer(msg.code.getCode()).append(Parser.SEPARATOR).append(msg.message).append(Parser.SEPARATOR).append(StringUtil.toString(msg.params)).toString();
227    }
228    }
229   
230    /**
231    * Typesafe enum that contains all known error codes.
232    * <p>
233    * Note: for backwards compatibility, do not ever remove a code once its been released. Deprecate if necessary, but
234    * not remove.
235    */
 
236    public static final class Code
237    {
238    private static final Map /* <String Code> */ALL = new HashMap() /* <String Code> */;
239   
240    public static final Code UNKNOWN = new Code(Severity.ERROR, "UNKNOWN");
241   
242    public static final Code APP_UNKNOWN = new Code(Severity.ERROR, "APP_UNKNOWN");
243    public static final Code SYSTEM = new Code(Severity.ERROR, "SYSTEM");
244    public static final Code BAD_PROTOCOL_VERSION = new Code(Severity.ERROR, "BAD_PROTOCOL_VERSION");
245    public static final Code APP_ID_NOT_FOUND = new Code(Severity.ERROR, "APP_ID_NOT_FOUND");
246    public static final Code SECRET_KEY_NOT_FOUND = new Code(Severity.ERROR, "SECRET_KEY_NOT_FOUND");
247    public static final Code MAGIC_NUMBER_NOT_FOUND = new Code(Severity.ERROR, "MAGIC_NUMBER_NOT_FOUND");
248   
249    public static final Code BAD_REMOTE_IP = new Code(Severity.FAIL, "BAD_REMOTE_IP");
250    public static final Code BAD_XFORWARD_IP = new Code(Severity.FAIL, "BAD_XFORWARD_IP");
251    public static final Code BAD_URL = new Code(Severity.FAIL, "BAD_URL");
252    public static final Code OLD_CERT = new Code(Severity.FAIL, "OLD_CERT");
253    public static final Code MISSING_CERT = new Code(Severity.FAIL, "MISSING_CERT");
254    public static final Code BAD_MAGIC = new Code(Severity.FAIL, "BAD_MAGIC");
255    public static final Code USER_UNKNOWN = new Code(Severity.ERROR, "USER_UNKNOWN");
256    public static final Code PERMISSION_DENIED = new Code(Severity.ERROR, "PERMISSION_DENIED");
257   
 
258  3 toggle static Code get(String code)
259    {
260  3 final Code result = (Code) ALL.get(code);
261  3 return (result == null) ? Code.UNKNOWN : result;
262    }
263   
264    private final Severity severity;
265    private final String code;
266   
 
267  15 toggle private Code(Severity severity, final String code)
268    {
269  15 Null.not("severity", severity);
270  15 Null.not("code", code);
271  15 this.severity = severity;
272  15 this.code = code;
273  15 if (ALL.containsKey(code))
274    {
275  0 throw new IllegalArgumentException(code + " is already mapped as a " + this.getClass().getName());
276    }
277  15 ALL.put(code, this);
278    }
279   
 
280  4 toggle public Severity getSeverity()
281    {
282  4 return severity;
283    }
284   
 
285  62 toggle public String getCode()
286    {
287  62 return code;
288    }
289   
 
290    public static final class Severity
291    {
292    static final Severity ERROR = new Severity("ERROR");
293    static final Severity FAIL = new Severity("FAIL");
294   
295    private final String name;
296   
 
297  2 toggle private Severity(String name)
298    {
299  2 this.name = name;
300    }
301   
 
302  1 toggle public String toString()
303    {
304  1 return name;
305    }
306    }
307    }
308    }