This is an automated email from the ASF dual-hosted git repository.

svenmeier pushed a commit to branch WICKET-6563
in repository https://gitbox.apache.org/repos/asf/wicket.git


The following commit(s) were added to refs/heads/WICKET-6563 by this push:
     new 105e83f  WICKET-6563 support size limit
105e83f is described below

commit 105e83fcbd8ebe1a0bbc8cc57a2b3aee557ec06c
Author: Sven Meier <svenme...@apache.org>
AuthorDate: Tue Jan 22 19:19:28 2019 +0100

    WICKET-6563 support size limit
    
    for InSessionPageStore and InMemoryPageStore; corrected formatting
---
 .../pageStore/AbstractPersistentPageStore.java     |   6 +-
 .../wicket/pageStore/AsynchronousPageStore.java    |  37 ++--
 .../wicket/pageStore/DelegatingPageStore.java      |  21 +-
 .../org/apache/wicket/pageStore/DiskPageStore.java |   9 +-
 .../org/apache/wicket/pageStore/FilePageStore.java |  17 +-
 .../apache/wicket/pageStore/InMemoryPageStore.java | 140 ++++++++++---
 .../wicket/pageStore/InSessionPageStore.java       | 217 ++++++++++++++++-----
 .../apache/wicket/pageStore/RequestPageStore.java  |   9 +-
 .../wicket/pageStore/SerializingPageStore.java     |   6 +-
 .../wicket/pageStore/disk/NestedFolders.java       |  36 ++--
 .../wicket/pageStore/disk/PageWindowManager.java   |   3 +-
 11 files changed, 381 insertions(+), 120 deletions(-)

diff --git 
a/wicket-core/src/main/java/org/apache/wicket/pageStore/AbstractPersistentPageStore.java
 
b/wicket-core/src/main/java/org/apache/wicket/pageStore/AbstractPersistentPageStore.java
index b7d6a3d..918e8c1 100644
--- 
a/wicket-core/src/main/java/org/apache/wicket/pageStore/AbstractPersistentPageStore.java
+++ 
b/wicket-core/src/main/java/org/apache/wicket/pageStore/AbstractPersistentPageStore.java
@@ -146,7 +146,8 @@ public abstract class AbstractPersistentPageStore 
implements IPersistentPageStor
                        context.setSessionAttribute(KEY, attribute);
                }
                
