You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@wicket.apache.org by sv...@apache.org on 2018/07/03 18:18:51 UTC

wicket git commit: WICKET-6563 allow passing of SerializedPage

Repository: wicket
Updated Branches:
  refs/heads/WICKET-6563 bcf76f517 -> a3604f7c3


WICKET-6563 allow passing of SerializedPage

between page stores


Project: http://git-wip-us.apache.org/repos/asf/wicket/repo
Commit: http://git-wip-us.apache.org/repos/asf/wicket/commit/a3604f7c
Tree: http://git-wip-us.apache.org/repos/asf/wicket/tree/a3604f7c
Diff: http://git-wip-us.apache.org/repos/asf/wicket/diff/a3604f7c

Branch: refs/heads/WICKET-6563
Commit: a3604f7c359f9bbd2df03d57831c3f0d838ef521
Parents: bcf76f5
Author: Sven Meier <sv...@apache.org>
Authored: Tue Jul 3 20:18:10 2018 +0200
Committer: Sven Meier <sv...@apache.org>
Committed: Tue Jul 3 20:18:25 2018 +0200

----------------------------------------------------------------------
 .../wicket/DefaultPageManagerProvider.java      |   4 +-
 .../apache/wicket/pageStore/DiskPageStore.java  |  11 +-
 .../wicket/pageStore/InSessionPageStore.java    | 115 +++++++++----------
 .../apache/wicket/pageStore/SerializedPage.java |  74 ++++++++++++
 .../wicket/pageStore/SerializingPageStore.java  |  63 ++++++++++
 .../wicket/versioning/PageVersioningTest.java   |   7 +-
 6 files changed, 207 insertions(+), 67 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/wicket/blob/a3604f7c/wicket-core/src/main/java/org/apache/wicket/DefaultPageManagerProvider.java
----------------------------------------------------------------------
diff --git a/wicket-core/src/main/java/org/apache/wicket/DefaultPageManagerProvider.java b/wicket-core/src/main/java/org/apache/wicket/DefaultPageManagerProvider.java
index c800935..0539355 100644
--- a/wicket-core/src/main/java/org/apache/wicket/DefaultPageManagerProvider.java
+++ b/wicket-core/src/main/java/org/apache/wicket/DefaultPageManagerProvider.java
@@ -28,6 +28,7 @@ import org.apache.wicket.pageStore.InMemoryPageStore;
 import org.apache.wicket.pageStore.InSessionPageStore;
 import org.apache.wicket.pageStore.NoopPageStore;
 import org.apache.wicket.pageStore.RequestPageStore;
+import org.apache.wicket.pageStore.SerializingPageStore;
 import org.apache.wicket.serialize.ISerializer;
 import org.apache.wicket.settings.StoreSettings;
 import org.apache.wicket.util.lang.Args;
@@ -45,9 +46,10 @@ import org.apache.wicket.util.lang.Bytes;
  * <ul>
  * <li>{@link RequestPageStore} caching pages until end of the request</li>
  * <li>{@link InSessionPageStore} keeping the last accessed page in the session</li>
+ * <li>{@link SerializingPageStore} serializing all pages (so they are available for back-button </li>
  * <li>{@link InMemoryPageStore} keeping all pages</li>
  * </ul>
- * ... or if all pages should be kept in the session only:
+ * ... or if all pages should be kept in the session only without any serialization (no back-button support)
  * <ul>
  * <li>{@link RequestPageStore} caching pages until end of the request</li>
  * <li>{@link InSessionPageStore} keeping a limited count of pages in the session, e.g. 10</li>

http://git-wip-us.apache.org/repos/asf/wicket/blob/a3604f7c/wicket-core/src/main/java/org/apache/wicket/pageStore/DiskPageStore.java
----------------------------------------------------------------------
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 b810218..85bed3e 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
@@ -188,6 +188,10 @@ public class DiskPageStore implements IPersistentPageStore
 		}
 	}
 
