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

commit b7adbacda129c8a6cc9a8aa58883c1b712fcf6b3
Author: Sven Meier <[email protected]>
AuthorDate: Thu Dec 20 13:07:03 2018 +0100

    WICKET-6563 extract AbstractPersistentPageStore
---
 .../pageStore/AbstractPersistentPageStore.java     | 197 +++++++++++++++++++++
 .../org/apache/wicket/pageStore/DiskPageStore.java | 113 ++----------
 .../org/apache/wicket/pageStore/FilePageStore.java | 170 +++---------------
 .../apache/wicket/pageStore/InMemoryPageStore.java | 135 ++------------
 .../apache/wicket/pageStore/SerializedPage.java    |   2 +-
 .../wicket/pageStore/AbstractPageStoreTest.java    |   2 +
 6 files changed, 246 insertions(+), 373 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
new file mode 100644
index 0000000..d11f7db
--- /dev/null
+++ 
b/wicket-core/src/main/java/org/apache/wicket/pageStore/AbstractPersistentPageStore.java
@@ -0,0 +1,197 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.wicket.pageStore;
+
+import java.io.File;
+import java.io.Serializable;
+import java.util.Comparator;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+
+import javax.servlet.http.HttpSessionBindingEvent;
+import javax.servlet.http.HttpSessionBindingListener;
+
+import org.apache.wicket.Session;
+import org.apache.wicket.util.lang.Args;
+import org.apache.wicket.util.lang.Bytes;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Abstract base class for stores that keep an identifier in the session only, 
while holding the actual pages
+ * in a secondary persistent storage.
+ * 
+ * @see #getSessionIdentifier(IPageContext, boolean)
+ */
+public abstract class AbstractPersistentPageStore implements 
IPersistentPageStore
+{
+       private static final String KEY = "wicket:persistentPageStore";
+
+       private static final Logger log = 
LoggerFactory.getLogger(AbstractPersistentPageStore.class);
+
+       /**
+        * A cache that holds all persistent page stores, the key is the 
application name suffixed with the page store implementation class.
+        */
+       private static final ConcurrentMap<String, AbstractPersistentPageStore> 
STORES = new ConcurrentHashMap<>();
+
+       private final String storeKey;
+
+       protected AbstractPersistentPageStore(String applicationName)
+       {
+               this.storeKey = Args.notNull(applicationName, 
"applicationName") + ":" + getClass().getSimpleName();
+
+               if (STORES.containsKey(storeKey))
+               {
+                       throw new IllegalStateException(
+                               "Store with key '" + storeKey + "' already 
exists.");
+               }
+               STORES.put(storeKey, this);
+       }
+
+       @Override
+       public void destroy()
+       {
+               STORES.remove(storeKey);
+       }
+
+       @Override
+       public boolean canBeAsynchronous(IPageContext context)
+       {
+               // session attribute must be added here *before* any 
asynchronous calls
+               // when session is no longer available
+               getSessionIdentifier(context, true);
+
+               return true;
+       }
+
+       /**
+        * Get the distinct and stable identifier for the given context.
+        * 
+        * @param context the context to identify
+        * @param create should a new identifier be created if not there already
+        */
+       protected String getSessionIdentifier(IPageContext context, boolean 
create)
+       {
+               SessionAttribute attribute = context.getSessionAttribute(KEY);
+               if (attribute == null && create)
+               {
+                       attribute = new SessionAttribute(storeKey, 
context.getSessionId());
+                       context.setSessionAttribute(KEY, attribute);
+               }
+               
+               if (attribute == null) {
+                       return null;
+               }
+               return attribute.identifier;
+       }
+
+       /**
+        * Attribute held in session.
+        */
+       private static class SessionAttribute implements Serializable, 
HttpSessionBindingListener
+       {
+
+               private final String storeKey;
+
+               /**
+                * The identifier of the session, must not be equal to {@link 
Session#getId()}, e.g. when
+                * the container changes the id after authorization.
+                */
+               public final String identifier;
+
+               public SessionAttribute(String storeKey, String 
sessionIdentifier)
+               {
+                       this.storeKey = Args.notNull(storeKey, "storeKey");
+                       this.identifier = Args.notNull(sessionIdentifier, 
"sessionIdentifier");
+               }
+
+
+               @Override
+               public void valueBound(HttpSessionBindingEvent event)
+               {
+               }
+
+               @Override
+               public void valueUnbound(HttpSessionBindingEvent event)
+               {
+                       AbstractPersistentPageStore store = 
STORES.get(storeKey);
+                       if (store == null)
+                       {
+                               log.warn(
+                                       "Cannot remove data '{}' because disk 
store '{}' is no longer present.", identifier, storeKey);
+                       }
+                       else
+                       {
+                               store.removePersistent(identifier);
+                       }
+               }
+       }
+
+       public class LastModifiedComparator implements Comparator<File>
+       {
+
+               @Override
+               public int compare(File f1, File f2)
+               {
+                       return (int)(f2.lastModified() - f1.lastModified());
+               }
+
+       }
+
+       @Override
+       public String getContextIdentifier(IPageContext context)
+       {
+               return getSessionIdentifier(context, true);
+       }
+
+       protected abstract void removePersistent(String identifier);
+
+       protected static class PersistedPage implements IPersistedPage
+       {
+               private int pageId;
+
+               private String pageType;
+
+               private long pageSize;
+
+               public PersistedPage(int pageId, String pageType, long pageSize)
+               {
+                       this.pageId = pageId;
+                       this.pageType = pageType;
+                       this.pageSize = pageSize;
+               }
+
+               @Override
+               public int getPageId()
+               {
+                       return pageId;
+               }
+
+               @Override
+               public Bytes getPageSize()
+               {
+                       return Bytes.bytes(pageSize);
+               }
+
+               @Override
+               public String getPageType()
+               {
+                       return pageType;
+               }
+
+       }
+}
\ No newline at end of file
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 a8f5a0a..7b3e916 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
@@ -36,10 +36,6 @@ import java.util.Set;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ConcurrentMap;
 
-import javax.servlet.http.HttpSessionBindingEvent;
-import javax.servlet.http.HttpSessionBindingListener;
-
-import org.apache.wicket.Session;
 import org.apache.wicket.WicketRuntimeException;
 import org.apache.wicket.page.IManageablePage;
 import org.apache.wicket.pageStore.disk.NestedFolders;
@@ -66,24 +62,15 @@ import org.slf4j.LoggerFactory;
  * This leads to pages with identical id superfluously kept in the file, while 
older pages are prematurely expelled.
  * Any following request to these older pages will then fail with {@link 
PageExpiredException}.   
  */
-public class DiskPageStore implements IPersistentPageStore
+public class DiskPageStore extends AbstractPersistentPageStore
 {
        private static final Logger log = 
LoggerFactory.getLogger(DiskPageStore.class);
 
-       private static final String KEY = "wicket:DiskPageStore";
-
        /**
         * Name of the file where the page index is stored.
         */
        private static final String INDEX_FILE_NAME = "DiskPageStoreIndex";
 
-       /**
-        * A cache that holds all page stores.
-        */
-       private static final ConcurrentMap<String, DiskPageStore> DISK_STORES = 
new ConcurrentHashMap<>();
-
-       private final String applicationName;
-
        private final ISerializer serializer;
 
        private final Bytes maxSizePerSession;
@@ -124,7 +111,8 @@ public class DiskPageStore implements IPersistentPageStore
        public DiskPageStore(String applicationName, File fileStoreFolder, 
Bytes maxSizePerSession,
                ISerializer serializer)
        {
-               this.applicationName = Args.notNull(applicationName, 
"applicationName");
+               super(applicationName);
+               
                this.folders = new NestedFolders(new File(fileStoreFolder, 
applicationName + "-filestore"));
                this.maxSizePerSession = Args.notNull(maxSizePerSession, 
"maxSizePerSession");
                this.serializer = serializer; // optional
@@ -149,13 +137,6 @@ public class DiskPageStore implements IPersistentPageStore
                                        + "See 
org.apache.wicket.Application.setPageManagerProvider(IPageManagerProvider)",
                                e);
                }
-
-               if (DISK_STORES.containsKey(applicationName))
-               {
-                       throw new IllegalStateException(
-                               "Store for application with key '" + 
applicationName + "' already exists.");
-               }
-               DISK_STORES.put(applicationName, this);
        }
 
        /**
@@ -173,8 +154,7 @@ public class DiskPageStore implements IPersistentPageStore
                log.debug("Destroying...");
                saveIndex();
 
-               DISK_STORES.remove(applicationName);
-
+               super.destroy();
                log.debug("Destroyed.");
        }
 
@@ -183,7 +163,7 @@ public class DiskPageStore implements IPersistentPageStore
        {
                // session attribute must be added here *before* any 
asynchronous calls
                // when session is no longer available
-               getSessionAttribute(context, true);
+               getSessionIdentifier(context, true);
 
                return true;
        }
@@ -236,15 +216,18 @@ public class DiskPageStore implements IPersistentPageStore
        @Override
        public void removeAllPages(IPageContext context)
        {
-               DiskData diskData = getDiskData(context, false);
-               if (diskData != null)
+               String identifier = getSessionIdentifier(context, false);
+               if (identifier != null)
                {
-                       removeDiskData(diskData);
+                       removePersistent(identifier);
                }
        }
 
-       protected void removeDiskData(DiskData diskData)
+       @Override
+       protected void removePersistent(String identifier)
        {
+               DiskData diskData = getDiskData(identifier, false);
+
                synchronized (diskDatas)
                {
                        diskDatas.remove(diskData.sessionIdentifier);
@@ -295,14 +278,14 @@ public class DiskPageStore implements IPersistentPageStore
         */
        protected DiskData getDiskData(final IPageContext context, final 
boolean create)
        {
-               SessionAttribute attribute = getSessionAttribute(context, 
create);
+               String identifier = getSessionIdentifier(context, create);
 
-               if (!create && attribute == null)
+               if (!create && identifier == null)
                {
                        return null;
                }
 
-               return getDiskData(attribute.identifier, create);
+               return getDiskData(identifier, create);
        }
 
        protected DiskData getDiskData(String sessionIdentifier, boolean create)
@@ -317,17 +300,6 @@ public class DiskPageStore implements IPersistentPageStore
                return existing != null ? existing : data;
        }
 
