1 /**
2 * Copyright (C) 2005-2009 Alfresco Software Limited.
3 *
4 * This file is part of the Spring Surf Extension project.
5 *
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 */
18
19 package org.springframework.extensions.surf.exception;
20
21 import java.util.Date;
22 import java.util.concurrent.atomic.AtomicInteger;
23
24 import org.springframework.extensions.surf.util.I18NUtil;
25
26 /**
27 * Base exception for Spring Surf platform (i18n enabled)
28 *
29 * @author gavinc
30 */
31 public class PlatformRuntimeException extends RuntimeException
32 {
33 /**
34 * Serial version UUID
35 */
36 private static final long serialVersionUID = 3834594313622859827L;
37
38 /**
39 * Helper factory method making use of variable argument numbers
40 */
41 public static PlatformRuntimeException create(String msgId, Object ...objects)
42 {
43 return new PlatformRuntimeException(msgId, objects);
44 }
45
46 /**
47 * Helper factory method making use of variable argument numbers
48 */
49 public static PlatformRuntimeException create(Throwable cause, String msgId, Object ...objects)
50 {
51 return new PlatformRuntimeException(msgId, objects, cause);
52 }
53
54 /**
55 * Utility to convert a general Throwable to a RuntimeException. No conversion is done if the
56 * throwable is already a <tt>RuntimeException</tt>.
57 *
58 * @see #create(Throwable, String, Object...)
59 */
60 public static RuntimeException makeRuntimeException(Throwable e, String msgId, Object ...objects)
61 {
62 if (e instanceof RuntimeException)
63 {
64 return (RuntimeException) e;
65 }
66 // Convert it
67 return PlatformRuntimeException.create(e, msgId, objects);
68 }
69
70 /**
71 * Constructor
72 *
73 * @param msgId the message id
74 */
75 public PlatformRuntimeException(String msgId)
76 {
77 super(resolveMessage(msgId, null));
78 }
79
80 /**
81 * Constructor
82 *
83 * @param msgId the message id
84 * @param msgParams the message parameters
85 */
86 public PlatformRuntimeException(String msgId, Object[] msgParams)
87 {
88 super(resolveMessage(msgId, msgParams));
89 }
90
91 /**
92 * Constructor
93 *
94 * @param msgId the message id
95 * @param cause the exception cause
96 */
97 public PlatformRuntimeException(String msgId, Throwable cause)
98 {
99 super(resolveMessage(msgId, null), cause);
100 }
101
102 /**
103 * Constructor
104 *
105 * @param msgId the message id
106 * @param msgParams the message parameters
107 * @param cause the exception cause
108 */
109 public PlatformRuntimeException(String msgId, Object[] msgParams, Throwable cause)
110 {
111 super(resolveMessage(msgId, msgParams), cause);
112 }
113
114 /**
115 * Resolves the message id to the localised string.
116 * <p>
117 * If a localised message can not be found then the message Id is
118 * returned.
119 *
120 * @param messageId the message Id
121 * @param params message parameters
122 * @return the localised message (or the message id if none found)
123 */
124 private static String resolveMessage(String messageId, Object[] params)
125 {
126 String message = I18NUtil.getMessage(messageId, params);
127 if (message == null)
128 {
129 // If a localised string cannot be found then return the messageId
130 message = messageId;
131 }
132 return buildErrorLogNumber(message);
133 }
134
135 /**
136 * Generate an error log number - based on MMDDXXXX - where M is month,
137 * D is day and X is an atomic integer count.
138 *
139 * @param message Message to prepend the error log number to
140 *
141 * @return message with error log number prefix
142 */
143 private static String buildErrorLogNumber(String message)
144 {
145 // ensure message is not null
146 if (message == null)
147 {
148 message= "";
149 }
150
151 Date today = new Date();
152 StringBuilder buf = new StringBuilder(message.length() + 10);
153 padInt(buf, today.getMonth(), 2);
154 padInt(buf, today.getDate(), 2);
155 padInt(buf, errorCounter.getAndIncrement(), 4);
156 buf.append(' ');
157 buf.append(message);
158 return buf.toString();
159 }
160
161 /**
162 * Helper to zero pad a number to specified length
163 */
164 private static void padInt(StringBuilder buffer, int value, int length)
165 {
166 String strValue = Integer.toString(value);
167 for (int i = length - strValue.length(); i > 0; i--)
168 {
169 buffer.append('0');
170 }
171 buffer.append(strValue);
172 }
173
174 private static AtomicInteger errorCounter = new AtomicInteger();
175 }