001: /*
002: * Created on Nov 15, 2005
003: */
004: package uk.org.ponder.rsf.preservation;
005:
006: import org.springframework.beans.factory.BeanNameAware;
007:
008: import uk.org.ponder.beanutil.BeanLocator;
009: import uk.org.ponder.beanutil.WriteableBeanLocator;
010: import uk.org.ponder.rsf.request.RequestSubmittedValueCache;
011: import uk.org.ponder.rsf.request.SubmittedValueEntry;
012: import uk.org.ponder.rsf.state.ExpiredFlowException;
013: import uk.org.ponder.rsf.state.RSVCApplier;
014: import uk.org.ponder.rsf.state.TokenStateHolder;
015: import uk.org.ponder.stringutil.StringList;
016: import uk.org.ponder.util.Logger;
017: import uk.org.ponder.util.UniversalRuntimeException;
018:
019: // This seems itself to be a request-scope bean.
020: public class RSVCPreservationStrategy implements
021: StatePreservationStrategy, BeanNameAware {
022:
023: private TokenStateHolder holder;
024: private StringList beannames;
025:
026: private RSVCApplier rsvcapplier;
027: private RequestSubmittedValueCache requestrsvc;
028: private String ourbeanname;
029:
030: public void setPreservingBeans(StringList beannames) {
031: this .beannames = beannames;
032: }
033:
034: public void setTokenStateHolder(TokenStateHolder holder) {
035: this .holder = holder;
036: }
037:
038: public void setRequestRSVC(RequestSubmittedValueCache requestrsvc) {
039: this .requestrsvc = requestrsvc;
040: }
041:
042: public void setRSVCApplier(RSVCApplier rsvcapplier) {
043: this .rsvcapplier = rsvcapplier;
044: }
045:
046: // This is called at the END of the request cycle, assuming there is an
047: // ongoing request.
048: public int preserve(BeanLocator source, String tokenid) {
049: String token = ourbeanname + tokenid;
050: // OK. assume anything ALREADY there for this token needs continued
051: //preserving, with accretion.
052: RequestSubmittedValueCache tokenstate = (RequestSubmittedValueCache) holder
053: .getTokenState(ourbeanname + tokenid);
054: if (tokenstate == null) {
055: tokenstate = new RequestSubmittedValueCache();
056: }
057: int entries = requestrsvc.getEntries();
058: boolean[] done = new boolean[entries];
059: // the initial set of "dependent EL" is the set of bean names we were
060: // asked to persist.
061: StringList dependentel = beannames.copy();
062: for (int i = 0; i < dependentel.size(); ++i) {
063: String dep = dependentel.stringAt(i);
064:
065: for (int j = 0; j < entries; ++j) {
066: if (done[j])
067: continue;
068: SubmittedValueEntry sve = requestrsvc.entryAt(j);
069: if (sve.valuebinding.startsWith(dep)) {
070: tokenstate.addEntry(sve);
071: Logger.log.info("RSVCPres saving SVE valuebinding "
072: + sve.valuebinding + " newvalue "
073: + sve.newvalue);
074: done[j] = true;
075: // "funnel outward" dependencies to everything (hopefully just transit
076: // beans) that have been used to initialise preserving beans.
077: if (sve.isEL) {
078: String el = (String) sve.newvalue;
079: dependentel.add(el);
080: }
081: }
082: }
083: }
084: holder.putTokenState(token, tokenstate);
085: Logger.log.info("RSVCPres saved " + tokenstate.getEntries()
086: + " entries to token " + token);
087: return entries;
088: }
089:
090: public int restore(WriteableBeanLocator target, String tokenid) {
091: String token = ourbeanname + tokenid;
092: RequestSubmittedValueCache tokenstate = (RequestSubmittedValueCache) holder
093: .getTokenState(token);
094: if (tokenstate == null) {
095: throw UniversalRuntimeException.accumulate(
096: new ExpiredFlowException(),
097: "Client requested restoration of expired flow state with ID "
098: + tokenid + " which has expired");
099: } else {
100: Logger.log.info("RSVCPres recovered "
101: + tokenstate.getEntries() + " entries from token "
102: + token);
103: rsvcapplier.applyValues(tokenstate);
104: return tokenstate.getEntries();
105: }
106: }
107:
108: public void clear(String tokenid) {
109: holder.clearTokenState(ourbeanname + tokenid);
110: }
111:
112: public void setBeanName(String name) {
113: this.ourbeanname = name;
114: }
115:
116: }
|