EMMA Coverage Report (generated Tue Feb 12 22:23:49 ICT 2008)
[all classes][net.sourceforge.hivetranse.exception]

COVERAGE SUMMARY FOR SOURCE FILE [SqlExceptionMapper.java]

nameclass, %method, %block, %line, %
SqlExceptionMapper.java100% (1/1)100% (10/10)73%  (234/319)84%  (59/70)

COVERAGE BREAKDOWN BY CLASS AND METHOD

nameclass, %method, %block, %line, %
     
class SqlExceptionMapper100% (1/1)100% (10/10)73%  (234/319)84%  (59/70)
addCodesMapping (Class, String, Location): void 100% (1/1)52%  (75/144)77%  (20/26)
translate (Throwable): Throwable 100% (1/1)75%  (36/48)77%  (10/13)
findState (String): Class 100% (1/1)85%  (22/26)71%  (5/7)
SqlExceptionMapper (List): void 100% (1/1)100% (6/6)100% (2/2)
SqlExceptionMapper (Log, List): void 100% (1/1)100% (30/30)100% (8/8)
addMapping (SqlCodesMappingContribution): void 100% (1/1)100% (21/21)100% (5/5)
addStatesMapping (Class, String): void 100% (1/1)100% (20/20)100% (6/6)
buildException (SQLException, Class): Throwable 100% (1/1)100% (15/15)100% (1/1)
findCode (int): Class 100% (1/1)100% (7/7)100% (1/1)
preTranslate (SQLException): Class 100% (1/1)100% (2/2)100% (1/1)

1//  Copyright 2004-2007 Jean-Francois Poilpret
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14 
15package net.sourceforge.hivetranse.exception;
16 
17import java.sql.SQLException;
18import java.util.HashMap;
19import java.util.List;
20import java.util.Map;
21import java.util.StringTokenizer;
22 
23import org.apache.commons.logging.Log;
24import org.apache.commons.logging.LogFactory;
25import org.apache.hivemind.Location;
26import org.apache.hivemind.util.ConstructorUtils;
27 
28import net.sourceforge.hiveutils.service.ExceptionMapper;
29 
30/**
31 *
32 * @author Jean-Francois Poilpret
33 */
34public class SqlExceptionMapper implements ExceptionMapper
35{
36        public SqlExceptionMapper(List<SqlCodesMappingContribution> config)
37        {
38                this(LogFactory.getLog(SqlExceptionMapper.class), config);
39        }
40        
41        public SqlExceptionMapper(Log logger, List<SqlCodesMappingContribution> config)
42        {
43                _logger = logger;
44                for (SqlCodesMappingContribution contrib: config)
45                {
46                        // Add codes list to _classes
47                        addMapping(contrib);
48                }
49        }
50        
51        public Throwable        translate(Throwable t)
52        {
53                if (t instanceof SQLException)
54                {
55                        SQLException e = (SQLException) t;
56                        Class clazz;
57                        // First check if a specific mapping exists (by a subclass)
58                        clazz = preTranslate(e);
59                        if (clazz != null)
60                        {
61                                return buildException(e, clazz);
62                        }
63                        // Then check if a mapping exists for the ErrorCode
64                        clazz = findCode(e.getErrorCode());
65                        if (clazz != null)
66                        {
67                                return buildException(e, clazz);
68                        }
69                        // Then check if a mapping exists for the SqlState or a part of it
70                        clazz = findState(e.getSQLState());
71                        if (clazz != null)
72                        {
73                                return buildException(e, clazz);
74                        }
75                        return buildException(e, UnknownDataAccessException.class);
76                }
77                else
78                {
79                        return t;
80                }
81        }
82        
83        protected void        addMapping(SqlCodesMappingContribution contrib)
84        {
85                if (contrib.getCodes() != null)
86                {
87                        addCodesMapping(contrib.getClazz(), contrib.getCodes(), contrib.getLocation());
88                }
89                if (contrib.getStates() != null)
90                {
91                        addStatesMapping(contrib.getClazz(), contrib.getStates());
92                }
93        }
94        
95        protected void        addCodesMapping(Class clazz, String codes, Location location)
96        {
97                // Parse codes list
98                StringTokenizer tokenize = new StringTokenizer(codes, ", \t\n\r");
99                int i = 0;
100                String token = null;
101                while (tokenize.hasMoreTokens())
102                {
103                        try
104                        {
105                                i++;
106                                token = tokenize.nextToken();
107                                // Also allow ranges min:max
108                                int index = token.indexOf(':');
109                                if (index == -1)
110                                {
111                                        Integer code = Integer.valueOf(token);
112                                        _codes.put(code, clazz);
113                                }
114                                else if (index == 0 || index == token.length() - 1)
115                                {
116                                        _logger.warn(        "addCodesMapping() could not add item[" + i + 
117                                                                        "] (" + token + ") from configuration " + 
118                                                                        location);
119                                }
120                                else
121                                {
122                                        int min = Integer.parseInt(token.substring(0, index));
123                                        int max = Integer.parseInt(token.substring(index + 1));
124                                        if (min < max)
125                                        {
126                                                for (int code = min; code <= max; code++)
127                                                {
128                                                        _codes.put(code, clazz);
129                                                }
130                                        }
131                                        else
132                                        {
133                                                _logger.warn(        "addCodesMapping() could not add item[" + i + 
134                                                                                "] (" + token + ") from configuration " + 
135                                                                                location + " [min=" + min + ",max=" + max);
136                                        }
137                                }
138                        }
139                        catch (NumberFormatException e)
140                        {
141                                _logger.warn(        "addCodesMapping() could not add item[" + i + 
142                                                                "] (" + token + ") from configuration " + 
143                                                                location, e);
144                        }
145                }
146        }
147        
148        protected void        addStatesMapping(Class clazz, String states)
149        {
150                // Parse status list
151                StringTokenizer tokenize = new StringTokenizer(states, ", \t\n\r");
152                while (tokenize.hasMoreTokens())
153                {
154                        String state = tokenize.nextToken();
155                        _states.put(state, clazz);
156                }
157        }
158        
159        protected Class        findCode(int code)
160        {
161                return _codes.get(code);
162        }
163        
164        protected Class        findState(String state)
165        {
166                if (state == null)
167                {
168                        return null;
169                }
170                
171                // Search exact state, then partial state
172                for (int i = state.length(); i > 0; i--)
173                {
174                        Class clazz = _states.get(state.substring(0, i));
175                        if (clazz != null)
176                        {
177                                return clazz;
178                        }
179                }
180                return null;
181        }
182        
183        protected Throwable        buildException(SQLException e, Class clazz)
184        {
185                return (Throwable) ConstructorUtils.invokeConstructor(
186                                                                                clazz, new Object[]{e.getMessage(), e});
187        }
188 
189        // Can be overridden
190        protected Class                preTranslate(SQLException e)
191        {
192                return null;
193        }
194 
195        private final Log        _logger;
196        // Map ErrorCode -> class
197        protected final Map<Integer, Class>        _codes = new HashMap<Integer, Class>();
198        // Map SQLState -> class
199        protected final Map<String, Class>        _states = new HashMap<String, Class>();
200}

[all classes][net.sourceforge.hivetranse.exception]
EMMA 2.0.5312 (C) Vladimir Roubtsov