Statistics
| Revision:

gvsig-tools / org.gvsig.tools / library / trunk / org.gvsig.tools / org.gvsig.tools.lib / src / main / java / org / gvsig / tools / exception / BaseException.java @ 3067

History | View | Annotate | Download (12.7 KB)

1
/**
2
 * gvSIG. Desktop Geographic Information System.
3
 *
4
 * Copyright (C) 2007-2013 gvSIG Association.
5
 *
6
 * This program is free software; you can redistribute it and/or
7
 * modify it under the terms of the GNU General Public License
8
 * as published by the Free Software Foundation; either version 2
9
 * of the License, or (at your option) any later version.
10
 *
11
 * This program is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 * GNU General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU General Public License
17
 * along with this program; if not, write to the Free Software
18
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19
 * MA  02110-1301, USA.
20
 *
21
 * For any additional information, do not hesitate to contact us
22
 * at info AT gvsig.com, or visit our website www.gvsig.com.
23
 */
24
/*
25
 * AUTHORS (In addition to CIT):
26
 */
27
package org.gvsig.tools.exception;
28

    
29
import java.lang.reflect.Method;
30
import java.util.HashMap;
31
import java.util.Iterator;
32
import java.util.Map;
33
import org.apache.commons.lang3.StringUtils;
34
import org.gvsig.tools.ToolsLocator;
35
import org.gvsig.tools.i18n.I18nManager;
36

    
37
/**
38
 * 
39
 * Esta clase esta pensada para actuar como clase base para las excepciones que
40
 * se lanzan dentro del proyecto de gvSIG.
41
 * 
42
 * A?ade la implementacion necesaria para disponer de mensajes de error
43
 * internacionalizables, a traves del metodo getLocalizedMessage, asi como una
44
 * serie de metodos que nos permiten obtener los mesanes de error de la cadena
45
 * de excepciones enlazadas a traves de su "causa", asi como utilidades que
46
 * permitan recorrer de forma comoda esta cadena de excepciones por medio de un
47
 * Iterador.
48
 * 
49
 * @author Equipo de desarrollo de gvSIG.
50
 * 
51
 */
