001 /*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements. See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License. You may obtain a copy of the License at
008 *
009 * http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017 package org.apache.commons.transaction.file;
018
019 import java.io.PrintWriter;
020 import java.io.StringWriter;
021
022 /**
023 * Signals any kind of error or failure state in a {@link ResourceManager}.
024 *
025 * @version $Id: ResourceManagerException.java 493628 2007-01-07 01:42:48Z joerg $
026 */
027 public class ResourceManagerException extends Exception implements ResourceManagerErrorCodes {
028
029 private static final int[] ERROR_CODES =
030 {
031 ERR_SYSTEM,
032 ERR_SYSTEM_INCONSISTENT,
033 ERR_NO_TX,
034 ERR_TXID_INVALID,
035 ERR_TX_INACTIVE,
036 ERR_TX_INCONSISTENT,
037 ERR_DUP_TX,
038 ERR_THREAD_INVALID,
039 ERR_ISOLATION_LEVEL_UNSUPPORTED,
040 ERR_RESOURCEID_INVALID,
041 ERR_RESOURCE_EXISTS,
042 ERR_NO_SUCH_RESOURCE,
043 ERR_LOCK,
044 ERR_NO_LOCK,
045 ERR_MARKED_FOR_ROLLBACK,
046 };
047
048 private static final String[] ERROR_CODE_STRINGS =
049 {
050 "ERR_SYSTEM",
051 "ERR_SYSTEM_INCONSISTENT",
052 "ERR_NO_TX",
053 "ERR_TXID_INVALID",
054 "ERR_TX_INACTIVE",
055 "ERR_TX_INCONSISTENT",
056 "ERR_DUP_TX",
057 "ERR_THREAD_INVALID",
058 "ERR_ISOLATION_LEVEL_UNSUPPORTED",
059 "ERR_RESOURCEID_INVALID",
060 "ERR_RESOURCE_EXISTS",
061 "ERR_NO_SUCH_RESOURCE",
062 "ERR_LOCK",
063 "ERR_NO_LOCK",
064 "ERR_MARKED_FOR_ROLLBACK",
065 };
066
067 private static final String[] ERROR_CODE_TEXTS =
068 {
069 "System error",
070 "Inconsistent system data",
071 "Unknown transaction",
072 "Invalid transaction id",
073 "Transaction inactive",
074 "Inconsistent transaction data",
075 "Duplicate transaction id",
076 "Thread of control is the one that not start tx",
077 "Isolation level unsupported",
078 "Specified resource id is invalid",
079 "Resource already exists",
080 "No such resource",
081 "Locking error",
082 "Could not acquire lock",
083 "Transaction already marked for rollback" };
084
085 public static final String ERR_UNKNOWN_TEXT = "Unknown error";
086 public static final String ERR_UNKNOWN_CODE = "ERR_UNKNOWN";
087
088 protected final int status;
089 protected final Object txId;
090
091 protected static final String composeMessage(String msg, int status, Object txId, Throwable cause) {
092 String message = composeMessage(msg, status, txId);
093 StringBuffer messageBuffer = new StringBuffer(message);
094 messageBuffer.append("\nCaused by: ");
095 StringWriter sw = new StringWriter();
096 cause.printStackTrace(new PrintWriter(sw));
097 messageBuffer.append(sw.getBuffer());
098 return messageBuffer.toString();
099 }
100
101 protected static final String composeMessage(String msg, int status, Object txId) {
102 StringBuffer composed = new StringBuffer();
103 if (txId != null) {
104 composed.append(txId).append(": ");
105 }
106 if (msg != null) {
107 composed.append(msg);
108 if (status != -1) {
109 composed.append(" (").append(statusToCode(status)).append(')');
110 }
111 } else if (status != -1) {
112 composed.append(statusToText(status));
113 }
114
115 return composed.toString();
116 }
117
118 public static final String statusToText(int status) {
119 if (status == ERR_UNKNOWN) {
120 return ERR_UNKNOWN_TEXT;
121 } else {
122 int pos = -1;
123 for (int i = 0; i < ERROR_CODES.length; i++) {
124 int code = ERROR_CODES[i];
125 if (status == code) {
126 pos = i;
127 break;
128 }
129 }
130 if (pos == -1) {
131 return ERR_UNKNOWN_TEXT + ", code: " + status;
132 } else {
133 return ERROR_CODE_TEXTS[pos];
134 }
135 }
136 }
137
138 public static final String statusToCode(int status) {
139 if (status == ERR_UNKNOWN) {
140 return ERR_UNKNOWN_CODE;
141 } else {
142 int pos = -1;
143 for (int i = 0; i < ERROR_CODES.length; i++) {
144 int code = ERROR_CODES[i];
145 if (status == code) {
146 pos = i;
147 break;
148 }
149 }
150 if (pos == -1) {
151 return ERR_UNKNOWN_CODE + ": " + status;
152 } else {
153 return ERROR_CODE_STRINGS[pos];
154 }
155 }
156 }
157
158 public ResourceManagerException(String message, int status, Object txId) {
159 super(ResourceManagerException.composeMessage(message, status, txId));
160 this.status = status;
161 this.txId = txId;
162 }
163
164 public ResourceManagerException(int status, Object txId) {
165 this(null, status, txId);
166 }
167
168 public ResourceManagerException(String message) {
169 super(message);
170 this.status = ERR_UNKNOWN;
171 this.txId = null;
172 }
173
174 public ResourceManagerException(String message, int status, Object txId, Throwable cause) {
175 // XXX can not do this, as 1.3 Throwable does not allow cause in ctor :(
176 // super(ResourceManagerException.composeMessage(message, status, txId), cause);
177 // for now format cause by ourselves
178 super(ResourceManagerException.composeMessage(message, status, txId, cause));
179 this.status = status;
180 this.txId = txId;
181 }
182
183 public ResourceManagerException(String message, int status, Throwable cause) {
184 this(message, status, null, cause);
185 }
186
187 public ResourceManagerException(String message, Throwable cause) {
188 this(message, ERR_UNKNOWN, cause);
189 }
190
191 public ResourceManagerException(int status, Object txId, Throwable cause) {
192 this(null, status, txId, cause);
193 }
194
195 public String statusToString() {
196 return ResourceManagerException.statusToText(status);
197 }
198
199 public int getStatus() {
200 return status;
201 }
202
203 }