blob: e47ad9073a9cf9c61a369e5296ca2261796769b9 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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.apache.cocoon.components.flow.java;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
/**
* Continuation object to store the current execution. The continuation
* object can only used once.
*
* @author <a href="mailto:stephan@apache.org">Stephan Michels</a>
* @author <a href="mailto:tcurdt@apache.org">Torsten Curdt</a>
* @version CVS $Id$
*/
public class Continuation {
private static final Map continuations = Collections.synchronizedMap(new HashMap());
private final String functionName;
private final ContinuationStack stack;
private Object context;
public boolean restoring = false;
public boolean capturing = false;
/**
* Create new continuation.
*/
public Continuation(final String functionName, final Object context) {
this.functionName = functionName;
this.stack = new ContinuationStack();
this.context = context;
}
/**
* Create a new continuation, which continue a previous continuation.
*/
public Continuation(final Continuation parent, final Object context) {
if (parent == null)
throw new NullPointerException("Parent continuation is null");
this.functionName = parent.functionName;
this.stack = new ContinuationStack(parent.stack);
this.context = context;
this.restoring = true;
}
public String getFunctionName() {
return functionName;
}
/**
* Return the stack, which is used to store the frame information.
*/
public ContinuationStack getStack() {
return stack;
}
/**
* Return context object, which is associated to this continuation.
*/
public Object getContext() {
return context;
}
/**
* Suspend the running continuation or restore the suspended continuation.
*
* With the help of byte code manipulation this method is run twice, once at
* the end of request 1 to suspend the continuation and a second time at the
* beginning of the request 2.
*/
public static void suspend() {
Continuation continuation = Continuation.currentContinuation();
if (continuation == null)
throw new IllegalStateException("No continuation is running");
if (continuation.restoring) {
// restoring
continuation.capturing = false;
} else {
// suspending
continuation.context = null;
continuation.capturing = true;
}
continuation.restoring = false;
}
/**
* True, if the continuation restores the previous stack trace to the
* last invocation of suspend().
*/
public boolean isRestoring() {
return restoring;
}
/**
* True, if the continuation freezes the stack trace, and stops the continuation.
*/
public boolean isCapturing() {
return capturing;
}
/**
* Bind the continuation to running thread.
*/
public void registerThread() {
continuations.put(Thread.currentThread(), this);
}
/**
* Unbind the continuation to running thread.
*/
public void deregisterThread() {
continuations.remove(Thread.currentThread());
}
/**
* Return the continuation, which is associated to the
* current thread.
*/
public static Continuation currentContinuation() {
Thread t = Thread.currentThread();
return (Continuation) continuations.get(t);
}
}