-               if (attribute == null) {
+               if (attribute == null)
+               {
                        return null;
                }
                return attribute.identifier;
@@ -160,7 +161,8 @@ public abstract class AbstractPersistentPageStore 
implements IPersistentPageStor
         * @param context context
         * @return identifier for the sseion
         */
-       protected String createSessionIdentifier(IPageContext context) {
+       protected String createSessionIdentifier(IPageContext context)
+       {
                return context.getSessionId();
        }
 
diff --git 
a/wicket-core/src/main/java/org/apache/wicket/pageStore/AsynchronousPageStore.java
 
b/wicket-core/src/main/java/org/apache/wicket/pageStore/AsynchronousPageStore.java
index 9eb0c95..42f3233 100644
--- 
a/wicket-core/src/main/java/org/apache/wicket/pageStore/AsynchronousPageStore.java
+++ 
b/wicket-core/src/main/java/org/apache/wicket/pageStore/AsynchronousPageStore.java
@@ -165,7 +165,8 @@ public class AsynchronousPageStore extends 
DelegatingPageStore
                @Override
                public <T> void setRequestData(MetaDataKey<T> key, T value)
                {
-                       if (asynchronous) {
+                       if (asynchronous)
+                       {
                                throw new WicketRuntimeException("no request 
available asynchronuously");
                        }
                        
@@ -178,7 +179,8 @@ public class AsynchronousPageStore extends 
DelegatingPageStore
                @Override
                public <T> T getRequestData(MetaDataKey<T> key)
                {
-                       if (asynchronous) {
+                       if (asynchronous)
+                       {
                                throw new WicketRuntimeException("no request 
available asynchronuously");
                        }
                        
@@ -194,11 +196,13 @@ public class AsynchronousPageStore extends 
DelegatingPageStore
                @Override
                public <T extends Serializable> void setSessionAttribute(String 
key, T value)
                {
-                       if (asynchronous) {
+                       if (asynchronous)
+                       {
                                throw new WicketRuntimeException("no session 
available asynchronuously");
                        }
                        
-                       if (value != null) {
+                       if (value != null)
+                       {
                                attributeCache.put(key, value);
                        }
 
@@ -215,9 +219,11 @@ public class AsynchronousPageStore extends 
DelegatingPageStore
                @Override
                public <T extends Serializable> T getSessionAttribute(String 
key)
                {
-                       if (asynchronous) {
+                       if (asynchronous)
+                       {
                                T value = (T)attributeCache.get(key);
-                               if (value != null) {
+                               if (value != null)
+                               {
                                        return value;
                                }
                                
@@ -225,7 +231,8 @@ public class AsynchronousPageStore extends 
DelegatingPageStore
                        }
                        
                        T value = context.getSessionAttribute(key);
-                       if (value != null) {
+                       if (value != null)
+                       {
                                attributeCache.put(key, value);
                        }
                        
@@ -238,7 +245,8 @@ public class AsynchronousPageStore extends 
DelegatingPageStore
                @Override
                public <T extends Serializable> T setSessionData(MetaDataKey<T> 
key, T value)
                {
-                       if (asynchronous) {
+                       if (asynchronous)
+                       {
                                throw new WicketRuntimeException("no session 
available asynchronuously");
                        }
                        
@@ -366,7 +374,8 @@ public class AsynchronousPageStore extends 
DelegatingPageStore
        public void addPage(IPageContext context, IManageablePage page)
        {
                PendingAdd add = new PendingAdd(context, page);
-               if (getDelegate().canBeAsynchronous(add)) {
+               if (getDelegate().canBeAsynchronous(add))
+               {
                        String key = add.getKey();
                        queueMap.put(key, add);
                        try
@@ -387,7 +396,9 @@ public class AsynchronousPageStore extends 
DelegatingPageStore
                                log.error(e.getMessage(), e);
                                queueMap.remove(key);
                        }
-               } else {
+               }
+               else
+               {
                        log.warn("Delegated page store '{}' can not be 
asynchronous", getDelegate().getClass().getName());
                }
                
@@ -398,10 +409,12 @@ public class AsynchronousPageStore extends 
DelegatingPageStore
        public void removeAllPages(IPageContext context)
        {
                Iterator<PendingAdd> iterator = queue.iterator();
-               while (iterator.hasNext()) {
+               while (iterator.hasNext())
+               {
                        PendingAdd add = iterator.next(); 
                
-                       if (add.sessionId.equals(context.getSessionId())) {
+                       if (add.sessionId.equals(context.getSessionId()))
+                       {
                                iterator.remove();
                        }
                }
diff --git 
a/wicket-core/src/main/java/org/apache/wicket/pageStore/DelegatingPageStore.java
 
b/wicket-core/src/main/java/org/apache/wicket/pageStore/DelegatingPageStore.java
index 4e40d04..ba256a0 100644
--- 
a/wicket-core/src/main/java/org/apache/wicket/pageStore/DelegatingPageStore.java
+++ 
b/wicket-core/src/main/java/org/apache/wicket/pageStore/DelegatingPageStore.java
@@ -26,7 +26,8 @@ public abstract class DelegatingPageStore implements 
IPageStore
 {
        private final IPageStore delegate;
        
-       protected DelegatingPageStore(IPageStore delegate) {
+       protected DelegatingPageStore(IPageStore delegate)
+       {
                this.delegate = Args.notNull(delegate, "delegate");
        }
 
@@ -45,32 +46,38 @@ public abstract class DelegatingPageStore implements 
IPageStore
        }
        
        @Override
-       public void addPage(IPageContext context, IManageablePage page) {
+       public void addPage(IPageContext context, IManageablePage page)
+       {
                delegate.addPage(context, page);
        }
 
        @Override
-       public void removePage(IPageContext context, IManageablePage page) {
+       public void removePage(IPageContext context, IManageablePage page)
+       {
                delegate.removePage(context, page);
        }
 
        @Override
-       public void removeAllPages(IPageContext context) {
+       public void removeAllPages(IPageContext context)
+       {
                delegate.removeAllPages(context);
        }
        
        @Override
-       public IManageablePage getPage(IPageContext context, int id) {
+       public IManageablePage getPage(IPageContext context, int id)
+       {
                return delegate.getPage(context, id);
        }
 
        @Override
-       public void detach(IPageContext context) {
+       public void detach(IPageContext context)
+       {
                delegate.detach(context);
        }
 
        @Override
-       public void destroy() {
+       public void destroy()
+       {
                delegate.destroy();
        }
 }
diff --git 
a/wicket-core/src/main/java/org/apache/wicket/pageStore/DiskPageStore.java 
b/wicket-core/src/main/java/org/apache/wicket/pageStore/DiskPageStore.java
index 067e41f..3fdaa55 100644
--- a/wicket-core/src/main/java/org/apache/wicket/pageStore/DiskPageStore.java
+++ b/wicket-core/src/main/java/org/apache/wicket/pageStore/DiskPageStore.java
@@ -47,6 +47,7 @@ import org.apache.wicket.util.file.Files;
 import org.apache.wicket.util.io.IOUtils;
 import org.apache.wicket.util.lang.Args;
 import org.apache.wicket.util.lang.Bytes;
+import org.apache.wicket.util.lang.Classes;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -141,7 +142,8 @@ public class DiskPageStore extends 
AbstractPersistentPageStore
         * Pages are already serialized.
         */
        @Override
-       public boolean supportsVersioning() {
+       public boolean supportsVersioning()
+       {
                return true;
        }
        
@@ -195,7 +197,8 @@ public class DiskPageStore extends 
AbstractPersistentPageStore
        protected void removeAllPersistedPages(String identifier)
        {
                DiskData diskData = getDiskData(identifier, false);
-               if (diskData != null) {
+               if (diskData != null)
+               {
                        synchronized (diskDatas)
                        {
                                diskDatas.remove(diskData.sessionIdentifier);
@@ -209,7 +212,7 @@ public class DiskPageStore extends 
AbstractPersistentPageStore
        {
                if (page instanceof SerializedPage == false)
                {
-                       throw new WicketRuntimeException("works with serialized 
pages only");
+                       throw new WicketRuntimeException("DiskPageStore works 
with serialized pages only");
                }
                SerializedPage serializedPage = (SerializedPage) page;
 
diff --git 
a/wicket-core/src/main/java/org/apache/wicket/pageStore/FilePageStore.java 
b/wicket-core/src/main/java/org/apache/wicket/pageStore/FilePageStore.java
index cb39dc5..8ebd85c 100644
--- a/wicket-core/src/main/java/org/apache/wicket/pageStore/FilePageStore.java
+++ b/wicket-core/src/main/java/org/apache/wicket/pageStore/FilePageStore.java
@@ -118,9 +118,11 @@ public class FilePageStore extends 
AbstractPersistentPageStore
        }
 
        @Override
-       protected IManageablePage getPersistedPage(String identifier, int id) {
+       protected IManageablePage getPersistedPage(String identifier, int id)
+       {
                byte[] data = readFile(identifier, id);
-               if (data == null) {
+               if (data == null)
+               {
                        return null;
                }
                
@@ -161,7 +163,8 @@ public class FilePageStore extends 
AbstractPersistentPageStore
        }
 
        @Override
-       protected void removePersistedPage(String identifier, IManageablePage 
page) {
+       protected void removePersistedPage(String identifier, IManageablePage 
page)
+       {
                File file = getPageFile(identifier, page.getPageId(), false);
                if (file.exists())
                {
@@ -173,15 +176,17 @@ public class FilePageStore extends 
AbstractPersistentPageStore
        }
 
        @Override
-       protected void removeAllPersistedPages(String identifier) {
+       protected void removeAllPersistedPages(String identifier)
+       {
                folders.remove(identifier);
        }
 
        @Override
-       protected void addPersistedPage(String identifier, IManageablePage 
page) {
+       protected void addPersistedPage(String identifier, IManageablePage page)
+       {
                if (page instanceof SerializedPage == false)
                {
-                       throw new WicketRuntimeException("works with serialized 
pages only");
+                       throw new WicketRuntimeException("FilePageStore works 
with serialized pages only");
                }
                SerializedPage serializedPage = (SerializedPage) page;
 
diff --git 
a/wicket-core/src/main/java/org/apache/wicket/pageStore/InMemoryPageStore.java 
b/wicket-core/src/main/java/org/apache/wicket/pageStore/InMemoryPageStore.java
index 31bbea0..4764018 100644
--- 
a/wicket-core/src/main/java/org/apache/wicket/pageStore/InMemoryPageStore.java
+++ 
b/wicket-core/src/main/java/org/apache/wicket/pageStore/InMemoryPageStore.java
@@ -23,10 +23,12 @@ import java.util.List;
 import java.util.Map;
 import java.util.Set;
 import java.util.concurrent.ConcurrentHashMap;
+import java.util.function.Supplier;
 import java.util.stream.Collectors;
 import java.util.stream.StreamSupport;
 
 import org.apache.wicket.Application;
+import org.apache.wicket.WicketRuntimeException;
 import org.apache.wicket.core.util.lang.WicketObjects;
 import org.apache.wicket.page.IManageablePage;
 import org.apache.wicket.util.lang.Args;
@@ -41,7 +43,7 @@ public class InMemoryPageStore extends 
AbstractPersistentPageStore
 
        private final Map<String, MemoryData> datas = new ConcurrentHashMap<>();
 
-       private int maxPages;
+       private final Supplier<MemoryData> dataCreator;
 
        /**
         * @param applicationName
@@ -51,9 +53,25 @@ public class InMemoryPageStore extends 
AbstractPersistentPageStore
         */
        public InMemoryPageStore(String applicationName, int maxPages)
        {
+               this(applicationName, () -> new CountLimitedData(maxPages));
+       }
+
+       /**
+        * @param applicationName
+        *            {@link Application#getName()}
+        * @param maxPages
+        *            max pages per session
+        */
+       public InMemoryPageStore(String applicationName, Bytes maxBytes)
+       {
+               this(applicationName, () -> new SizeLimitedData(maxBytes));
+       }
+
+       InMemoryPageStore(String applicationName, Supplier<MemoryData> 
dataCreator)
+       {
                super(applicationName);
                
-               this.maxPages = Args.withinRange(1, Integer.MAX_VALUE, 
maxPages, "maxPages");
+               this.dataCreator = dataCreator;
        }
 
        /**
@@ -85,7 +103,7 @@ public class InMemoryPageStore extends 
AbstractPersistentPageStore
                {
                        synchronized (data)
                        {
-                               data.remove(page);
+                               data.remove(page.getPageId());
                        }
                }
        }
@@ -101,7 +119,7 @@ public class InMemoryPageStore extends 
AbstractPersistentPageStore
        {
                MemoryData data = getMemoryData(identifier, true);
 
-               data.add(page, maxPages);
+               data.add(page);
        }
 
        @Override
@@ -155,9 +173,12 @@ public class InMemoryPageStore extends 
AbstractPersistentPageStore
         */
        protected long getSize(IManageablePage page)
        {
-               if (page instanceof SerializedPage) {
+               if (page instanceof SerializedPage)
+               {
                        return ((SerializedPage)page).getData().length;
-               } else {
+               }
+               else
+               {
                        return WicketObjects.sizeof(page);
                }
        }
@@ -169,7 +190,7 @@ public class InMemoryPageStore extends 
AbstractPersistentPageStore
                        return datas.get(identifier);
                }
 
-               MemoryData data = new MemoryData();
+               MemoryData data = dataCreator.get();
                MemoryData existing = datas.putIfAbsent(identifier, data);
                return existing != null ? existing : data;
        }
@@ -177,9 +198,9 @@ public class InMemoryPageStore extends 
AbstractPersistentPageStore
        /**
         * Data kept in memory.
         */
-       static class MemoryData implements Iterable<IManageablePage>
+       static abstract class MemoryData implements Iterable<IManageablePage>
        {
-               private LinkedHashMap<Integer, IManageablePage> pages = new 
LinkedHashMap<>();
+               LinkedHashMap<Integer, IManageablePage> pages = new 
LinkedHashMap<>();
 
                @Override
                public Iterator<IManageablePage> iterator()
@@ -187,25 +208,15 @@ public class InMemoryPageStore extends 
AbstractPersistentPageStore
                        return pages.values().iterator();
                }
 
-               public synchronized void add(IManageablePage page, int maxPages)
+               public synchronized void add(IManageablePage page)
                {
                        pages.remove(page.getPageId());
                        pages.put(page.getPageId(), page);
-
-                       Iterator<IManageablePage> iterator = 
pages.values().iterator();
-                       int size = pages.size();
-                       while (size > maxPages)
-                       {
-                               iterator.next();
-
-                               iterator.remove();
-                               size--;
-                       }
                }
 
-               public void remove(IManageablePage page)
+               public IManageablePage remove(int pageId)
                {
-                       pages.remove(page.getPageId());
+                       return pages.remove(pageId);
                }
 
                public void removeAll()
@@ -219,5 +230,90 @@ public class InMemoryPageStore extends 
AbstractPersistentPageStore
 
                        return page;
                }
+               
+               protected void removeFirst() {
+                       Iterator<IManageablePage> iterator = 
pages.values().iterator();
+                       iterator.next();
+                       iterator.remove();
+               }
+       }
+       
+       /**
+        * Limit pages by count.
+        */
+       static class CountLimitedData extends MemoryData
+       {
+
+               private int maxPages;
+
+               public CountLimitedData(int maxPages)
+               {
+                       this.maxPages = Args.withinRange(1, Integer.MAX_VALUE, 
maxPages, "maxPages");
+               }
+       
+               @Override
+               public synchronized void add(IManageablePage page)
+               {
+                       super.add(page);
+                       
+                       while (pages.size() > maxPages)
+                       {
+                               removeFirst();
+                       }
+               }
+       }
+       
+       /**
+        * Limit pages by size.
+        */
+       static class SizeLimitedData extends MemoryData
+       {
+               
+               private Bytes maxBytes;
+               
+               private long size;
+
+               public SizeLimitedData(Bytes maxBytes)
+               {
+                       Args.notNull(maxBytes, "maxBytes");
+                       
+                       this.maxBytes = Args.withinRange(Bytes.bytes(1), 
Bytes.MAX, maxBytes, "maxBytes");
+               }
+               
+               @Override
+               public synchronized void add(IManageablePage page)
+               {
+                       if (page instanceof SerializedPage == false)
+                       {
+                               throw new 
WicketRuntimeException("InMemoryPageStore limited by size works with serialized 
pages only");
+                       }
+                       
+                       super.add(page);
+                       
+                       size += ((SerializedPage) page).getData().length;
+
+                       while (size > maxBytes.bytes())
+                       {
+                               removeFirst();
+                       }
+               }
+               
+               @Override
+               public synchronized IManageablePage remove(int pageId)
+               {
+                       SerializedPage page = (SerializedPage) 
super.remove(pageId);
+                       
+                       size -= ((SerializedPage) page).getData().length;
+                       
+                       return page;
+               }
+               
+               @Override
+               public synchronized void removeAll()
+               {
+                       super.removeAll();
+                       
+                       size = 0;
+               }
        }
 }
\ No newline at end of file
diff --git 
a/wicket-core/src/main/java/org/apache/wicket/pageStore/InSessionPageStore.java 
b/wicket-core/src/main/java/org/apache/wicket/pageStore/InSessionPageStore.java
index 7662fb8..c880ce0 100644
--- 
a/wicket-core/src/main/java/org/apache/wicket/pageStore/InSessionPageStore.java
+++ 
b/wicket-core/src/main/java/org/apache/wicket/pageStore/InSessionPageStore.java
@@ -22,15 +22,18 @@ import java.io.Serializable;
 import java.util.Iterator;
 import java.util.LinkedList;
 import java.util.List;
+import java.util.function.Supplier;
 
 import javax.servlet.http.HttpSession;
 
 import org.apache.wicket.DefaultPageManagerProvider;
 import org.apache.wicket.MetaDataKey;
 import org.apache.wicket.Session;
+import org.apache.wicket.WicketRuntimeException;
 import org.apache.wicket.page.IManageablePage;
 import org.apache.wicket.serialize.ISerializer;
 import org.apache.wicket.util.lang.Args;
+import org.apache.wicket.util.lang.Bytes;
 import org.apache.wicket.util.lang.Classes;
 
 /**
@@ -49,11 +52,13 @@ public class InSessionPageStore extends DelegatingPageStore
 
        private final ISerializer serializer;
 
-       private int maxPages;
+       private final Supplier<SessionData> dataCreator;
        
        /**
-        * Use this constructor if pages should not be persisted along with 
their session, e.g. because a delegated peristent page store
-        * keeps them anyway for backup. 
+        * Keep {@code maxPages} in each session.
+        * <p>
+        * If the container serializes sessions to disk, any non-{@code 
SerializedPage} added to this store
+        * will be dropped.   
         * 
         * @param delegate
         *            store to delegate to
@@ -66,7 +71,10 @@ public class InSessionPageStore extends DelegatingPageStore
        }
        
        /**
-        * Use this constructor if pages should be serialized along with their 
session.
+        * Keep {@code maxPages} in each session.
+        * <p>
+        * If the container serializes sessions to disk, any non-{@code 
SerializedPage} added to this store
+        * will be automatically serialized.   
         * 
         * @param delegate
         *            store to delegate to
@@ -77,18 +85,40 @@ public class InSessionPageStore extends DelegatingPageStore
         */
        public InSessionPageStore(IPageStore delegate, int maxPages, 
ISerializer serializer)
        {
+               this(delegate, serializer, () -> new 
CountLimitedData(maxPages));
+       }
+
+       /**
+        * Keep page up to {@code maxBytes} in each session.
+        * <p>
+        * All pages added to this store must be {@code SerializedPage}s. You 
can achieve this by letting
+        * a {@link SerializingPageStore} delegate to this store.
+        * 
+        * @param delegate
+        *            store to delegate to
+        * @param maxBytes
+        *            maximum bytes to keep in session
+        */
+       public InSessionPageStore(IPageStore delegate, Bytes maxBytes)
+       {
+               this(delegate, null, () -> new SizeLimitedData(maxBytes));
+       }
+
+       private InSessionPageStore(IPageStore delegate, ISerializer serializer, 
Supplier<SessionData> dataCreator)
+       {
                super(delegate);
 
                this.serializer = serializer;
-
-               this.maxPages = maxPages;
+               
+               this.dataCreator = dataCreator;
        }
 
        @Override
        public IManageablePage getPage(IPageContext context, int id)
        {
                SessionData data = getSessionData(context, false);
-               if (data != null) {
+               if (data != null)
+               {
                        IManageablePage page = data.get(id);
                        if (page != null)
                        {
@@ -104,7 +134,7 @@ public class InSessionPageStore extends DelegatingPageStore
        {
                SessionData data = getSessionData(context, true);
 
-               data.add(context, page, maxPages);
+               data.add(page);
                
                getDelegate().addPage(context, page);
        }
@@ -113,8 +143,9 @@ public class InSessionPageStore extends DelegatingPageStore
        public void removePage(IPageContext context, IManageablePage page)
        {
                SessionData data = getSessionData(context, false);
-               if (data != null) {
-                       data.remove(page);
+               if (data != null)
+               {
+                       data.remove(page.getPageId());
                }
 
                getDelegate().removePage(context, page);
@@ -124,7 +155,8 @@ public class InSessionPageStore extends DelegatingPageStore
        public void removeAllPages(IPageContext context)
        {
                SessionData data = getSessionData(context, false);
-               if (data != null) {
+               if (data != null)
+               {
                        data.removeAll();
                }
 
@@ -136,12 +168,13 @@ public class InSessionPageStore extends 
DelegatingPageStore
                SessionData data = context.getSessionData(KEY);
                if (data == null && create)
                {
-                       data = context.setSessionData(KEY, new SessionData());
+                       data = context.setSessionData(KEY, dataCreator.get());
                }
 
-               if (data != null && serializer != null) {
+               if (data != null && serializer != null)
+               {
                        // data might be deserialized so initialize again
-                       data.init(serializer);
+                       data.supportSessionSerialization(serializer);
                }
 
                return data;
@@ -151,7 +184,7 @@ public class InSessionPageStore extends DelegatingPageStore
         * Data kept in the {@link Session}, might get serialized along with 
its containing
         * {@link HttpSession}.
         */
-       static class SessionData implements Serializable
+       static abstract class SessionData implements Serializable
        {
 
                transient ISerializer serializer;
@@ -161,39 +194,47 @@ public class InSessionPageStore extends 
DelegatingPageStore
                 * <p>
                 * Kept in list instead of map, since life pages might change 
their id during a request.
                 */
-               private List<IManageablePage> pages = new LinkedList<>();
+               List<IManageablePage> pages = new LinkedList<>();
 
                /**
-                * This method <em>must</em> be called each time it is 
retrieved from the session: <br/>
-                * After deserializing from persisted session the serializer is 
no longer referenced and all
-                * contained pages are in a serialized state.
+                * Call this method if session serialization should be 
supported, i.e. all pages get serialized along with the session.
                 */
-               public void init(ISerializer serializer)
+               public void supportSessionSerialization(ISerializer serializer)
                {
                        this.serializer = Args.notNull(serializer, 
"serializer");
                }
 
-               public synchronized void add(IPageContext context, 
IManageablePage page, int maxPages)
+               public synchronized void add(IManageablePage page)
                {
                        // move to end
-                       remove(page);
+                       remove(page.getPageId());
+                       
                        pages.add(page);
-
-                       while (pages.size() > maxPages)
-                       {
-                               pages.remove(0);
-                       }
                }
 
-               public synchronized void remove(IManageablePage page)
+               public synchronized IManageablePage removeFirst()
+               {
+                       IManageablePage page = pages.get(0);
+                       
+                       remove(page.getPageId());
+                       
+                       return page;
+               }
+               
+               public synchronized IManageablePage remove(int pageId)
                {
                        Iterator<IManageablePage> iterator = pages.iterator();
-                       while (iterator.hasNext()) {
-                               if (iterator.next().getPageId() == 
page.getPageId()) {
+                       while (iterator.hasNext())
+                       {
+                               IManageablePage page = iterator.next();
+                               
+                               if (page.getPageId() == pageId)
+                               {
                                        iterator.remove();
-                                       break;
+                                       return page;
                                }
                        }
+                       return null;
                }
 
                public synchronized void removeAll()
@@ -203,13 +244,12 @@ public class InSessionPageStore extends 
DelegatingPageStore
 
                public synchronized IManageablePage get(int id)
                {
-                       IManageablePage page = null;
-                       
                        for (int p = 0; p < pages.size(); p++)
                        {
                                IManageablePage candidate = pages.get(p);
 
-                               if (candidate.getPageId() == id) {
+                               if (candidate.getPageId() == id)
+                               {
                                        if (candidate instanceof SerializedPage 
&& serializer != null)
                                        {
                                                candidate = 
(IManageablePage)serializer.deserialize(((SerializedPage)candidate).getData());
@@ -217,12 +257,11 @@ public class InSessionPageStore extends 
DelegatingPageStore
                                                pages.set(p, candidate);
                                        }
                                        
-                                       page = candidate;
-                                       break;
+                                       return candidate;
                                }
                        }
 
-                       return page;
+                       return null;
                }
 
                /**
@@ -230,21 +269,21 @@ public class InSessionPageStore extends 
DelegatingPageStore
                 */
                private void writeObject(final ObjectOutputStream output) 
throws IOException
                {
-                       if (serializer == null) {
-                               pages.clear();
-                       } else {
-                               // serialize pages if not already
-                               for (int p = 0; p < pages.size(); p++)
+                       // handle non-serialized pages
+                       for (int p = 0; p < pages.size(); p++)
+                       {
+                               IManageablePage page = pages.get(p);
+                               
+                               if ((page instanceof SerializedPage) == false)
                                {
-                                       IManageablePage page = pages.get(p);
-                                       
-                                       if ((page instanceof SerializedPage) == 
false)
+                                       if (serializer == null)
+                                       {
+                                               pages.remove(p);
+                                               p--;
+                                       }
+                                       else
                                        {
-                                               if (serializer == null)
-                                               {
-                                                       throw new 
IllegalStateException("SessionData#init() was not called");
-                                               }
-                                               pages.set(p,  new 
SerializedPage(page.getPageId(), Classes.name(page.getClass()), 
serializer.serialize(page)));
+                                               pages.set(p, new 
SerializedPage(page.getPageId(), Classes.name(page.getClass()), 
serializer.serialize(page)));
                                        }
                                }
                        }
@@ -252,4 +291,82 @@ public class InSessionPageStore extends DelegatingPageStore
                        output.defaultWriteObject();
                }
        }
+       
+       /**
+        * Limit pages by count.
+        */
+       static class CountLimitedData extends SessionData
+       {
+               
+               private int maxPages;
+
+               public CountLimitedData(int maxPages)
+               {
+                       this.maxPages = Args.withinRange(1, Integer.MAX_VALUE, 
maxPages, "maxPages");
+               }
+               
+               public synchronized void add(IManageablePage page)
+               {
+                       super.add(page);
+                       
+                       while (pages.size() > maxPages)
+                       {
+                               removeFirst();
+                       }
+               }
+       }
+       
+       /**
+        * Limit pages by size.
+        */
+       static class SizeLimitedData extends SessionData
+       {
+
+               private Bytes maxBytes;
+               
+               private long size;
+
+               public SizeLimitedData(Bytes maxBytes)
+               {
+                       Args.notNull(maxBytes, "maxBytes");
+                       
+                       this.maxBytes = Args.withinRange(Bytes.bytes(1), 
Bytes.MAX, maxBytes, "maxBytes");
+               }
+               
+               @Override
+               public synchronized void add(IManageablePage page)
+               {
+                       if (page instanceof SerializedPage == false)
+                       {
+                               throw new 
WicketRuntimeException("InSessionPageStore limited by size works with 
serialized pages only");
+                       }
+                       
+                       super.add(page);
+                       
+                       size += ((SerializedPage) page).getData().length;
+
+                       while (size > maxBytes.bytes())
+                       {
+                               removeFirst();
+                       }
+               }
+               
+               @Override
+               public synchronized IManageablePage remove(int pageId)
+               {
+                       SerializedPage page = (SerializedPage) 
super.remove(pageId);
+                       
+                       size -= ((SerializedPage) page).getData().length;
+                       
+                       return page;
+               }
+               
+               @Override
+               public synchronized void removeAll()
+               {
+                       super.removeAll();
+                       
+                       size = 0;
+               }
+       }
 }
\ No newline at end of file
diff --git 
a/wicket-core/src/main/java/org/apache/wicket/pageStore/RequestPageStore.java 
b/wicket-core/src/main/java/org/apache/wicket/pageStore/RequestPageStore.java
index 69a1210..f7ee6d8 100644
--- 
a/wicket-core/src/main/java/org/apache/wicket/pageStore/RequestPageStore.java
+++ 
b/wicket-core/src/main/java/org/apache/wicket/pageStore/RequestPageStore.java
@@ -135,9 +135,12 @@ public class RequestPageStore extends DelegatingPageStore
                        return pages;
                }
 
-               public IManageablePage get(int id) {
-                       for (IManageablePage page : pages) {
-                               if (page.getPageId() == id) {
+               public IManageablePage get(int id)
+               {
+                       for (IManageablePage page : pages)
+                       {
+                               if (page.getPageId() == id)
+                               {
                                        return page;
                                }
                        }
diff --git 
a/wicket-core/src/main/java/org/apache/wicket/pageStore/SerializingPageStore.java
 
b/wicket-core/src/main/java/org/apache/wicket/pageStore/SerializingPageStore.java
index 0a20825..bd19872 100644
--- 
a/wicket-core/src/main/java/org/apache/wicket/pageStore/SerializingPageStore.java
+++ 
b/wicket-core/src/main/java/org/apache/wicket/pageStore/SerializingPageStore.java
@@ -65,7 +65,8 @@ public class SerializingPageStore extends DelegatingPageStore
        {
                IManageablePage page = getDelegate().getPage(context, id);
 
-               if (page instanceof SerializedPage) {
+               if (page instanceof SerializedPage)
+               {
                        page = 
(IManageablePage)serializer.deserialize(((SerializedPage)page).getData());
                }
                return page;
@@ -74,7 +75,8 @@ public class SerializingPageStore extends DelegatingPageStore
        @Override
        public void addPage(IPageContext context, IManageablePage page)
        {
-               if (page instanceof SerializedPage == false) {
+               if (page instanceof SerializedPage == false)
+               {
                        page = new SerializedPage(page.getPageId(), 
Classes.name(page.getClass()), serializer.serialize(page));
                }
                getDelegate().addPage(context, page);
diff --git 
a/wicket-core/src/main/java/org/apache/wicket/pageStore/disk/NestedFolders.java 
b/wicket-core/src/main/java/org/apache/wicket/pageStore/disk/NestedFolders.java
index 6fe5954..7636d83 100644
--- 
a/wicket-core/src/main/java/org/apache/wicket/pageStore/disk/NestedFolders.java
+++ 
b/wicket-core/src/main/java/org/apache/wicket/pageStore/disk/NestedFolders.java
@@ -37,7 +37,8 @@ public class NestedFolders
         * 
         * @param base base has to be a folder
         */
-       public NestedFolders(File base) {
+       public NestedFolders(File base)
+       {
                this.base = Args.notNull(base, "base");
        }
        
@@ -53,7 +54,8 @@ public class NestedFolders
         * @param create
         * @return
         */
-       public File get(String name, final boolean create) {
+       public File get(String name, final boolean create)
+       {
                name = name.replace('*', '_');
                name = name.replace('/', '_');
                name = name.replace(':', '_');
@@ -61,13 +63,15 @@ public class NestedFolders
                String path = createPathFrom(name);
 
                File folder = new File(base, path);
-               if (create && folder.exists() == false) {
+               if (create && folder.exists() == false)
+               {
                        Files.mkdirs(folder);
                }
                return folder;
        }
 
-       private String createPathFrom(final String name) {
+       private String createPathFrom(final String name)
+       {
                int hash = Math.abs(name.hashCode());
                String low = String.valueOf(hash % 9973);
                String high = String.valueOf((hash / 9973) % 9973);
@@ -89,14 +93,18 @@ public class NestedFolders
        public void remove(String name)
        {
                File folder = get(name, false);
-               if (folder.exists()) {
+               if (folder.exists())
+               {
                        Files.removeFolder(folder);
                        
                        File high = folder.getParentFile();
-                       if (high.list().length == 0) {
-                               if (Files.removeFolder(high)) {
+                       if (high.list().length == 0)
+                       {
+                               if (Files.removeFolder(high))
+                               {
                                        File low = high.getParentFile();
-                                       if (low.list().length == 0) {
+                                       if (low.list().length == 0)
+                                       {
                                                Files.removeFolder(low);
                                        }
                                }
@@ -113,10 +121,14 @@ public class NestedFolders
        {
                Set<File> files = new HashSet<>();
                
-               if (base.exists()) {
-                       for (File low : Files.list(base)) {
-                               for (File high: Files.list(low)) {
-                                       for (File file : Files.list(high)) {
+               if (base.exists())
+               {
+                       for (File low : Files.list(base))
+                       {
+                               for (File high: Files.list(low))
+                               {
+                                       for (File file : Files.list(high))
+                                       {
                                                files.add(file);
                                        }
                                }
diff --git 
a/wicket-core/src/main/java/org/apache/wicket/pageStore/disk/PageWindowManager.java
 
b/wicket-core/src/main/java/org/apache/wicket/pageStore/disk/PageWindowManager.java
index f20d156..ad60dab 100644
--- 
a/wicket-core/src/main/java/org/apache/wicket/pageStore/disk/PageWindowManager.java
+++ 
b/wicket-core/src/main/java/org/apache/wicket/pageStore/disk/PageWindowManager.java
@@ -64,7 +64,8 @@ public class PageWindowManager implements Serializable
                }
 
                @Override
-               public String getPageType() {
+               public String getPageType()
+               {
                        return type;
                }
                

Reply via email to