-       protected SessionAttribute getSessionAttribute(IPageContext context, 
boolean create)
-       {
-               SessionAttribute attribute = context.getSessionAttribute(KEY);
-               if (attribute == null && create)
-               {
-                       attribute = new SessionAttribute(applicationName, 
context.getSessionId());
-                       context.setSessionAttribute(KEY, attribute);
-               }
-               return attribute;
-       }
-
        /**
         * Load the index
         */
@@ -415,14 +387,6 @@ public class DiskPageStore implements IPersistentPageStore
        }
 
        @Override
-       public String getContextIdentifier(IPageContext context)
-       {
-               SessionAttribute sessionAttribute = 
getSessionAttribute(context, true);
-
-               return sessionAttribute.identifier;
-       }
-
-       @Override
        public Bytes getTotalSize()
        {
                long size = 0;
@@ -651,51 +615,4 @@ public class DiskPageStore implements IPersistentPageStore
                File sessionFolder = folders.get(sessionIdentifier, true);
                return new File(sessionFolder, "data").getAbsolutePath();
        }
-
-       /**
-        * Attribute held in session.
-        */
-       static class SessionAttribute implements Serializable, 
HttpSessionBindingListener
-       {
-
-               private final String applicationName;
-
-               /**
-                * The identifier of the session, must not be equal to {@link 
Session#getId()}, e.g. when
-                * the container changes the id after authorization.
-                */
-               public final String identifier;
-
-               public SessionAttribute(String applicationName, String 
sessionIdentifier)
-               {
-                       this.applicationName = Args.notNull(applicationName, 
"applicationName");
-                       this.identifier = Args.notNull(sessionIdentifier, 
"sessionIdentifier");
-               }
-
-
-               @Override
-               public void valueBound(HttpSessionBindingEvent event)
-               {
-               }
-
-               @Override
-               public void valueUnbound(HttpSessionBindingEvent event)
-               {
-                       DiskPageStore store = DISK_STORES.get(applicationName);
-                       if (store == null)
-                       {
-                               log.warn(
-                                       "Cannot remove data '{}' because disk 
store for application '{}' is no longer present.",
-                                       identifier, applicationName);
-                       }
-                       else
-                       {
-                               DiskData diskData = 
store.getDiskData(identifier, false);
-                               if (diskData != null)
-                               {
-                                       store.removeDiskData(diskData);
-                               }
-                       }
-               }
-       }
 }
