001: /*
002: * ====================================================================
003: * Copyright (c) 2004-2008 TMate Software Ltd. All rights reserved.
004: *
005: * This software is licensed as described in the file COPYING, which
006: * you should have received as part of this distribution. The terms
007: * are also available at http://svnkit.com/license.html
008: * If newer versions of this license are posted there, you may use a
009: * newer version instead, at your option.
010: * ====================================================================
011: */
012: package org.tmatesoft.svn.core;
013:
014: import java.io.Serializable;
015: import java.text.MessageFormat;
016:
017: /**
018: * The <b>SVNErrorMessage</b> class represents error and warning messages describing
019: * reasons of exceptions occurred during runtime. An error message may be of two levels:
020: * <ul>
021: * <li>Error type</li>
022: * <li>Warning type</li>
023: * </ul>
024: * An error message may contain an error messages stack trace, what is useful for
025: * error reason investigations. Also such a message contains an error code ({@link SVNErrorCode})
026: * what gives an ability to find out what kind of an error it is.
027: *
028: * <p>
029: * Error messages may be formatted. <b>SVNErrorMessage</b> performs formatting with the
030: * help of the JDK's {@link MessageFormat} class. To make a formatted message, use
031: * {@link MessageFormat} parsable format patterns and provide an array of related objects
032: * when creating an <b>SVNErrorMessage</b>.
033: *
034: * <p>
035: * Error messages may be supplied within exceptions of the main exception type -
036: * {@link SVNException}.
037: *
038: * @version 1.1.1
039: * @author TMate Software Ltd.
040: */
041: public class SVNErrorMessage implements Serializable {
042: /**
043: * Error messages of this type are considered to be errors (most critical) rather
044: * than warnings.
045: */
046: public static final int TYPE_ERROR = 0;
047: /**
048: * Error messages of this type are considered to be warnings, what in certain
049: * situations may be OK.
050: */
051: public static final int TYPE_WARNING = 1;
052:
053: private Object[] myObjects;
054: private String myMessage;
055: private SVNErrorCode myErrorCode;
056: private int myType;
057: private SVNErrorMessage myChildErrorMessage;
058: private Throwable myThrowable;
059:
060: private static final Object[] EMPTY_ARRAY = new Object[0];
061:
062: /**
063: * This is a type of an error message denoting an error of an unknown nature.
064: * This corresponds to an {@link SVNErrorCode#UNKNOWN} error.
065: */
066: public static SVNErrorMessage UNKNOWN_ERROR_MESSAGE = create(SVNErrorCode.UNKNOWN);
067:
068: /**
069: * Creates an error message given an error code.
070: *
071: * @param code an error code
072: * @return a new error message
073: */
074: public static SVNErrorMessage create(SVNErrorCode code) {
075: return create(code, "", TYPE_ERROR);
076: }
077:
078: /**
079: * Creates an error message given an error code and description.
080: *
081: * @param code an error code
082: * @param message an error description
083: * @return a new error message
084: */
085: public static SVNErrorMessage create(SVNErrorCode code,
086: String message) {
087: return create(code, message, TYPE_ERROR);
088: }
089:
090: /**
091: * Creates an error message given an error code and cause.
092: *
093: * @param code an error code
094: * @param cause cause of the error
095: * @return a new error message
096: */
097: public static SVNErrorMessage create(SVNErrorCode code,
098: Throwable cause) {
099: if (cause != null) {
100: return new SVNErrorMessage(code, cause.getMessage(),
101: new Object[0], cause, TYPE_ERROR);
102: }
103: return create(code);
104: }
105:
106: /**
107: * Creates an error message given an error code, description and may be a related
108: * object to be formatted with the error description.
109: * To format the provided <code>object</code> with the <code>message</code>, you
110: * should use valid format patterns parsable for {@link MessageFormat}.
111: *
112: * @param code an error code
113: * @param message an error description
114: * @param object an object related to the error <code>message</code>
115: * @return a new error message
116: */
117: public static SVNErrorMessage create(SVNErrorCode code,
118: String message, Object object) {
119: return create(code, message, object, TYPE_ERROR);
120: }
121:
122: /**
123: * Creates an error message given an error code, description and may be related
124: * objects to be formatted with the error description.
125: * To format the provided <code>objects</code> with the <code>message</code>, you
126: * should use valid format patterns parsable for {@link MessageFormat}.
127: *
128: * @param code an error code
129: * @param message an error description
130: * @param objects an array of objects related to the error <code>message</code>
131: * @return a new error message
132: */
133: public static SVNErrorMessage create(SVNErrorCode code,
134: String message, Object[] objects) {
135: return create(code, message, objects, TYPE_ERROR);
136: }
137:
138: /**
139: * Creates an error message given an error code, description and a type (
140: * whether it's a warning or an error).
141: *
142: * @param code an error code
143: * @param message an error description
144: * @param type an error type
145: * @return a new error message
146: */
147: public static SVNErrorMessage create(SVNErrorCode code,
148: String message, int type) {
149: return new SVNErrorMessage(code, message, EMPTY_ARRAY, null,
150: type);
151: }
152:
153: /**
154: * Creates an error message given an error code, description, an error type
155: * (whether it's a warning or an error) and may be a related object to be
156: * formatted with the error description. To format the provided <code>object</code>
157: * with the <code>message</code>, you should use valid format patterns parsable for
158: * {@link MessageFormat}.
159: *
160: * @param code an error code
161: * @param message an error description
162: * @param object an object related to the error <code>message</code>
163: * @param type an error type
164: * @return a new error message
165: */
166: public static SVNErrorMessage create(SVNErrorCode code,
167: String message, Object object, int type) {
168: return new SVNErrorMessage(code == null ? SVNErrorCode.BASE
169: : code, message == null ? "" : message,
170: object == null ? new Object[] { "NULL" }
171: : new Object[] { object }, null, type);
172: }
173:
174: /**
175: * Creates an error message given an error code, description, an error type
176: * (whether it's a warning or an error) and may be related objects to be
177: * formatted with the error description. To format the provided <code>objects</code>
178: * with the <code>message</code>, you should use valid format patterns parsable for
179: * {@link MessageFormat}.
180: *
181: * @param code an error code
182: * @param message an error description
183: * @param objects an array of objects related to the error <code>message</code>
184: * @param type an error type
185: * @return a new error message
186: */
187: public static SVNErrorMessage create(SVNErrorCode code,
188: String message, Object[] objects, int type) {
189: return new SVNErrorMessage(code == null ? SVNErrorCode.BASE
190: : code, message == null ? "" : message,
191: objects == null ? EMPTY_ARRAY : objects, null, type);
192: }
193:
194: protected SVNErrorMessage(SVNErrorCode code, String message,
195: Object[] relatedObjects, Throwable th, int type) {
196: myErrorCode = code;
197: if (message != null && message.startsWith("svn: ")) {
198: message = message.substring("svn: ".length());
199: }
200: myMessage = message;
201: myObjects = relatedObjects;
202: myType = type;
203: myThrowable = th;
204: }
205:
206: /**
207: * Returns the type of the error (whether it's a warning or an error).
208: *
209: * @return the type of this error message
210: */
211: public int getType() {
212: return myType;
213: }
214:
215: /**
216: * Returns the error code of the error.
217: *
218: * @return th error code of the error
219: */
220: public SVNErrorCode getErrorCode() {
221: return myErrorCode;
222: }
223:
224: /**
225: * Returns an error description formatted with the
226: * related objects if needed. This call is equivalent to
227: * a call to {@link #toString()}
228: *
229: * @return an error message
230: */
231: public String getMessage() {
232: return toString();
233: }
234:
235: /**
236: * Gets a string representation of the entire stack trace of
237: * error messages (if they were provided) starting with the initial
238: * cause of the error.
239: *
240: * @return a string representing a full list of error messages
241: */
242: public String getFullMessage() {
243: SVNErrorMessage err = this ;
244: StringBuffer buffer = new StringBuffer();
245: while (err != null) {
246: buffer.append(err.getMessage());
247: if (err.hasChildErrorMessage()) {
248: buffer.append('\n');
249: }
250: err = err.getChildErrorMessage();
251: }
252: return buffer.toString();
253: }
254:
255: /**
256: * Returns an error description which may contain message format
257: * patterns.
258: *
259: * @return an error description
260: */
261: public String getMessageTemplate() {
262: return myMessage;
263: }
264:
265: /**
266: * Returns objects (if any) that were provided to be formatted
267: * with the error description. Objects are formatted by the standard
268: * {@link MessageFormat} engine.
269: *
270: * @return an array of objects
271: */
272: public Object[] getRelatedObjects() {
273: return myObjects;
274: }
275:
276: /**
277: * Returns an error message (if any) that was returned from a
278: * deeper method call. So the topmost error messages have the
279: * entire chain of error messages down to the real error cause.
280: *
281: * @return a child error message object (if this object is not the
282: * first one)
283: */
284: public SVNErrorMessage getChildErrorMessage() {
285: return myChildErrorMessage;
286: }
287:
288: /**
289: * Says if this error message object has got a child error message.
290: *
291: * @return <span class="javakeyword">true</span> if has,
292: * <span class="javakeyword">false</span> otherwise (for
293: * example, an initial error message would not have a child
294: * error message)
295: */
296: public boolean hasChildErrorMessage() {
297: return myChildErrorMessage != null;
298: }
299:
300: /**
301: * Returns throwable that is cause of the error if any.
302: *
303: * @return throwable that caused error or null if not applicable or not known.
304: */
305: public Throwable getCause() {
306: return myThrowable;
307: }
308:
309: /**
310: * Returns a string representation of this error message object
311: * formatting (if needed) the error description with the provided related objects.
312: * If no error description pattern has been provided, the return
313: * value includes a string representation of the error code (see {@link SVNErrorCode}).
314: *
315: * @return a string representing this object.
316: */
317: public String toString() {
318: StringBuffer line = new StringBuffer();
319: if (getType() == TYPE_WARNING
320: && getErrorCode() == SVNErrorCode.REPOS_POST_COMMIT_HOOK_FAILED) {
321: line.append("Warning: ");
322: } else if (getType() == TYPE_WARNING) {
323: line.append("svn: warning: ");
324: } else {
325: line.append("svn: ");
326: }
327: if ("".equals(myMessage)) {
328: line.append(myErrorCode.getDescription());
329: } else {
330: line.append(myObjects.length > 0 ? MessageFormat.format(
331: myMessage, myObjects) : myMessage);
332: }
333: return line.toString();
334: }
335:
336: /**
337: * Sets a child error message for this one.
338: *
339: * @param childMessage a child error message
340: */
341: public void setChildErrorMessage(SVNErrorMessage childMessage) {
342: myChildErrorMessage = childMessage;
343: }
344:
345: /**
346: * Wraps this error message into a new one that is returned as
347: * a parent error message. A parent message is set the error code
348: * of this error message, a new error description and this error
349: * message as its child.
350: *
351: * @param parentMessage a parent error description
352: * @return a parent error message
353: */
354: public SVNErrorMessage wrap(String parentMessage) {
355: SVNErrorMessage parentError = SVNErrorMessage.create(this
356: .getErrorCode(), parentMessage);
357: parentError.setChildErrorMessage(this );
358: return parentError;
359: }
360:
361: /**
362: * Wraps this error message into a new one that is returned as
363: * a parent error message. A parent message is set the error code
364: * of this error message, a new error description and this error
365: * message as its child.
366: *
367: * @param parentMessage a parent error description
368: * @param relatedObject an object to be formatted with <code>parentMessage</code>
369: * @return a parent error message
370: */
371: public SVNErrorMessage wrap(String parentMessage,
372: Object relatedObject) {
373: SVNErrorMessage parentError = SVNErrorMessage.create(this
374: .getErrorCode(), parentMessage, relatedObject);
375: parentError.setChildErrorMessage(this );
376: return parentError;
377: }
378:
379: public SVNErrorMessage wrap(String parentMessage,
380: Object[] relatedObjects) {
381: SVNErrorMessage parentError = SVNErrorMessage.create(this
382: .getErrorCode(), parentMessage, relatedObjects);
383: parentError.setChildErrorMessage(this );
384: return parentError;
385: }
386:
387: /**
388: * Returns true if this message is a warning message, not error one.
389: *
390: * @return true or false
391: */
392: public boolean isWarning() {
393: return myType == TYPE_WARNING;
394: }
395:
396: }
|