+	/**
+	 * Supports {@link SerializedPage}s too - for this to work the delegating
+	 * {@link IPageStore} must use the same {@link ISerializer} as this one.
+	 */
 	@Override
 	public void addPage(IPageContext context, IManageablePage page)
 	{
@@ -196,7 +200,12 @@ public class DiskPageStore implements IPersistentPageStore
 		{
 			log.debug("Storing data for page with id '{}' in session with id '{}'", page.getPageId(), context.getSessionId());
 			
-			byte[] data = serializer.serialize(page);
+			byte[] data;
+			if (page instanceof SerializedPage) {
+				data = ((SerializedPage)page).getData();
+			} else {
+				data = serializer.serialize(page);
+			}
 			
 			diskData.savePage(page.getPageId(), page.getClass(), data);
 		}

http://git-wip-us.apache.org/repos/asf/wicket/blob/a3604f7c/wicket-core/src/main/java/org/apache/wicket/pageStore/InSessionPageStore.java
----------------------------------------------------------------------
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 3914464..e3d3e07 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
@@ -20,11 +20,12 @@ import java.io.IOException;
 import java.io.ObjectOutputStream;
 import java.io.Serializable;
 import java.util.Iterator;
-import java.util.LinkedHashMap;
-import java.util.Map.Entry;
+import java.util.LinkedList;
+import java.util.List;
 
 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;
@@ -33,8 +34,10 @@ import org.apache.wicket.serialize.ISerializer;
 import org.apache.wicket.util.lang.Args;
 
 /**
- * A store keeping a configurable maximum of pages in the session, delegating all or excessive pages
- * to another store.
+ * A store keeping a configurable maximum of pages in the session.
+ * <p>
+ * This store is used by {@link DefaultPageManagerProvider} as a cache in front 
+ * of a persistent store.
  */
 public class InSessionPageStore extends DelegatingPageStore
 {
@@ -47,9 +50,7 @@ public class InSessionPageStore extends DelegatingPageStore
 	private ISerializer serializer;
 
 	private int maxPages;
-
-	private boolean delegateAll = false;
-
+	
 	/**
 	 * Use this constructor, if sessions are never serialized.
 	 * 
@@ -93,16 +94,6 @@ public class InSessionPageStore extends DelegatingPageStore
 		this.maxPages = maxPages;
 	}
 
-	/**
-	 * Delegated all pages, even those that are still kept in the session.
-	 */
-	public InSessionPageStore delegateAll()
-	{
-		delegateAll = true;
-
-		return this;
-	}
-
 	@Override
 	public IManageablePage getPage(IPageContext context, int id)
 	{
@@ -120,7 +111,9 @@ public class InSessionPageStore extends DelegatingPageStore
 	{
 		SessionData data = getSessionData(context);
 
-		data.addAndDelegate(context, page, maxPages, delegateAll, getDelegate());
+		data.add(context, page, maxPages);
+		
+		super.addPage(context, page);
 	}
 
 	@Override
@@ -167,8 +160,10 @@ public class InSessionPageStore extends DelegatingPageStore
 
 		/**
 		 * Pages, may partly be serialized.
+		 * <p>
+		 * Kept in list instead of map, since life pages might change their id during a request.
 		 */
-		private LinkedHashMap<Integer, Serializable> pages = new LinkedHashMap<>();
+		private List<IManageablePage> pages = new LinkedList<>();
 
 		/**
 		 * This method <em>must</em> be called each time it is retrieved from the session: <br/>
@@ -180,45 +175,27 @@ public class InSessionPageStore extends DelegatingPageStore
 			this.serializer = Args.notNull(serializer, "serializer");
 		}
 
-		public synchronized void addAndDelegate(IPageContext context, IManageablePage page,
-			int maxPages, boolean delegateAll, IPageStore delegate)
+		public synchronized void add(IPageContext context, IManageablePage page, int maxPages)
 		{
-			pages.remove(page.getPageId());
-			pages.put(page.getPageId(), page);
+			// move to end
+			remove(page);
+			pages.add(page);
 
-			Serializable expelled = null;
-			if (pages.size() > maxPages)
-			{
-				Iterator<Serializable> iterator = pages.values().iterator();
-				expelled = iterator.next();
-				iterator.remove();
-			}
-
-			if (delegateAll)
-			{
-				delegate.addPage(context, page);
-			}
-			else
+			while (pages.size() > maxPages)
 			{
-				// when pages are not delegated automatically, we have to catch up
-				// on an expelled page now
-				if (expelled != null)
-				{
-					if (expelled instanceof byte[])
-					{
-						// ... which results in this suboptimal case, when the session was persisted:
-						// in that case the expelled page is still in a serialized state, so we have
-						// to deserialize it first to be able to delegate it 
-						expelled = (IManageablePage)serializer.deserialize((byte[])expelled);
-					}
-					delegate.addPage(context, (IManageablePage)expelled);
-				}
+				pages.remove(0);
 			}
 		}
 
 		public synchronized void remove(IManageablePage page)
 		{
-			pages.remove(page.getPageId());
+			Iterator<IManageablePage> iterator = pages.iterator();
+			while (iterator.hasNext()) {
+				if (iterator.next().getPageId() == page.getPageId()) {
+					iterator.remove();
+					break;
+				}
+			}
 		}
 
 		public synchronized void removeAll()
@@ -228,20 +205,30 @@ public class InSessionPageStore extends DelegatingPageStore
 
 		public synchronized IManageablePage get(int id)
 		{
-			Serializable serializable = pages.get(id);
-
-			if (serializable instanceof byte[])
+			IManageablePage page = null;
+			
+			for (int p = 0; p < pages.size(); p++)
 			{
-				if (serializer == null)
-				{
-					throw new IllegalStateException("SessionData#init() was not called");
-				}
-				serializable = (Serializable)serializer.deserialize((byte[])serializable);
+				IManageablePage candidate = pages.get(p);
 
-				pages.put(id, serializable);
+				if (candidate.getPageId() == id) {
+					if (candidate instanceof SerializedPage)
+					{
+						if (serializer == null)
+						{
+							throw new IllegalStateException("SessionData#init() was not called");
+						}
+						candidate = (IManageablePage)serializer.deserialize(((SerializedPage)candidate).getData());
+		
+						pages.set(id, candidate);
+					}
+					
+					page = candidate;
+					break;
+				}
 			}
 
-			return (IManageablePage)serializable;
+			return page;
 		}
 
 		/**
@@ -250,15 +237,17 @@ public class InSessionPageStore extends DelegatingPageStore
 		private void writeObject(final ObjectOutputStream output) throws IOException
 		{
 			// serialize pages if not already
-			for (Entry<Integer, Serializable> entry : pages.entrySet())
+			for (int p = 0; p < pages.size(); p++)
 			{
-				if (entry.getValue() instanceof IManageablePage)
+				IManageablePage page = pages.get(p);
+				
+				if ((page instanceof SerializedPage) == false)
 				{
 					if (serializer == null)
 					{
 						throw new IllegalStateException("SessionData#init() was not called");
 					}
-					entry.setValue(serializer.serialize(entry.getValue()));
+					pages.set(p,  new SerializedPage(page.getPageId(), serializer.serialize(page)));
 				}
 			}
 

http://git-wip-us.apache.org/repos/asf/wicket/blob/a3604f7c/wicket-core/src/main/java/org/apache/wicket/pageStore/SerializedPage.java
----------------------------------------------------------------------
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
new file mode 100644
index 0000000..86291d9
--- /dev/null
+++ b/wicket-core/src/main/java/org/apache/wicket/pageStore/SerializedPage.java
@@ -0,0 +1,74 @@
+/*
+ * 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 org.apache.wicket.page.IManageablePage;
+import org.apache.wicket.util.lang.Args;
+
+/**
+ * A wrapper around a serialized page.
+ * <p>
+ * {@link IPageStore} might choose to use this representation of a page internally,
+ * or accept it in {@link IPageStore#addPage(IPageContext, IManageablePage)}.
+ */
+class SerializedPage implements IManageablePage
+{
+
+	private final int pageId;
+
+	private final byte[] data;
+
+	public SerializedPage(int pageId, byte[] data)
+	{
+		this.pageId = pageId;
+		this.data = Args.notNull(data, "data");
+	}
+
+	@Override
+	public boolean isPageStateless()
+	{
+		return false;
+	}
+
+	@Override
+	public int getPageId()
+	{
+		return pageId;
+	}
+
+	public byte[] getData()
+	{
+		return data;
+	}
+	
+	@Override
+	public void detach()
+	{
+	}
+
+	@Override
+	public boolean setFreezePageId(boolean freeze)
+	{
+		return false;
+	}
+	
+	@Override
+	public String toString()
+	{
+		return "[SerializedPage id = " + pageId + "]";
+	}
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/wicket/blob/a3604f7c/wicket-core/src/main/java/org/apache/wicket/pageStore/SerializingPageStore.java
----------------------------------------------------------------------
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
new file mode 100644
index 0000000..3b5ac3a
--- /dev/null
+++ b/wicket-core/src/main/java/org/apache/wicket/pageStore/SerializingPageStore.java
@@ -0,0 +1,63 @@
+/*
+ * 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 org.apache.wicket.page.IManageablePage;
+import org.apache.wicket.serialize.ISerializer;
+import org.apache.wicket.util.lang.Args;
+
+/**
+ * A store that serializes all pages before delegating and vice versa.
+ */
+public class SerializingPageStore extends DelegatingPageStore
+{
+
+	private ISerializer serializer;
+
+	/**
+	 * @param delegate
+	 *            store to delegate to
+	 * @param serializer
+	 *            serializer to use if session gets persisted
+	 */
+	public SerializingPageStore(IPageStore delegate, ISerializer serializer)
+	{
+		super(delegate);
+
+		this.serializer = Args.notNull(serializer, "serializer");
+	}
+
+	@Override
+	public IManageablePage getPage(IPageContext context, int id)
+	{
+		IManageablePage page = super.getPage(context, id);
+		if (page instanceof SerializedPage) {
+			page = (IManageablePage)serializer.deserialize(((SerializedPage)page).getData());
+		}
+
+		return super.getPage(context, id);
+	}
+
+	@Override
+	public void addPage(IPageContext context, IManageablePage page)
+	{
+		if (page instanceof SerializedPage == false) {
+			page = new SerializedPage(page.getPageId(), serializer.serialize(page));
+		}
+		super.addPage(context, page);
+	}
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/wicket/blob/a3604f7c/wicket-core/src/test/java/org/apache/wicket/versioning/PageVersioningTest.java
----------------------------------------------------------------------
diff --git a/wicket-core/src/test/java/org/apache/wicket/versioning/PageVersioningTest.java b/wicket-core/src/test/java/org/apache/wicket/versioning/PageVersioningTest.java
index 4e6420e..3f0e443 100644
--- a/wicket-core/src/test/java/org/apache/wicket/versioning/PageVersioningTest.java
+++ b/wicket-core/src/test/java/org/apache/wicket/versioning/PageVersioningTest.java
@@ -26,8 +26,9 @@ import org.apache.wicket.page.PageManager;
 import org.apache.wicket.pageStore.IPageStore;
 import org.apache.wicket.pageStore.InMemoryPageStore;
 import org.apache.wicket.pageStore.InSessionPageStore;
-import org.apache.wicket.pageStore.NoopPageStore;
+import org.apache.wicket.pageStore.SerializingPageStore;
 import org.apache.wicket.protocol.http.WebApplication;
+import org.apache.wicket.serialize.java.JavaSerializer;
 import org.apache.wicket.util.tester.WicketTester;
 import org.junit.After;
 import org.junit.Before;
@@ -59,7 +60,9 @@ public class PageVersioningTest
 			{
 				return () ->
 				{
-					final IPageStore store = new InSessionPageStore(new NoopPageStore(), Integer.MAX_VALUE);
+					InMemoryPageStore inMemory = new InMemoryPageStore("test", Integer.MAX_VALUE);
+					SerializingPageStore serializing = new SerializingPageStore(inMemory, new JavaSerializer("test"));
+					final IPageStore store = new InSessionPageStore(serializing, Integer.MAX_VALUE);
 					return new PageManager(store);
 				};
 			}