You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@wicket.apache.org by eh...@apache.org on 2007/04/04 08:19:22 UTC
svn commit: r525432 - in
/incubator/wicket/branches/wicket-1.x/jdk-1.4/wicket/src/main/java/wicket:
PageMap.java RequestCycle.java Session.java
Author: ehillenius
Date: Tue Apr 3 23:19:21 2007
New Revision: 525432
URL: http://svn.apache.org/viewvc?view=rev&rev=525432
Log:
fixes for stateless session support
Modified:
incubator/wicket/branches/wicket-1.x/jdk-1.4/wicket/src/main/java/wicket/PageMap.java
incubator/wicket/branches/wicket-1.x/jdk-1.4/wicket/src/main/java/wicket/RequestCycle.java
incubator/wicket/branches/wicket-1.x/jdk-1.4/wicket/src/main/java/wicket/Session.java
Modified: incubator/wicket/branches/wicket-1.x/jdk-1.4/wicket/src/main/java/wicket/PageMap.java
URL: http://svn.apache.org/viewvc/incubator/wicket/branches/wicket-1.x/jdk-1.4/wicket/src/main/java/wicket/PageMap.java?view=diff&rev=525432&r1=525431&r2=525432
==============================================================================
--- incubator/wicket/branches/wicket-1.x/jdk-1.4/wicket/src/main/java/wicket/PageMap.java (original)
+++ incubator/wicket/branches/wicket-1.x/jdk-1.4/wicket/src/main/java/wicket/PageMap.java Tue Apr 3 23:19:21 2007
@@ -29,23 +29,25 @@
*/
public abstract class PageMap implements IClusterable, IPageMap
{
- private static final long serialVersionUID = 1L;
+ /**
+ * Visitor interface for visiting entries in this map
+ *
+ * @author Jonathan Locke
+ */
+ static interface IVisitor
+ {
+ /**
+ * @param entry
+ * The page map entry
+ */
+ public void entry(final IPageMapEntry entry);
+ }
/** Name of default pagemap */
public static final String DEFAULT_NAME = null;
- /** URL to continue to after a given page. */
- private String interceptContinuationURL;
-
- /** Name of this page map */
- private final String name;
-
- /** Next available page identifier in this page map. */
- private int pageId = 0;
-
- /** The session where this PageMap resides */
- private transient Session session;
+ private static final long serialVersionUID = 1L;
/**
* Gets a page map for a page map name, automatically creating the page map
@@ -62,19 +64,17 @@
return (session != null) ? session.pageMapForName(pageMapName, true) : null;
}
- /**
- * Visitor interface for visiting entries in this map
- *
- * @author Jonathan Locke
- */
- static interface IVisitor
- {
- /**
- * @param entry
- * The page map entry
- */
- public void entry(final IPageMapEntry entry);
- }
+ /** URL to continue to after a given page. */
+ private String interceptContinuationURL;
+
+ /** Name of this page map */
+ private final String name;
+
+ /** Next available page identifier in this page map. */
+ private int pageId = 0;
+
+ /** The session where this PageMap resides */
+ private transient Session session;
/**
@@ -97,6 +97,61 @@
/**
+ * @see wicket.IPageMap#attributeForId(int)
+ */
+ public final String attributeForId(final int id)
+ {
+ return attributePrefix() + id;
+ }
+
+ /**
+ * @see wicket.IPageMap#clear()
+ */
+ public void clear()
+ {
+ // Remove all entries
+ visitEntries(new IVisitor()
+ {
+ public void entry(IPageMapEntry entry)
+ {
+ removeEntry(entry);
+ }
+ });
+ }
+
+ /**
+ * Redirects to any intercept page previously specified by a call to
+ * redirectToInterceptPage.
+ *
+ * @return True if an original destination was redirected to
+ * @see PageMap#redirectToInterceptPage(Page)
+ */
+ public final boolean continueToOriginalDestination()
+ {
+ // Get request cycle
+ final RequestCycle cycle = RequestCycle.get();
+
+ // If there's a place to go to
+ if (interceptContinuationURL != null)
+ {
+ cycle.setRequestTarget(new RedirectRequestTarget(interceptContinuationURL));
+
+ // Reset interception URL
+ interceptContinuationURL = null;
+
+ // Force session to replicate page maps
+ dirty();
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * @see wicket.IPageMap#get(int, int)
+ */
+ public abstract Page get(final int id, int versionNumber);
+
+ /**
* @see wicket.IPageMap#getEntry(int)
*/
public final IPageMapEntry getEntry(final int id)
@@ -121,6 +176,28 @@
}
/**
+ * @see wicket.IPageMap#getSizeInBytes()
+ */
+ public final long getSizeInBytes()
+ {
+ long size = Objects.sizeof(this);
+ Iterator it = getEntries().iterator();
+ while (it.hasNext())
+ {
+ IPageMapEntry entry = (IPageMapEntry)it.next();
+ if (entry instanceof Page)
+ {
+ size += ((Page)entry).getSizeInBytes();
+ }
+ else
+ {
+ size += Objects.sizeof(entry);
+ }
+ }
+ return size;
+ }
+
+ /**
* @see wicket.IPageMap#isDefault()
*/
public final boolean isDefault()
@@ -137,53 +214,10 @@
return this.pageId++;
}
- protected final void dirty()
- {
- session.dirtyPageMap(this);
- }
-
/**
- * @see wicket.IPageMap#attributeForId(int)
- */
- public final String attributeForId(final int id)
- {
- return attributePrefix() + id;
- }
-
- /**
- * @return The attribute prefix for this page map
- */
- final String attributePrefix()
- {
- return Session.pageMapEntryAttributePrefix + name + ":";
- }
-
- /**
- * Redirects to any intercept page previously specified by a call to
- * redirectToInterceptPage.
- *
- * @return True if an original destination was redirected to
- * @see PageMap#redirectToInterceptPage(Page)
+ * @see wicket.IPageMap#put(wicket.Page)
*/
- public final boolean continueToOriginalDestination()
- {
- // Get request cycle
- final RequestCycle cycle = RequestCycle.get();
-
- // If there's a place to go to
- if (interceptContinuationURL != null)
- {
- cycle.setRequestTarget(new RedirectRequestTarget(interceptContinuationURL));
-
- // Reset interception URL
- interceptContinuationURL = null;
-
- // Force session to replicate page maps
- dirty();
- return true;
- }
- return false;
- }
+ public abstract void put(final Page page);
/**
* Redirects browser to an intermediate page such as a sign-in page. The
@@ -192,12 +226,16 @@
* continue to the current URL at some later time; otherwise just use
* setResponsePage or, when you are in a constructor, redirectTo.
*
- * @param page
- * The page to temporarily redirect to
+ * @param pageClazz
+ * The page clazz to temporarily redirect to
*/
- public final void redirectToInterceptPage(final Page page)
+ public final void redirectToInterceptPage(final Class pageClazz)
{
- Session.get().bind();
+ Session session = Session.get();
+ if (session.isTemporary())
+ {
+ session.bind();
+ }
// Get the request cycle
final RequestCycle cycle = RequestCycle.get();
@@ -206,26 +244,30 @@
interceptContinuationURL = cycle.getRequest().getURL();
// Page map is dirty
- dirty();
+ session.dirtyPageMap(this);
// Redirect to the page
cycle.setRedirect(true);
- cycle.setResponsePage(page);
+ cycle.setResponsePage(pageClazz);
}
-
- /**
+
+ /**
* Redirects browser to an intermediate page such as a sign-in page. The
* current request's URL is saved exactly as it was requested for future use
* by continueToOriginalDestination(); Only use this method when you plan to
* continue to the current URL at some later time; otherwise just use
* setResponsePage or, when you are in a constructor, redirectTo.
*
- * @param pageClazz
- * The page clazz to temporarily redirect to
+ * @param page
+ * The page to temporarily redirect to
*/
- public final void redirectToInterceptPage(final Class pageClazz)
+ public final void redirectToInterceptPage(final Page page)
{
- Session.get().bind();
+ Session session = Session.get();
+ if (session.isTemporary())
+ {
+ session.bind();
+ }
// Get the request cycle
final RequestCycle cycle = RequestCycle.get();
@@ -234,51 +276,11 @@
interceptContinuationURL = cycle.getRequest().getURL();
// Page map is dirty
- session.dirtyPageMap(this);
+ dirty();
// Redirect to the page
cycle.setRedirect(true);
- cycle.setResponsePage(pageClazz);
- }
-
- /**
- * @see wicket.IPageMap#clear()
- */
- public void clear()
- {
- // Remove all entries
- visitEntries(new IVisitor()
- {
- public void entry(IPageMapEntry entry)
- {
- removeEntry(entry);
- }
- });
- }
-
- /**
- * @see wicket.IPageMap#setSession(wicket.Session)
- */
- public final void setSession(final Session session)
- {
- this.session = session;
- }
-
- /**
- * @param visitor
- * The visitor to call at each Page in this PageMap.
- */
- protected final void visitEntries(final IVisitor visitor)
- {
- final List attributes = session.getAttributeNames();
- for (final Iterator iterator = attributes.iterator(); iterator.hasNext();)
- {
- final String attribute = (String)iterator.next();
- if (attribute.startsWith(attributePrefix()))
- {
- visitor.entry((IPageMapEntry)session.getAttribute(attribute));
- }
- }
+ cycle.setResponsePage(page);
}
/**
@@ -308,62 +310,68 @@
public abstract void removeEntry(final IPageMapEntry entry);
/**
- * @see wicket.IPageMap#put(wicket.Page)
+ * @see wicket.IPageMap#setSession(wicket.Session)
*/
- public abstract void put(final Page page);
-
+ public final void setSession(final Session session)
+ {
+ this.session = session;
+ }
/**
- * @see wicket.IPageMap#get(int, int)
+ * @see java.lang.Object#toString()
*/
- public abstract Page get(final int id, int versionNumber);
+ public String toString()
+ {
+ return "[PageMap name=" + name + "]";
+ }
+
/**
- * @see wicket.IPageMap#getSizeInBytes()
+ * @return List of entries in this page map
*/
- public final long getSizeInBytes()
+ private final List getEntries()
{
- long size = Objects.sizeof(this);
- Iterator it = getEntries().iterator();
- while(it.hasNext())
+ final List attributes = session.getAttributeNames();
+ final List list = new ArrayList();
+ for (final Iterator iterator = attributes.iterator(); iterator.hasNext();)
{
- IPageMapEntry entry = (IPageMapEntry)it.next();
- if (entry instanceof Page)
- {
- size += ((Page)entry).getSizeInBytes();
- }
- else
+ final String attribute = (String)iterator.next();
+ if (attribute.startsWith(attributePrefix()))
{
- size += Objects.sizeof(entry);
+ list.add(session.getAttribute(attribute));
}
}
- return size;
+ return list;
+ }
+
+ protected final void dirty()
+ {
+ session.dirtyPageMap(this);
}
/**
- * @return List of entries in this page map
+ * @param visitor
+ * The visitor to call at each Page in this PageMap.
*/
- private final List getEntries()
+ protected final void visitEntries(final IVisitor visitor)
{
final List attributes = session.getAttributeNames();
- final List list = new ArrayList();
for (final Iterator iterator = attributes.iterator(); iterator.hasNext();)
{
final String attribute = (String)iterator.next();
if (attribute.startsWith(attributePrefix()))
{
- list.add(session.getAttribute(attribute));
+ visitor.entry((IPageMapEntry)session.getAttribute(attribute));
}
}
- return list;
}
/**
- * @see java.lang.Object#toString()
+ * @return The attribute prefix for this page map
*/
- public String toString()
+ final String attributePrefix()
{
- return "[PageMap name=" + name + "]";
+ return Session.pageMapEntryAttributePrefix + name + ":";
}
}
Modified: incubator/wicket/branches/wicket-1.x/jdk-1.4/wicket/src/main/java/wicket/RequestCycle.java
URL: http://svn.apache.org/viewvc/incubator/wicket/branches/wicket-1.x/jdk-1.4/wicket/src/main/java/wicket/RequestCycle.java?view=diff&rev=525432&r1=525431&r2=525432
==============================================================================
--- incubator/wicket/branches/wicket-1.x/jdk-1.4/wicket/src/main/java/wicket/RequestCycle.java (original)
+++ incubator/wicket/branches/wicket-1.x/jdk-1.4/wicket/src/main/java/wicket/RequestCycle.java Tue Apr 3 23:19:21 2007
@@ -716,13 +716,14 @@
}
else
{
- if (listener == IRedirectListener.INTERFACE)
+
+ page.setPageStateless(Boolean.FALSE);
+ // make session non-volatile if not already so
+ Session session = Session.get();
+ if (session.isTemporary())
{
- page.setPageStateless(Boolean.FALSE);
+ session.bind();
}
-
- // trigger creation of the actual session in case it was deferred
- session.getSessionStore().getSessionId(request, true);
// Get the listener interface name
target = new ListenerInterfaceRequestTarget(page, component, listener);
Modified: incubator/wicket/branches/wicket-1.x/jdk-1.4/wicket/src/main/java/wicket/Session.java
URL: http://svn.apache.org/viewvc/incubator/wicket/branches/wicket-1.x/jdk-1.4/wicket/src/main/java/wicket/Session.java?view=diff&rev=525432&r1=525431&r2=525432
==============================================================================
--- incubator/wicket/branches/wicket-1.x/jdk-1.4/wicket/src/main/java/wicket/Session.java (original)
+++ incubator/wicket/branches/wicket-1.x/jdk-1.4/wicket/src/main/java/wicket/Session.java Tue Apr 3 23:19:21 2007
@@ -18,6 +18,7 @@
import java.io.Serializable;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
@@ -122,14 +123,19 @@
public abstract class Session implements IClusterable, IConverterLocator
{
- private static final long serialVersionUID = 1L;
-
- /** meta data key for missing body tags logging. */
- public static final MetaDataKey PAGEMAP_ACCESS_MDK = new MetaDataKey(
- PageMapAccessMetaData.class)
+ /**
+ * Visitor interface for visiting page maps
+ *
+ * @author Jonathan Locke
+ */
+ public static interface IPageMapVisitor
{
- private static final long serialVersionUID = 1L;
- };
+ /**
+ * @param pageMap
+ * The page map
+ */
+ public void pageMap(final IPageMap pageMap);
+ }
/**
* meta data for recording map map access.
@@ -152,11 +158,17 @@
}
}
+ /** meta data key for missing body tags logging. */
+ public static final MetaDataKey PAGEMAP_ACCESS_MDK = new MetaDataKey(
+ PageMapAccessMetaData.class)
+ {
+ private static final long serialVersionUID = 1L;
+ };
+
/** Name of session attribute under which this session is stored */
public static final String SESSION_ATTRIBUTE_NAME = "session";
- /** Prefix for attributes holding page map entries */
- static final String pageMapEntryAttributePrefix = "p:";
+ private static final long serialVersionUID = 1L;
/** Thread-local current session. */
private static final ThreadLocal current = new ThreadLocal();
@@ -173,59 +185,18 @@
/** Attribute prefix for page maps stored in the session */
private static final String pageMapAttributePrefix = "m:";
- /**
- * Cached instance of agent info which is typically designated by calling
- * {@link RequestCycle#newClientInfo()}.
- */
- private ClientInfo clientInfo;
-
- /** The converter instance. */
- private transient IConverterLocator converterSupplier;
-
- /** True if session state has been changed */
- private transient boolean dirty = false;
-
- /** The locale to use when loading resources for this session. */
- private Locale locale;
-
- /** A number to generate names for auto create pagemaps */
- private int autoCreatePageMapCounter = 0;
-
- /** A linked list for last used pagemap queue */
- private LinkedList/* <IPageMap> */usedPageMaps = new LinkedList();
-
- /** Any special "skin" style to use when loading resources. */
- private String style;
-
- /** feedback messages */
- private FeedbackMessages feedbackMessages = new FeedbackMessages();
-
- private transient Map pageMapsUsedInRequest;
-
- /** cached id because you can't access the id after session unbound */
- private String id = null;
-
- /**
- * Temporary instance of the session store. Should be set on each request as
- * it is not supposed to go in the session.
- */
- private transient ISessionStore sessionStore;
-
- /** Application level meta data. */
- private MetaDataEntry[] metaData;
+ /** Prefix for attributes holding page map entries */
+ static final String pageMapEntryAttributePrefix = "p:";
/**
- * Visitor interface for visiting page maps
+ * Checks if the <code>Session</code> threadlocal is set in this thread
*
- * @author Jonathan Locke
+ * @return true if {@link Session#get()} can return the instance of session,
+ * false otherwise
*/
- public static interface IPageMapVisitor
+ public static boolean exists()
{
- /**
- * @param pageMap
- * The page map
- */
- public void pageMap(final IPageMap pageMap);
+ return current.get() != null;
}
/**
@@ -245,17 +216,6 @@
}
/**
- * Checks if the <code>Session</code> threadlocal is set in this thread
- *
- * @return true if {@link Session#get()} can return the instance of session,
- * false otherwise
- */
- public static boolean exists()
- {
- return current.get() != null;
- }
-
- /**
* THIS METHOD IS NOT PART OF THE WICKET PUBLIC API. DO NOT CALL IT.
* <p>
* Sets session for calling thread.
@@ -284,6 +244,53 @@
}
/**
+ * Holds attributes for sessions that are still temporary/ not bound to a
+ * session store. Only used when {@link #isTemporary()} is true.
+ */
+ private transient Map temporarySessionAttributes;
+
+ /**
+ * Cached instance of agent info which is typically designated by calling
+ * {@link RequestCycle#newClientInfo()}.
+ */
+ private ClientInfo clientInfo;
+
+ /** The converter instance. */
+ private transient IConverterLocator converterSupplier;
+
+ /** True if session state has been changed */
+ private transient boolean dirty = false;
+
+ /** The locale to use when loading resources for this session. */
+ private Locale locale;
+
+ /** A number to generate names for auto create pagemaps */
+ private int autoCreatePageMapCounter = 0;
+
+ /** A linked list for last used pagemap queue */
+ private LinkedList/* <IPageMap> */usedPageMaps = new LinkedList();
+
+ /** Any special "skin" style to use when loading resources. */
+ private String style;
+
+ /** feedback messages */
+ private FeedbackMessages feedbackMessages = new FeedbackMessages();
+
+ private transient Map pageMapsUsedInRequest;
+
+ /** cached id because you can't access the id after session unbound */
+ private String id = null;
+
+ /**
+ * Temporary instance of the session store. Should be set on each request as
+ * it is not supposed to go in the session.
+ */
+ private transient ISessionStore sessionStore;
+
+ /** Application level meta data. */
+ private MetaDataEntry[] metaData;
+
+ /**
* Constructor.
*
* @param application
@@ -303,43 +310,75 @@
/**
* Force binding this session to the application's
- * {@link ISessionStore session store}. A Wicket application can operate in
- * a session-less mode as long as stateless pages are used. Session objects
- * will be then created for each request, but they will only live for that
- * request. You can recognize temporary sessions by calling
- * {@link #isTemporary()} which basically checks whether the session's id is
- * null. Hence, temporary sessions have no session id.
+ * {@link ISessionStore session store} if not already done so.
+ * <p>
+ * A Wicket application can operate in a session-less mode as long as
+ * stateless pages are used. Session objects will be then created for each
+ * request, but they will only live for that request. You can recognize
+ * temporary sessions by calling {@link #isTemporary()} which basically
+ * checks whether the session's id is null. Hence, temporary sessions have
+ * no session id.
+ * </p>
* <p>
* By calling this method, the session will be bound (made not-temporary) if
* it was not bound yet. It is useful for cases where you want to be
* absolutely sure this session object will be available in next requests.
* </p>
+ * <p>
+ * This method should not typically be called by clients
+ * </p>
*/
public final void bind()
{
ISessionStore store = getSessionStore();
Request request = RequestCycle.get().getRequest();
- if (store.getSessionId(request, false) == null)
+ if (store.lookup(request) == null)
+ {
+ synchronized (this)
+ {
+ // explicitly create a session
+ this.id = store.getSessionId(request, true);
+ // bind it
+ store.bind(request, this);
+
+ if (temporarySessionAttributes != null)
+ {
+ for (Iterator i = temporarySessionAttributes.entrySet().iterator(); i.hasNext();)
+ {
+ Entry entry = (Entry)i.next();
+ store.setAttribute(request, String.valueOf(entry.getKey()), entry
+ .getValue());
+ }
+ temporarySessionAttributes = null;
+ }
+
+ RequestCycle.get().setUpdateSession(true);
+ }
+ }
+ else
{
- // explicitly create a session
- this.id = store.getSessionId(request, true);
- // bind it
- store.bind(request, this);
+ log.warn("trying to bind an already bound and non-temporary session");
}
- RequestCycle.get().setUpdateSession(true);
}
/**
- * Whether this session is temporary. A Wicket application can operate in a
- * session-less mode as long as stateless pages are used. If this session
- * object is temporary, it will not be available on a next request.
+ * Cleans up any unrendered, dangling feedback messages there may be. This
+ * implementation calls {@link FeedbackMessages#clearComponentSpecific()} to
+ * aggresively ensure there won't be memory leaks. Clients can override this
+ * method to e.g. call {@link FeedbackMessages#clearPageSpecific(Page)}.
+ * <p>
+ * This method should be called from by the framework right before a even
+ * handler is called. There is no need for clients to call this method
+ * directly
+ * </p>
*
- * @return Whether this session is temporary (which is the same as it's id
- * being null)
+ * @param page
+ * any current page (the page on which the event handler is that
+ * is about to be processed)
*/
- public final boolean isTemporary()
+ public void cleanupFeedbackMessages(Page page)
{
- return getId() == null;
+ feedbackMessages.clearComponentSpecific();
}
/**
@@ -358,6 +397,49 @@
}
/**
+ * Automatically creates a page map, giving it a session unique name.
+ *
+ * @return Created PageMap
+ */
+ public synchronized final IPageMap createAutoPageMap()
+ {
+ return newPageMap(createAutoPageMapName());
+ }
+
+ /**
+ * With this call you can create a pagemap name but not create the pagemap
+ * itself already. It will give the first pagemap name where it couldn't
+ * find a current pagemap for.
+ *
+ * It will return the same name if you call it 2 times in a row.
+ *
+ * @return The created pagemap name
+ */
+ public synchronized final String createAutoPageMapName()
+ {
+ String name = "wicket-" + autoCreatePageMapCounter;
+ IPageMap pm = pageMapForName(name, false);
+ while (pm != null)
+ {
+ autoCreatePageMapCounter++;
+ name = "wicket-" + autoCreatePageMapCounter;
+ pm = pageMapForName(name, false);
+ }
+ return name;
+ }
+
+ /**
+ * Registers an error feedback message for this session
+ *
+ * @param message
+ * The feedback message
+ */
+ public final void error(final String message)
+ {
+ addFeedbackMessage(message, FeedbackMessage.ERROR);
+ }
+
+ /**
* Get the application that is currently working with this session.
*
* @return Returns the application.
@@ -404,6 +486,28 @@
}
/**
+ * Gets the converter instance. This method returns the cached converter for
+ * the current locale. Whenever the locale is changed, the cached value is
+ * cleared and the converter will be recreated for the new locale on a next
+ * request.
+ *
+ * @param type
+ * TODO
+ *
+ * @return the converter
+ */
+ public final IConverter getConverter(Class/* <?> */type)
+ {
+ if (converterSupplier == null)
+ {
+ // Let the factory create a new converter
+ converterSupplier = getApplication().getApplicationSettings()
+ .getConverterLocatorFactory().newConverterLocator();
+ }
+ return converterSupplier.getConverter(type);
+ }
+
+ /**
* @return The default page map
*/
public final IPageMap getDefaultPageMap()
@@ -412,6 +516,16 @@
}
/**
+ * Gets feedback messages stored in session
+ *
+ * @return unmodifiable list of feedback messages
+ */
+ public final FeedbackMessages getFeedbackMessages()
+ {
+ return feedbackMessages;
+ }
+
+ /**
* Gets the unique id for this session from the underlying SessionStore. May
* be null if a concrete session is not yet created.
*
@@ -535,80 +649,28 @@
}
return null;
}
-
- /**
- * @return The page factory for this session
- */
- public final IPageFactory getPageFactory()
- {
- return getApplication().getSessionSettings().getPageFactory();
- }
-
- /**
- * @param page
- * The page, or null if no page context is available
- * @return The page factory for the page, or the default page factory if
- * page was null
- */
- public final IPageFactory getPageFactory(final Page page)
- {
- if (page != null)
- {
- return page.getPageFactory();
- }
- return getPageFactory();
- }
-
- /**
- * Gets a page map for the given name, automatically creating it if need be.
- *
- * @param pageMapName
- * Name of page map, or null for default page map
- * @param autoCreate
- * True if the page map should be automatically created if it
- * does not exist
- * @return PageMap for name
- */
- public final IPageMap pageMapForName(String pageMapName, final boolean autoCreate)
- {
- IPageMap pageMap = (IPageMap)getAttribute(attributeForPageMapName(pageMapName));
- if (pageMap == null && autoCreate)
- {
- pageMap = newPageMap(pageMapName);
- }
- return pageMap;
- }
-
- /**
- * Automatically creates a page map, giving it a session unique name.
- *
- * @return Created PageMap
+
+ /**
+ * @return The page factory for this session
*/
- public synchronized final IPageMap createAutoPageMap()
+ public final IPageFactory getPageFactory()
{
- return newPageMap(createAutoPageMapName());
+ return getApplication().getSessionSettings().getPageFactory();
}
/**
- * With this call you can create a pagemap name but not create the pagemap
- * itself already. It will give the first pagemap name where it couldn't
- * find a current pagemap for.
- *
- * It will return the same name if you call it 2 times in a row.
- *
- * @return The created pagemap name
+ * @param page
+ * The page, or null if no page context is available
+ * @return The page factory for the page, or the default page factory if
+ * page was null
*/
- public synchronized final String createAutoPageMapName()
+ public final IPageFactory getPageFactory(final Page page)
{
- String name = "wicket-" + autoCreatePageMapCounter;
- IPageMap pm = pageMapForName(name, false);
- while (pm != null)
+ if (page != null)
{
- autoCreatePageMapCounter++;
- name = "wicket-" + autoCreatePageMapCounter;
- pm = pageMapForName(name, false);
+ return page.getPageFactory();
}
- return name;
+ return getPageFactory();
}
/**
@@ -653,6 +715,17 @@
}
/**
+ * Registers an informational feedback message for this session
+ *
+ * @param message
+ * The feedback message
+ */
+ public final void info(final String message)
+ {
+ addFeedbackMessage(message, FeedbackMessage.INFO);
+ }
+
+ /**
* Set the session for each PageMap
*/
public final void init()
@@ -680,6 +753,19 @@
}
/**
+ * Whether this session is temporary. A Wicket application can operate in a
+ * session-less mode as long as stateless pages are used. If this session
+ * object is temporary, it will not be available on a next request.
+ *
+ * @return Whether this session is temporary (which is the same as it's id
+ * being null)
+ */
+ public final boolean isTemporary()
+ {
+ return getId() == null;
+ }
+
+ /**
* Creates a new page map with a given name
*
* @param name
@@ -721,6 +807,26 @@
}
/**
+ * Gets a page map for the given name, automatically creating it if need be.
+ *
+ * @param pageMapName
+ * Name of page map, or null for default page map
+ * @param autoCreate
+ * True if the page map should be automatically created if it
+ * does not exist
+ * @return PageMap for name
+ */
+ public final IPageMap pageMapForName(String pageMapName, final boolean autoCreate)
+ {
+ IPageMap pageMap = (IPageMap)getAttribute(attributeForPageMapName(pageMapName));
+ if (pageMap == null && autoCreate)
+ {
+ pageMap = newPageMap(pageMapName);
+ }
+ return pageMap;
+ }
+
+ /**
* @param pageMap
* Page map to remove
*/
@@ -761,6 +867,7 @@
dirty();
}
+
/**
* Set the locale for this session.
*
@@ -854,18 +961,6 @@
}
}
-
- /**
- * Registers an informational feedback message for this session
- *
- * @param message
- * The feedback message
- */
- public final void info(final String message)
- {
- addFeedbackMessage(message, FeedbackMessage.INFO);
- }
-
/**
* Registers a warning feedback message for this session
*
@@ -878,49 +973,6 @@
}
/**
- * Registers an error feedback message for this session
- *
- * @param message
- * The feedback message
- */
- public final void error(final String message)
- {
- addFeedbackMessage(message, FeedbackMessage.ERROR);
- }
-
- /**
- * Gets feedback messages stored in session
- *
- * @return unmodifiable list of feedback messages
- */
- public final FeedbackMessages getFeedbackMessages()
- {
- return feedbackMessages;
- }
-
- /**
- * Gets the converter instance. This method returns the cached converter for
- * the current locale. Whenever the locale is changed, the cached value is
- * cleared and the converter will be recreated for the new locale on a next
- * request.
- *
- * @param type
- * TODO
- *
- * @return the converter
- */
- public final IConverter getConverter(Class/* <?> */type)
- {
- if (converterSupplier == null)
- {
- // Let the factory create a new converter
- converterSupplier = getApplication().getApplicationSettings()
- .getConverterLocatorFactory().newConverterLocator();
- }
- return converterSupplier.getConverter(type);
- }
-
- /**
* Adds a feedback message to the list of messages
*
* @param message
@@ -934,6 +986,16 @@
}
/**
+ * @param pageMapName
+ * Name of page map
+ * @return Session attribute holding page map
+ */
+ private final String attributeForPageMapName(final String pageMapName)
+ {
+ return pageMapAttributePrefix + pageMapName;
+ }
+
+ /**
* Any detach logic for session subclasses. This is called on the end of
* handling a request, when the RequestCycle is about to be detached from
* the current thread.
@@ -959,10 +1021,20 @@
*/
protected final Object getAttribute(final String name)
{
- RequestCycle cycle = RequestCycle.get();
- if (cycle != null)
+ if (!isTemporary())
+ {
+ RequestCycle cycle = RequestCycle.get();
+ if (cycle != null)
+ {
+ return getSessionStore().getAttribute(cycle.getRequest(), name);
+ }
+ }
+ else
{
- return getSessionStore().getAttribute(cycle.getRequest(), name);
+ if (temporarySessionAttributes != null)
+ {
+ return temporarySessionAttributes.get(name);
+ }
}
return null;
}
@@ -972,12 +1044,22 @@
*/
protected final List getAttributeNames()
{
- RequestCycle cycle = RequestCycle.get();
- if (cycle != null)
+ if (!isTemporary())
{
- return getSessionStore().getAttributeNames(cycle.getRequest());
+ RequestCycle cycle = RequestCycle.get();
+ if (cycle != null)
+ {
+ return getSessionStore().getAttributeNames(cycle.getRequest());
+ }
}
- return null;
+ else
+ {
+ if (temporarySessionAttributes != null)
+ {
+ return new ArrayList(temporarySessionAttributes.keySet());
+ }
+ }
+ return Collections.EMPTY_LIST;
}
/**
@@ -1007,10 +1089,20 @@
*/
protected final void removeAttribute(String name)
{
- RequestCycle cycle = RequestCycle.get();
- if (cycle != null)
+ if (!isTemporary())
+ {
+ RequestCycle cycle = RequestCycle.get();
+ if (cycle != null)
+ {
+ getSessionStore().removeAttribute(cycle.getRequest(), name);
+ }
+ }
+ else
{
- getSessionStore().removeAttribute(cycle.getRequest(), name);
+ if (temporarySessionAttributes != null)
+ {
+ temporarySessionAttributes.remove(name);
+ }
}
}
@@ -1024,33 +1116,47 @@
*/
protected final void setAttribute(String name, Object value)
{
- RequestCycle cycle = RequestCycle.get();
- if (cycle == null)
+ if (!isTemporary())
{
- throw new WicketRuntimeException("Can not set the attribute. No RequestCycle available");
- }
+ RequestCycle cycle = RequestCycle.get();
+ if (cycle == null)
+ {
+ throw new IllegalStateException(
+ "Cannot set the attribute: no RequestCycle available");
+ }
- ISessionStore store = getSessionStore();
- Request request = cycle.getRequest();
+ ISessionStore store = getSessionStore();
+ Request request = cycle.getRequest();
- // extra check on session binding event
- if (value == this)
- {
- Object current = store.getAttribute(request, name);
- if (current == null)
+ // extra check on session binding event
+ if (value == this)
{
- String id = store.getSessionId(request, false);
- if (id != null)
+ Object current = store.getAttribute(request, name);
+ if (current == null)
{
- // this is a new instance. wherever it came from, bind the
- // session now
- store.bind(request, (Session)value);
+ String id = store.getSessionId(request, false);
+ if (id != null)
+ {
+ // this is a new instance. wherever it came from, bind
+ // the session now
+ store.bind(request, (Session)value);
+ }
}
}
- }
- // Set the actual attribute
- store.setAttribute(request, name, value);
+ // Set the actual attribute
+ store.setAttribute(request, name, value);
+ }
+ else
+ {
+ // we don't have to synchronize, as it is impossible a temporary
+ // session instance gets shared across threads
+ if (temporarySessionAttributes == null)
+ {
+ temporarySessionAttributes = new HashMap(3);
+ }
+ temporarySessionAttributes.put(name, value);
+ }
}
/**
@@ -1145,26 +1251,6 @@
}
/**
- * Cleans up any unrendered, dangling feedback messages there may be. This
- * implementation calls {@link FeedbackMessages#clearComponentSpecific()} to
- * aggresively ensure there won't be memory leaks. Clients can override this
- * method to e.g. call {@link FeedbackMessages#clearPageSpecific(Page)}.
- * <p>
- * This method should be called from by the framework right before a even
- * handler is called. There is no need for clients to call this method
- * directly
- * </p>
- *
- * @param page
- * any current page (the page on which the event handler is that
- * is about to be processed)
- */
- public void cleanupFeedbackMessages(Page page)
- {
- feedbackMessages.clearComponentSpecific();
- }
-
- /**
* @param page
* The page to add to dirty objects list
*/
@@ -1177,31 +1263,6 @@
}
}
- /**
- * INTERNAL API. The request cycle when detached will call this.
- *
- */
- final void requestDetached()
- {
- if (pageMapsUsedInRequest != null)
- {
- synchronized (pageMapsUsedInRequest)
- {
- Thread t = Thread.currentThread();
- Iterator it = pageMapsUsedInRequest.entrySet().iterator();
- while (it.hasNext())
- {
- Entry entry = (Entry)it.next();
- if (entry.getValue() == t)
- {
- it.remove();
- }
- }
- pageMapsUsedInRequest.notifyAll();
- }
- }
- }
-
/**
* @param map
@@ -1222,16 +1283,6 @@
}
/**
- * @param pageMapName
- * Name of page map
- * @return Session attribute holding page map
- */
- private final String attributeForPageMapName(final String pageMapName)
- {
- return pageMapAttributePrefix + pageMapName;
- }
-
- /**
* @return The current thread dirty objects list
*/
List getDirtyObjectsList()
@@ -1243,5 +1294,30 @@
dirtyObjects.set(list);
}
return list;
+ }
+
+ /**
+ * INTERNAL API. The request cycle when detached will call this.
+ *
+ */
+ final void requestDetached()
+ {
+ if (pageMapsUsedInRequest != null)
+ {
+ synchronized (pageMapsUsedInRequest)
+ {
+ Thread t = Thread.currentThread();
+ Iterator it = pageMapsUsedInRequest.entrySet().iterator();
+ while (it.hasNext())
+ {
+ Entry entry = (Entry)it.next();
+ if (entry.getValue() == t)
+ {
+ it.remove();
+ }
+ }
+ pageMapsUsedInRequest.notifyAll();
+ }
+ }
}
}