You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@struts.apache.org by mr...@apache.org on 2005/11/27 08:10:27 UTC
svn commit: r349187 [2/6] - in /struts/flow/trunk: ./ src/examples/WEB-INF/
src/examples/WEB-INF/guess/ src/examples/WEB-INF/portlet/
src/examples/WEB-INF/remote/ src/examples/remote/ src/java/
src/java/org/apache/struts/flow/ src/java/org/apache/strut...
Modified: struts/flow/trunk/src/java/org/apache/struts/flow/core/ContinuationsManagerImpl.java
URL: http://svn.apache.org/viewcvs/struts/flow/trunk/src/java/org/apache/struts/flow/core/ContinuationsManagerImpl.java?rev=349187&r1=349186&r2=349187&view=diff
==============================================================================
--- struts/flow/trunk/src/java/org/apache/struts/flow/core/ContinuationsManagerImpl.java (original)
+++ struts/flow/trunk/src/java/org/apache/struts/flow/core/ContinuationsManagerImpl.java Sat Nov 26 23:10:08 2005
@@ -1,21 +1,22 @@
/*
- * Copyright 1999-2004 The Apache Software Foundation.
+ * Copyright 1999-2004 The Apache Software Foundation.
*
- * 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
+ * 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
+ * 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.
+ * 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.struts.flow.core;
import java.security.SecureRandom;
+import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
@@ -26,79 +27,109 @@
import java.util.SortedSet;
import java.util.TreeSet;
+import javax.servlet.http.HttpSessionBindingEvent;
+import javax.servlet.http.HttpSessionBindingListener;
+
+import org.apache.commons.chain.web.WebContext;
+import org.apache.commons.chain.web.servlet.ServletWebContext;
+
+//import org.apache.avalon.framework.configuration.Configurable;
+//import org.apache.avalon.framework.configuration.Configuration;
+//import org.apache.avalon.framework.context.Context;
+//import org.apache.avalon.framework.context.ContextException;
+//import org.apache.avalon.framework.context.Contextualizable;
+//import org.apache.avalon.framework.logger.AbstractLogEnabled;
+//import org.apache.avalon.framework.service.ServiceException;
+//import org.apache.avalon.framework.service.ServiceManager;
+//import org.apache.avalon.framework.service.Serviceable;
+//import org.apache.avalon.framework.thread.ThreadSafe;
+//import org.apache.cocoon.components.ContextHelper;
+//import org.apache.cocoon.components.thread.RunnableManager;
+//import org.apache.cocoon.environment.ObjectModelHelper;
+//import org.apache.cocoon.environment.Request;
+//import org.apache.cocoon.environment.Session;
+
+
/**
- * The default implementation of {@link ContinuationsManager}.
- *
- *@author <a href="mailto:ovidiu@cup.hp.com">Ovidiu Predescu</a>
- *@author <a href="mailto:Michael.Melhem@managesoft.com">Michael Melhem</a>
- *@since March 19, 2002
- *@see ContinuationsManager
- *@version CVS $Id: ContinuationsManagerImpl.java,v 1.3 2004/06/02 21:56:54
- * mrdon Exp $
+ * The default implementation of {@link ContinuationsManager}. <br/>There are
+ * two modes of work: <br/>
+ * <ul>
+ * <li><b>standard mode </b>- continuations are stored in single holder. No
+ * security is applied to continuation lookup. Anyone can invoke a continuation
+ * only knowing the ID. Set "session-bound-continuations" configuration option
+ * to false to activate this mode.</li>
+ * <li><b>secure mode </b>- each session has it's own continuations holder. A
+ * continuation is only valid for the same session it was created for. Session
+ * invalidation causes all bound continuations to be invalidated as well. Use
+ * this setting for web applications. Set "session-bound-continuations"
+ * configuration option to true to activate this mode.</li>
+ * </ul>
+ *
+ * @author <a href="mailto:ovidiu@cup.hp.com">Ovidiu Predescu </a>
+ * @author <a href="mailto:Michael.Melhem@managesoft.com">Michael Melhem </a>
+ * @since March 19, 2002
+ * @see ContinuationsManager
+ * @version CVS $Id: ContinuationsManagerImpl.java 293111 2005-10-02 13:39:20Z reinhard $
*/
-public class ContinuationsManagerImpl
- implements ContinuationsManager {
-
- private final static int CONTINUATION_ID_LENGTH = 20;
+public class ContinuationsManagerImpl implements ContinuationsManager {
- /** Random object for creating continuation ids */
- protected SecureRandom random = null;
+ static final int CONTINUATION_ID_LENGTH = 20;
+ static final String EXPIRE_CONTINUATIONS = "expire-continuations";
/**
- * How long a continuation exists in memory since the last access. The
- * time is in miliseconds, and the default is 1 hour.
+ * Random number generator used to create continuation ID
*/
- protected int defaultTimeToLive = 1 * 60 * 60 * 1000;
-
- /** Maintains the forrest of <code>WebContinuation</code> trees. */
- protected Set forrest = Collections.synchronizedSet(new HashSet());
+ protected SecureRandom random;
+ protected byte[] bytes;
/**
- * Association between <code>WebContinuation</code> ids and the
- * corresponding <code>WebContinuation</code> object.
+ * How long does a continuation exist in memory since the last
+ * access? The time is in miliseconds, and the default is 1 hour.
*/
- protected Map idToWebCont = Collections.synchronizedMap(new HashMap());
+ protected int defaultTimeToLive = 3600 * 1000;
/**
- * Sorted set of <code>WebContinuation</code> instances, based on their
- * expiration time. This is used by the background thread to invalidate
- * continuations.
+ * Maintains the forest of <code>WebContinuation</code> trees.
+ * This set is used only for debugging puroses by
+ * {@link #displayAllContinuations()} method.
*/
- protected SortedSet expirations = Collections.synchronizedSortedSet(new TreeSet());
-
- private Thread expireThread;
+ protected Set forest = Collections.synchronizedSet(new HashSet());
/**
- * Gets the logger
- *
- *@return The logger value
+ * Main continuations holder. Used unless continuations are stored in user
+ * session.
*/
- public Logger getLogger() {
- return Factory.getLogger();
- }
-
-
+ protected WebContinuationsHolder continuationsHolder;
+
/**
- * Constructor for the ContinuationsManagerImpl object. Initializes the random
- * seed for continuation ids and starts the expiration thread.
- *
- *@exception Exception If anything goes wrong
+ * Sorted set of <code>WebContinuation</code> instances, based on
+ * their expiration time. This is used by the background thread to
+ * invalidate continuations.
*/
+ protected SortedSet expirations = Collections.synchronizedSortedSet(new TreeSet());
+
+ protected boolean bindContinuationsToSession;
+
+ private Thread expireThread;
+
+ private long expirePeriod = 180000;
+
public ContinuationsManagerImpl() throws Exception {
try {
random = SecureRandom.getInstance("SHA1PRNG");
- } catch (java.security.NoSuchAlgorithmException nsae) {
- // maybe we are on IBM's SDK
+ } catch(java.security.NoSuchAlgorithmException nsae) {
+ // Maybe we are on IBM's SDK
random = SecureRandom.getInstance("IBMSecureRandom");
}
random.setSeed(System.currentTimeMillis());
+ bytes = new byte[CONTINUATION_ID_LENGTH];
expireThread = new Thread(
new Runnable() {
public void run() {
boolean shouldKeepRunning = true;
while (shouldKeepRunning) {
try {
- Thread.sleep(60 * 1000);
+ Thread.sleep(expirePeriod);
} catch (InterruptedException ex) {
getLogger().debug("Continuation expiration thread interrupted");
shouldKeepRunning = false;
@@ -114,9 +145,21 @@
expireThread.setName("Flow continuations expiration thread");
expireThread.setPriority(Thread.MIN_PRIORITY);
expireThread.start();
+
+ this.continuationsHolder = new WebContinuationsHolder();
}
-
-
+
+
+ /**
+ * Gets the logger
+ *
+ *@return The logger value
+ */
+ public Logger getLogger() {
+ return Factory.getLogger();
+ }
+
+
/**
* Set the default time to live value
*
@@ -125,149 +168,130 @@
public void setDefaultTimeToLive(int ttl) {
this.defaultTimeToLive = ttl;
}
+
+ public void setExpirationPeriod(long period) {
+ this.expirePeriod = period;
+ }
+
+ public void setBindContinuationsToSession(boolean bind) {
+ this.bindContinuationsToSession = bind;
+ if (this.bindContinuationsToSession) {
+ this.continuationsHolder = null;
+ }
+ }
- /**
- * Create a <code>WebContinuation</code> object given a native continuation
- * object and its parent. If the parent continuation is null, the <code>WebContinuation</code>
- * returned becomes the root of a tree in the forrest.
- *
- *@param kont an <code>Object</code> value
- *@param parent a <code>WebContinuation</code> value
- *@param timeToLive an <code>int</code> value indicating how long in
- * seconds this continuation will live in the server if not accessed
- *@param disposer a <code>ContinuationsDisposer</code> instance to
- * called when the continuation gets cleaned up.
- *@return a <code>WebContinuation</code> value
- *@see WebContinuation
- */
public WebContinuation createWebContinuation(Object kont,
- WebContinuation parent,
- int timeToLive,
- ContinuationsDisposer disposer) {
+ WebContinuation parent,
+ int timeToLive,
+ String interpreterId,
+ ContinuationsDisposer disposer,
+ WebContext webctx) {
int ttl = (timeToLive == 0 ? defaultTimeToLive : timeToLive);
- WebContinuation wk = generateContinuation(kont, parent, ttl, disposer);
+ WebContinuation wk = generateContinuation(kont, parent, ttl, interpreterId, disposer, webctx);
+ //wk.enableLogging(getLogger());
if (parent == null) {
- forrest.add(wk);
- }
-
- // REVISIT: This Places only the "leaf" nodes in the expirations Sorted Set.
- // do we really want to do this?
- if (parent != null) {
- if (wk.getParentContinuation().getChildren().size() < 2) {
- expirations.remove(wk.getParentContinuation());
- }
+ forest.add(wk);
+ } else {
+ handleParentContinuationExpiration(parent);
}
- expirations.add(wk);
-
- // No need to add the WebContinuation in idToWebCont as it was
- // already done during its construction.
+ handleLeafContinuationExpiration(wk);
if (getLogger().isDebugEnabled()) {
- getLogger().debug("WK: Just Created New Continuation " + wk.getId());
+ getLogger().debug("WK: Created continuation " + wk.getId());
}
return wk;
}
-
-
+
/**
- * Invalidates a <code>WebContinuation</code>. This effectively means that
- * the continuation object associated with it will no longer be accessible
- * from Web pages. Invalidating a <code>WebContinuation</code> invalidates
- * all the <code>WebContinuation</code>s which are children of it.
- *
- *@param wk a <code>WebContinuation</code> value
+ * When a new continuation is created in @link #createWebContinuation(Object, WebContinuation, int, String, ContinuationsDisposer),
+ * it is registered in the expiration set in order to be evaluated by the invalidation mechanism.
*/
- public void invalidateWebContinuation(WebContinuation wk) {
- WebContinuation parent = wk.getParentContinuation();
- if (parent == null) {
- forrest.remove(wk);
- } else {
- List parentKids = parent.getChildren();
- parentKids.remove(wk);
- }
-
- _invalidate(wk);
+ protected void handleLeafContinuationExpiration(WebContinuation wk) {
+ expirations.add(wk);
}
-
- private void _invalidate(WebContinuation wk) {
- if (getLogger().isDebugEnabled()) {
- getLogger().debug("WK: Manual Expire of Continuation " + wk.getId());
- }
- disposeContinuation(wk);
- expirations.remove(wk);
-
- // Invalidate all the children continuations as well
- List children = wk.getChildren();
- int size = children.size();
- for (int i = 0; i < size; i++) {
- _invalidate((WebContinuation) children.get(i));
+ /**
+ * When a new continuation is created in @link #createWebContinuation(Object, WebContinuation, int, String, ContinuationsDisposer),
+ * its parent continuation is removed from the expiration set. This way only leaf continuations are part of
+ * the expiration set.
+ */
+ protected void handleParentContinuationExpiration(WebContinuation parent) {
+ if (parent.getChildren().size() < 2) {
+ expirations.remove(parent);
}
- }
-
-
+ }
+
/**
- * Makes the continuation inaccessible for lookup, and triggers possible
- * needed cleanup code through the ContinuationsDisposer interface.
- *
- *@param wk the continuation to dispose.
+ * Get a list of all web continuations (data only)
*/
- private void disposeContinuation(WebContinuation wk) {
- idToWebCont.remove(wk.getId());
-
- // Call specific possible implementation-specific clean-up on this continuation.
- ContinuationsDisposer disposer = wk.getDisposer();
- if (disposer != null) {
- disposer.disposeContinuation(wk);
+ public List getWebContinuationsDataBeanList() {
+ List beanList = new ArrayList();
+ for(Iterator it = this.forest.iterator(); it.hasNext();) {
+ beanList.add(new WebContinuationDataBean((WebContinuation) it.next()));
}
+ return beanList;
}
-
- /**
- * Given a <code>WebContinuation</code> id, retrieve the associated <code>WebContinuation</code>
- * object.
- *
- *@param id a <code>String</code> value
- *@return a <code>WebContinuation</code> object, or null if no such
- * <code>WebContinuation</code> could be found.
- */
- public WebContinuation lookupWebContinuation(String id) {
- // REVISIT: Is the folliwing check needed to avoid threading issues:
+ public WebContinuation lookupWebContinuation(String id, String interpreterId, WebContext webctx) {
+ // REVISIT: Is the following check needed to avoid threading issues:
// return wk only if !(wk.hasExpired) ?
- return (WebContinuation) idToWebCont.get(id);
+ WebContinuationsHolder continuationsHolder = lookupWebContinuationsHolder(false, webctx);
+ if (continuationsHolder == null)
+ return null;
+
+ WebContinuation kont = continuationsHolder.get(id);
+ if (kont == null)
+ return null;
+
+ if (!kont.interpreterMatches(interpreterId)) {
+ getLogger().error(
+ "WK: Continuation (" + kont.getId()
+ + ") lookup for wrong interpreter. Bound to: "
+ + kont.getInterpreterId() + ", looked up for: "
+ + interpreterId);
+ return null;
+ }
+ return kont;
}
-
/**
- * Create <code>WebContinuation</code> and generate unique identifier for
- * it. The identifier is generated using a cryptographically strong
- * algorithm to prevent people to generate their own identifiers. <p>
- *
- * It has the side effect of interning the continuation object in the
- * <code>idToWebCont</code> hash table.
- *
- *@param kont an <code>Object</code> value representing continuation
- *@param parent value representing parent <code>WebContinuation</code>
- *@param ttl <code>WebContinuation</code> time to live
- *@param disposer <code>ContinuationsDisposer</code> instance to use for
- * cleanup of the continuation.
- *@return the generated <code>WebContinuation</code> with unique
- * identifier
- */
- private WebContinuation generateContinuation(Object kont,
- WebContinuation parent,
- int ttl,
- ContinuationsDisposer disposer) {
+ * Create <code>WebContinuation</code> and generate unique identifier for
+ * it. The identifier is generated using a cryptographically strong
+ * algorithm to prevent people to generate their own identifiers.
+ *
+ * <p>
+ * It has the side effect of interning the continuation object in the
+ * <code>idToWebCont</code> hash table.
+ *
+ * @param kont
+ * an <code>Object</code> value representing continuation
+ * @param parent
+ * value representing parent <code>WebContinuation</code>
+ * @param ttl
+ * <code>WebContinuation</code> time to live
+ * @param interpreterId
+ * id of interpreter invoking continuation creation
+ * @param disposer
+ * <code>ContinuationsDisposer</code> instance to use for
+ * cleanup of the continuation.
+ * @return the generated <code>WebContinuation</code> with unique
+ * identifier
+ */
+ protected WebContinuation generateContinuation(Object kont,
+ WebContinuation parent,
+ int ttl,
+ String interpreterId,
+ ContinuationsDisposer disposer,
+ WebContext webctx) {
- byte[] bytes = new byte[CONTINUATION_ID_LENGTH];
char[] result = new char[bytes.length * 2];
WebContinuation wk = null;
-
+ WebContinuationsHolder continuationsHolder = lookupWebContinuationsHolder(true, webctx);
while (true) {
random.nextBytes(bytes);
@@ -277,11 +301,17 @@
result[2 * i + 1] = Character.forDigit(Math.abs(ch & 0x0f), 16);
}
- String id = new String(result);
- synchronized (idToWebCont) {
- if (!idToWebCont.containsKey(id)) {
- wk = new WebContinuation(id, kont, parent, ttl, disposer);
- idToWebCont.put(id, wk);
+ final String id = new String(result);
+ synchronized (continuationsHolder) {
+ if (!continuationsHolder.contains(id)) {
+ if (this.bindContinuationsToSession)
+ wk = new HolderAwareWebContinuation(id, kont, parent,
+ ttl, interpreterId, disposer,
+ continuationsHolder);
+ else
+ wk = new WebContinuation(id, kont, parent, ttl,
+ interpreterId, disposer);
+ continuationsHolder.addContinuation(wk);
break;
}
}
@@ -290,49 +320,97 @@
return wk;
}
+ public void invalidateWebContinuation(WebContinuation wk, WebContext webctx) {
+ WebContinuationsHolder continuationsHolder = lookupWebContinuationsHolder(false, webctx);
+ if (!continuationsHolder.contains(wk)) {
+ //TODO this looks like a security breach - should we throw?
+ return;
+ }
+ _detach(wk);
+ _invalidate(continuationsHolder, wk);
+ }
+
+ private void _invalidate(WebContinuationsHolder continuationsHolder, WebContinuation wk) {
+ if (getLogger().isDebugEnabled()) {
+ getLogger().debug("WK: Manual expire of continuation " + wk.getId());
+ }
+ disposeContinuation(continuationsHolder, wk);
+ expirations.remove(wk);
+
+ // Invalidate all the children continuations as well
+ List children = wk.getChildren();
+ int size = children.size();
+ for (int i = 0; i < size; i++) {
+ _invalidate(continuationsHolder, (WebContinuation) children.get(i));
+ }
+ }
+
+ /**
+ * Detach this continuation from parent. This method removes
+ * continuation from {@link #forest} set, or, if it has parent,
+ * from parent's children collection.
+ * @param continuationsHolder
+ * @param wk Continuation to detach from parent.
+ */
+ protected void _detach(WebContinuation wk) {
+ WebContinuation parent = wk.getParentContinuation();
+ if (parent == null) {
+ forest.remove(wk);
+ } else
+ wk.detachFromParent();
+ }
/**
- * Removes an expired leaf <code>WebContinuation</code> node from its
- * continuation tree, and recursively removes its parent(s) if it they have
- * expired and have no (other) children.
+ * Makes the continuation inaccessible for lookup, and triggers possible needed
+ * cleanup code through the ContinuationsDisposer interface.
+ * @param continuationsHolder
*
- *@param wk <code>WebContinuation</code> node
+ * @param wk the continuation to dispose.
*/
- private void removeContinuation(WebContinuation wk) {
+ protected void disposeContinuation(WebContinuationsHolder continuationsHolder, WebContinuation wk) {
+ continuationsHolder.removeContinuation(wk);
+ wk.dispose();
+ }
+
+ /**
+ * Removes an expired leaf <code>WebContinuation</code> node
+ * from its continuation tree, and recursively removes its
+ * parent(s) if it they have expired and have no (other) children.
+ * @param continuationsHolder
+ *
+ * @param wk <code>WebContinuation</code> node
+ */
+ protected void removeContinuation(WebContinuationsHolder continuationsHolder,
+ WebContinuation wk) {
if (wk.getChildren().size() != 0) {
return;
}
// remove access to this contination
- disposeContinuation(wk);
-
- WebContinuation parent = wk.getParentContinuation();
- if (parent == null) {
- forrest.remove(wk);
- } else {
- List parentKids = parent.getChildren();
- parentKids.remove(wk);
- }
+ disposeContinuation(continuationsHolder, wk);
+ _detach(wk);
if (getLogger().isDebugEnabled()) {
- getLogger().debug("WK: deleted this WK: " + wk.getId());
+ getLogger().debug("WK: Deleted continuation: " + wk.getId());
}
// now check if parent needs to be removed.
+ WebContinuation parent = wk.getParentContinuation();
if (null != parent && parent.hasExpired()) {
- removeContinuation(parent);
+ //parent must have the same continuations holder, lookup not needed
+ removeContinuation(continuationsHolder, parent);
}
}
-
/**
- * Dump to Log file the current contents of the expirations <code>SortedSet</code>
+ * Dump to Log file the current contents of
+ * the expirations <code>SortedSet</code>
*/
- private void displayExpireSet() {
- Iterator iter = expirations.iterator();
- StringBuffer wkSet = new StringBuffer("\nWK; Expire Set Size: " + expirations.size());
- while (iter.hasNext()) {
- final WebContinuation wk = (WebContinuation) iter.next();
+ protected void displayExpireSet() {
+ StringBuffer wkSet = new StringBuffer("\nWK; Expire set size: " + expirations.size());
+ Iterator i = expirations.iterator();
+ while (i.hasNext()) {
+ final WebContinuation wk = (WebContinuation) i.next();
final long lat = wk.getLastAccessTime() + wk.getTimeToLive();
wkSet.append("\nWK: ")
.append(wk.getId())
@@ -349,59 +427,194 @@
getLogger().debug(wkSet.toString());
}
-
/**
- * Dump to Log file all <code>WebContinuation</code>s in the system
+ * Dump to Log file all <code>WebContinuation</code>s
+ * in the system
*/
public void displayAllContinuations() {
- Iterator iter = forrest.iterator();
- while (iter.hasNext()) {
- ((WebContinuation) iter.next()).display();
+ final Iterator i = forest.iterator();
+ while (i.hasNext()) {
+ ((WebContinuation) i.next()).display();
}
}
+ /**
+ * Remove all continuations which have already expired.
+ */
+ protected void expireContinuations() {
+ long now = 0;
+ if (getLogger().isDebugEnabled()) {
+ now = System.currentTimeMillis();
- /** Destroys all continuations and any other resident objects */
- public void destroy() {
- expirations.clear();
- Set clone = new HashSet(forrest);
- for (Iterator i = clone.iterator(); i.hasNext(); ) {
- removeContinuation((WebContinuation) i.next());
+ /* Continuations before clean up:
+ getLogger().debug("WK: Forest before cleanup: " + forest.size());
+ displayAllContinuations();
+ displayExpireSet();
+ */
}
- if (expireThread != null && expireThread.isAlive()) {
- expireThread.interrupt();
+ // Clean up expired continuations
+ int count = 0;
+ WebContinuation wk;
+ Iterator i = expirations.iterator();
+ while (i.hasNext() && ((wk = (WebContinuation) i.next()).hasExpired())) {
+ i.remove();
+ WebContinuationsHolder continuationsHolder = null;
+ if ( wk instanceof HolderAwareWebContinuation )
+ continuationsHolder = ((HolderAwareWebContinuation) wk).getContinuationsHolder();
+ else
+ continuationsHolder = this.continuationsHolder;
+ removeContinuation(continuationsHolder, wk);
+ count++;
}
- }
-
- /** Remove all continuations which have already expired */
- private void expireContinuations() {
- // log state before continuations clean up
if (getLogger().isDebugEnabled()) {
- getLogger().debug("WK: Forrest size: " + forrest.size());
+ getLogger().debug("WK Cleaned up " + count + " continuations in " +
+ (System.currentTimeMillis() - now));
+
+ /* Continuations after clean up:
+ getLogger().debug("WK: Forest after cleanup: " + forest.size());
displayAllContinuations();
displayExpireSet();
+ */
}
+ }
- // clean up
- if (getLogger().isDebugEnabled()) {
- getLogger().debug("WK CurrentSystemTime[" + System.currentTimeMillis() +
- "]: Cleaning up expired Continuations....");
+ /**
+ * Method used by WebContinuationsHolder to notify the continuations manager
+ * about session invalidation. Invalidates all continuations held by passed
+ * continuationsHolder.
+ */
+ protected void invalidateContinuations(
+ WebContinuationsHolder continuationsHolder) {
+ // TODO: this avoids ConcurrentModificationException, still this is not
+ // the best solution and should be changed
+ Object[] continuationIds = continuationsHolder.getContinuationIds()
+ .toArray();
+
+ for (int i = 0; i < continuationIds.length; i++) {
+ WebContinuation wk = continuationsHolder.get(continuationIds[i]);
+ if (wk != null) {
+ _detach(wk);
+ _invalidate(continuationsHolder, wk);
+ }
}
- WebContinuation wk;
- Iterator iter = expirations.iterator();
- while (iter.hasNext() && ((wk = (WebContinuation) iter.next()).hasExpired())) {
- iter.remove();
- this.removeContinuation(wk);
+ }
+
+ /**
+ * Lookup a proper web continuations holder.
+ * @param createNew
+ * should the manager create a continuations holder in session
+ * when none found?
+ */
+ public WebContinuationsHolder lookupWebContinuationsHolder(boolean createNew, WebContext webctx) {
+ //there is only one holder if continuations are not bound to session
+ if (!this.bindContinuationsToSession)
+ return this.continuationsHolder;
+
+ //if continuations bound to session lookup a proper holder in the session
+ if (!createNew && webctx instanceof ServletWebContext) {
+ if (((ServletWebContext) webctx).getRequest().getSession(false) == null) {
+ return null;
+ }
}
- // log state after continuations clean up
- if (getLogger().isDebugEnabled()) {
- getLogger().debug("WK: Forrest size: " + forrest.size());
- displayAllContinuations();
- displayExpireSet();
+ WebContinuationsHolder holder =
+ (WebContinuationsHolder) webctx.getSessionScope().get(
+ WebContinuationsHolder.CONTINUATIONS_HOLDER);
+ if (!createNew)
+ return holder;
+
+ if (holder != null)
+ return holder;
+
+ holder = new WebContinuationsHolder();
+ webctx.getSessionScope().put(WebContinuationsHolder.CONTINUATIONS_HOLDER,
+ holder);
+ return holder;
+ }
+
+ /**
+ * A holder for WebContinuations. When bound to session notifies the
+ * continuations manager of session invalidation.
+ */
+ public class WebContinuationsHolder implements HttpSessionBindingListener {
+ private final static String CONTINUATIONS_HOLDER =
+ "o.a.c.c.f.SCMI.WebContinuationsHolder";
+
+ private Map holder = Collections.synchronizedMap(new HashMap());
+
+ public WebContinuation get(Object id) {
+ return (WebContinuation) this.holder.get(id);
+ }
+
+ public void addContinuation(WebContinuation wk) {
+ this.holder.put(wk.getId(), wk);
+ }
+
+ public void removeContinuation(WebContinuation wk) {
+ this.holder.remove(wk.getId());
+ }
+
+ public Set getContinuationIds() {
+ return holder.keySet();
+ }
+
+ public boolean contains(String continuationId) {
+ return this.holder.containsKey(continuationId);
+ }
+
+ public boolean contains(WebContinuation wk) {
+ return contains(wk.getId());
+ }
+
+ public void valueBound(HttpSessionBindingEvent event) {
+ }
+
+ public void valueUnbound(HttpSessionBindingEvent event) {
+ invalidateContinuations(this);
+ }
+ }
+
+ /**
+ * WebContinuation extension that holds also the information about the
+ * holder. This information is needed to cleanup a proper holder after
+ * continuation's expiration time.
+ */
+ protected class HolderAwareWebContinuation extends WebContinuation {
+ private WebContinuationsHolder continuationsHolder;
+
+ public HolderAwareWebContinuation(String id, Object continuation,
+ WebContinuation parentContinuation, int timeToLive,
+ String interpreterId, ContinuationsDisposer disposer,
+ WebContinuationsHolder continuationsHolder) {
+ super(id, continuation, parentContinuation, timeToLive,
+ interpreterId, disposer);
+ this.continuationsHolder = continuationsHolder;
+ }
+
+ public WebContinuationsHolder getContinuationsHolder() {
+ return continuationsHolder;
+ }
+
+ //retain comparation logic from parent
+ public int compareTo(Object other) {
+ return super.compareTo(other);
+ }
+ }
+
+
+ /** Destroys all continuations and any other resident objects */
+ public void destroy() {
+ /*expirations.clear();
+ Set clone = new HashSet(forest);
+ for (Iterator i = clone.iterator(); i.hasNext(); ) {
+ removeContinuation((WebContinuation) i.next());
+ }
+ */
+ if (expireThread != null && expireThread.isAlive()) {
+ expireThread.interrupt();
}
}
-}
+}
Modified: struts/flow/trunk/src/java/org/apache/struts/flow/core/DefaultCallVariableRegistrar.java
URL: http://svn.apache.org/viewcvs/struts/flow/trunk/src/java/org/apache/struts/flow/core/DefaultCallVariableRegistrar.java?rev=349187&r1=349186&r2=349187&view=diff
==============================================================================
--- struts/flow/trunk/src/java/org/apache/struts/flow/core/DefaultCallVariableRegistrar.java (original)
+++ struts/flow/trunk/src/java/org/apache/struts/flow/core/DefaultCallVariableRegistrar.java Sat Nov 26 23:10:08 2005
@@ -16,7 +16,7 @@
package org.apache.struts.flow.core;
import org.mozilla.javascript.Scriptable;
-import org.apache.commons.chain.Context;
+import org.apache.commons.chain.web.WebContext;
import java.lang.reflect.Constructor;
/**
@@ -64,11 +64,11 @@
* static variable
*@return The instance value
*/
- public Object getInstance(Scriptable scope, Context ctx) {
+ public Object getInstance(Scriptable scope, WebContext ctx) {
try {
Constructor c = null;
try {
- c = variableClass.getConstructor(new Class[]{Context.class});
+ c = variableClass.getConstructor(new Class[]{WebContext.class});
} catch (NoSuchMethodException ex) {
// ignored
}
Modified: struts/flow/trunk/src/java/org/apache/struts/flow/core/DefaultStaticVariableRegistrar.java
URL: http://svn.apache.org/viewcvs/struts/flow/trunk/src/java/org/apache/struts/flow/core/DefaultStaticVariableRegistrar.java?rev=349187&r1=349186&r2=349187&view=diff
==============================================================================
--- struts/flow/trunk/src/java/org/apache/struts/flow/core/DefaultStaticVariableRegistrar.java (original)
+++ struts/flow/trunk/src/java/org/apache/struts/flow/core/DefaultStaticVariableRegistrar.java Sat Nov 26 23:10:08 2005
@@ -16,7 +16,7 @@
package org.apache.struts.flow.core;
import org.mozilla.javascript.Scriptable;
-import org.apache.commons.chain.Context;
+import org.apache.commons.chain.web.WebContext;
/**
* Defines a variable registrar used to define a static variable in the global
@@ -61,7 +61,7 @@
* static variable
*@return The instance value
*/
- public Object getInstance(Scriptable scope, Context ctx) {
+ public Object getInstance(Scriptable scope, WebContext ctx) {
return variable;
}
Modified: struts/flow/trunk/src/java/org/apache/struts/flow/core/Factory.java
URL: http://svn.apache.org/viewcvs/struts/flow/trunk/src/java/org/apache/struts/flow/core/Factory.java?rev=349187&r1=349186&r2=349187&view=diff
==============================================================================
--- struts/flow/trunk/src/java/org/apache/struts/flow/core/Factory.java (original)
+++ struts/flow/trunk/src/java/org/apache/struts/flow/core/Factory.java Sat Nov 26 23:10:08 2005
@@ -61,5 +61,6 @@
}
return continuationsManager;
}
+
}
Modified: struts/flow/trunk/src/java/org/apache/struts/flow/core/FlowException.java
URL: http://svn.apache.org/viewcvs/struts/flow/trunk/src/java/org/apache/struts/flow/core/FlowException.java?rev=349187&r1=349186&r2=349187&view=diff
==============================================================================
--- struts/flow/trunk/src/java/org/apache/struts/flow/core/FlowException.java (original)
+++ struts/flow/trunk/src/java/org/apache/struts/flow/core/FlowException.java Sat Nov 26 23:10:08 2005
@@ -1,122 +1,159 @@
/*
- * Copyright 1999-2004 The Apache Software Foundation.
- *
- * 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.
+ * Copyright 1999-2004 The Apache Software Foundation.
+ *
+ * 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.apache.struts.flow.core;
-import java.io.PrintStream;
-import java.io.PrintWriter;
+import java.util.List;
+
+import org.apache.struts.flow.core.location.LocatedException;
+import org.apache.struts.flow.core.location.LocatedRuntimeException;
+import org.apache.struts.flow.core.location.Location;
+import org.apache.struts.flow.core.location.MultiLocatable;
/**
- * This Exception wraps any exceptions thrown by Flow.
+ * This Exception is thrown every time there is a problem in processing
+ * a request.
+ *
+ * @author <a href="mailto:pier@apache.org">Pierpaolo Fumagalli</a>
+ * (Apache Software Foundation)
+ * @version CVS $Id: FlowException.java 280632 2005-09-13 19:35:46Z sylvain $
*/
-public class FlowException extends RuntimeException {
-
- /** The Throwable that caused this exception to be thrown. */
- private final Throwable throwable;
-
-
+public class FlowException extends LocatedRuntimeException implements MultiLocatable {
+
/**
- * Construct a new <code>FlowException</code> instance.
- *
- *@param message The detail message for this exception.
+ * Construct a new <code>FlowException</code> instance.
*/
- public FlowException(final String message) {
- this(message, null);
- }
-
-
- /**
- * Construct a new <code>FlowException</code> instance.
- *
- *@param message The detail message for this exception.
- *@param throwable the root cause of the exception
- */
- public FlowException(final String message, final Throwable throwable) {
+ public FlowException(String message) {
super(message);
- this.throwable = throwable;
- }
-
-
- /**
- * Retrieve root cause of the exception.
- *
- *@return the root cause
- */
- public final Throwable getCause() {
- return throwable;
}
-
-
+
/**
- * Creates a new <code>FlowException</code> instance.
+ * Creates a new <code>FlowException</code> instance.
*
- *@param ex an <code>Exception</code> value
+ * @param ex an <code>Exception</code> value
*/
public FlowException(Exception ex) {
- this(ex.getMessage(), ex);
+ super(ex.getMessage(), ex);
}
-
-
+
/**
- * Gets a detailed log of the exception
- *
- *@return The message
+ * Construct a new <code>FlowException</code> that references
+ * a parent Exception.
*/
- public String toString() {
- StringBuffer s = new StringBuffer();
- s.append(super.toString());
- final Throwable t = getCause();
- if (t != null) {
- s.append(t.toString());
+ public FlowException(String message, Throwable t) {
+ super(message, t);
+ }
+
+ /**
+ * Construct a new <code>FlowException</code> that has an associated location.
+ */
+ public FlowException(String message, Location location) {
+ super(message, location);
+ }
+
+ /**
+ * Construct a new <code>FlowException</code> that has a parent exception
+ * and an associated location.
+ * <p>
+ * This constructor is protected to enforce the use of {@link #throwLocated(String, Throwable, Location)}
+ * which limits exception nesting as far as possible.
+ */
+ protected FlowException(String message, Throwable t, Location location) {
+ super(message, t, location);
+ }
+
+ /**
+ * Throw a located exception given an existing exception and the location where
+ * this exception was catched.
+ * <p>
+ * If the exception is already a <code>FlowException</code> or a {@link LocatedRuntimeException},
+ * the location is added to the original exception's location chain and the original exception
+ * is rethrown (<code>description</code> is ignored) to limit exception nesting. Otherwise, a new
+ * <code>FlowException</code> is thrown, wrapping the original exception.
+ * <p>
+ * Note: this method returns an exception as a convenience if you want to keep the <code>throw</code>
+ * semantics in the caller code, i.e. write<br>
+ * <code> throw FlowException.throwLocated(...);</code><br>
+ * instead of<br>
+ * <code> FlowException.throwLocated(...);</code><br>
+ * <code> return;</code>
+ *
+ * @param message a message (can be <code>null</code>)
+ * @param thr the original exception (can be <code>null</code>)
+ * @param location the location (can be <code>null</code>)
+ * @return a (fake) located exception
+ * @throws FlowException or <code>LocatedRuntimeException</code>
+ */
+ public static FlowException throwLocated(String message, Throwable thr, Location location) throws FlowException {
+ if (thr instanceof FlowException) {
+ FlowException pe = (FlowException)thr;
+ pe.addLocation(location);
+ throw pe;
+
+ } else if (thr instanceof LocatedRuntimeException) {
+ LocatedRuntimeException re = (LocatedRuntimeException)thr;
+ re.addLocation(location);
+ // Rethrow
+ throw re;
}
- return s.toString();
+
+ throw new FlowException(message, thr, location);
}
-
-
- /** Prints the exception and its cause */
- public void printStackTrace() {
- super.printStackTrace();
- if (getCause() != null) {
- getCause().printStackTrace();
- }
- }
-
-
+
/**
- * Prints the exception and its cause
- *
- *@param s The stream to print to
- */
- public void printStackTrace(PrintStream s) {
- super.printStackTrace(s);
- if (getCause() != null) {
- getCause().printStackTrace(s);
+ * Throw a located exception given an existing exception and the locations where
+ * this exception was catched.
+ * <p>
+ * If the exception is already a <code>FlowException</code> or a {@link LocatedRuntimeException},
+ * the locations are added to the original exception's location chain and the original exception
+ * is rethrown (<code>description</code> is ignored) to limit exception nesting. Otherwise, a new
+ * <code>FlowException</code> is thrown, wrapping the original exception.
+ * <p>
+ * Note: this method returns an exception as a convenience if you want to keep the <code>throw</code>
+ * semantics in the caller code, i.e. write<br>
+ * <code> throw FlowException.throwLocated(...);</code><br>
+ * instead of<br>
+ * <code> FlowException.throwLocated(...);</code><br>
+ * <code> return;</code>
+ *
+ * @param message a message (can be <code>null</code>)
+ * @param thr the original exception (can be <code>null</code>)
+ * @param locations the locations (can be <code>null</code>)
+ * @return a (fake) located exception
+ * @throws FlowException or <code>LocatedRuntimeException</code>
+ */
+ public static FlowException throwLocated(String message, Throwable thr, List locations) throws FlowException {
+ MultiLocatable multiloc;
+ if (thr instanceof FlowException) {
+ multiloc = (FlowException)thr;
+ } else if (thr instanceof LocatedRuntimeException) {
+ multiloc = (LocatedRuntimeException)thr;
+ } else {
+ multiloc = new FlowException(message, thr);
}
- }
-
-
- /**
- * Prints the exception and its cause
- *
- *@param s The writer to print to
- */
- public void printStackTrace(PrintWriter s) {
- super.printStackTrace(s);
- if (getCause() != null) {
- getCause().printStackTrace(s);
+
+ if (locations != null) {
+ for (int i = 0; i < locations.size(); i++) {
+ multiloc.addLocation((Location)locations.get(i));
+ }
+ }
+
+ if (multiloc instanceof LocatedRuntimeException) {
+ throw (LocatedRuntimeException)multiloc;
+ } else {
+ throw (FlowException)multiloc;
}
}
}
-
Added: struts/flow/trunk/src/java/org/apache/struts/flow/core/FlowHelper.java
URL: http://svn.apache.org/viewcvs/struts/flow/trunk/src/java/org/apache/struts/flow/core/FlowHelper.java?rev=349187&view=auto
==============================================================================
--- struts/flow/trunk/src/java/org/apache/struts/flow/core/FlowHelper.java (added)
+++ struts/flow/trunk/src/java/org/apache/struts/flow/core/FlowHelper.java Sat Nov 26 23:10:08 2005
@@ -0,0 +1,101 @@
+/*
+ * Copyright 1999-2004 The Apache Software Foundation.
+ *
+ * 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.apache.struts.flow.core;
+
+import org.mozilla.javascript.Undefined;
+import org.mozilla.javascript.Wrapper;
+
+import java.util.Map;
+
+/**
+ * Provides the interface between the flow controller layer and the
+ * view layer. A view can obtain the context object sent by a flow
+ * script and the current web continuation, if any.
+ */
+public class FlowHelper {
+
+ // Constants defining keys in the object model used to store the various objects.
+ // These constants are private so that access to these objects only go through the
+ // accessors provided below.
+ //
+ // These objects are stored in the object model rather than as request attributes,
+ // as object model is cloned for subrequests (see EnvironmentWrapper), whereas
+ // request attributes are shared between the "real" request and all of its
+ // child requests.
+
+ /**
+ * Request attribute name used to store flow context.
+ */
+ private static final String CONTEXT_OBJECT = "cocoon.flow.context";
+
+ /**
+ * Request attribute name used to store flow continuation.
+ */
+ private static final String CONTINUATION_OBJECT = "cocoon.flow.continuation";
+
+ /**
+ * Get the flow context object associated with the current request
+ *
+ * @param objectModel The Cocoon Environment's object model
+ * @return The context object
+ */
+ public final static Object getContextObject(Map objectModel) {
+ return objectModel.get(CONTEXT_OBJECT);
+ }
+
+ /**
+ * Get the web continuation associated with the current request
+ *
+ * @param objectModel The Cocoon Environment's object model
+ * @return The web continuation
+ */
+ public final static WebContinuation getWebContinuation(Map objectModel) {
+ return (WebContinuation)objectModel.get(CONTINUATION_OBJECT);
+ }
+
+ /**
+ * Set the web continuation associated with the current request
+ *
+ * @param objectModel The Cocoon Environment's object model
+ * @param kont The web continuation
+ */
+ public final static void setWebContinuation(Map objectModel,
+ WebContinuation kont) {
+ objectModel.put(CONTINUATION_OBJECT, kont);
+ }
+
+ /**
+ * Set the flow context object associated with the current request
+ *
+ * @param objectModel The Cocoon Environment's object model
+ * @param obj The context object
+ */
+ public final static void setContextObject(Map objectModel, Object obj) {
+ objectModel.put(CONTEXT_OBJECT, obj);
+ }
+
+ /**
+ * Unwrap a Rhino object (getting the raw java object) and convert undefined to null
+ */
+ public static Object unwrap(Object obj) {
+ if (obj instanceof Wrapper) {
+ obj = ((Wrapper)obj).unwrap();
+ } else if (obj == Undefined.instance) {
+ obj = null;
+ }
+ return obj;
+ }
+}
Propchange: struts/flow/trunk/src/java/org/apache/struts/flow/core/FlowHelper.java
------------------------------------------------------------------------------
svn:executable = *
Added: struts/flow/trunk/src/java/org/apache/struts/flow/core/Interpreter.java
URL: http://svn.apache.org/viewcvs/struts/flow/trunk/src/java/org/apache/struts/flow/core/Interpreter.java?rev=349187&view=auto
==============================================================================
--- struts/flow/trunk/src/java/org/apache/struts/flow/core/Interpreter.java (added)
+++ struts/flow/trunk/src/java/org/apache/struts/flow/core/Interpreter.java Sat Nov 26 23:10:08 2005
@@ -0,0 +1,181 @@
+/*
+ * Copyright 1999-2004 The Apache Software Foundation.
+ *
+ * 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.apache.struts.flow.core;
+
+import java.util.List;
+
+import org.apache.commons.chain.web.WebContext;
+
+/**
+ * The interface to the flow scripting languages. This interface is
+ * for a component, which implements the appropriate language to be
+ * used for describing the flow. A system could have multiple
+ * components that implement this interface, each of them for a
+ * different scripting language.
+ *
+ * <p>A flow script defines what is the page flow in an interactive
+ * Web application. Usually the flow is defined in a high level
+ * programming language which provides the notion of continuations,
+ * which allows for the flow of the application to be described as a
+ * simple procedural program, without having to think about the
+ * application as a finite state machine which changes its internal
+ * state on each HTTP request from the client browser.
+ *
+ * <p>However an implementation may choose to use its own
+ * representation of an application, which may include XML
+ * representations of finite state machines. Note: this API has no
+ * provision for such implementations.
+ *
+ * <p>The component represented by this interface is called in three
+ * situations:
+ *
+ * <ul>
+ * <li>
+ * <p>From the sitemap, to invoke a top level function defined in a
+ * * given implementation language of the flow. This is done from
+ * the * sitemap using the construction:
+ *
+ * <pre>
+ * <map:call function="..." language="..."/>
+ * </pre>
+ *
+ * <p>The <code>language</code> attribute can be ignored if the *
+ * default language is used.
+ *
+ * <li>
+ * <p>From the sitemap, to continue a previously started
+ * computation. A previously started computation is saved in the
+ * form of a continuation inside the flow implementation language.
+ *
+ * <p>This case is similar with the above one, but the function
+ * invoked has a special name, specific to each language
+ * implementation. See the language implementation for more
+ * information on the function name and the arguments it receives.
+ *
+ * <li>
+ * <p>From a program in the flow layer. This is done to invoke a
+ * pipeline defined in the sitemap, to generate the response of the
+ * request.
+ * </ul>
+ *
+ * @author <a href="mailto:ovidiu@cup.hp.com">Ovidiu Predescu</a>
+ * @since March 11, 2002
+ * @version CVS $Id: Interpreter.java 106091 2004-11-21 14:20:13Z lgawron $
+ */
+public interface Interpreter {
+
+ public static class Argument {
+ public String name;
+ public String value;
+
+ public Argument(String name, String value) {
+ this.name = name;
+ this.value = value;
+ }
+
+ public String toString() {
+ return name + ": " + value;
+ }
+ }
+
+ /**
+ * @return the unique ID for this interpreter.
+ */
+ String getInterpreterID();
+
+ /**
+ * Set the unique ID for this interpreter.
+ */
+ void setInterpreterID(String interpreterID);
+
+ /**
+ * This method is called from the sitemap, using the syntax
+ *
+ * <pre>
+ * <map:call function="..."/>
+ * </pre>
+ *
+ * The method will execute the named function, which must be defined
+ * in the given language. There is no assumption made on how various
+ * arguments are passed to the function.
+ *
+ * <p>The <code>params</code> argument is a <code>List</code> object
+ * that contains <code>Interpreter.Argument</code> instances,
+ * representing the parameters to be passed to the called
+ * function. An <code>Argument</code> instance is a key-value pair,
+ * where the key is the name of the parameter, and the value is its
+ * desired value. Most languages will ignore the name value and
+ * simply pass to the function, in a positional order, the values of
+ * the argument. Some languages however can pass the arguments in a
+ * different order than the original prototype of the function. For
+ * these languages the ability to associate the actual argument with
+ * a formal parameter using its name is essential.
+ *
+ * <p>A particular language implementation may decide to put the
+ * environment, request, response etc. objects in the dynamic scope
+ * available to the function at the time of the call. Other
+ * implementations may decide to pass these as arguments to the
+ * called function.
+ *
+ * <p>The current implementation assumes the sitemap implementation
+ * is TreeProcessor.
+ *
+ * @param funName a <code>String</code> value, the name of the
+ * function to call
+ * @param params a <code>List</code> object whose components are
+ * CallFunctionNode.Argument instances. The interpretation of the
+ * parameters is left to the actual implementation of the
+ * interpreter.
+ * @param redirector a <code>Redirector</code> used to call views
+ */
+ Object callFunction(String funName, List params, WebContext chainCtx)
+ throws Exception;
+
+ /**
+ * Forward the request to a Cocoon pipeline.
+ *
+ * @param uri a <code>String</code>, the URI of the forwarded request
+ * @param bizData an <code>Object</code>, the business data object
+ * to be made available to the forwarded pipeline
+ * @param continuation a <code>WebContinuation</code>, the
+ * continuation to be called to resume the processing
+ * @param redirector a <code>Redirector</code> used to call views
+ * @exception Exception if an error occurs
+ */
+ //void forwardTo(String uri, Object bizData, WebContinuation continuation,
+ // Redirector redirector)
+ //throws Exception;
+
+ /**
+ * Continues a previously started processing. The continuation
+ * object where the processing should start from is indicated by the
+ * <code>continuationId</code> string.
+ *
+ * @param continuationId a <code>String</code> value
+ *
+ * @param params a <code>List</code> value, containing the
+ * parameters to be passed when invoking the continuation. As
+ * opposed to the parameters passed by <code>callFunction</code>,
+ * these parameters will only become available in the language's
+ * environment, if at all.
+ *
+ * @param redirector a <code>Redirector</code> used to call views
+ * @exception Exception if an error occurs
+ */
+ void handleContinuation(String continuationId, List params,
+ WebContext chainCtx)
+ throws Exception;
+}
Propchange: struts/flow/trunk/src/java/org/apache/struts/flow/core/Interpreter.java
------------------------------------------------------------------------------
svn:executable = *
Modified: struts/flow/trunk/src/java/org/apache/struts/flow/core/InvalidContinuationException.java
URL: http://svn.apache.org/viewcvs/struts/flow/trunk/src/java/org/apache/struts/flow/core/InvalidContinuationException.java?rev=349187&r1=349186&r2=349187&view=diff
==============================================================================
--- struts/flow/trunk/src/java/org/apache/struts/flow/core/InvalidContinuationException.java (original)
+++ struts/flow/trunk/src/java/org/apache/struts/flow/core/InvalidContinuationException.java Sat Nov 26 23:10:08 2005
@@ -1,46 +1,40 @@
/*
- * Copyright 1999-2004 The Apache Software Foundation.
- *
- * 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.
+ * Copyright 1999-2004 The Apache Software Foundation.
+ *
+ * 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.apache.struts.flow.core;
/**
- * This Exception is thrown whenever an invalid continuation is given.
+ * This Exception is thrown whenever an invalid continuation is given.
*
- *@author <a href="mailto:tcollen@neuagency.com">Tony Collen</a>
+ * @author <a href="mailto:tcollen@neuagency.com">Tony Collen</a>
+ * @version CVS $Id: InvalidContinuationException.java 233343 2005-08-18 18:06:44Z sylvain $
*/
public class InvalidContinuationException extends FlowException {
/**
- * Construct a new <code>InvalidContinuationException</code> instance.
- *
- *@param message The message of the exception
+ * Construct a new <code>InvalidContinuationException</code> instance.
*/
public InvalidContinuationException(String message) {
- super(message, null);
+ super(message);
}
-
/**
- * Construct a new <code>InvalidContinuationException</code> that
- * references a parent Exception.
- *
- *@param message The message
- *@param t The throwable to wrap
+ * Construct a new <code>InvalidContinuationException</code> that references
+ * a parent Exception.
*/
public InvalidContinuationException(String message, Throwable t) {
super(message, t);
}
}
-
Modified: struts/flow/trunk/src/java/org/apache/struts/flow/core/Logger.java
URL: http://svn.apache.org/viewcvs/struts/flow/trunk/src/java/org/apache/struts/flow/core/Logger.java?rev=349187&r1=349186&r2=349187&view=diff
==============================================================================
--- struts/flow/trunk/src/java/org/apache/struts/flow/core/Logger.java (original)
+++ struts/flow/trunk/src/java/org/apache/struts/flow/core/Logger.java Sat Nov 26 23:10:08 2005
@@ -59,6 +59,16 @@
public void debug(String msg) {
System.out.println("JS-DEBUG: " + msg);
}
+
+ /**
+ * Logs a debugging message
+ *
+ *@param msg The message
+ */
+ public void debug(String msg, Throwable t) {
+ System.out.println("JS-DEBUG: " + msg);
+ t.printStackTrace();
+ }
/**
Modified: struts/flow/trunk/src/java/org/apache/struts/flow/core/VariableRegistrar.java
URL: http://svn.apache.org/viewcvs/struts/flow/trunk/src/java/org/apache/struts/flow/core/VariableRegistrar.java?rev=349187&r1=349186&r2=349187&view=diff
==============================================================================
--- struts/flow/trunk/src/java/org/apache/struts/flow/core/VariableRegistrar.java (original)
+++ struts/flow/trunk/src/java/org/apache/struts/flow/core/VariableRegistrar.java Sat Nov 26 23:10:08 2005
@@ -16,7 +16,7 @@
package org.apache.struts.flow.core;
import org.mozilla.javascript.Scriptable;
-import org.apache.commons.chain.Context;
+import org.apache.commons.chain.web.WebContext;
/**
* Defines a variable registrar used to define either a static or
@@ -43,7 +43,7 @@
* @param ctx The commons chain context for the call, null if defining
* a static variable
*/
- public Object getInstance(Scriptable scope, Context ctx);
+ public Object getInstance(Scriptable scope, WebContext ctx);
/**
* Gets the variable name
Modified: struts/flow/trunk/src/java/org/apache/struts/flow/core/WebContinuation.java
URL: http://svn.apache.org/viewcvs/struts/flow/trunk/src/java/org/apache/struts/flow/core/WebContinuation.java?rev=349187&r1=349186&r2=349187&view=diff
==============================================================================
--- struts/flow/trunk/src/java/org/apache/struts/flow/core/WebContinuation.java (original)
+++ struts/flow/trunk/src/java/org/apache/struts/flow/core/WebContinuation.java Sat Nov 26 23:10:08 2005
@@ -1,114 +1,137 @@
/*
- * Copyright 1999-2004 The Apache Software Foundation.
+ * Copyright 1999-2004 The Apache Software Foundation.
*
- * 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
+ * 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
+ * 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.
+ * 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.struts.flow.core;
import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.HashMap;
import java.util.List;
+import java.util.Map;
+
/**
- * Representation of continuations in a Web environment. <p>
+ * Representation of continuations in a Web environment.
*
- * Because a user may click on the back button of the browser and restart a
- * saved computation in a continuation, each <code>WebContinuation</code>
- * becomes the parent of a subtree of continuations. <p>
+ * <p>Because a user may click on the back button of the browser and
+ * restart a saved computation in a continuation, each
+ * <code>WebContinuation</code> becomes the parent of a subtree of
+ * continuations.
*
- * If there is no parent <code>WebContinuation</code>, the created continuation
- * becomes the root of a tree of <code>WebContinuation</code>s.
+ * <p>If there is no parent <code>WebContinuation</code>, the created
+ * continuation becomes the root of a tree of
+ * <code>WebContinuation</code>s.
*
- *@author <a href="mailto:ovidiu@cup.hp.com">Ovidiu Predescu</a>
- *@since March 19, 2002
- *@version CVS $Id: WebContinuation.java,v 1.2 2004/06/02 21:56:54 mrdon Exp
- * $
+ * @author <a href="mailto:ovidiu@cup.hp.com">Ovidiu Predescu</a>
+ * @since March 19, 2002
+ * @version CVS $Id: WebContinuation.java 292158 2005-09-28 10:24:51Z sylvain $
*/
public class WebContinuation implements Comparable {
- /** The continuation this object represents. */
+ /**
+ * The continuation this object represents.
+ */
protected Object continuation;
/**
- * The parent <code>WebContinuation</code> from which processing last
- * started. If null, there is no parent continuation associated, and this
- * is the first one to be created in a processing. In this case this <code>WebContinuation</code>
- * instance becomes the root of the tree maintained by the <code>ContinuationsManager</code>
- * .
+ * The parent <code>WebContinuation</code> from which processing
+ * last started. If null, there is no parent continuation
+ * associated, and this is the first one to be created in a
+ * processing. In this case this <code>WebContinuation</code>
+ * instance becomes the root of the tree maintained by the
+ * <code>ContinuationsManager</code>.
*
- *@see ContinuationsManager
+ * @see ContinuationsManager
*/
protected WebContinuation parentContinuation;
/**
- * The children continuations. These are continuations created by resuming
- * the processing from the point stored by <code>continuation</code>.
+ * The children continuations. These are continuations created by
+ * resuming the processing from the point stored by
+ * <code>continuation</code>.
*/
protected List children = new ArrayList();
/**
- * The continuation id used to represent this instance in Web pages.
+ * The continuation id used to represent this instance in Web pages.
*/
protected String id;
+
+ /**
+ * Interpreter id that this continuation is bound to
+ */
+ protected String interpreterId;
/**
- * A user definable object. This is present for convenience, to store any
- * information associated with this <code>WebContinuation</code> a
- * particular implementation might need.
+ * A user definable object. This is present for convenience, to
+ * store any information associated with this
+ * <code>WebContinuation</code> a particular implementation might
+ * need.
*/
protected Object userObject;
/**
- * When was this continuation accessed last time. Each time the
- * continuation is accessed, this time is set to the time of the access.
+ * When was this continuation accessed last time. Each time the
+ * continuation is accessed, this time is set to the time of the
+ * access.
*/
protected long lastAccessTime;
/**
- * Indicates how long does this continuation will live (in seconds). The
- * continuation will be removed once the current time is bigger than <code>lastAccessTime + timeToLive</code>
- * .
+ * Indicates how long does this continuation will live (in
+ * seconds). The continuation will be removed once the current time
+ * is bigger than <code>lastAccessTime + timeToLive</code>.
*/
protected int timeToLive;
/**
- * Holds the <code>ContinuationsDisposer</code> to call when this
- * continuation gets invalidated.
+ * Holds the <code>ContinuationsDisposer</code> to call when this continuation
+ * gets invalidated.
*/
protected ContinuationsDisposer disposer;
+ /**
+ * The attributes of this continuation
+ */
+ private Map attributes;
/**
- * Create a <code>WebContinuation</code> object. Saves the object in the
- * hash table of continuations maintained by <code>manager</code> (this is
- * done as a side effect of obtaining and identifier from it).
- *
- *@param continuation an <code>Object</code> value
- *@param parentContinuation a <code>WebContinuation</code> value
- *@param timeToLive time this continuation should live
- *@param disposer a <code>ContinuationsDisposer</code> to call
- * when this continuation gets invalidated.
- *@param id Description of the Parameter
+ * Create a <code>WebContinuation</code> object. Saves the object in
+ * the hash table of continuations maintained by
+ * <code>manager</code> (this is done as a side effect of obtaining
+ * and identifier from it).
+ *
+ * @param continuation an <code>Object</code> value
+ * @param parentContinuation a <code>WebContinuation</code> value
+ * @param timeToLive time this continuation should live
+ * @param disposer a <code>ContinuationsDisposer</code> to call when this
+ * continuation gets invalidated.
*/
WebContinuation(String id,
- Object continuation,
- WebContinuation parentContinuation,
- int timeToLive,
- ContinuationsDisposer disposer) {
+ Object continuation,
+ WebContinuation parentContinuation,
+ int timeToLive,
+ String interpreterId,
+ ContinuationsDisposer disposer) {
this.id = id;
this.continuation = continuation;
this.parentContinuation = parentContinuation;
this.updateLastAccessTime();
this.timeToLive = timeToLive;
+ this.interpreterId = interpreterId;
this.disposer = disposer;
if (parentContinuation != null) {
@@ -116,27 +139,77 @@
}
}
+ /**
+ * Get an attribute of this continuation
+ *
+ * @param name the attribute name.
+ */
+ public Object getAttribute(String name) {
+ if (this.attributes == null)
+ return null;
+
+ return this.attributes.get(name);
+ }
+
+ /**
+ * Set an attribute of this continuation
+ *
+ * @param name the attribute name
+ * @param value its value
+ */
+ public void setAttribute(String name, Object value) {
+ if (this.attributes == null) {
+ this.attributes = Collections.synchronizedMap(new HashMap());
+ }
+
+ this.attributes.put(name, value);
+ }
+
+ /**
+ * Remove an attribute of this continuation
+ *
+ * @param name the attribute name
+ */
+ public void removeAttribute(String name) {
+ if (this.attributes == null)
+ return;
+
+ this.attributes.remove(name);
+ }
+
+ /**
+ * Enumerate the attributes of this continuation.
+ *
+ * @return an enumeration of strings
+ */
+ public Iterator getAttributeNames() {
+ if (this.attributes == null)
+ return Collections.EMPTY_LIST.iterator();
+
+ ArrayList keys = new ArrayList(this.attributes.keySet());
+ return keys.iterator();
+ }
/**
- * Return the continuation object.
+ * Return the continuation object.
*
- *@return an <code>Object</code> value
+ * @return an <code>Object</code> value
*/
public Object getContinuation() {
updateLastAccessTime();
return continuation;
}
-
/**
- * Return the ancestor continuation situated <code>level</code>s above the
- * current continuation. The current instance is considered to be at level
- * 0. The parent continuation of the receiving instance at level 1, its
- * parent is at level 2 relative to the receiving instance. If <code>level</code>
- * is bigger than the depth of the tree, the root of the tree is returned.
+ * Return the ancestor continuation situated <code>level</code>s
+ * above the current continuation. The current instance is
+ * considered to be at level 0. The parent continuation of the
+ * receiving instance at level 1, its parent is at level 2 relative
+ * to the receiving instance. If <code>level</code> is bigger than
+ * the depth of the tree, the root of the tree is returned.
*
- *@param level an <code>int</code> value
- *@return a <code>WebContinuation</code> value
+ * @param level an <code>int</code> value
+ * @return a <code>WebContinuation</code> value
*/
public WebContinuation getContinuation(int level) {
if (level <= 0) {
@@ -149,107 +222,110 @@
}
}
-
/**
- * Return the parent <code>WebContinuation</code>. Equivalent with <code>getContinuation(1)</code>
- * .
+ * Return the parent <code>WebContinuation</code>. Equivalent with
+ * <code>getContinuation(1)</code>.
*
- *@return a <code>WebContinuation</code> value
+ * @return a <code>WebContinuation</code> value
*/
public WebContinuation getParentContinuation() {
return parentContinuation;
}
-
/**
- * Return the children <code>WebContinuation</code> which were created as a
- * result of resuming the processing from the current <code>continuation</code>
- * .
+ * Return the children <code>WebContinuation</code> which were
+ * created as a result of resuming the processing from the current
+ * <code>continuation</code>.
*
- *@return a <code>List</code> value
+ * @return a <code>List</code> value
*/
public List getChildren() {
return children;
}
-
/**
- * Returns the string identifier of this <code>WebContinuation</code>.
+ * Returns the string identifier of this
+ * <code>WebContinuation</code>.
*
- *@return a <code>String</code> value
+ * @return a <code>String</code> value
*/
public String getId() {
return id;
}
+ /**
+ * Returns the string identifier of the interpreter to which
+ * this <code>WebContinuation</code> is bound.
+ *
+ * @return a <code>String</code> value
+ */
+ public String getInterpreterId() {
+ return interpreterId;
+ }
/**
- * Returns the last time this <code>WebContinuation</code> was accessed.
+ * Returns the last time this
+ * <code>WebContinuation</code> was accessed.
*
- *@return a <code>long</code> value
+ * @return a <code>long</code> value
*/
public long getLastAccessTime() {
return lastAccessTime;
}
-
/**
- * Returns the the timetolive for this <code>WebContinuation</code>.
+ * Returns the the timetolive for this
+ * <code>WebContinuation</code>.
*
- *@return a <code>long</code> value
+ * @return a <code>long</code> value
*/
public long getTimeToLive() {
return this.timeToLive;
}
-
/**
- * Sets the user object associated with this instance.
+ * Sets the user object associated with this instance.
*
- *@param obj an <code>Object</code> value
+ * @param obj an <code>Object</code> value
*/
public void setUserObject(Object obj) {
this.userObject = obj;
}
-
/**
- * Obtains the user object associated with this instance.
+ * Obtains the user object associated with this instance.
*
- *@return an <code>Object</code> value
+ * @return an <code>Object</code> value
*/
public Object getUserObject() {
return userObject;
}
-
/**
- * Obtains the <code>ContinuationsDisposer</code> to call when this
- * continuation is invalidated.
+ * Obtains the <code>ContinuationsDisposer</code> to call when this continuation
+ * is invalidated.
*
- *@return a <code>ContinuationsDisposer</code> instance or null if there
- * are no specific clean-up actions required.
+ * @return a <code>ContinuationsDisposer</code> instance or null if there are
+ * no specific clean-up actions required.
*/
ContinuationsDisposer getDisposer() {
return this.disposer;
}
-
/**
- * Returns the hash code of the associated identifier.
+ * Returns the hash code of the associated identifier.
*
- *@return an <code>int</code> value
+ * @return an <code>int</code> value
*/
public int hashCode() {
return id.hashCode();
}
-
/**
- * True if the identifiers are the same, false otherwise.
+ * True if the identifiers are the same, false otherwise.
*
- *@param another an <code>Object</code> value
- *@return a <code>boolean</code> value
+ * @param another an <code>Object</code> value
+ * @return a <code>boolean</code> value
*/
public boolean equals(Object another) {
if (another instanceof WebContinuation) {
@@ -258,44 +334,41 @@
return false;
}
-
/**
- * Compares the expiration time of this instance with that of the
- * WebContinuation passed as argument. <p>
+ * Compares the expiration time of this instance with that of the
+ * WebContinuation passed as argument.
*
- * <b>Note:</b> this class has a natural ordering that is inconsistent with
- * <code>equals</code>.</p> .
+ * <p><b>Note:</b> this class has a natural ordering that is
+ * inconsistent with <code>equals</code>.</p>.
*
- *@param other an <code>Object</code> value, which should be a <code>WebContinuation</code>
- * instance
- *@return an <code>int</code> value
+ * @param other an <code>Object</code> value, which should be a
+ * <code>WebContinuation</code> instance
+ * @return an <code>int</code> value
*/
public int compareTo(Object other) {
WebContinuation wk = (WebContinuation) other;
return (int) ((lastAccessTime + timeToLive)
- - (wk.lastAccessTime + wk.timeToLive));
+ - (wk.lastAccessTime + wk.timeToLive));
}
-
/**
- * Debugging method. <p>
+ * Debugging method.
*
- * Assumes the receiving instance as the root of a tree and displays the
- * tree of continuations.
+ * <p>Assumes the receiving instance as the root of a tree and
+ * displays the tree of continuations.
*/
public void display() {
- getLogger().debug("\nWK: Tree" + display(0));
+ Factory.getLogger().debug("\nWK: Tree" + display(0));
}
-
/**
- * Debugging method. <p>
+ * Debugging method.
*
- * Displays the receiving instance as if it is at the <code>indent</code>
- * depth in the tree of continuations. Each level is indented 2 spaces.
+ * <p>Displays the receiving instance as if it is at the
+ * <code>indent</code> depth in the tree of continuations. Each
+ * level is indented 2 spaces.
*
- *@param depth an <code>int</code> value
- *@return Description of the Return Value
+ * @param depth an <code>int</code> value
*/
protected String display(int depth) {
StringBuffer tree = new StringBuffer("\n");
@@ -328,26 +401,17 @@
return tree.toString();
}
-
- /** Update the continuation in the */
- protected void updateLastAccessTime() {
- lastAccessTime = System.currentTimeMillis();
- }
-
/**
- * Gets the logger
- *
- *@return The logger value
+ * Update the continuation in the
*/
- public Logger getLogger() {
- return Factory.getLogger();
+ protected void updateLastAccessTime() {
+ lastAccessTime = System.currentTimeMillis();
}
-
/**
- * Determines whether this continuation has expired
+ * Determines whether this continuation has expired
*
- *@return a <code>boolean</code> value
+ * @return a <code>boolean</code> value
*/
public boolean hasExpired() {
long currentTime = System.currentTimeMillis();
@@ -355,5 +419,32 @@
return (currentTime > expireTime);
}
-}
+ /**
+ * Dispose this continuation. Should be called on invalidation.
+ */
+ public void dispose() {
+ // Call possible implementation-specific clean-up on this continuation.
+ if (this.disposer != null) {
+ this.disposer.disposeContinuation(this);
+ }
+ // Remove continuation object - will also serve as "disposed" flag
+ this.continuation = null;
+ }
+
+ /**
+ * Return true if this continuation was disposed of
+ */
+ public boolean disposed() {
+ return this.continuation == null;
+ }
+
+ public boolean interpreterMatches( String interpreterId ) {
+ return (interpreterId == null ? false : interpreterId.equals(this.interpreterId));
+ }
+
+ public void detachFromParent() {
+ if (getParentContinuation() != null)
+ getParentContinuation().getChildren().remove(this);
+ }
+}
Added: struts/flow/trunk/src/java/org/apache/struts/flow/core/WebContinuationDataBean.java
URL: http://svn.apache.org/viewcvs/struts/flow/trunk/src/java/org/apache/struts/flow/core/WebContinuationDataBean.java?rev=349187&view=auto
==============================================================================
--- struts/flow/trunk/src/java/org/apache/struts/flow/core/WebContinuationDataBean.java (added)
+++ struts/flow/trunk/src/java/org/apache/struts/flow/core/WebContinuationDataBean.java Sat Nov 26 23:10:08 2005
@@ -0,0 +1,93 @@
+/*
+ * Copyright 1999-2005 The Apache Software Foundation.
+ *
+ * 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.apache.struts.flow.core;
+
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.Iterator;
+import java.util.List;
+
+/**
+ * Access to continuation data for monitoring applications
+ */
+public class WebContinuationDataBean {
+
+ private static final String TYPE_JAVAFLOW = "javaflow";
+ private static final String TYPE_FLOWSCRIPT = "flowscript";
+ private static final String HAS_EXPIRED_NO = "no";
+ private static final String HAS_EXPIRED_YES = "yes";
+
+ private WebContinuation wc;
+ private SimpleDateFormat formatter = new SimpleDateFormat("HH:mm:ss");
+ private List _children = new ArrayList();
+
+ public WebContinuationDataBean(WebContinuation wc) {
+ this.wc = wc;
+ for (Iterator it = wc.getChildren().iterator(); it.hasNext();) {
+ WebContinuationDataBean child = new WebContinuationDataBean(
+ (WebContinuation) it.next());
+ this._children.add(child);
+ }
+ }
+
+ public String getId() {
+ return wc.getId();
+ }
+
+ public String getLastAccessTime() {
+ return formatter.format(new Date(wc.getLastAccessTime()));
+ }
+
+ public String getInterpreterId() {
+ return wc.getInterpreterId();
+ }
+
+ public String getTimeToLiveInMinutes() {
+ return Long.toString(wc.getTimeToLive() / 1000 / 60);
+ }
+
+ public String getTimeToLive() {
+ return Long.toString(wc.getTimeToLive());
+ }
+
+ public String getExpireTime() {
+ return formatter.format(new Date(wc.getLastAccessTime()
+ + wc.getTimeToLive()));
+ }
+
+ public String hasExpired() {
+ if ((wc.getLastAccessTime() + wc.getTimeToLive()) < System
+ .currentTimeMillis()) {
+ return HAS_EXPIRED_YES;
+ }
+ return HAS_EXPIRED_NO;
+
+ }
+
+ public String getType() {
+ if (wc.getUserObject().getClass().getName().indexOf(
+ "FOM_WebContinuation") > 0) {
+ return TYPE_FLOWSCRIPT;
+ }
+ return TYPE_JAVAFLOW;
+ }
+
+ public List get_children() {
+ return this._children;
+ }
+
+}
Propchange: struts/flow/trunk/src/java/org/apache/struts/flow/core/WebContinuationDataBean.java
------------------------------------------------------------------------------
svn:executable = *
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@struts.apache.org
For additional commands, e-mail: dev-help@struts.apache.org