org.codehaus.wadi.core.contextualiser.SerialContextualiser.java Source code

Java tutorial

Introduction

Here is the source code for org.codehaus.wadi.core.contextualiser.SerialContextualiser.java

Source

/**
 *
 * Copyright 2003-2005 Core Developers Network Ltd.
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */
package org.codehaus.wadi.core.contextualiser;

import java.util.concurrent.locks.Lock;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.codehaus.wadi.core.ConcurrentMotableMap;
import org.codehaus.wadi.core.motable.Immoter;
import org.codehaus.wadi.core.motable.Motable;

/**
 * Ensure that any Contextualisations that pass through are serialised according to the strategy imposed by our Collapser.
 *
 * @author <a href="mailto:jules@coredevelopers.net">Jules Gosnell</a>
 * @version $Revision$
 */
public class SerialContextualiser extends AbstractDelegatingContextualiser {
    private static final Log log = LogFactory.getLog(SerialContextualiser.class);

    private final Collapser collapser;
    private final ExclusiveContextualiserLockHandler lockHandler;

    public SerialContextualiser(Contextualiser next, Collapser collapser, ConcurrentMotableMap map) {
        super(next);
        if (null == collapser) {
            throw new IllegalArgumentException("collapser is required");
        } else if (null == map) {
            throw new IllegalArgumentException("map is required");
        }
        this.collapser = collapser;

        lockHandler = new BasicExclusiveContextualiserLockHandler(map);
    }

    public boolean contextualise(Invocation invocation, Object id, Immoter immoter, boolean exclusiveOnly)
            throws InvocationException {
        Lock invocationLock = collapser.getLock(id);

        // the promotion begins here. allocate a lock and continue...
        try {
            invocationLock.lockInterruptibly();
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            throw new InvocationException(e);
        } catch (Exception e) {
            throw new InvocationException("Could not acquire serialization lock for session " + id, e);
        }

        try {
            // whilst we were waiting for the motionLock, the session in question may have been moved back into memory 
            // somehow. before we proceed, confirm that this has not happened.
            Motable context = lockHandler.acquire(invocation, id);
            if (null != context) {
                try {
                    return immoter.contextualise(invocation, id, context);
                } finally {
                    lockHandler.release(invocation, context);
                }
            }

            // session was not promoted whilst we were waiting for motionLock. Continue down Contextualiser stack.
            return next.contextualise(invocation, id, immoter, exclusiveOnly);
        } finally {
            invocationLock.unlock();
        }
    }

}