1 28 package org.objectweb.jonas_ejb.container.jorm; 29 30 import java.util.ArrayList ; 31 import java.util.Arrays ; 32 import java.util.Iterator ; 33 import java.util.NoSuchElementException ; 34 import javax.ejb.EJBException ; 35 import org.objectweb.jonas_ejb.container.JEntityFactory; 36 import org.objectweb.jonas_ejb.container.TraceEjb; 37 import org.objectweb.jorm.api.PBinding; 38 import org.objectweb.jorm.api.PClassMapping; 39 import org.objectweb.jorm.api.PException; 40 import org.objectweb.jorm.api.PExceptionProtocol; 41 import org.objectweb.jorm.api.PGenClassAccessor; 42 import org.objectweb.jorm.api.PIndexedElem; 43 import org.objectweb.jorm.naming.api.PBinder; 44 import org.objectweb.jorm.naming.api.PName; 45 import org.objectweb.jorm.naming.api.PNameManager; 46 import org.objectweb.jorm.naming.api.PExceptionNaming; 47 import org.objectweb.util.monolog.api.BasicLevel; 48 49 50 56 public abstract class GenClassImpl implements PGenClassAccessor { 57 58 62 protected ArrayList pIndexedElems = null; 63 64 78 protected int[] deletedLength = null; 79 80 85 protected int size; 86 87 90 protected boolean isModified = false; 91 92 97 protected PClassMapping gcm = null; 98 99 102 protected PBinding pb = null; 103 104 110 protected GenClassListener listener = null; 111 112 115 public GenClassImpl(PClassMapping gcm) { 116 this(); 117 this.gcm = gcm; 118 } 119 120 125 public GenClassImpl() { 126 pIndexedElems = new ArrayList (0); 127 size = 0; 128 deletedLength = new int[0]; 129 isModified = false; 130 } 131 132 138 public void setPClassMapping(PClassMapping gcm) { 139 this.gcm = gcm; 140 } 141 142 145 public void reset() { 146 pIndexedElems.clear(); 147 size = 0; 148 deletedLength = new int[0]; 149 isModified = false; 150 } 151 152 157 public void setPBinding(PBinding pb) { 158 this.pb = pb; 159 } 160 161 166 public PBinding gcGetPBinding() { 167 return pb; 168 } 169 170 public void setListener(GenClassListener gcl) { 171 listener = gcl; 172 } 173 174 public GenClassListener getListener() { 175 return listener; 176 } 177 178 181 public boolean gcIsModified() { 182 return isModified; 183 } 184 185 191 public void read(PName pn, Object connection, Object tx) throws PException { 192 if (TraceEjb.genclass.isLoggable(BasicLevel.DEBUG)) { 193 TraceEjb.genclass.log(BasicLevel.DEBUG, "PName=" + pn); 194 } 195 if (pn == null || pn.isNull()) { 196 reset(); 197 return; 198 } 199 if (pb == null) { 200 throw new PExceptionProtocol("Impossible to read a persitent object withoout PBinding"); 201 } 202 Object conn = (connection == null 204 ? gcm.getPMapper().getConnection() 205 : connection); 206 if (TraceEjb.genclass.isLoggable(BasicLevel.DEBUG)) { 207 TraceEjb.genclass.log(BasicLevel.DEBUG, "Load the genclass"); 208 } 209 pb.bind(pn); 210 pb.read(conn, this, tx); 211 isModified = false; 213 214 if (connection == null) { 216 gcm.getPMapper().closeConnection(conn); 217 } 218 } 219 220 227 public void write(PName pn, Object connection) throws PException { 228 if (TraceEjb.genclass.isLoggable(BasicLevel.DEBUG)) { 229 TraceEjb.genclass.log(BasicLevel.DEBUG, ""); 230 } 231 if (pn == null || pn.isNull()) { 233 throw new PExceptionProtocol("Impossible to write a persitent object with a null PName: " + pn); 234 } 235 if (isModified) { 236 Object conn = (connection == null 238 ? gcm.getPMapper().getConnection() 239 : connection); 240 241 if (pb == null) { 242 throw new PExceptionProtocol("Impossible to write a persitent object without PBinding"); 243 } 244 if (TraceEjb.genclass.isLoggable(BasicLevel.DEBUG)) { 245 TraceEjb.genclass.log(BasicLevel.DEBUG, "Store the genclass " + pn); 246 } 247 pb.bind(pn); 248 pb.write(conn, this); 249 251 isModified = false; 255 int pos = 0; 256 for (int i = 0; i < deletedLength.length; i++) { 257 pos += deletedLength[i]; 258 pIndexedElems.remove(pos); 259 } 260 deletedLength = new int[0]; 261 for (Iterator it = pIndexedElems.iterator(); it.hasNext();) { 262 GenClassElement gce = (GenClassElement) it.next(); 263 gce.status = PIndexedElem.ELEM_UNMODIFIED; 264 gce.hasBeenCreated = false; 265 } 266 267 if (connection == null) { 269 gcm.getPMapper().closeConnection(conn); 270 } 271 } 272 } 274 275 public void doNotWrite(PObject po) { 276 GenClassElement gce = null; 277 for (Iterator it = pIndexedElems.iterator(); it.hasNext() && gce == null;) { 278 gce = (GenClassElement) it.next(); 279 if (gce.value != null) { 280 if (po == gce.value) { 281 break; 282 } 283 } else if (gce.pname != null && gce.pname.equals(po.getPName())) { 284 break; 285 } 286 gce = null; 287 } 288 if (gce == null) { 289 throw new EJBException ("Impossible to mark the element as written " 290 + "because it does not be found in the GenClass: " 291 + po.getPName()); 292 } 293 if (TraceEjb.genclass.isLoggable(BasicLevel.DEBUG)) { 294 TraceEjb.genclass.log(BasicLevel.DEBUG, 295 "assign ELEM_UNMODIFIED to " + po.getPName()); 296 } 297 gce.status = PIndexedElem.ELEM_UNMODIFIED; 298 } 299 300 303 307 public Object getMemoryInstance() { 308 return this; 309 } 310 311 312 315 321 public void paAdd(PIndexedElem elem, Object conn) throws PException { 322 pIndexedElems.add(elem); 323 size++; 324 } 326 327 331 public PIndexedElem createPIndexedElem() { 332 return new GenClassElement(this); 333 } 334 335 339 public boolean paDeltaSupported() { 340 return true; 341 } 342 343 348 public int paGetNbElem() { 349 return pIndexedElems.size(); 350 } 351 352 355 public Iterator paIterator() { 356 return pIndexedElems.iterator(); 357 } 358 359 366 public void paSetNbElem(int nbelem) { 367 if (TraceEjb.genclass.isLoggable(BasicLevel.DEBUG)) { 368 TraceEjb.genclass.log(BasicLevel.DEBUG, "nbElem: " + nbelem); 369 } 370 if (nbelem == -1) { 371 pIndexedElems.clear(); 372 } else { 373 pIndexedElems = new ArrayList (nbelem); 374 } 375 deletedLength = new int[0]; 376 size = 0; 377 } 378 379 380 383 388 protected int gcGetRealIndex(int idx) { 389 int a = idx; 390 int i = 0; 391 while (i < deletedLength.length && (a -= deletedLength[i]) >= 0) { 392 i++; 393 } 394 return idx + i; 395 } 396 397 410 protected void gcAdd(PObject element, boolean callListener) { 411 int pos = 0; 413 GenClassElement gce = null; 414 int i = 0; 415 while (i < deletedLength.length) { 416 pos += deletedLength[i]; 417 gce = (GenClassElement) pIndexedElems.get(pos); 418 if (gce.value == element) { 419 break; 420 } 421 pos++; 422 i++; 423 } 424 if (i < deletedLength.length) { 425 if (gce.hasBeenCreated) { 426 throw new EJBException ("Internal error state: A deleted element has not been created"); 427 } 428 if (TraceEjb.genclass.isLoggable(BasicLevel.DEBUG)) { 429 TraceEjb.genclass.log(BasicLevel.DEBUG, 430 "The element added was previously removed. i: " + i 431 + "gce.pname: " + gce.pname); 432 } 433 gce.status = PIndexedElem.ELEM_UNMODIFIED; 436 if (deletedLength.length == 1) { 437 deletedLength = new int[0]; 438 } else { 439 int[] old = deletedLength; 440 deletedLength = new int[deletedLength.length - 1]; 441 System.arraycopy(old, 0, deletedLength, 0, i); 442 if (i < deletedLength.length) { 443 System.arraycopy(old, i + 1, 444 deletedLength, i, 445 deletedLength.length - i - 1); 446 deletedLength[i] += old[i] + 1; 447 } 448 } 449 } else { 450 if (TraceEjb.genclass.isLoggable(BasicLevel.DEBUG)) { 451 try { 452 TraceEjb.genclass.log(BasicLevel.DEBUG, "Add the element '" 453 + element.getPName().encodeString()); 454 } catch (PExceptionNaming pExceptionNaming) { 455 } 456 } 457 gce = (GenClassElement) createPIndexedElem(); 458 gce.value = element; 459 gce.status = PIndexedElem.ELEM_CREATED; 460 gce.hasBeenCreated = true; 461 listener.isLegalElement(gce); 463 pIndexedElems.add(gce); 464 } 465 isModified = true; 466 size++; 467 if (callListener) { 469 listener.gcAdd(gce); 470 } 471 } 472 473 480 protected Object gcRemove(Object element, boolean callListener) throws PException { 481 GenClassElement gce = null; 483 boolean found = false; 484 int b = 0; int i = 0; int a; 487 for (a = 0; a < pIndexedElems.size() && !found; a++) { 488 gce = (GenClassElement) pIndexedElems.get(a); 489 if (gce.status == PIndexedElem.ELEM_DELETED) { 490 i++; 491 b = 0; 492 continue; } 494 b++; 495 if (gce.pname != null && gce.value == null) { 496 gce.value = gcDeref(gce.pname); 497 } 498 found = (element == null && gce.value == null) 499 || (element != null && element.equals(gce.value)); 500 } 501 if (!found) { 502 if (TraceEjb.genclass.isLoggable(BasicLevel.DEBUG)) { 503 TraceEjb.genclass.log(BasicLevel.DEBUG, "Nothing to remove"); 504 } 505 return null; 506 } 507 508 if (callListener) { 510 listener.gcRemove(gce, false); 511 } 512 if (gce.hasBeenCreated) { 513 if (TraceEjb.genclass.isLoggable(BasicLevel.DEBUG)) { 515 TraceEjb.genclass.log(BasicLevel.DEBUG, "Remove permanantly the element"); 516 } 517 pIndexedElems.remove(a - 1); 518 if (i < deletedLength.length) { 519 deletedLength[i]--; 522 } 523 } else { 524 gce.status = PIndexedElem.ELEM_DELETED; 526 527 if (TraceEjb.genclass.isLoggable(BasicLevel.DEBUG)) { 529 TraceEjb.genclass.log(BasicLevel.DEBUG, 530 "Add the entry in the deletedLength array: i:" + i + " / b:" + b + ")"); 531 } 532 int[] old = deletedLength; 533 deletedLength = new int[old.length + 1]; 534 System.arraycopy(old, 0, deletedLength, 0, i); 535 deletedLength[i] = b - 1; 536 if (i < old.length) { 537 deletedLength[i + 1] = old[i] - b; 538 System.arraycopy(old, i + 1, deletedLength, i + 2, old.length - i - 1); 539 } 540 } 541 isModified = true; 542 size--; 543 return gce.value; 545 } 546 547 private static String toString(int[] t) { 548 StringBuffer sb = new StringBuffer ("["); 549 for (int i = 0; i < t.length;) { 550 sb.append(t[i]); 551 i++; 552 if (i < t.length) { 553 sb.append(','); 554 } 555 } 556 sb.append(']'); 557 return sb.toString(); 558 } 559 560 public int gcGetSize() { 561 return size; 562 } 563 564 protected boolean gcContains(PObject element, Object connection) 565 throws PException { 566 Object conn = (connection == null 568 ? gcm.getPMapper().getConnection() 569 : connection); 570 571 boolean result = false; 572 for (Iterator it = gcIterator(conn); !result && it.hasNext();) { 573 Object o = it.next(); 574 result = (element == null && o == null) 575 || (element != null && element.equals(o)); 576 } 577 578 if (connection == null) { 579 gcm.getPMapper().closeConnection(conn); 581 } 582 if (TraceEjb.genclass.isLoggable(BasicLevel.DEBUG)) { 583 try { 584 TraceEjb.genclass.log(BasicLevel.DEBUG, "Looking for the element '" 585 + element.getPName().encodeString() 586 + ". return " + result); 587 } catch (PExceptionNaming pExceptionNaming) { 588 } 589 } 590 return result; 591 } 592 593 protected Iterator gcIterator() throws PException { 594 return gcIterator(null); 595 } 596 597 602 protected Iterator gcIterator(Object connection) throws PException { 603 return new ElementIterator(this, connection); 604 } 605 606 614 protected PObject gcGetElement(GenClassElement gce, Object connection) throws PException { 615 if (gce.pname != null && gce.value == null) { 616 if (gce.pname == null || gce.pname.isNull()) { 618 return null; 619 } 620 PName current = gce.pname; 621 622 Object conn = (connection == null 624 ? gcm.getPMapper().getConnection() 625 : connection); 626 627 Object res = current.resolve(conn); 629 while (res != null && res instanceof PName && !res.equals(current)) { 630 current = (PName) res; 631 res = current.resolve(conn); 632 } 633 634 if (connection == null) { 636 gcm.getPMapper().closeConnection(conn); 637 } 638 639 gce.value = gcDeref(current); 641 } 642 return gce.value; 643 } 644 645 649 public void gcClear(boolean delete) { 650 if (TraceEjb.genclass.isLoggable(BasicLevel.DEBUG)) { 651 TraceEjb.genclass.log(BasicLevel.DEBUG, "Clear the gc"); 652 } 653 655 for (Iterator it = pIndexedElems.iterator(); it.hasNext();) { 657 GenClassElement gce = (GenClassElement) it.next(); 658 if (gce.status != PIndexedElem.ELEM_DELETED) { 659 if (gce.pname != null && gce.value == null) { 660 gce.value = gcDeref(gce.pname); 661 } 662 if (TraceEjb.genclass.isLoggable(BasicLevel.DEBUG)) { 663 TraceEjb.genclass.log(BasicLevel.DEBUG, "listener.gcRemove"); 664 } 665 listener.gcRemove(gce, delete); 666 } 667 } 668 669 for (Iterator it = pIndexedElems.iterator(); it.hasNext();) { 671 GenClassElement gce = (GenClassElement) it.next(); 672 if (gce.status != PIndexedElem.ELEM_DELETED) { 673 gce.status = PIndexedElem.ELEM_DELETED; 674 if (gce.hasBeenCreated) { 675 if (TraceEjb.genclass.isLoggable(BasicLevel.DEBUG)) { 677 TraceEjb.genclass.log(BasicLevel.DEBUG, "Clear permanantly an element"); 678 } 679 it.remove(); 680 } 681 } 682 } 683 size = 0; 685 isModified = true; 686 687 deletedLength = new int[pIndexedElems.size()]; 691 Arrays.fill(deletedLength, 0); 692 694 } 695 696 protected PObject gcDeref(PName pn) { 697 JEntityFactory f = (JEntityFactory) 698 ((PBinder) pn.getPNameManager()).getBinderClassMapping(); 699 if (f.getLocalHome() != null) { 700 return ((PObjectHome) f.getLocalHome()).getPObject(pn); 701 } else { 702 return ((PObjectHome) f.getHome()).getPObject(pn); 703 } 704 } 705 706 709 protected PName gcObject2ref(PObject value) throws PException { 710 if (value != null) { 711 Object conn = gcm.getPMapper().getConnection(); 712 PNameManager pnm = (PNameManager) gcm.getPNameCoder(); 713 PName pn = pnm.export(conn, value.getPName(), null); 714 gcm.getPMapper().closeConnection(conn); 715 return pn; 716 } else { 717 return gcm.getPNameCoder().getNull(); 718 } 719 } 720 721 public void printState() { 722 if (!TraceEjb.genclass.isLoggable(BasicLevel.DEBUG)) { 723 return; 724 } 725 TraceEjb.genclass.log(BasicLevel.DEBUG, "deletedLength: " + toString(deletedLength)); 726 TraceEjb.genclass.log(BasicLevel.DEBUG, "pIndexedElems.size():" + pIndexedElems.size()); 727 TraceEjb.genclass.log(BasicLevel.DEBUG, "isModified: " + isModified); 728 TraceEjb.genclass.log(BasicLevel.DEBUG, "size:" + size); 729 int i = 0; 730 for (Iterator it = pIndexedElems.iterator(); it.hasNext();) { 731 GenClassElement gce = (GenClassElement) it.next(); 732 TraceEjb.genclass.log(BasicLevel.DEBUG, "GCE:" + i 733 + " / status:" + gce.status 734 + " / hasBeenCreated:" + gce.hasBeenCreated 735 ); 736 TraceEjb.genclass.log(BasicLevel.DEBUG, "- pname:" + gce.pname); 737 TraceEjb.genclass.log(BasicLevel.DEBUG, "- value:" + gce.value); 738 i++; 739 } 740 } 741 742 747 protected class ElementIterator implements Iterator { 748 749 private int cursor = 0; 750 private int next = 0; 751 private GenClassImpl gc; 752 private Object conn; 753 754 public ElementIterator(GenClassImpl gc, Object connection) { 755 this.gc = gc; 756 conn = connection; 757 reset(); 758 } 759 760 public void reset() { 761 cursor = -1; 762 next = nextExist(cursor); 763 } 764 765 private int nextExist(int pos) { 766 int tmp = pos + 1; 767 while (tmp < pIndexedElems.size()) { 768 if (((GenClassElement) pIndexedElems.get(tmp)).status != PIndexedElem.ELEM_DELETED) { 769 return tmp; 771 } 772 tmp++; 773 } 774 return -1; 776 } 777 778 781 788 public boolean hasNext() { 789 return next != -1; 790 } 791 792 798 public Object next() { 799 if (next == -1) { 800 throw new NoSuchElementException (); 801 } 802 cursor = next; 803 try { 804 GenClassElement gce = (GenClassElement) pIndexedElems.get(cursor); 805 gc.gcGetElement(gce, conn); 806 next = nextExist(cursor); 808 return gce.value; 809 } catch (PException e) { 810 next = -1; 811 TraceEjb.genclass.log(BasicLevel.ERROR, "Impossible to obtain value:", e); 812 throw new NoSuchElementException ("Impossible to obtain value:" + e); 813 } 814 } 815 816 public void remove() { 817 try { 818 gcRemove(((GenClassElement) pIndexedElems.get(cursor)).value, true); 819 } catch (PException e) { 820 throw new UnsupportedOperationException (e.getMessage()); 821 } 822 } 823 } 824 } 825 | Popular Tags |