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: */
017: package org.apache.cocoon.webapps.session.components;
018:
019: import java.util.HashMap;
020: import java.util.Map;
021:
022: import org.apache.avalon.framework.component.Component;
023: import org.apache.avalon.framework.context.Context;
024: import org.apache.avalon.framework.context.ContextException;
025: import org.apache.avalon.framework.context.Contextualizable;
026: import org.apache.avalon.framework.logger.AbstractLogEnabled;
027: import org.apache.avalon.framework.thread.ThreadSafe;
028: import org.apache.cocoon.ProcessingException;
029: import org.apache.cocoon.components.ContextHelper;
030: import org.apache.cocoon.environment.Request;
031: import org.apache.cocoon.environment.Session;
032: import org.apache.cocoon.webapps.session.TransactionManager;
033: import org.apache.cocoon.webapps.session.context.SessionContext;
034:
035: /**
036: * This is the default implementation for the transaction manager.
037: *
038: * @author <a href="mailto:cziegeler@apache.org">Carsten Ziegeler</a>
039: * @deprecated This block is deprecated and will be removed in future versions.
040: * @version CVS $Id: DefaultTransactionManager.java 433543 2006-08-22 06:22:54Z crossley $
041: */
042: public final class DefaultTransactionManager extends AbstractLogEnabled
043: implements Component, ThreadSafe, TransactionManager,
044: Contextualizable {
045:
046: protected Context context;
047:
048: /**
049: * Get the transaction states from the current session
050: */
051: private TransactionState getSessionContextsTransactionState(
052: SessionContext context) {
053: final Request request = ContextHelper.getRequest(this .context);
054: final Session session = request.getSession(true);
055: Map transactionStates = (Map) session.getAttribute(this
056: .getClass().getName());
057: if (transactionStates == null) {
058: transactionStates = new HashMap(5, 3);
059: session.setAttribute(this .getClass().getName(),
060: transactionStates);
061: }
062: TransactionState state = (TransactionState) transactionStates
063: .get(context);
064: if (state == null) {
065: state = new TransactionState();
066: transactionStates.put(context, state);
067: }
068: return state;
069: }
070:
071: private static class TransactionState {
072: /** number readers reading*/
073: public int nr = 0;
074: /** number of readers total (reading or waiting to read)*/
075: public int nrtotal = 0;
076: /** number writers writing, 0 or 1 */
077: public int nw = 0;
078: /** number of writers total (writing or waiting to write)*/
079: public int nwtotal = 0;
080: }
081:
082: /**
083: * Reset the transaction management state.
084: */
085: public void resetTransactions(SessionContext context) {
086: TransactionState ts = this
087: .getSessionContextsTransactionState(context);
088: ts.nr = 0;
089: ts.nrtotal = 0;
090: ts.nw = 0;
091: ts.nwtotal = 0;
092: }
093:
094: /**
095: * Start a reading transaction.
096: * This call must always be matched with a stopReadingTransaction().
097: * Otherwise the session context is blocked.
098: */
099: public synchronized void startReadingTransaction(
100: SessionContext context) throws ProcessingException {
101: TransactionState ts = this
102: .getSessionContextsTransactionState(context);
103: ts.nrtotal++;
104: while (ts.nw != 0) {
105: try {
106: wait();
107: } catch (InterruptedException local) {
108: throw new ProcessingException("Interrupted", local);
109: }
110: }
111: ts.nr++;
112: }
113:
114: /**
115: * Stop a reading transaction.
116: * This call must always be done for each startReadingTransaction().
117: * Otherwise the session context is blocked.
118: */
119: public synchronized void stopReadingTransaction(
120: SessionContext context) {
121: TransactionState ts = this
122: .getSessionContextsTransactionState(context);
123: ts.nr--;
124: ts.nrtotal--;
125: if (ts.nrtotal == 0)
126: notify();
127: }
128:
129: /**
130: * Start a writing transaction.
131: * This call must always be matched with a stopWritingTransaction().
132: * Otherwise the session context is blocked.
133: */
134: public synchronized void startWritingTransaction(
135: SessionContext context) throws ProcessingException {
136: TransactionState ts = this
137: .getSessionContextsTransactionState(context);
138: ts.nwtotal++;
139: while (ts.nrtotal + ts.nw != 0) {
140: try {
141: wait();
142: } catch (InterruptedException local) {
143: throw new ProcessingException("Interrupted", local);
144: }
145: }
146: ts.nw = 1;
147: }
148:
149: /**
150: * Stop a writing transaction.
151: * This call must always be done for each startWritingTransaction().
152: * Otherwise the session context is blocked.
153: */
154: public synchronized void stopWritingTransaction(
155: SessionContext context) {
156: TransactionState ts = this
157: .getSessionContextsTransactionState(context);
158: ts.nw = 0;
159: ts.nwtotal--;
160: notifyAll();
161: }
162:
163: /* (non-Javadoc)
164: * @see org.apache.avalon.framework.context.Contextualizable#contextualize(org.apache.avalon.framework.context.Context)
165: */
166: public void contextualize(Context context) throws ContextException {
167: this.context = context;
168: }
169:
170: }
|