1 10 package org.mmbase.module.core; 11 12 import java.util.*; 13 import org.mmbase.module.corebuilders.*; 14 15 import org.mmbase.util.logging.Logger; 16 import org.mmbase.util.logging.Logging; 17 import org.mmbase.security.*; 18 19 24 public class TransactionManager implements TransactionManagerInterface { 25 26 private static final Logger log = Logging.getLoggerInstance(TransactionManager.class); 27 28 public static final String EXISTS_NO = "no"; 29 public static final int I_EXISTS_NO = 0; 30 public static final String EXISTS_YES = "yes"; 31 public static final int I_EXISTS_YES = 1; 32 public static final String EXISTS_NOLONGER = "nolonger"; 33 public static final int I_EXISTS_NOLONGER = 2; 34 35 private TemporaryNodeManagerInterface tmpNodeManager; 36 private MMBase mmbase; 37 protected Map transactions = new HashMap(); 38 protected TransactionResolver transactionResolver; 39 40 public TransactionManager(MMBase mmbase, TemporaryNodeManagerInterface tmpn) { 41 this.mmbase = mmbase; 42 this.tmpNodeManager = tmpn; 43 transactionResolver = new TransactionResolver(mmbase); 44 mmbase.getMMBaseCop(); 45 } 46 52 synchronized public Collection getTransaction(String transactionName) throws TransactionManagerException { 53 Collection transaction = (Collection) transactions.get(transactionName); 54 if (transaction == null) { 55 throw new TransactionManagerException("Transaction " + transactionName + " does not exist (existing are " + transactions.keySet() + ")"); 56 } else { 57 return transaction; 58 } 59 } 60 61 67 synchronized public Collection createTransaction(String transactionName) throws TransactionManagerException { 68 if (!transactions.containsKey(transactionName)) { 69 Vector transactionNodes = new Vector(); 70 transactions.put(transactionName, transactionNodes); 71 return transactionNodes; 72 } else { 73 throw new TransactionManagerException("Transaction " + transactionName + " already exists"); 74 } 75 } 76 77 81 synchronized protected Collection deleteTransaction(String transactionName) { 82 return (Collection) transactions.remove(transactionName); 83 } 84 85 88 public Vector getNodes(Object user, String transactionName) { 89 try { 90 return (Vector)getTransaction(transactionName); 91 } catch (TransactionManagerException tme) { 92 return null; 93 } 94 } 95 96 104 public String create(Object user, String transactionName) throws TransactionManagerException { 105 createTransaction(transactionName); 106 if (log.isDebugEnabled()) { 107 log.debug("Create transaction for " + transactionName); 108 } 109 return transactionName; 110 } 111 112 119 public Collection get(Object user, String transactionName) throws TransactionManagerException { 120 return getTransaction(transactionName); 121 } 122 123 public String addNode(String transactionName, String owner, String tmpnumber) 124 throws TransactionManagerException { 125 Collection transaction = getTransaction(transactionName); 126 MMObjectNode node = tmpNodeManager.getNode(owner, tmpnumber); 127 if (node != null) { 128 if (!transaction.contains(node)) { 129 transaction.add(node); 130 } 134 } else { 135 throw new TransactionManagerException("Node " + tmpnumber + " doesn't exist."); 136 } 137 return tmpnumber; 138 } 139 140 public String removeNode(String transactionName, String owner, String tmpnumber) 141 throws TransactionManagerException { 142 Collection transaction = getTransaction(transactionName); 143 MMObjectNode node = tmpNodeManager.getNode(owner, tmpnumber); 144 if (node!=null) { 145 if (transaction.contains(node)) { 146 transaction.remove(node); 147 } 150 } else { 151 throw new TransactionManagerException("Node " + tmpnumber + " doesn't exist."); 152 } 153 return tmpnumber; 154 } 155 156 public String deleteObject(String transactionName, String owner, String tmpnumber) 157 throws TransactionManagerException { 158 Collection transaction = getTransaction(transactionName); 159 MMObjectNode node = tmpNodeManager.getNode(owner, tmpnumber); 160 if (node!=null) { 161 if (transaction.contains(node)) { 162 node.setValue("_exists",EXISTS_NOLONGER); 164 } else { 165 throw new TransactionManagerException("Node " + tmpnumber + " is not in transaction " + transactionName); 166 } 167 } else { 168 throw new TransactionManagerException("Node " + tmpnumber + " doesn't exist."); 169 } 170 return tmpnumber; 171 } 172 173 public String cancel(Object user, String transactionName) throws TransactionManagerException { 174 Collection transaction = getTransaction(transactionName); 175 MMObjectBuilder builder = mmbase.getTypeDef(); 177 for (Iterator i = transaction.iterator(); i.hasNext(); ) { 178 MMObjectNode node=(MMObjectNode)i.next(); 179 builder.removeTmpNode(node.getStringValue(MMObjectBuilder.TMP_FIELD_NUMBER)); 180 } 181 deleteTransaction(transactionName); 182 if (log.isDebugEnabled()) { 183 log.debug("Removed transaction (after cancel) " + transactionName + "\n" + transaction); 184 } 185 return transactionName; 186 } 187 188 public String commit(Object user, String transactionName) throws TransactionManagerException { 189 Collection transaction = getTransaction(transactionName); 190 try { 191 boolean resolved = transactionResolver.resolve(transaction); 192 if (!resolved) { 193 log.error("Can't resolve transaction " + transactionName); 194 log.error("Nodes \n" + transaction); 195 throw new TransactionManagerException("Can't resolve transaction " + transactionName + "" + transaction); 196 } else { 197 resolved = performCommits(user, transaction); 198 if (!resolved) { 199 log.error("Can't commit transaction " + transactionName); 200 log.error("Nodes \n" + transaction); 201 throw new TransactionManagerException("Can't commit transaction " + transactionName); 202 } 203 } 204 } finally { 205 MMObjectBuilder builder = mmbase.getTypeDef(); 207 for (Iterator i = transaction.iterator(); i.hasNext(); ) { 208 MMObjectNode node=(MMObjectNode)i.next(); 209 builder.removeTmpNode(node.getStringValue(MMObjectBuilder.TMP_FIELD_NUMBER)); 210 } 211 deleteTransaction(transactionName); 212 if (log.isDebugEnabled()) { 213 log.debug("Removed transaction (after commit) " + transactionName + "\n" + transaction); 214 } 215 } 216 return transactionName; 217 } 218 219 private final static int UNCOMMITED = 0; 220 private final static int COMMITED = 1; 221 private final static int FAILED = 2; 222 private final static int NODE = 3; 223 private final static int RELATION = 4; 224 225 boolean performCommits(Object user, Collection nodes) { 226 if (nodes == null || nodes.size() == 0) { 227 log.warn("Empty list of nodes"); 228 return true; 229 } 230 231 int[] nodestate = new int[nodes.size()]; 232 int[] nodeexist = new int[nodes.size()]; 233 String username = findUserName(user),exists; 234 235 log.debug("Checking types and existance"); 236 237 int i = 0; 238 for (Iterator nodeIterator = nodes.iterator(); nodeIterator.hasNext(); i++) { 239 MMObjectNode node = (MMObjectNode)nodeIterator.next(); 240 nodestate[i] = UNCOMMITED; 242 exists = node.getStringValue("_exists"); 243 if (exists == null) { 244 throw new IllegalStateException ("The _exists field does not exist on node "+node); 245 } else if (exists.equals(EXISTS_NO)) { 246 nodeexist[i]=I_EXISTS_NO; 247 } else if (exists.equals(EXISTS_YES)) { 248 nodeexist[i]=I_EXISTS_YES; 249 } else if (exists.equals(EXISTS_NOLONGER)) { 250 nodeexist[i]=I_EXISTS_NOLONGER; 251 } else { 252 throw new IllegalStateException ("Invalid value for _exists on node "+node); 253 } 254 } 255 256 log.debug("Commiting nodes"); 257 258 i = 0; 260 for (Iterator nodeIterator = nodes.iterator(); nodeIterator.hasNext(); i++) { 261 MMObjectNode node = (MMObjectNode)nodeIterator.next(); 262 if (!(node.getBuilder() instanceof InsRel)) { 263 if (nodeexist[i] == I_EXISTS_YES ) { 264 boolean commitOK; 266 if (user instanceof UserContext) { 267 commitOK = node.commit((UserContext)user); 268 } else { 269 commitOK = node.parent.safeCommit(node); 270 } 271 if (commitOK) { 272 nodestate[i] = COMMITED; 273 } else { 274 nodestate[i] = FAILED; 275 } 276 } else if (nodeexist[i] == I_EXISTS_NO ) { 277 int insertOK; 278 if (user instanceof UserContext) { 279 insertOK = node.insert((UserContext)user); 280 } else { 281 insertOK = node.parent.safeInsert(node, username); 282 } 283 if (insertOK > 0) { 284 nodestate[i] = COMMITED; 285 } else { 286 nodestate[i] = FAILED; 287 String message = "When this failed, it is possible that the creation of an insrel went right, which leads to a database inconsistency.. stop now.. (transaction 2.0: [rollback?])"; 288 log.error(message); 289 throw new RuntimeException (message); 290 } 291 } 292 } 293 } 294 295 log.debug("Commiting relations"); 296 297 i = 0; 299 for (Iterator nodeIterator = nodes.iterator(); nodeIterator.hasNext(); i++) { 300 MMObjectNode node = (MMObjectNode)nodeIterator.next(); 301 if (node.getBuilder() instanceof InsRel) { 302 if (nodeexist[i] == I_EXISTS_YES ) { 304 boolean commitOK; 305 if (user instanceof UserContext) { 306 commitOK = node.commit((UserContext)user); 307 } else { 308 commitOK = node.parent.safeCommit(node); 309 } 310 if (commitOK) { 311 nodestate[i] = COMMITED; 312 } else { 313 nodestate[i] = FAILED; 314 } 315 } else if (nodeexist[i] == I_EXISTS_NO ) { 316 int insertOK; 317 if (user instanceof UserContext) { 318 insertOK = node.insert((UserContext)user); 319 } else { 320 insertOK = node.parent.safeInsert(node, username); 321 } 322 if (insertOK > 0) { 323 nodestate[i] = COMMITED; 324 } else { 325 nodestate[i] = FAILED; 326 String message = "relation failed(transaction 2.0: [rollback?])"; 327 log.error(message); 328 } 329 } 330 } 331 } 332 333 log.debug("Deleting relations"); 334 335 i = 0; 337 for (Iterator nodeIterator = nodes.iterator(); nodeIterator.hasNext(); i++) { 338 MMObjectNode node = (MMObjectNode)nodeIterator.next(); 339 if (node.getBuilder() instanceof InsRel && nodeexist[i] == I_EXISTS_NOLONGER) { 340 if (user instanceof UserContext) { 342 node.remove((UserContext)user); 343 } else { 344 node.parent.removeNode(node); 345 } 346 nodestate[i]=COMMITED; 347 } 348 } 349 350 log.debug("Deleting nodes"); 351 i = 0; 353 for (Iterator nodeIterator = nodes.iterator(); nodeIterator.hasNext(); i++) { 354 MMObjectNode node = (MMObjectNode)nodeIterator.next(); 355 if (!(node.getBuilder() instanceof InsRel) && (nodeexist[i] == I_EXISTS_NOLONGER)) { 356 if (user instanceof UserContext) { 358 node.remove((UserContext)user); 359 } else { 360 node.parent.removeNode(node); 361 } 362 nodestate[i]=COMMITED; 363 } 364 } 365 366 boolean okay=true; 368 i = 0; 369 for (Iterator nodeIterator = nodes.iterator(); nodeIterator.hasNext(); i++) { 370 MMObjectNode node = (MMObjectNode)nodeIterator.next(); 371 if (nodestate[i] == FAILED) { 372 okay=false; 373 log.error("Failed node "+node.toString()); 374 } 375 } 376 return okay; 377 } 378 379 public String findUserName(Object user) { 380 if (user instanceof UserContext) { 381 return ((UserContext)user).getIdentifier(); 382 } else { 383 return ""; 384 } 385 } 386 387 } 388 | Popular Tags |