\ No newline at end of file
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 a27f447..661e3bb 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
@@ -18,7 +18,6 @@ package org.apache.wicket.pageStore;
 
 import java.io.File;
 import java.io.IOException;
-import java.io.Serializable;
 import java.nio.ByteBuffer;
 import java.nio.MappedByteBuffer;
 import java.nio.channels.FileChannel;
@@ -32,13 +31,7 @@ import java.util.Comparator;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Set;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.ConcurrentMap;
 
-import javax.servlet.http.HttpSessionBindingEvent;
-import javax.servlet.http.HttpSessionBindingListener;
-
-import org.apache.wicket.Session;
 import org.apache.wicket.WicketRuntimeException;
 import org.apache.wicket.page.IManageablePage;
 import org.apache.wicket.pageStore.disk.NestedFolders;
@@ -58,7 +51,7 @@ import org.slf4j.LoggerFactory;
  * in its own file. This improves on a {@link DiskPageStore disadvantage of 
DiskPageStore} surfacing
  * with alternating Ajax requests from different browser tabs.  
  */
-public class FilePageStore implements IPersistentPageStore
+public class FilePageStore extends AbstractPersistentPageStore
 {
        private static final String ATTRIBUTE_PAGE_TYPE = 
"user.wicket_page_type";
 
@@ -66,15 +59,6 @@ public class FilePageStore implements IPersistentPageStore
 
        private static final Logger log = 
LoggerFactory.getLogger(FilePageStore.class);
 
-       private static final String KEY = "wicket:FilePageStore";
-
-       /**
-        * A cache that holds all page stores.
-        */
-       private static final ConcurrentMap<String, FilePageStore> FILE_STORES = 
new ConcurrentHashMap<>();
-
-       private final String applicationName;
-
        private final ISerializer serializer;
 
        private final Bytes maxSizePerSession;
@@ -110,20 +94,13 @@ public class FilePageStore implements IPersistentPageStore
         * @param serializer
         *            for serialization of pages
         */
-       public FilePageStore(String applicationName, File fileStoreFolder, 
Bytes maxSizePerSession,
-               ISerializer serializer)
+       public FilePageStore(String applicationName, File fileStoreFolder, 
Bytes maxSizePerSession, ISerializer serializer)
        {
-               this.applicationName = Args.notNull(applicationName, 
"applicationName");
+               super(applicationName);
+               
                this.folders = new NestedFolders(new File(fileStoreFolder, 
applicationName + "-filestore"));
                this.maxSizePerSession = Args.notNull(maxSizePerSession, 
"maxSizePerSession");
                this.serializer = serializer; // optional
-
-               if (FILE_STORES.containsKey(applicationName))
-               {
-                       throw new IllegalStateException(
-                               "Store for application with key '" + 
applicationName + "' already exists.");
-               }
-               FILE_STORES.put(applicationName, this);
        }
 
        /**
@@ -135,16 +112,6 @@ public class FilePageStore implements IPersistentPageStore
                return serializer != null;
        }
 
-       @Override
-       public void destroy()
-       {
-               log.debug("Destroying...");
-
-               FILE_STORES.remove(applicationName);
-
-               log.debug("Destroyed.");
-       }
-
        private File getPageFile(String sessionId, int id, boolean create)
        {
                File folder = folders.get(sessionId, create);
@@ -157,7 +124,7 @@ public class FilePageStore implements IPersistentPageStore
        {
                // session attribute must be added here *before* any 
asynchronous calls
                // when session is no longer available
-               getSessionAttribute(context, true);
+               getSessionIdentifier(context, true);
 
                return true;
        }
@@ -165,13 +132,13 @@ public class FilePageStore implements IPersistentPageStore
        @Override
        public IManageablePage getPage(IPageContext context, int id)
        {
-               SessionAttribute attribute = getSessionAttribute(context, 
false);
-               if (attribute == null)
+               String identifier = getSessionIdentifier(context, false);
+               if (identifier == null)
                {
                        return null;
                }
 
-               byte[] data = readFile(attribute.identifier, id);
+               byte[] data = readFile(identifier, id);
                if (data == null) {
                        return null;
                }
@@ -225,19 +192,18 @@ public class FilePageStore implements IPersistentPageStore
        @Override
        public void removePage(IPageContext context, IManageablePage page)
        {
-               SessionAttribute attribute = getSessionAttribute(context, 
false);
-               if (attribute == null)
+               String identifier = getSessionIdentifier(context, false);
+               if (identifier == null)
                {
                        return;
                }
 
-               File file = getPageFile(attribute.identifier, page.getPageId(), 
false);
+               File file = getPageFile(identifier, page.getPageId(), false);
                if (file.exists())
                {
                        if (!file.delete())
                        {
-                               log.warn("cannot remove page data for session 
{} page {}", attribute.identifier,
-                                       page.getPageId());
+                               log.warn("cannot remove page data for session 
{} page {}", identifier, page.getPageId());
                        }
                }
        }
@@ -245,16 +211,17 @@ public class FilePageStore implements IPersistentPageStore
        @Override
        public void removeAllPages(IPageContext context)
        {
-               SessionAttribute attribute = getSessionAttribute(context, 
false);
-               if (attribute == null)
+               String identifier = getSessionIdentifier(context, false);
+               if (identifier == null)
                {
                        return;
                }
 
-               removeFolder(attribute.identifier);
+               removePersistent(identifier);
        }
 
-       private void removeFolder(String identifier)
+       @Override
+       protected void removePersistent(String identifier)
        {
                folders.remove(identifier);
        }
@@ -266,8 +233,8 @@ public class FilePageStore implements IPersistentPageStore
        @Override
        public void addPage(IPageContext context, IManageablePage page)
        {
-               SessionAttribute attribute = getSessionAttribute(context, 
false);
-               if (attribute == null)
+               String identifier = getSessionIdentifier(context, false);
+               if (identifier == null)
                {
                        return;
                }
@@ -289,9 +256,9 @@ public class FilePageStore implements IPersistentPageStore
                        data = serializer.serialize(page);
                }
 
-               writeFile(attribute.identifier, page.getPageId(), type, data);
+               writeFile(identifier, page.getPageId(), type, data);
 
-               checkMaxSize(attribute.identifier);
+               checkMaxSize(identifier);
        }
 
        private void writeFile(String identifier, int pageId, String pageType, 
byte[] data)
@@ -342,60 +309,6 @@ public class FilePageStore implements IPersistentPageStore
                }
        }
 
-       protected SessionAttribute getSessionAttribute(IPageContext context, 
boolean create)
-       {
-               SessionAttribute attribute = context.getSessionAttribute(KEY);
-               if (attribute == null && create)
-               {
-                       attribute = new SessionAttribute(applicationName, 
context.getSessionId());
-                       context.setSessionAttribute(KEY, attribute);
-               }
-               return attribute;
-       }
-
-       /**
-        * Attribute held in session.
-        */
-       static class SessionAttribute implements Serializable, 
HttpSessionBindingListener
-       {
-
-               private final String applicationName;
-
-               /**
-                * The identifier of the session, must not be equal to {@link 
Session#getId()}, e.g. when
-                * the container changes the id after authorization.
-                */
-               public final String identifier;
-
-               public SessionAttribute(String applicationName, String 
sessionIdentifier)
-               {
-                       this.applicationName = Args.notNull(applicationName, 
"applicationName");
-                       this.identifier = Args.notNull(sessionIdentifier, 
"sessionIdentifier");
-               }
-
-
-               @Override
-               public void valueBound(HttpSessionBindingEvent event)
-               {
-               }
-
-               @Override
-               public void valueUnbound(HttpSessionBindingEvent event)
-               {
-                       FilePageStore store = FILE_STORES.get(applicationName);
-                       if (store == null)
-                       {
-                               log.warn(
-                                       "Cannot remove data '{}' because disk 
store for application '{}' is no longer present.",
-                                       identifier, applicationName);
-                       }
-                       else
-                       {
-                               store.removeFolder(identifier);
-                       }
-               }
-       }
-
        public class LastModifiedComparator implements Comparator<File>
        {
 
@@ -408,12 +321,6 @@ public class FilePageStore implements IPersistentPageStore
        }
 
        @Override
-       public String getContextIdentifier(IPageContext context)
-       {
-               return getSessionAttribute(context, true).identifier;
-       }
-
-       @Override
        public Set<String> getContextIdentifiers()
        {
                Set<String> identifiers = new HashSet<>();
@@ -532,39 +439,4 @@ public class FilePageStore implements IPersistentPageStore
 
                return Bytes.bytes(total);
        }
-
-       private static class PersistedPage implements IPersistedPage
-       {
-               private int pageId;
-
-               private String pageType;
-
-               private long pageSize;
-
-               public PersistedPage(int pageId, String pageType, long pageSize)
-               {
-                       this.pageId = pageId;
-                       this.pageType = pageType;
-                       this.pageSize = pageSize;
-               }
-
-               @Override
-               public int getPageId()
-               {
-                       return pageId;
-               }
-
-               @Override
-               public Bytes getPageSize()
-               {
-                       return Bytes.bytes(pageSize);
-               }
-
-               @Override
-               public String getPageType()
-               {
-                       return pageType;
-               }
-
-       }
 }