52
@SuppressWarnings("UseSpecificCatch")
53
public abstract class BaseException extends Exception implements IBaseException {
54
        /**
55
         *
56
         */
57
        private static final long serialVersionUID = 6631799898764636572L;
58
        final static String BLANKS = "                                                                                                     ";
59
        static ExceptionTranslator translator = null;
60

    
61
        protected String messageKey;
62

    
63
        /**
64
         * TODO: remove the variable, use the Exception get/setMessage() instead.
65
         */
66
        protected String formatString;
67

    
68
        /**
69
         * Unique code of error.
70
         */
71
        protected long code;
72
        private Map values;
73

    
74
        /**
75
         * Empty constructor, don't use it anymore.
76
         * 
77
         * @deprecated
78
         */
79
        public BaseException() {
80
        }
81

    
82
        /**
83
         * Constructs a BaseException with a default message format, a key to find a
84
         * localized message format, and a unique code to identify the exception.
85
         * 
86
         * @param message
87
         *            the default messageFormat to describe the exception
88
         * @param key
89
         *            the key to use to search a localized messageFormnata
90
         * @param code
91
         *            the unique code to identify the exception
92
         */
93
        public BaseException(String message, String key, long code) {
94
                super(message);
95
                this.values = null;
96
                this.formatString = message;
97
                this.messageKey = key;
98
                this.code = code;
99
        }
100

    
101
        /**
102
         * Constructs a BaseException with a default message format, a key to find a
103
         * localized message format, and a unique code to identify the exception.
104
         * 
105
         * @param message
106
         *            the default messageFormat to describe the exception
107
         * @param cause
108
         *            the original cause of the exception
109
         * @param key
110
         *            the key to use to search a localized messageFormnata
111
         * @param code
112
         *            the unique code to identify the exception
113
         */
114
        public BaseException(String message, Throwable cause, String key, long code) {
115
                super(message, cause);
116
                this.formatString = message;
117
                this.messageKey = key;
118
                this.code = code;
119
        }
120

    
121
        /**
122
         * Returns the format string received in the parameter with its keys
123
         * replaced with the corresponding values of the map.
124
         * 
125
         * @param formatString
126
         * @param values
127
         *            map
128
         * @return string formatted
129
         */
130
        private String format(String formatString, Map values) {
131
                if (values != null) {
132

    
133
                        // If there is no message format, create a text with the values.
134
                        if (formatString == null) {
135
                                return "values = ".concat(values.toString());
136
                        } else {
137
                                // Replace the keys as variables with the values in the Map
138
                                Iterator keys = values.keySet().iterator();
139
                                String message = formatString;
140
                                while (keys.hasNext()) {
141
                                        String key = (String) keys.next();
142
                                        Object value = values.get(key);
143
                                        message = replaceVariable(message, key, value == null ? ""
144
                                                        : value.toString());
145
                                }
146
                                return message;
147
                        }
148
                }
149
                // Return the original format message in any other case
150
                return formatString;
151
        }
152

    
153
        /**
154
         * Method to replace message variables.
155
         */
156
        private String replaceVariable(String text, String varName,String replacementString) {
157
                String s = StringUtils.replace(text, "%(".concat(varName).concat(")s"), replacementString);
158
                
159
                // El siguiente reemplazo lo hacemos por que hay muchos mensajes de
160
                // error que no llevan la "s" tras el parentetsis de cierre.
161
                s = StringUtils.replace(s, "%(".concat(varName).concat(")"), replacementString);
162
                return s;
163
        }
164

    
165
        @Override
166
        public String getMessage() {
167
                return format(this.formatString, values());
168
        }
169

    
170
        @Override
171
        public String getMessage(int indent) {
172
                return insertBlanksAtStart(format(formatString, values()), indent);
173
        }
174

    
175
        @Override
176
        public String getLocalizedMessage() {
177
                return getLocalizedMessage(translator, 0);
178
        }
179

    
180
        @Override
181
    public String getLocalizedMessage(ExceptionTranslator translator, int indent) {
182

    
183
        String fmt;
184
        if (translator == null) {
185
            translator = BaseException.translator;
186
        }
187
        if (translator == null) {
188
            I18nManager i18n = ToolsLocator.getI18nManager();
189
            fmt = i18n.getTranslation(getMessageKey());
190
            if (fmt == null || fmt.startsWith("_")) {
191
                fmt = getFormatString();
192
            }
193
        } else {
194
            fmt = getMessageKey();
195
            if (fmt == null) {
196
                fmt = getFormatString();
197
            } else {
198
                String fmt2 = translator.getText(fmt);
199
                if (fmt2 == null || fmt.equals(fmt2)) {
200
                    return getMessage(indent);
201
                } else {
202
                    fmt = fmt2;
203
                }
204
            }
205
        }
206
        return insertBlanksAtStart(format(fmt, values()), indent);
207
    }
208

    
209
        @Override
210
        public String getMessageStack() {
211
                return getMessageStack(0);
212
        }
213

    
214
        @Override
215
        public String getMessageStack(int indent) {
216
            return getMessageStack(this, indent);
217
        }
218
        
219
        public static String getHTMLMessageStack(Throwable th) {
220
                Iterator iter = new BaseExceptionIterator(th);
221
                StringBuilder msgBuffer = new StringBuilder();
222
                int i = 1;
223
                msgBuffer.append("<ul>\n");
224
                while (iter.hasNext()) {
225
                        Throwable ex = ((Throwable) iter.next());
226

    
227
                        if (ex instanceof IBaseException) {
228
                                IBaseException bex = (IBaseException) ex;
229
                                 msgBuffer.append("<li>");
230
                                 msgBuffer.append(bex.getMessage());
231
                                 msgBuffer.append(" (");
232
                                 msgBuffer.append(bex.getClass().getSimpleName());
233
                                 msgBuffer.append(")");
234
                                 
235
                                 msgBuffer.append("</li>\n");
236
                        } else if( ex !=null ) {
237
                                 msgBuffer.append("<li>");
238
                                 msgBuffer.append(ex.getMessage());
239
                                 msgBuffer.append(" (");
240
                                 msgBuffer.append(ex.getClass().getSimpleName());
241
                                 msgBuffer.append(")");
242
                                 msgBuffer.append("</li>\n");
243
                        }
244

    
245
                        i++;
246
                }
247
                msgBuffer.append("</ul>\n");
248
                return msgBuffer.toString();
249
        }
250

    
251
        public static String getMessageStack(Throwable th, int indent) {
252
                Iterator iter = new BaseExceptionIterator(th);
253
                StringBuilder msgBuffer = new StringBuilder();
254
                int i = 1;
255
                while (iter.hasNext()) {
256
                        Throwable ex = ((Throwable) iter.next());
257

    
258
                        if (msgBuffer.length() > 0) {
259
                                msgBuffer.append("\n");
260
                        }
261

    
262
                        if (ex instanceof IBaseException) {
263
                                IBaseException bex = (IBaseException) ex;
264
                                 msgBuffer.append(bex.getMessage(indent * i));
265
                        } else if( ex !=null ) {
266
                                msgBuffer.append(
267
                                    insertBlanksAtStart(ex.getMessage(), indent* i)
268
                                );
269
                        }
270

    
271
                        i++;
272
                }
273
                return msgBuffer.toString();
274
        }
275

    
276
        @Override
277
        public String getLocalizedMessageStack() {
278
                return getLocalizedMessageStack(BaseException.translator, 0);
279
        }
280

    
281
        @Override
282
        public String getLocalizedMessageStack(ExceptionTranslator translator,
283
                        int indent) {
284
                Iterator iter = this.iterator();
285
                StringBuilder msgBuffer = new StringBuilder();
286
                // msgBuffer.append(this.getLocalizedMessage());
287
                Exception ex;
288
                while (iter.hasNext()) {
289
                        ex = ((Exception) iter.next());
290
                        if (msgBuffer.length() > 0) {
291
                                msgBuffer.append("\n");
292
                        }
293

    
294
                        if (ex instanceof IBaseException) {
295
                                IBaseException bex = (IBaseException) ex;
296
                                msgBuffer.append(bex.getLocalizedMessage(translator, indent));
297
                        } else if( ex !=null ) {
298
                                msgBuffer.append(ex.getLocalizedMessage());
299
                                msgBuffer.append(" (");
300
                                msgBuffer.append(ex.getClass().getName());
301
                                msgBuffer.append(")");
302
                        }
303
                }
304
                return msgBuffer.toString();
305
        }
306

    
307
        /**
308
         * Inserts blanks at the start of a string.
309
         * 
310
         * @param str
311
         *            A string.
312
         * @param len
313
         *            Quantity of blanks to insert at the start of str.
314
         * @return A string compund by the quantity of blanks that len indicates and
315
         *         str.
316
         */
317
        static String insertBlanksAtStart(String str, int len) {
318
                int blanksLen = len > BLANKS.length() ? BLANKS.length() : (len < 0 ? 0
319
                                : len);
320

    
321
                return BLANKS.substring(0, blanksLen) + str;
322
        }
323

    
324
        @Override
325
        public long getCode() {
326
                return this.code;
327
        }
328

    
329
        /**
330
         * Sets the exception's code.
331
         * @param code
332
         */
333
        public void setCode(long code) {
334
                this.code = code;
335
        }
336

    
337
        @Override
338
        public String getFormatString() {
339
                return this.formatString;
340
        }
341

    
342
        /**
343
         * Sets the format string.
344
         * 
345
         * @param formatString
346
         */
347
        public void setFormatString(String formatString) {
348
                this.formatString = formatString;
349
        }
350

    
351
        @Override
352
        public String getMessageKey() {
353
                return this.messageKey;
354
        }
355

    
356
        /**
357
         * Sets the property messageKey.
358
         * 
359
         * @param messageKey
360
         */
361
        public void setMessageKey(String messageKey) {
362
                this.messageKey = messageKey;
363
        }
364

    
365
        @Override
366
        public Iterator iterator() {
367
                return new BaseExceptionIterator(this);
368
        }
369

    
370
        /**
371
         * @return A map that serves to replace in the format string the keys with
372
         *         the corresponding values.
373
         */
374
        protected Map values() {
375
                if (values == null) {
376
                        values = new HashMap();
377
                }
378
                return values;
379
        }
380
        
381
        @Override
382
        public Object getValue(String name) {
383
            return this.values.get(name);
384
        }
385

    
386
        protected void setValue(String name, Object value) {
387
                if (values == null) {
388
                        values = new HashMap();
389
                }
390
                values.put(name, value);
391
        }
392

    
393
        /**
394
         * Sets the property translator.
395
         * 
396
         * @param translator
397
         *            It(He,She) is used to translate the messages associated with
398
         *            the exceptions.
399
         */
400
        public static void setTranslator(ExceptionTranslator translator) {
401
                BaseException.translator = translator;
402
        }
403

    
404
        public static void setTranslator(Object translator) {
405
                BaseException.translator = new TranslatorWraper(translator);
406
        }
407

    
408
        public static boolean containsCause(Throwable ex, Class<? extends Throwable> searchException) {
409
            if(searchException.isInstance(ex)){
410
                return true;
411
            }
412
            BaseExceptionIterator it = new BaseExceptionIterator(ex);
413
            while (it.hasNext()) {
414
                if(searchException.isInstance(it.next())){
415
                    return true;
416
                }
417
            }
418
            return false;
419
        }
420

    
421
}
422

    
423
@SuppressWarnings("UseSpecificCatch")
424
class TranslatorWraper implements ExceptionTranslator {
425

    
426
        private Object translator = null;
427
        private Method method = null;
428

    
429
        public TranslatorWraper(Object translator) {
430
                Class theClass = translator.getClass();
431
                String s = "";
432

    
433
                this.translator = translator;
434
                try {
435
                        method = theClass
436
                                        .getMethod("getText", new Class[] { s.getClass() });
437
                } catch (Exception e) {
438
                        throw new RuntimeException(
439
                                        "El objeto translator suministrado no tiene el metodo getText apropiado.",
440
                                        e);
441
                }
442

    
443
        }
444

    
445
        @Override
446
        public String getText(String key) {
447
                try {
448
                        return (String) (method.invoke(translator, (Object[]) new String[] { key }));
449
                } catch (Exception e) {
450
                        return key;
451
                }
452
        }
453

    
454
}