001: /*
002: * Created on Oct 20, 2005
003: */
004: package uk.org.ponder.rsf.hibernate3;
005:
006: import java.util.ArrayList;
007: import java.util.List;
008:
009: import org.hibernate.Session;
010: import org.hibernate.SessionFactory;
011: import org.hibernate.Transaction;
012:
013: import uk.org.ponder.beanutil.entity.EntityIDRewriter;
014: import uk.org.ponder.rsf.flow.ARIResult;
015: import uk.org.ponder.rsf.request.EarlyRequestParser;
016: import uk.org.ponder.rsf.state.entity.support.NewEntityIDRewriter;
017: import uk.org.ponder.saxalizer.SAXalizerMappingContext;
018: import uk.org.ponder.util.RunnableInvoker;
019: import uk.org.ponder.util.UniversalRuntimeException;
020:
021: /**
022: * An "Alteration Wrapper" appropriate for a straightforward use of Hibernate.
023: * This will open and rollback a transaction around every request cycle, except
024: * an action cycle which reports the END_FLOW propagation status (all non-flow
025: * cycles will report this). Cooperates with HibernateEntityBeanLocators to
026: * ensure new entities are correctly saved, etc. This implementation could be
027: * replaced for more advanced usages, for example use of a Hibernate
028: * "application" (or "long") transaction strategy.
029: *
030: * @author Antranig Basman (amb26@ponder.org.uk)
031: *
032: */
033:
034: public class HibernateAlterationWrapper implements RunnableInvoker {
035: private SessionFactory sessionfactory;
036: private Session session;
037: private Transaction transaction;
038: private List precommits = new ArrayList();
039: private ARIResult ariresult;
040: private String requesttype;
041: private SAXalizerMappingContext mappingcontext;
042: private EntityIDRewriter idrewriter;
043: private RunnableInvoker chainedwrapper;
044:
045: public void setSessionFactory(SessionFactory sessionfactory) {
046: this .sessionfactory = sessionfactory;
047: // Logger.log.info("HAW got SessionFactory " + sessionfactory);
048: // ClassLoader ours = getClass().getClassLoader();
049: // ClassLoader sfs = sessionfactory.getClass().getClassLoader();
050: // Logger.log.info("Our classloader: " + ours + " hash " + ours.hashCode()
051: // + " SessionFactory classloader: "
052: // + sfs + " hash " + sfs.hashCode());
053: }
054:
055: public Session getSession() {
056: return session;
057: }
058:
059: public Transaction getTransaction() {
060: return transaction;
061: }
062:
063: // precommit actions are currently only registration of ID change listeners,
064: // which are actually disused in favour of rewriteNewEntityIDs below.
065: public void registerPreCommitAction(Runnable precommit) {
066: precommits.add(precommit);
067: }
068:
069: public void setRequestType(String requesttype) {
070: this .requesttype = requesttype;
071: }
072:
073: // NB - this is a lazy dependency (due to circularity from RSFActionHandler) -
074: // use pea proxy methods
075: public void setARIResult(ARIResult ariresult) {
076: this .ariresult = ariresult;
077: }
078:
079: public void setMappingContext(SAXalizerMappingContext mappingcontext) {
080: this .mappingcontext = mappingcontext;
081: }
082:
083: public void setEntityIDRewriter(EntityIDRewriter idprocessor) {
084: this .idrewriter = idprocessor;
085: }
086:
087: /**
088: * Set a wrapper to "wrap-over" the Runnable returned by this wrapper.
089: *
090: * @param wrapper
091: */
092: public void setChainedInvoker(RunnableInvoker chainedwrapper) {
093: this .chainedwrapper = chainedwrapper;
094: }
095:
096: private boolean willCommit() {
097: // Note that ariresult is a lazy bean, and may precipitate all forms of
098: // mayhem if it is inappropriately loaded...
099: return (requesttype.equals(EarlyRequestParser.ACTION_REQUEST) && ariresult
100: .get().propagateBeans.equals(ARIResult.FLOW_END));
101: }
102:
103: public void invokeRunnable(final Runnable towrap) {
104: Runnable togo = new Runnable() {
105: public void run() {
106: try {
107: session = sessionfactory.openSession();
108: transaction = session.beginTransaction();
109: towrap.run();
110:
111: if (willCommit()) {
112: for (int i = 0; i < precommits.size(); ++i) {
113: ((Runnable) precommits.get(i)).run();
114: }
115: transaction.commit();
116: rewriteNewEntityIDs();
117: } else {
118: transaction.rollback();
119: }
120: } catch (Exception e) {
121: HibernateUtil.rollbackTransaction(transaction);
122: throw UniversalRuntimeException.accumulate(e);
123:
124: } finally {
125: HibernateUtil.closeSession(session);
126: }
127: }
128: };
129:
130: if (chainedwrapper == null) {
131: togo.run();
132: } else {
133: chainedwrapper.invokeRunnable(togo);
134: }
135: }
136:
137: private void rewriteNewEntityIDs() {
138: NewEntityIDRewriter.rewriteEntityIDs(
139: ariresult.get().resultingView, mappingcontext,
140: idrewriter);
141: }
142:
143: }
|