\ No newline at end of file
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 81e5f23..5c6dafb 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
@@ -16,7 +16,6 @@
  */
 package org.apache.wicket.pageStore;
 
-import java.io.Serializable;
 import java.util.ArrayList;
 import java.util.Iterator;
 import java.util.LinkedHashMap;
@@ -24,38 +23,22 @@ import java.util.List;
 import java.util.Map;
 import java.util.Set;
 import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.ConcurrentMap;
 import java.util.stream.Collectors;
 import java.util.stream.StreamSupport;
 
-import javax.servlet.http.HttpSessionBindingEvent;
-import javax.servlet.http.HttpSessionBindingListener;
-
 import org.apache.wicket.Application;
-import org.apache.wicket.Session;
 import org.apache.wicket.core.util.lang.WicketObjects;
 import org.apache.wicket.page.IManageablePage;
-import org.apache.wicket.util.lang.Args;
 import org.apache.wicket.util.lang.Bytes;
-import org.apache.wicket.util.lang.Classes;
 
 /**
  * A storage of pages in memory.
  */
-public class InMemoryPageStore implements IPersistentPageStore
+public class InMemoryPageStore extends AbstractPersistentPageStore
 {
 
-       /**
-        * A registry of all page instances.
-        */
-       private static final ConcurrentMap<String, InMemoryPageStore> 
IN_MEMORY_STORES = new ConcurrentHashMap<>();
-
-       private static final String KEY = "wicket:InMemoryPageStore";
-
        private final Map<String, MemoryData> datas = new ConcurrentHashMap<>();
 
-       private String applicationName;
-
        private int maxPages;
 
        /**
@@ -66,10 +49,8 @@ public class InMemoryPageStore implements 
IPersistentPageStore
         */
        public InMemoryPageStore(String applicationName, int maxPages)
        {
-               this.applicationName = Args.notNull(applicationName, 
"applicationName");
+               super(applicationName);
                this.maxPages = maxPages;
-
-               IN_MEMORY_STORES.put(applicationName, this);
        }
 
        /**
@@ -91,30 +72,11 @@ public class InMemoryPageStore implements 
IPersistentPageStore
        {
                // session attribute must be added here *before* any 
asynchronous calls
                // when session is no longer available
-               getSessionAttribute(context, true);
+               getSessionIdentifier(context, true);
 
                return true;
        }
 
-       protected SessionAttribute getSessionAttribute(IPageContext context, 
boolean create)
-       {
-               SessionAttribute attribute = context.getSessionAttribute(KEY);
-               if (attribute == null && create)
-               {
-                       attribute = new SessionAttribute(applicationName, 
context.getSessionId());
-                       context.setSessionAttribute(KEY, attribute);
-               }
-               return attribute;
-       }
-
-       @Override
-       public void destroy()
-       {
-               datas.clear();
-
-               IN_MEMORY_STORES.remove(applicationName);
-       }
-
        @Override
        public IManageablePage getPage(IPageContext context, int id)
        {
@@ -164,12 +126,6 @@ public class InMemoryPageStore implements 
IPersistentPageStore
        }
 
        @Override
-       public String getContextIdentifier(IPageContext context)
-       {
-               return context.getSessionId();
-       }
-
-       @Override
        public Set<String> getContextIdentifiers()
        {
                return datas.keySet();
@@ -187,7 +143,7 @@ public class InMemoryPageStore implements 
IPersistentPageStore
                synchronized (data)
                {
                        return StreamSupport.stream(data.spliterator(), false)
-                               .map(page -> new PersistedPage(page, 
getSize(page)))
+                               .map(page -> new 
PersistedPage(page.getPageId(), page instanceof SerializedPage ? 
((SerializedPage)page).getPageType() : page.getClass().getName(), 
getSize(page)))
                                .collect(Collectors.toList());
                }
        }
@@ -225,23 +181,24 @@ public class InMemoryPageStore implements 
IPersistentPageStore
 
        private MemoryData getMemoryData(IPageContext context, boolean create)
        {
-               SessionAttribute attribute = getSessionAttribute(context, 
create);
+               String identifier = getSessionIdentifier(context, create);
 
                if (!create)
                {
-                       if (attribute == null) {
+                       if (identifier == null) {
                                return null;
                        } else {
-                               return datas.get(attribute.identifier);
+                               return datas.get(identifier);
                        }
                }
 
                MemoryData data = new MemoryData();
-               MemoryData existing = datas.putIfAbsent(attribute.identifier, 
data);
+               MemoryData existing = datas.putIfAbsent(identifier, data);
                return existing != null ? existing : data;
        }
 
-       private void removeMemoryData(String identifier)
+       @Override
+       protected void removePersistent(String identifier)
        {
                datas.remove(identifier);
        }
@@ -292,76 +249,4 @@ public class InMemoryPageStore implements 
IPersistentPageStore
                        return page;
                }
        }
-
-       /**
-        * Attribute held in session.
-        */
-       static class SessionAttribute implements Serializable, 
HttpSessionBindingListener
-       {
-
-               private final String applicationName;
-
-               /**
-                * The identifier of the session, must not be equal to {@link 
Session#getId()}, e.g. when
-                * the container changes the id after authorization.
-                */
-               public final String identifier;
-
-               public SessionAttribute(String applicationName, String 
sessionIdentifier)
-               {
-                       this.applicationName = Args.notNull(applicationName, 
"applicationName");
-                       this.identifier = Args.notNull(sessionIdentifier, 
"sessionIdentifier");
-               }
-
-
-               @Override
-               public void valueBound(HttpSessionBindingEvent event)
-               {
-               }
-
-               @Override
-               public void valueUnbound(HttpSessionBindingEvent event)
-               {
-                       InMemoryPageStore store = 
IN_MEMORY_STORES.get(applicationName);
-                       if (store != null)
-                       {
-                               store.removeMemoryData(identifier);
-                       }
-               }
-       }
-       
-       private static class PersistedPage implements IPersistedPage
-       {
-
-               private final int id;
-
-               private final String type;
-
-               private final long size;
-
-               public PersistedPage(IManageablePage page, long size)
-               {
-                       this.id = page.getPageId();
-                       this.type = page instanceof SerializedPage ? 
((SerializedPage)page).getPageType() : Classes.name(page.getClass());;
-                       this.size = size;
-               }
-
-               @Override
-               public int getPageId()
-               {
-                       return id;
-               }
-
-               @Override
-               public String getPageType()
-               {
-                       return type;
-               }
-
-               @Override
-               public Bytes getPageSize()
-               {
-                       return Bytes.bytes(size);
-               }
-       }
 }
