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 */ 017package org.apache.commons.transaction.file; 018 019import java.io.PrintWriter; 020import 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 */ 027public 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}