\ No newline at end of file
diff --git 
a/wicket-core/src/main/java/org/apache/wicket/pageStore/SerializedPage.java 
b/wicket-core/src/main/java/org/apache/wicket/pageStore/SerializedPage.java
index 5d858b5..40ad202 100644
--- a/wicket-core/src/main/java/org/apache/wicket/pageStore/SerializedPage.java
+++ b/wicket-core/src/main/java/org/apache/wicket/pageStore/SerializedPage.java
@@ -31,7 +31,7 @@ import org.apache.wicket.util.lang.Args;
  * 
  * @see SerializingPageStore
  */
-class SerializedPage implements IManageablePage
+public class SerializedPage implements IManageablePage
 {
 
        private final int pageId;
diff --git 
a/wicket-core/src/test/java/org/apache/wicket/pageStore/AbstractPageStoreTest.java
 
b/wicket-core/src/test/java/org/apache/wicket/pageStore/AbstractPageStoreTest.java
index 48d5c01..9842e82 100644
--- 
a/wicket-core/src/test/java/org/apache/wicket/pageStore/AbstractPageStoreTest.java
+++ 
b/wicket-core/src/test/java/org/apache/wicket/pageStore/AbstractPageStoreTest.java
@@ -75,6 +75,8 @@ public abstract class AbstractPageStoreTest
        @Test
        void storePage2()
        {
+               pageStore.destroy();
+               
                IPageContext context = new DummyPageContext(sessionId);
                int maxEntries = 10;
 

Reply via email to