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/02 21:25:20 UTC
[1/5] wicket git commit: WICKET-6563 new IPageStore implementation
Repository: wicket
Updated Branches:
refs/heads/WICKET-6563 [created] bcf76f517
http://git-wip-us.apache.org/repos/asf/wicket/blob/bcf76f51/wicket-core/src/test/java/org/apache/wicket/request/handler/PageIdPoliticTest.java
----------------------------------------------------------------------
diff --git a/wicket-core/src/test/java/org/apache/wicket/request/handler/PageIdPoliticTest.java b/wicket-core/src/test/java/org/apache/wicket/request/handler/PageIdPoliticTest.java
index 978e87b..f9877c0 100644
--- a/wicket-core/src/test/java/org/apache/wicket/request/handler/PageIdPoliticTest.java
+++ b/wicket-core/src/test/java/org/apache/wicket/request/handler/PageIdPoliticTest.java
@@ -26,17 +26,15 @@ import org.apache.wicket.markup.IMarkupResourceStreamProvider;
import org.apache.wicket.markup.html.WebComponent;
import org.apache.wicket.markup.html.WebPage;
import org.apache.wicket.mock.MockApplication;
+import org.apache.wicket.page.IManageablePage;
import org.apache.wicket.page.IPageManager;
-import org.apache.wicket.page.IPageManagerContext;
-import org.apache.wicket.page.PageStoreManager;
-import org.apache.wicket.pageStore.DefaultPageStore;
-import org.apache.wicket.pageStore.IPageStore;
+import org.apache.wicket.page.PageManager;
+import org.apache.wicket.pageStore.IPageContext;
+import org.apache.wicket.pageStore.InMemoryPageStore;
import org.apache.wicket.request.Url;
-import org.apache.wicket.serialize.java.JavaSerializer;
import org.apache.wicket.util.resource.IResourceStream;
import org.apache.wicket.util.resource.StringResourceStream;
import org.apache.wicket.util.tester.WicketTester;
-import org.apache.wicket.versioning.InMemoryPageStore;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
@@ -48,7 +46,7 @@ import org.junit.Test;
public class PageIdPoliticTest extends Assert
{
private WicketTester tester;
- private InMemoryPageStore dataStore;
+ private InMemoryPageStore pageStore;
private MockApplication application;
private int storeCount;
@@ -87,12 +85,12 @@ public class PageIdPoliticTest extends Assert
public void setUp() throws Exception
{
application = new MockApplication();
- dataStore = new InMemoryPageStore()
+ pageStore = new InMemoryPageStore("test", Integer.MAX_VALUE)
{
@Override
- public void storeData(String sessionId, int pageId, byte[] pageAsBytes)
+ public void addPage(IPageContext context, IManageablePage page)
{
- super.storeData(sessionId, pageId, pageAsBytes);
+ super.addPage(context, page);
storeCount++;
}
};
@@ -104,12 +102,9 @@ public class PageIdPoliticTest extends Assert
return new IPageManagerProvider()
{
@Override
- public IPageManager apply(IPageManagerContext pageManagerContext)
+ public IPageManager get()
{
- IPageStore pageStore = new DefaultPageStore(new JavaSerializer(
- application.getApplicationKey()), dataStore, 4);
- return new PageStoreManager(application.getName(), pageStore,
- pageManagerContext);
+ return new PageManager(pageStore);
}
};
}
http://git-wip-us.apache.org/repos/asf/wicket/blob/bcf76f51/wicket-core/src/test/java/org/apache/wicket/request/handler/PageProviderTest.java
----------------------------------------------------------------------
diff --git a/wicket-core/src/test/java/org/apache/wicket/request/handler/PageProviderTest.java b/wicket-core/src/test/java/org/apache/wicket/request/handler/PageProviderTest.java
index 3f87b08..1f9740a 100644
--- a/wicket-core/src/test/java/org/apache/wicket/request/handler/PageProviderTest.java
+++ b/wicket-core/src/test/java/org/apache/wicket/request/handler/PageProviderTest.java
@@ -62,8 +62,8 @@ public class PageProviderTest extends WicketTestCase
// storing test page
TestMapperContext mapperContext = new TestMapperContext();
- mapperContext.getPageManager().touchPage(testPage);
- mapperContext.getPageManager().commitRequest();
+ mapperContext.getPageManager().addPage(testPage);
+ mapperContext.getPageManager().detach();
// by cleaning session cache we make sure of not being testing the same in-memory instance
mapperContext.cleanSessionCache();
@@ -77,8 +77,8 @@ public class PageProviderTest extends WicketTestCase
// changing some sate
StatefullMockPage providedPage = (StatefullMockPage)pageProvider.getPageInstance();
providedPage.state = newState;
- mapperContext.getPageManager().touchPage(providedPage);
- mapperContext.getPageManager().commitRequest();
+ mapperContext.getPageManager().addPage(providedPage);
+ mapperContext.getPageManager().detach();
mapperContext.cleanSessionCache();
@@ -212,8 +212,8 @@ public class PageProviderTest extends WicketTestCase
{
TestMapperContext mapperContext = new TestMapperContext();
Page page = new TestPage();
- mapperContext.getPageManager().touchPage(page);
- mapperContext.getPageManager().commitRequest();
+ mapperContext.getPageManager().addPage(page);
+ mapperContext.getPageManager().detach();
// by cleaning session cache we make sure of not being testing the same in-memory instance
mapperContext.cleanSessionCache();
@@ -235,8 +235,8 @@ public class PageProviderTest extends WicketTestCase
{
TestMapperContext mapperContext = new TestMapperContext();
Page page = new TestPage();
- mapperContext.getPageManager().touchPage(page);
- mapperContext.getPageManager().commitRequest();
+ mapperContext.getPageManager().addPage(page);
+ mapperContext.getPageManager().detach();
// by cleaning session cache we make sure of not being testing the same in-memory instance
mapperContext.cleanSessionCache();
@@ -252,8 +252,8 @@ public class PageProviderTest extends WicketTestCase
{
TestMapperContext mapperContext = new TestMapperContext();
Page page = new TestPage();
- mapperContext.getPageManager().touchPage(page);
- mapperContext.getPageManager().commitRequest();
+ mapperContext.getPageManager().addPage(page);
+ mapperContext.getPageManager().detach();
PageProvider pageProvider = new PageProvider(page.getPageId(), page.getRenderCount());
JavaSerializer javaSerializer = new JavaSerializer("app");
http://git-wip-us.apache.org/repos/asf/wicket/blob/bcf76f51/wicket-core/src/test/java/org/apache/wicket/versioning/InMemoryPageStore.java
----------------------------------------------------------------------
diff --git a/wicket-core/src/test/java/org/apache/wicket/versioning/InMemoryPageStore.java b/wicket-core/src/test/java/org/apache/wicket/versioning/InMemoryPageStore.java
deleted file mode 100644
index f69a918..0000000
--- a/wicket-core/src/test/java/org/apache/wicket/versioning/InMemoryPageStore.java
+++ /dev/null
@@ -1,126 +0,0 @@
-/*
- * 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.versioning;
-
-import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
-
-import org.apache.wicket.pageStore.IDataStore;
-
-/**
- * An implementation of {@link IDataStore} that stores the data in memory. Used only for testing
- * purposes.
- *
- * @author martin-g
- */
-public class InMemoryPageStore implements IDataStore
-{
-
- /**
- * A map of : sessionId => pageId => pageAsBytes
- */
- private final ConcurrentHashMap<String, Map<Integer, byte[]>> store;
-
- /**
- * Construct.
- */
- public InMemoryPageStore()
- {
- store = new ConcurrentHashMap<> ();
- }
-
- @Override
- public void destroy()
- {
- store.clear();
- }
-
- /**
- * @see org.apache.wicket.pageStore.IDataStore#getData(java.lang.String, int)
- */
- @Override
- public byte[] getData(String sessionId, int pageId)
- {
- byte[] pageAsBytes = null;
-
- final Map<Integer, byte[]> sessionPages = store.get(sessionId);
- if (sessionPages != null)
- {
- pageAsBytes = sessionPages.get(pageId);
- }
-
- return pageAsBytes;
- }
-
- /**
- * @see org.apache.wicket.pageStore.IDataStore#removeData(java.lang.String, int)
- */
- @Override
- public void removeData(String sessionId, int pageId)
- {
- final Map<Integer, byte[]> sessionPages = store.get(sessionId);
- if (sessionPages != null)
- {
- sessionPages.remove(pageId);
- }
- }
-
- /**
- * @see org.apache.wicket.pageStore.IDataStore#removeData(java.lang.String)
- */
- @Override
- public void removeData(String sessionId)
- {
- store.remove(sessionId);
- }
-
- /**
- * @see org.apache.wicket.pageStore.IDataStore#storeData(java.lang.String, int, byte[])
- */
- @Override
- public void storeData(String sessionId, int pageId, byte[] pageAsBytes)
- {
- Map<Integer, byte[]> sessionPages = store.get(sessionId);
- if (sessionPages == null)
- {
- sessionPages = new ConcurrentHashMap<>();
- Map<Integer, byte[]> tmpSessionPages = store.putIfAbsent(sessionId, sessionPages);
- if (tmpSessionPages != null)
- {
- sessionPages = tmpSessionPages;
- }
- }
-
- sessionPages.put(pageId, pageAsBytes);
- }
-
- /**
- * @see org.apache.wicket.pageStore.IDataStore#isReplicated()
- */
- @Override
- public boolean isReplicated()
- {
- return false;
- }
-
- @Override
- public boolean canBeAsynchronous()
- {
- return false;
- }
-
-}
http://git-wip-us.apache.org/repos/asf/wicket/blob/bcf76f51/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 9ac60fc..4e6420e 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
@@ -22,13 +22,12 @@ import static org.junit.Assert.assertNotNull;
import org.apache.wicket.IPageManagerProvider;
import org.apache.wicket.Page;
import org.apache.wicket.page.IPageManager;
-import org.apache.wicket.page.IPageManagerContext;
-import org.apache.wicket.page.PageStoreManager;
-import org.apache.wicket.pageStore.AsynchronousDataStore;
-import org.apache.wicket.pageStore.DefaultPageStore;
-import org.apache.wicket.pageStore.IDataStore;
+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.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;
@@ -58,21 +57,10 @@ public class PageVersioningTest
@Override
protected IPageManagerProvider newTestPageManagerProvider()
{
- return new IPageManagerProvider()
+ return () ->
{
-
- @Override
- public IPageManager apply(IPageManagerContext pageManagerContext)
- {
-
- final IDataStore dataStore = new InMemoryPageStore();
- final AsynchronousDataStore asyncDS = new AsynchronousDataStore(dataStore,
- 100);
- final DefaultPageStore pageStore = new DefaultPageStore(new JavaSerializer(
- application.getApplicationKey()), asyncDS, 40);
- return new PageStoreManager(application.getName(), pageStore,
- pageManagerContext);
- }
+ final IPageStore store = new InSessionPageStore(new NoopPageStore(), Integer.MAX_VALUE);
+ return new PageManager(store);
};
}
http://git-wip-us.apache.org/repos/asf/wicket/blob/bcf76f51/wicket-devutils/src/main/java/org/apache/wicket/devutils/debugbar/DebugBarInitializer.java
----------------------------------------------------------------------
diff --git a/wicket-devutils/src/main/java/org/apache/wicket/devutils/debugbar/DebugBarInitializer.java b/wicket-devutils/src/main/java/org/apache/wicket/devutils/debugbar/DebugBarInitializer.java
index ae17d8e..2fcdca3 100644
--- a/wicket-devutils/src/main/java/org/apache/wicket/devutils/debugbar/DebugBarInitializer.java
+++ b/wicket-devutils/src/main/java/org/apache/wicket/devutils/debugbar/DebugBarInitializer.java
@@ -38,7 +38,7 @@ public class DebugBarInitializer implements IInitializer
DebugBar.registerContributor(VersionDebugContributor.DEBUG_BAR_CONTRIB, application);
DebugBar.registerContributor(InspectorDebugPanel.DEBUG_BAR_CONTRIB, application);
DebugBar.registerContributor(SessionSizeDebugPanel.DEBUG_BAR_CONTRIB, application);
- DebugBar.registerContributor(PageSizeDebugPanel.DEBUG_BAR_CONTRIB, application);
+ DebugBar.registerContributor(PageStoreDebugPanel.DEBUG_BAR_CONTRIB, application);
}
}
http://git-wip-us.apache.org/repos/asf/wicket/blob/bcf76f51/wicket-devutils/src/main/java/org/apache/wicket/devutils/debugbar/InspectorDebugPanel.java
----------------------------------------------------------------------
diff --git a/wicket-devutils/src/main/java/org/apache/wicket/devutils/debugbar/InspectorDebugPanel.java b/wicket-devutils/src/main/java/org/apache/wicket/devutils/debugbar/InspectorDebugPanel.java
index 33a0705..4de5cd4 100644
--- a/wicket-devutils/src/main/java/org/apache/wicket/devutils/debugbar/InspectorDebugPanel.java
+++ b/wicket-devutils/src/main/java/org/apache/wicket/devutils/debugbar/InspectorDebugPanel.java
@@ -18,12 +18,13 @@ package org.apache.wicket.devutils.debugbar;
import org.apache.wicket.Component;
import org.apache.wicket.Page;
+import org.apache.wicket.core.util.lang.WicketObjects;
import org.apache.wicket.devutils.inspector.InspectorPage;
import org.apache.wicket.model.IModel;
-import org.apache.wicket.model.Model;
import org.apache.wicket.request.mapper.parameter.PageParameters;
import org.apache.wicket.request.resource.PackageResourceReference;
import org.apache.wicket.request.resource.ResourceReference;
+import org.apache.wicket.util.lang.Bytes;
/**
* A panel that adds a link to the inspector to the debug bar.
@@ -73,7 +74,22 @@ public class InspectorDebugPanel extends StandardDebugPanel
@Override
protected IModel<String> getDataModel()
{
- return new Model<>("Inspector");
+ return new IModel<String>()
+ {
+ private static final long serialVersionUID = 1L;
+
+ @Override
+ public String getObject()
+ {
+ Page enclosingPage = getPage();
+ long pageSize = WicketObjects.sizeof(enclosingPage);
+ Bytes pageSizeInBytes = (pageSize > -1 ? Bytes.bytes(pageSize) : null);
+ String pageSizeAsString = pageSizeInBytes != null ? pageSizeInBytes.toString()
+ : "unknown";
+
+ return "Page: " + pageSizeAsString;
+ }
+ };
}
@Override
http://git-wip-us.apache.org/repos/asf/wicket/blob/bcf76f51/wicket-devutils/src/main/java/org/apache/wicket/devutils/debugbar/PageSizeDebugPanel.java
----------------------------------------------------------------------
diff --git a/wicket-devutils/src/main/java/org/apache/wicket/devutils/debugbar/PageSizeDebugPanel.java b/wicket-devutils/src/main/java/org/apache/wicket/devutils/debugbar/PageSizeDebugPanel.java
deleted file mode 100644
index f386783..0000000
--- a/wicket-devutils/src/main/java/org/apache/wicket/devutils/debugbar/PageSizeDebugPanel.java
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
- * 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.devutils.debugbar;
-
-import org.apache.wicket.Component;
-import org.apache.wicket.Page;
-import org.apache.wicket.core.util.lang.WicketObjects;
-import org.apache.wicket.markup.html.WebPage;
-import org.apache.wicket.markup.html.link.BookmarkablePageLink;
-import org.apache.wicket.model.IModel;
-import org.apache.wicket.request.resource.PackageResourceReference;
-import org.apache.wicket.request.resource.ResourceReference;
-import org.apache.wicket.util.lang.Bytes;
-
-/**
- * A panel for the debug bar that shows the size of the currently shown page.
- * <p>
- * <strong>Note</strong>: this size includes the size of the debug bar itself too!
- */
-public class PageSizeDebugPanel extends StandardDebugPanel
-{
- private static final long serialVersionUID = 1L;
-
- /** */
- public static final IDebugBarContributor DEBUG_BAR_CONTRIB = new IDebugBarContributor()
- {
- private static final long serialVersionUID = 1L;
-
- @Override
- public Component createComponent(final String id, final DebugBar debugBar)
- {
- return new PageSizeDebugPanel(id);
- }
-
- };
-
- /**
- * Construct.
- *
- * @param id
- */
- public PageSizeDebugPanel(final String id)
- {
- super(id);
- }
-
- @Override
- protected Class<? extends Page> getLinkPageClass()
- {
- // not used
- return WebPage.class;
- }
-
- // Disable the link because there is no page with more detailed information
- @Override
- protected BookmarkablePageLink<Void> createLink(final String id)
- {
- BookmarkablePageLink<Void> bookmarkablePageLink = super.createLink(id);
- bookmarkablePageLink.setEnabled(false);
- return bookmarkablePageLink;
- }
-
- @Override
- protected ResourceReference getImageResourceReference()
- {
- // TODO: need better image for this:
- return new PackageResourceReference(SessionSizeDebugPanel.class, "harddrive.png");
- }
-
- @Override
- protected IModel<String> getDataModel()
- {
- return new IModel<String>()
- {
- private static final long serialVersionUID = 1L;
-
- @Override
- public String getObject()
- {
- Page enclosingPage = getPage();
- long pageSize = WicketObjects.sizeof(enclosingPage);
- Bytes pageSizeInBytes = (pageSize > -1 ? Bytes.bytes(pageSize) : null);
- String pageSizeAsString = pageSizeInBytes != null ? pageSizeInBytes.toString()
- : "unknown";
-
- return "Page: " + pageSizeAsString;
- }
- };
- }
-}
http://git-wip-us.apache.org/repos/asf/wicket/blob/bcf76f51/wicket-devutils/src/main/java/org/apache/wicket/devutils/debugbar/PageStoreDebugPanel.java
----------------------------------------------------------------------
diff --git a/wicket-devutils/src/main/java/org/apache/wicket/devutils/debugbar/PageStoreDebugPanel.java b/wicket-devutils/src/main/java/org/apache/wicket/devutils/debugbar/PageStoreDebugPanel.java
new file mode 100644
index 0000000..eedb590
--- /dev/null
+++ b/wicket-devutils/src/main/java/org/apache/wicket/devutils/debugbar/PageStoreDebugPanel.java
@@ -0,0 +1,84 @@
+/*
+ * 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.devutils.debugbar;
+
+import org.apache.wicket.Component;
+import org.apache.wicket.Page;
+import org.apache.wicket.devutils.diskstore.PageStorePage;
+import org.apache.wicket.model.IModel;
+import org.apache.wicket.pageStore.IPersistentPageStore;
+import org.apache.wicket.request.resource.PackageResourceReference;
+import org.apache.wicket.request.resource.ResourceReference;
+
+/**
+ * A panel that adds a link to persisted pages to the debug bar.
+ */
+public class PageStoreDebugPanel extends StandardDebugPanel
+{
+ private static final long serialVersionUID = 1L;
+
+ /** */
+ public static final IDebugBarContributor DEBUG_BAR_CONTRIB = new IDebugBarContributor()
+ {
+ private static final long serialVersionUID = 1L;
+
+ @Override
+ public Component createComponent(final String id, final DebugBar debugBar)
+ {
+ return new PageStoreDebugPanel(id);
+ }
+ };
+
+ /**
+ * Construct.
+ *
+ * @param id
+ * The component id
+ */
+ public PageStoreDebugPanel(final String id)
+ {
+ super(id);
+ }
+
+ @Override
+ protected Class<? extends Page> getLinkPageClass()
+ {
+ return PageStorePage.class;
+ }
+
+ @Override
+ protected ResourceReference getImageResourceReference()
+ {
+ return new PackageResourceReference(PageStoreDebugPanel.class, "harddrive.png");
+ }
+
+ @Override
+ protected IModel<String> getDataModel()
+ {
+ return new IModel<String>()
+ {
+ private static final long serialVersionUID = 1L;
+
+ @Override
+ public String getObject()
+ {
+ IPersistentPageStore store = PageStorePage.getPersistentPageStore();
+ return String.format("Persisted: %s", store == null ? "N/A" : store.getTotalSize());
+ }
+ };
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/wicket/blob/bcf76f51/wicket-devutils/src/main/java/org/apache/wicket/devutils/debugbar/StandardDebugPanel.java
----------------------------------------------------------------------
diff --git a/wicket-devutils/src/main/java/org/apache/wicket/devutils/debugbar/StandardDebugPanel.java b/wicket-devutils/src/main/java/org/apache/wicket/devutils/debugbar/StandardDebugPanel.java
index c88499e..921b009 100644
--- a/wicket-devutils/src/main/java/org/apache/wicket/devutils/debugbar/StandardDebugPanel.java
+++ b/wicket-devutils/src/main/java/org/apache/wicket/devutils/debugbar/StandardDebugPanel.java
@@ -50,7 +50,7 @@ public abstract class StandardDebugPanel extends DevUtilsPanel
protected void onInitialize()
{
super.onInitialize();
- BookmarkablePageLink<Void> link = createLink("link");
+ WebMarkupContainer link = createLink("link");
add(link);
ResourceReference img = getImageResourceReference();
if (img == null)
@@ -64,7 +64,7 @@ public abstract class StandardDebugPanel extends DevUtilsPanel
link.add(new Label("data", getDataModel()));
}
- protected BookmarkablePageLink<Void> createLink(final String id)
+ protected WebMarkupContainer createLink(final String id)
{
return new BookmarkablePageLink<>(id, getLinkPageClass(), getLinkPageParameters());
}
http://git-wip-us.apache.org/repos/asf/wicket/blob/bcf76f51/wicket-devutils/src/main/java/org/apache/wicket/devutils/diskstore/DebugDiskDataStore.java
----------------------------------------------------------------------
diff --git a/wicket-devutils/src/main/java/org/apache/wicket/devutils/diskstore/DebugDiskDataStore.java b/wicket-devutils/src/main/java/org/apache/wicket/devutils/diskstore/DebugDiskDataStore.java
deleted file mode 100644
index 9c3d882..0000000
--- a/wicket-devutils/src/main/java/org/apache/wicket/devutils/diskstore/DebugDiskDataStore.java
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- * 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.devutils.diskstore;
-
-import java.io.File;
-import java.util.ArrayList;
-import java.util.List;
-
-import org.apache.wicket.Application;
-import org.apache.wicket.pageStore.DiskDataStore;
-import org.apache.wicket.pageStore.PageWindowManager;
-import org.apache.wicket.pageStore.PageWindowManager.PageWindow;
-import org.apache.wicket.protocol.http.WebApplication;
-import org.apache.wicket.util.lang.Bytes;
-
-/**
- * An extension of {@link DiskDataStore} that is able to browse the content of the file storage.
- * <p>
- * To enable it add in YourApplication#init():
- *
- * <pre>
- * <code>
- * DebugDiskDataStore.register(this);
- * </code>
- * </pre>
- *
- * </p>
- * <p>
- * The data can be browsed at: <em>/wicket/internal/debug/diskDataStore</em>
- */
-public class DebugDiskDataStore extends DiskDataStore
-{
-
- /**
- * Construct.
- *
- * @param applicationName
- * @param fileStoreFolder
- * @param maxSizePerSession
- */
- public DebugDiskDataStore(String applicationName, File fileStoreFolder, Bytes maxSizePerSession)
- {
- super(applicationName, fileStoreFolder, maxSizePerSession);
-
- }
-
- /**
- *
- * @param sessionId
- * @param count
- * @return a list of the last N page windows
- */
- public List<PageWindow> getLastPageWindows(String sessionId, int count)
- {
- List<PageWindow> pageWindows = new ArrayList<>();
-
- SessionEntry sessionEntry = getSessionEntry(sessionId, false);
- if (sessionEntry != null)
- {
- PageWindowManager windowManager = sessionEntry.getManager();
- pageWindows.addAll(windowManager.getLastPageWindows(count));
- }
- return pageWindows;
- }
-
- @Override
- public File getStoreFolder()
- {
- return super.getStoreFolder();
- }
-
- /**
- * Configures the page manager provider and mounts the page at
- * <em>wicket/internal/debug/diskDataStore</em>
- *
- * @param application
- */
- public static void register(final Application application)
- {
- application.setPageManagerProvider(new DebugPageManagerProvider(application));
-
- ((WebApplication)application).mountPage("wicket/internal/debug/diskDataStore",
- DiskStoreBrowserPage.class);
- }
-
-}
http://git-wip-us.apache.org/repos/asf/wicket/blob/bcf76f51/wicket-devutils/src/main/java/org/apache/wicket/devutils/diskstore/DebugPageManagerProvider.java
----------------------------------------------------------------------
diff --git a/wicket-devutils/src/main/java/org/apache/wicket/devutils/diskstore/DebugPageManagerProvider.java b/wicket-devutils/src/main/java/org/apache/wicket/devutils/diskstore/DebugPageManagerProvider.java
deleted file mode 100644
index 7893638..0000000
--- a/wicket-devutils/src/main/java/org/apache/wicket/devutils/diskstore/DebugPageManagerProvider.java
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * 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.devutils.diskstore;
-
-import java.io.File;
-
-import org.apache.wicket.Application;
-import org.apache.wicket.DefaultPageManagerProvider;
-import org.apache.wicket.pageStore.DiskDataStore;
-import org.apache.wicket.pageStore.IDataStore;
-import org.apache.wicket.settings.StoreSettings;
-import org.apache.wicket.util.lang.Bytes;
-
-/**
- */
-public class DebugPageManagerProvider extends DefaultPageManagerProvider
-{
-
- private DebugDiskDataStore dataStore;
-
- /**
- * Construct.
- *
- * @param application
- */
- public DebugPageManagerProvider(Application application)
- {
- super(application);
- }
-
- /**
- * @return the extended with debug information {@link DiskDataStore}
- */
- public DebugDiskDataStore getDataStore()
- {
- return dataStore;
- }
-
- @Override
- protected IDataStore newDataStore()
- {
- StoreSettings storeSettings = application.getStoreSettings();
- File fileStoreFolder = storeSettings.getFileStoreFolder();
- Bytes maxSizePerSession = storeSettings.getMaxSizePerSession();
- dataStore = new DebugDiskDataStore(application.getName(), fileStoreFolder,
- maxSizePerSession);
- return dataStore;
- }
-}
http://git-wip-us.apache.org/repos/asf/wicket/blob/bcf76f51/wicket-devutils/src/main/java/org/apache/wicket/devutils/diskstore/DiskStoreBrowserPage.html
----------------------------------------------------------------------
diff --git a/wicket-devutils/src/main/java/org/apache/wicket/devutils/diskstore/DiskStoreBrowserPage.html b/wicket-devutils/src/main/java/org/apache/wicket/devutils/diskstore/DiskStoreBrowserPage.html
deleted file mode 100644
index 307884c..0000000
--- a/wicket-devutils/src/main/java/org/apache/wicket/devutils/diskstore/DiskStoreBrowserPage.html
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
- 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.
--->
-<!DOCTYPE html>
-<html xmlns="http://www.w3.org/1999/xhtml" xmlns:wicket="http://wicket.apache.org">
-
- <head>
- <title>Debug DiskDataStore page</title>
- </head>
-
- <body>
-
- <div wicket:id="tree">default</div>
-
- </body>
-
-</html>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/wicket/blob/bcf76f51/wicket-devutils/src/main/java/org/apache/wicket/devutils/diskstore/DiskStoreBrowserPage.java
----------------------------------------------------------------------
diff --git a/wicket-devutils/src/main/java/org/apache/wicket/devutils/diskstore/DiskStoreBrowserPage.java b/wicket-devutils/src/main/java/org/apache/wicket/devutils/diskstore/DiskStoreBrowserPage.java
deleted file mode 100644
index 066f9e6..0000000
--- a/wicket-devutils/src/main/java/org/apache/wicket/devutils/diskstore/DiskStoreBrowserPage.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * 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.devutils.diskstore;
-
-import org.apache.wicket.Component;
-import org.apache.wicket.devutils.diskstore.browser.BrowserPanel;
-import org.apache.wicket.markup.html.WebPage;
-import org.apache.wicket.request.mapper.parameter.PageParameters;
-
-/**
- * A page that shows the attributes (id, name, size) of the pages stored in the data stores.
- */
-public class DiskStoreBrowserPage extends WebPage
-{
-
- /**
- * Construct.
- *
- * @param parameters
- * the request parameters
- */
- public DiskStoreBrowserPage(final PageParameters parameters)
- {
- super(parameters);
-
- Component tree;
-// tree = new LabelTree("tree", new PageWindowModel(sessionId, dataStore));
- tree = new BrowserPanel("tree");
- add(tree);
- }
-
- @Override
- public boolean isVersioned()
- {
- return false;
- }
-}
http://git-wip-us.apache.org/repos/asf/wicket/blob/bcf76f51/wicket-devutils/src/main/java/org/apache/wicket/devutils/diskstore/PageStorePage.html
----------------------------------------------------------------------
diff --git a/wicket-devutils/src/main/java/org/apache/wicket/devutils/diskstore/PageStorePage.html b/wicket-devutils/src/main/java/org/apache/wicket/devutils/diskstore/PageStorePage.html
new file mode 100644
index 0000000..307884c
--- /dev/null
+++ b/wicket-devutils/src/main/java/org/apache/wicket/devutils/diskstore/PageStorePage.html
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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.
+-->
+<!DOCTYPE html>
+<html xmlns="http://www.w3.org/1999/xhtml" xmlns:wicket="http://wicket.apache.org">
+
+ <head>
+ <title>Debug DiskDataStore page</title>
+ </head>
+
+ <body>
+
+ <div wicket:id="tree">default</div>
+
+ </body>
+
+</html>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/wicket/blob/bcf76f51/wicket-devutils/src/main/java/org/apache/wicket/devutils/diskstore/PageStorePage.java
----------------------------------------------------------------------
diff --git a/wicket-devutils/src/main/java/org/apache/wicket/devutils/diskstore/PageStorePage.java b/wicket-devutils/src/main/java/org/apache/wicket/devutils/diskstore/PageStorePage.java
new file mode 100644
index 0000000..c5c52aa
--- /dev/null
+++ b/wicket-devutils/src/main/java/org/apache/wicket/devutils/diskstore/PageStorePage.java
@@ -0,0 +1,68 @@
+/*
+ * 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.devutils.diskstore;
+
+import org.apache.wicket.Session;
+import org.apache.wicket.devutils.diskstore.browser.BrowserPanel;
+import org.apache.wicket.markup.html.WebPage;
+import org.apache.wicket.pageStore.DelegatingPageStore;
+import org.apache.wicket.pageStore.IPageStore;
+import org.apache.wicket.pageStore.IPersistentPageStore;
+import org.apache.wicket.request.mapper.parameter.PageParameters;
+
+/**
+ * A page that shows the attributes (id, name, size) of the pages stored in the data stores.
+ */
+public class PageStorePage extends WebPage
+{
+
+ /**
+ * Construct.
+ *
+ * @param parameters
+ * the request parameters
+ */
+ public PageStorePage(final PageParameters parameters)
+ {
+ super(parameters);
+
+ add(new BrowserPanel("tree"));
+ }
+
+ @Override
+ public boolean isVersioned()
+ {
+ return false;
+ }
+
+ public static IPersistentPageStore getPersistentPageStore() {
+ IPageStore store = Session.get().getPageManager().getPageStore();
+ while (true) {
+ if (store instanceof IPersistentPageStore) {
+ return (IPersistentPageStore)store;
+ }
+
+ if (store instanceof DelegatingPageStore) {
+ store = ((DelegatingPageStore)store).getDelegate();
+ } else {
+ break;
+ }
+ }
+
+ return null;
+ }
+}
http://git-wip-us.apache.org/repos/asf/wicket/blob/bcf76f51/wicket-devutils/src/main/java/org/apache/wicket/devutils/diskstore/browser/BrowserPanel.html
----------------------------------------------------------------------
diff --git a/wicket-devutils/src/main/java/org/apache/wicket/devutils/diskstore/browser/BrowserPanel.html b/wicket-devutils/src/main/java/org/apache/wicket/devutils/diskstore/browser/BrowserPanel.html
index aba3252..c4ac731 100644
--- a/wicket-devutils/src/main/java/org/apache/wicket/devutils/diskstore/browser/BrowserPanel.html
+++ b/wicket-devutils/src/main/java/org/apache/wicket/devutils/diskstore/browser/BrowserPanel.html
@@ -18,11 +18,14 @@
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:wicket="http://wicket.apache.org">
<wicket:panel>
- <h3>Active sessions</h3>
+ <h3>Persistent store</h3>
+ <span wicket:id="store"></span>
+
+ <h3>Persisted sessions</h3>
<select wicket:id="sessions"></select> <a wicket:id="currentSessionLink" title="Selects the current session">Current session</a>
- <h3>Stored pages</h3> <a wicket:id="refresh" title="Refreshes the content of the table below">refresh</a>
- <table wicket:id="table" border="1" cellpadding="3" cellspacing="1"></table>
+ <h3>Persisted pages</h3> <a wicket:id="refresh" title="Refreshes the content of the table below">refresh</a>
+ <table wicket:id="table"></table>
</wicket:panel>
</html>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/wicket/blob/bcf76f51/wicket-devutils/src/main/java/org/apache/wicket/devutils/diskstore/browser/BrowserPanel.java
----------------------------------------------------------------------
diff --git a/wicket-devutils/src/main/java/org/apache/wicket/devutils/diskstore/browser/BrowserPanel.java b/wicket-devutils/src/main/java/org/apache/wicket/devutils/diskstore/browser/BrowserPanel.java
index 51cd5f7..6147fa8 100644
--- a/wicket-devutils/src/main/java/org/apache/wicket/devutils/diskstore/browser/BrowserPanel.java
+++ b/wicket-devutils/src/main/java/org/apache/wicket/devutils/diskstore/browser/BrowserPanel.java
@@ -20,15 +20,33 @@ import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
+import org.apache.wicket.PageReference;
+import org.apache.wicket.Session;
+import org.apache.wicket.ajax.AbstractAjaxTimerBehavior;
import org.apache.wicket.ajax.AjaxRequestTarget;
-import org.apache.wicket.ajax.AjaxSelfUpdatingTimerBehavior;
import org.apache.wicket.ajax.form.AjaxFormComponentUpdatingBehavior;
import org.apache.wicket.ajax.markup.html.AjaxFallbackLink;
+import org.apache.wicket.devutils.diskstore.PageStorePage;
+import org.apache.wicket.devutils.inspector.InspectorPage;
+import org.apache.wicket.extensions.markup.html.repeater.data.grid.ICellPopulator;
+import org.apache.wicket.extensions.markup.html.repeater.data.table.AbstractColumn;
+import org.apache.wicket.extensions.markup.html.repeater.data.table.DataTable;
+import org.apache.wicket.extensions.markup.html.repeater.data.table.DefaultDataTable;
import org.apache.wicket.extensions.markup.html.repeater.data.table.IColumn;
+import org.apache.wicket.extensions.markup.html.repeater.data.table.PropertyColumn;
+import org.apache.wicket.markup.ComponentTag;
+import org.apache.wicket.markup.MarkupStream;
+import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.html.form.DropDownChoice;
+import org.apache.wicket.markup.html.link.Link;
import org.apache.wicket.markup.html.panel.Panel;
+import org.apache.wicket.markup.repeater.Item;
import org.apache.wicket.model.IModel;
import org.apache.wicket.model.Model;
+import org.apache.wicket.pageStore.DefaultPageContext;
+import org.apache.wicket.pageStore.IPageContext;
+import org.apache.wicket.pageStore.IPersistedPage;
+import org.apache.wicket.pageStore.IPersistentPageStore;
import org.apache.wicket.util.time.Duration;
/**
@@ -47,10 +65,24 @@ public class BrowserPanel extends Panel
{
super(id);
+ final Label storeLabel = new Label("store", () -> {
+ IPersistentPageStore store = PageStorePage.getPersistentPageStore();
+
+ if (store == null) {
+ return "N/A";
+ }
+
+ return String.format("%s - %s", store.getClass().getName(), store.getTotalSize());
+ });
+ storeLabel.setOutputMarkupId(true);
+ add(storeLabel);
+
final DropDownChoice<String> sessionsSelector = createSessionsSelector("sessions");
+ sessionsSelector.setOutputMarkupId(true);
add(sessionsSelector);
- final BrowserTable table = createTable("table", sessionsSelector.getModel());
+ final DataTable<IPersistedPage, String> table = createTable("table", sessionsSelector.getModel());
+ table.setOutputMarkupId(true);
add(table);
AjaxFallbackLink<Void> refreshLink = new AjaxFallbackLink<Void>("refresh")
@@ -68,7 +100,7 @@ public class BrowserPanel extends Panel
@Override
public void onClick(Optional<AjaxRequestTarget> targetOptional)
{
- sessionsSelector.setModelObject(getCurrentSession().getObject());
+ sessionsSelector.setModelObject(getCurrentSessionIdentifier());
targetOptional.ifPresent(target -> target.add(sessionsSelector, table));
}
@@ -86,6 +118,18 @@ public class BrowserPanel extends Panel
@Override
protected void onUpdate(AjaxRequestTarget target)
{
+ target.add(storeLabel);
+ target.add(sessionsSelector);
+ target.add(table);
+ }
+ });
+
+ add(new AbstractAjaxTimerBehavior(Duration.seconds(5)) {
+
+ @Override
+ protected void onTimer(AjaxRequestTarget target)
+ {
+ target.add(storeLabel);
target.add(table);
}
});
@@ -93,40 +137,65 @@ public class BrowserPanel extends Panel
private DropDownChoice<String> createSessionsSelector(String id)
{
- IModel<String> defaultSession = getCurrentSession();
-
DropDownChoice<String> sessionsSelector = new DropDownChoice<String>("sessions",
- defaultSession, new SessionsProviderModel());
-
+ Model.of(getCurrentSessionIdentifier()), new SessionIdentifiersModel());
return sessionsSelector;
}
- private IModel<String> getCurrentSession()
+ private String getCurrentSessionIdentifier()
{
- return Model.of(getSession().getId());
+ IPersistentPageStore store = PageStorePage.getPersistentPageStore();
+ if (store == null) {
+ return null;
+ }
+
+ IPageContext context = new DefaultPageContext(Session.get());
+
+ return store.getSessionIdentifier(context);
}
- private BrowserTable createTable(String id, IModel<String> sessionId)
+ private DataTable<IPersistedPage, String> createTable(String id, IModel<String> sessionId)
{
- PageWindowProvider provider = new PageWindowProvider(sessionId);
-
- List<IColumn<PageWindowDescription, String>> columns = new ArrayList<>();
-
- PageWindowColumn pageIdColumn = new PageWindowColumn(Model.of("Id"), "id");
- columns.add(pageIdColumn);
+ PersistedPagesProvider provider = new PersistedPagesProvider(sessionId);
- PageWindowColumn pageNameColumn = new PageWindowColumn(Model.of("Name"), "name");
- columns.add(pageNameColumn);
+ List<IColumn<IPersistedPage, String>> columns = new ArrayList<>();
- PageWindowColumn pageSizeColumn = new PageWindowColumn(Model.of("Size"), "size");
- columns.add(pageSizeColumn);
+ columns.add(new AbstractColumn<IPersistedPage, String>(Model.of("Id"), "pageId")
+ {
+ @Override
+ public void populateItem(Item<ICellPopulator<IPersistedPage>> cellItem, String componentId, IModel<IPersistedPage> rowModel)
+ {
+ cellItem.add(new Link<IPersistedPage>(componentId, rowModel)
+ {
+ @Override
+ protected void onComponentTag(ComponentTag tag)
+ {
+ tag.setName("a");
+
+ super.onComponentTag(tag);
+ }
+
+ @Override
+ public void onComponentTagBody(MarkupStream markupStream, ComponentTag openTag)
+ {
+ replaceComponentTagBody(markupStream, openTag, "" + getModelObject().getPageId());
+ }
+
+ @Override
+ public void onClick()
+ {
+ setResponsePage(new InspectorPage(new PageReference(getModelObject().getPageId())));
+ }
+ });
+ }
+ });
+ columns.add(new PropertyColumn<>(Model.of("Type"), "pageType", "pageType"));
+ columns.add(new PropertyColumn<>(Model.of("Size"), "pageSize", "pageSize"));
- BrowserTable browserTable = new BrowserTable(id, columns, provider);
+ DefaultDataTable<IPersistedPage, String> browserTable = new DefaultDataTable<>(id, columns, provider, 20);
browserTable.setOutputMarkupId(true);
- browserTable.add(new AjaxSelfUpdatingTimerBehavior(Duration.seconds(5)));
-
return browserTable;
}
http://git-wip-us.apache.org/repos/asf/wicket/blob/bcf76f51/wicket-devutils/src/main/java/org/apache/wicket/devutils/diskstore/browser/BrowserTable.java
----------------------------------------------------------------------
diff --git a/wicket-devutils/src/main/java/org/apache/wicket/devutils/diskstore/browser/BrowserTable.java b/wicket-devutils/src/main/java/org/apache/wicket/devutils/diskstore/browser/BrowserTable.java
deleted file mode 100644
index 264d88a..0000000
--- a/wicket-devutils/src/main/java/org/apache/wicket/devutils/diskstore/browser/BrowserTable.java
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * 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.devutils.diskstore.browser;
-
-import java.util.List;
-
-import org.apache.wicket.extensions.markup.html.repeater.data.table.DefaultDataTable;
-import org.apache.wicket.extensions.markup.html.repeater.data.table.IColumn;
-
-/**
- * A data table that shows the attributes of the recently stored pages in the data store. The last
- * used pages are rendered first.
- */
-class BrowserTable extends DefaultDataTable<PageWindowDescription, String>
-{
-
- /**
- * Construct.
- *
- * @param id
- * the component id
- * @param columns
- * the columns that show the page attributes
- * @param provider
- * the provider of page descriptions
- */
- public BrowserTable(String id, List<IColumn<PageWindowDescription, String>> columns,
- PageWindowProvider provider)
- {
- super(id, columns, provider, 20);
- }
-
-}
http://git-wip-us.apache.org/repos/asf/wicket/blob/bcf76f51/wicket-devutils/src/main/java/org/apache/wicket/devutils/diskstore/browser/DataStoreHelper.java
----------------------------------------------------------------------
diff --git a/wicket-devutils/src/main/java/org/apache/wicket/devutils/diskstore/browser/DataStoreHelper.java b/wicket-devutils/src/main/java/org/apache/wicket/devutils/diskstore/browser/DataStoreHelper.java
deleted file mode 100644
index ff4bf67..0000000
--- a/wicket-devutils/src/main/java/org/apache/wicket/devutils/diskstore/browser/DataStoreHelper.java
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * 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.devutils.diskstore.browser;
-
-import org.apache.wicket.Application;
-import org.apache.wicket.devutils.diskstore.DebugDiskDataStore;
-import org.apache.wicket.devutils.diskstore.DebugPageManagerProvider;
-
-/**
- * A helper to work with {@link DebugDiskDataStore}
- */
-public final class DataStoreHelper
-{
-
- private DataStoreHelper()
- {
- }
-
- /**
- * @return the configured {@link DebugDiskDataStore}
- */
- public static DebugDiskDataStore getDataStore()
- {
- DebugPageManagerProvider pageManagerProvider = (DebugPageManagerProvider)Application.get()
- .getPageManagerProvider();
- DebugDiskDataStore dataStore = pageManagerProvider.getDataStore();
- return dataStore;
- }
-}
http://git-wip-us.apache.org/repos/asf/wicket/blob/bcf76f51/wicket-devutils/src/main/java/org/apache/wicket/devutils/diskstore/browser/PageWindowColumn.java
----------------------------------------------------------------------
diff --git a/wicket-devutils/src/main/java/org/apache/wicket/devutils/diskstore/browser/PageWindowColumn.java b/wicket-devutils/src/main/java/org/apache/wicket/devutils/diskstore/browser/PageWindowColumn.java
deleted file mode 100644
index ea21877..0000000
--- a/wicket-devutils/src/main/java/org/apache/wicket/devutils/diskstore/browser/PageWindowColumn.java
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * 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.devutils.diskstore.browser;
-
-import org.apache.wicket.Application;
-import org.apache.wicket.devutils.diskstore.DebugDiskDataStore;
-import org.apache.wicket.devutils.diskstore.DebugPageManagerProvider;
-import org.apache.wicket.extensions.markup.html.repeater.data.grid.ICellPopulator;
-import org.apache.wicket.extensions.markup.html.repeater.data.table.PropertyColumn;
-import org.apache.wicket.markup.html.basic.Label;
-import org.apache.wicket.markup.repeater.Item;
-import org.apache.wicket.model.IModel;
-import org.apache.wicket.serialize.ISerializer;
-
-/**
- * A column that shows the page attributes (id, name, size)
- */
-class PageWindowColumn extends PropertyColumn<PageWindowDescription, String>
-{
- /**
- * Construct.
- *
- * @param displayModel
- * the header
- * @param propertyExpression
- * the page attribute
- */
- public PageWindowColumn(IModel<String> displayModel, String propertyExpression)
- {
- super(displayModel, propertyExpression);
- }
-
- @Override
- public void populateItem(Item<ICellPopulator<PageWindowDescription>> cellItem,
- String componentId, IModel<PageWindowDescription> rowModel)
- {
- String label;
- PageWindowDescription windowDescription = rowModel.getObject();
- if ("name".equals(getPropertyExpression()))
- {
- int pageId = windowDescription.getId();
- DebugPageManagerProvider pageManagerProvider = (DebugPageManagerProvider)Application.get()
- .getPageManagerProvider();
- DebugDiskDataStore dataStore = pageManagerProvider.getDataStore();
- String sessionId = windowDescription.getSessionId();
- byte[] data = dataStore.getData(sessionId, pageId);
- ISerializer serializer = Application.get().getFrameworkSettings().getSerializer();
- Object page = serializer.deserialize(data);
- label = page.getClass().getName();
- }
- else if ("id".equals(getPropertyExpression()))
- {
- label = Integer.toString(windowDescription.getId());
- }
- else if ("size".equals(getPropertyExpression()))
- {
- label = Integer.toString(windowDescription.getSize());
- }
- else
- {
- label = "unknown: " + getPropertyExpression();
- }
-
- cellItem.add(new Label(componentId, label));
- }
-}
http://git-wip-us.apache.org/repos/asf/wicket/blob/bcf76f51/wicket-devutils/src/main/java/org/apache/wicket/devutils/diskstore/browser/PageWindowDescription.java
----------------------------------------------------------------------
diff --git a/wicket-devutils/src/main/java/org/apache/wicket/devutils/diskstore/browser/PageWindowDescription.java b/wicket-devutils/src/main/java/org/apache/wicket/devutils/diskstore/browser/PageWindowDescription.java
deleted file mode 100644
index b07c005..0000000
--- a/wicket-devutils/src/main/java/org/apache/wicket/devutils/diskstore/browser/PageWindowDescription.java
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * 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.devutils.diskstore.browser;
-
-import org.apache.wicket.pageStore.PageWindowManager.PageWindow;
-import org.apache.wicket.util.io.IClusterable;
-
-/**
- * A serializable representation of the page information
- */
-class PageWindowDescription implements IClusterable
-{
- /** the page id */
- private final int id;
-
- /** the page size */
- private final int size;
-
- /** the id of the session for which this page has been used */
- private final String sessionId;
-
- PageWindowDescription(PageWindow pageWindow, String sessionId)
- {
- id = pageWindow.getPageId();
- size = pageWindow.getFilePartSize();
- this.sessionId = sessionId;
- }
-
- public String getSessionId()
- {
- return sessionId;
- }
-
- public int getId()
- {
- return id;
- }
-
- public int getSize()
- {
- return size;
- }
-}
http://git-wip-us.apache.org/repos/asf/wicket/blob/bcf76f51/wicket-devutils/src/main/java/org/apache/wicket/devutils/diskstore/browser/PageWindowProvider.java
----------------------------------------------------------------------
diff --git a/wicket-devutils/src/main/java/org/apache/wicket/devutils/diskstore/browser/PageWindowProvider.java b/wicket-devutils/src/main/java/org/apache/wicket/devutils/diskstore/browser/PageWindowProvider.java
deleted file mode 100644
index dd8397c..0000000
--- a/wicket-devutils/src/main/java/org/apache/wicket/devutils/diskstore/browser/PageWindowProvider.java
+++ /dev/null
@@ -1,108 +0,0 @@
-/*
- * 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.devutils.diskstore.browser;
-
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.List;
-
-import org.apache.wicket.devutils.diskstore.DebugDiskDataStore;
-import org.apache.wicket.extensions.markup.html.repeater.data.sort.ISortState;
-import org.apache.wicket.extensions.markup.html.repeater.data.table.ISortableDataProvider;
-import org.apache.wicket.markup.repeater.data.IDataProvider;
-import org.apache.wicket.model.IModel;
-import org.apache.wicket.model.Model;
-import org.apache.wicket.pageStore.PageWindowManager.PageWindow;
-
-/**
- * An {@link IDataProvider} that extracts the information about the stored pages
- */
-class PageWindowProvider implements ISortableDataProvider<PageWindowDescription, String>
-{
- private static final int MAX_PAGES_TO_READ = 1000;
-
- /**
- * The model that brings the currently selected session id
- */
- private final IModel<String> sessionId;
-
- PageWindowProvider(final IModel<String> sessionId)
- {
- this.sessionId = sessionId;
- }
-
- @Override
- public Iterator<? extends PageWindowDescription> iterator(long first, long count)
- {
- List<PageWindow> lastPageWindows = getPageWindows();
- List<PageWindow> subList = lastPageWindows.subList((int)first, (int)(first + count));
- List<PageWindowDescription> pageDescriptions = new ArrayList<>();
- for (PageWindow pw : subList)
- {
- pageDescriptions.add(new PageWindowDescription(pw, sessionId.getObject()));
- }
-
- return pageDescriptions.iterator();
- }
-
- private List<PageWindow> getPageWindows()
- {
- List<PageWindow> lastPageWindows = new ArrayList<>();
- if (sessionId != null && sessionId.getObject() != null)
- {
- String sessId = sessionId.getObject();
- DebugDiskDataStore dataStore = DataStoreHelper.getDataStore();
- List<PageWindow> pageWindows = dataStore.getLastPageWindows(sessId, MAX_PAGES_TO_READ);
- lastPageWindows.addAll(pageWindows);
- }
- return lastPageWindows;
- }
-
- @Override
- public long size()
- {
- return getPageWindows().size();
- }
-
- /**
- * @param description
- *
- * {@inheritDoc}
- */
- @Override
- public IModel<PageWindowDescription> model(PageWindowDescription description)
- {
- return new Model<>(description);
- }
-
- @Override
- public void detach()
- {
- sessionId.detach();
- }
-
- /*
- * No sort state for now. The provider is ISortableDataProvider just because we use
- * DefaultDataTable
- */
- @Override
- public ISortState<String> getSortState()
- {
- return null;
- }
-
-}
http://git-wip-us.apache.org/repos/asf/wicket/blob/bcf76f51/wicket-devutils/src/main/java/org/apache/wicket/devutils/diskstore/browser/PersistedPagesProvider.java
----------------------------------------------------------------------
diff --git a/wicket-devutils/src/main/java/org/apache/wicket/devutils/diskstore/browser/PersistedPagesProvider.java b/wicket-devutils/src/main/java/org/apache/wicket/devutils/diskstore/browser/PersistedPagesProvider.java
new file mode 100644
index 0000000..a93e60f
--- /dev/null
+++ b/wicket-devutils/src/main/java/org/apache/wicket/devutils/diskstore/browser/PersistedPagesProvider.java
@@ -0,0 +1,130 @@
+/*
+ * 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.devutils.diskstore.browser;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.Iterator;
+import java.util.List;
+
+import org.apache.wicket.core.util.lang.PropertyResolver;
+import org.apache.wicket.devutils.diskstore.PageStorePage;
+import org.apache.wicket.extensions.markup.html.repeater.util.SortableDataProvider;
+import org.apache.wicket.markup.repeater.data.IDataProvider;
+import org.apache.wicket.model.IModel;
+import org.apache.wicket.model.Model;
+import org.apache.wicket.pageStore.IPersistedPage;
+import org.apache.wicket.pageStore.IPersistentPageStore;
+import org.apache.wicket.util.lang.Objects;
+
+/**
+ * An {@link IDataProvider} that extracts the information about {@link IPersistedPage}s.
+ */
+class PersistedPagesProvider extends SortableDataProvider<IPersistedPage, String>
+{
+ /**
+ * The model that brings the currently selected session id
+ */
+ private final IModel<String> sessionId;
+
+ private List<IPersistedPage> pages;
+
+ PersistedPagesProvider(final IModel<String> sessionId)
+ {
+ this.sessionId = sessionId;
+ }
+
+ @Override
+ public Iterator<? extends IPersistedPage> iterator(long first, long count)
+ {
+ List<IPersistedPage> pages = getPages();
+
+ if (getSort() != null) {
+ Collections.sort(pages, new SortComparator());
+ }
+
+ return pages.iterator();
+ }
+
+ private List<IPersistedPage> getPages()
+ {
+ if (pages == null)
+ {
+ pages = new ArrayList<>();
+
+ if (sessionId.getObject() != null)
+ {
+ String sessId = sessionId.getObject();
+
+ IPersistentPageStore dataStore = PageStorePage.getPersistentPageStore();
+
+ if (dataStore != null)
+ {
+ pages.addAll(dataStore.getPersistentPages(sessId));
+ }
+ }
+ }
+
+ return pages;
+ }
+
+ @Override
+ public long size()
+ {
+ return getPages().size();
+ }
+
+ /**
+ * @param description
+ *
+ * {@inheritDoc}
+ */
+ @Override
+ public IModel<IPersistedPage> model(IPersistedPage description)
+ {
+ return new Model<>(description);
+ }
+
+ @Override
+ public void detach()
+ {
+ sessionId.detach();
+
+ pages = null;
+ }
+
+ private class SortComparator implements Comparator<IPersistedPage>
+ {
+
+ @Override
+ public int compare(IPersistedPage page0, IPersistedPage page1)
+ {
+ Object value0 = PropertyResolver.getValue(getSort().getProperty(), page0);
+ Object value1 = PropertyResolver.getValue(getSort().getProperty(), page1);
+
+ int c = Objects.compareWithConversion(value0, value1);
+
+ if (getSort().isAscending() == false)
+ {
+ c = c * -1;
+ }
+
+ return c;
+ }
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/wicket/blob/bcf76f51/wicket-devutils/src/main/java/org/apache/wicket/devutils/diskstore/browser/SessionIdentifiersModel.java
----------------------------------------------------------------------
diff --git a/wicket-devutils/src/main/java/org/apache/wicket/devutils/diskstore/browser/SessionIdentifiersModel.java b/wicket-devutils/src/main/java/org/apache/wicket/devutils/diskstore/browser/SessionIdentifiersModel.java
new file mode 100644
index 0000000..5a39804
--- /dev/null
+++ b/wicket-devutils/src/main/java/org/apache/wicket/devutils/diskstore/browser/SessionIdentifiersModel.java
@@ -0,0 +1,59 @@
+/*
+ * 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.devutils.diskstore.browser;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import org.apache.wicket.Session;
+import org.apache.wicket.devutils.diskstore.PageStorePage;
+import org.apache.wicket.model.LoadableDetachableModel;
+import org.apache.wicket.pageStore.DefaultPageContext;
+import org.apache.wicket.pageStore.DiskPageStore;
+import org.apache.wicket.pageStore.IPageContext;
+import org.apache.wicket.pageStore.IPersistentPageStore;
+
+/**
+ * A model that collects the keys from the {@link DiskPageStore} folder
+ */
+public class SessionIdentifiersModel extends LoadableDetachableModel<List<String>>
+{
+
+ @Override
+ protected List<String> load()
+ {
+ IPersistentPageStore store = PageStorePage.getPersistentPageStore();
+ if (store == null)
+ {
+ return Collections.emptyList();
+ }
+
+ ArrayList<String> identifiers = new ArrayList<>(store.getSessionIdentifiers());
+
+ IPageContext context = new DefaultPageContext(Session.get());
+ String current = store.getSessionIdentifier(context);
+ if (identifiers.contains(current) == false)
+ {
+ // identifiers of the store seem no to match their sessions ids,
+ // thus add the default identifier so the select works properly
+ identifiers.add(current);
+ }
+
+ return identifiers;
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/wicket/blob/bcf76f51/wicket-devutils/src/main/java/org/apache/wicket/devutils/diskstore/browser/SessionsProviderModel.java
----------------------------------------------------------------------
diff --git a/wicket-devutils/src/main/java/org/apache/wicket/devutils/diskstore/browser/SessionsProviderModel.java b/wicket-devutils/src/main/java/org/apache/wicket/devutils/diskstore/browser/SessionsProviderModel.java
deleted file mode 100644
index 6638303..0000000
--- a/wicket-devutils/src/main/java/org/apache/wicket/devutils/diskstore/browser/SessionsProviderModel.java
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * 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.devutils.diskstore.browser;
-
-import java.io.File;
-import java.util.ArrayList;
-import java.util.List;
-
-import org.apache.wicket.Application;
-import org.apache.wicket.devutils.diskstore.DebugDiskDataStore;
-import org.apache.wicket.model.LoadableDetachableModel;
-import org.apache.wicket.pageStore.DiskDataStore;
-
-/**
- * A model that collects the session ids from the {@link DiskDataStore} folder
- */
-public class SessionsProviderModel extends LoadableDetachableModel<List<String>>
-{
-
- @Override
- protected List<String> load()
- {
- List<String> sessionIds = new ArrayList<>();
- if (Application.exists())
- {
- DebugDiskDataStore dataStore = DataStoreHelper.getDataStore();
- File appStoreFolder = dataStore.getStoreFolder();
- if (appStoreFolder.isDirectory())
- {
- String[] sessionIdFileNames = appStoreFolder.list();
- if (sessionIdFileNames != null)
- {
- for (String sessionId : sessionIdFileNames)
- {
- sessionIds.add(sessionId);
- }
- }
- }
- }
-
- return sessionIds;
- }
-}
http://git-wip-us.apache.org/repos/asf/wicket/blob/bcf76f51/wicket-devutils/src/main/java/org/apache/wicket/devutils/inspector/EnhancedPageView.java
----------------------------------------------------------------------
diff --git a/wicket-devutils/src/main/java/org/apache/wicket/devutils/inspector/EnhancedPageView.java b/wicket-devutils/src/main/java/org/apache/wicket/devutils/inspector/EnhancedPageView.java
index 50856ed..fef1826 100644
--- a/wicket-devutils/src/main/java/org/apache/wicket/devutils/inspector/EnhancedPageView.java
+++ b/wicket-devutils/src/main/java/org/apache/wicket/devutils/inspector/EnhancedPageView.java
@@ -86,42 +86,13 @@ public final class EnhancedPageView extends GenericPanel<Page>
*
* @param id
* See Component
- * @param page
+ * @param model
* The page to be analyzed
*/
- public EnhancedPageView(String id, Page page)
+ public EnhancedPageView(String id, IModel<Page> model)
{
- this(id, getModelFor(page == null ? null : page.getPageReference()));
- }
-
- private static IModel<Page> getModelFor(final PageReference pageRef)
- {
- return new LoadableDetachableModel<Page>()
- {
- private static final long serialVersionUID = 1L;
-
- @Override
- protected Page load()
- {
- if (pageRef == null)
- return null;
- Page page = pageRef.getPage();
- return page;
- }
- };
- }
-
- /**
- * Constructor.
- *
- * @param id
- * See Component
- * @param pageModel
- * The page to be analyzed
- */
- public EnhancedPageView(String id, IModel<Page> pageModel)
- {
- super(id, pageModel);
+ super(id, model);
+
expandState = new ExpandState();
expandState.expandAll();
showStatefulAndParentsOnly = false;
http://git-wip-us.apache.org/repos/asf/wicket/blob/bcf76f51/wicket-devutils/src/main/java/org/apache/wicket/devutils/inspector/InspectorPage.java
----------------------------------------------------------------------
diff --git a/wicket-devutils/src/main/java/org/apache/wicket/devutils/inspector/InspectorPage.java b/wicket-devutils/src/main/java/org/apache/wicket/devutils/inspector/InspectorPage.java
index 023583d..0ab7837 100644
--- a/wicket-devutils/src/main/java/org/apache/wicket/devutils/inspector/InspectorPage.java
+++ b/wicket-devutils/src/main/java/org/apache/wicket/devutils/inspector/InspectorPage.java
@@ -18,15 +18,15 @@ package org.apache.wicket.devutils.inspector;
import org.apache.wicket.Application;
import org.apache.wicket.Page;
+import org.apache.wicket.PageReference;
import org.apache.wicket.Session;
import org.apache.wicket.devutils.DevUtilsPage;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.html.image.Image;
import org.apache.wicket.markup.html.link.BookmarkablePageLink;
-import org.apache.wicket.page.IManageablePage;
+import org.apache.wicket.model.IModel;
import org.apache.wicket.request.mapper.parameter.PageParameters;
import org.apache.wicket.request.resource.PackageResourceReference;
-import org.apache.wicket.util.string.StringValueConversionException;
/**
@@ -47,23 +47,19 @@ public final class InspectorPage extends DevUtilsPage
*/
public InspectorPage(final PageParameters parameters)
{
+ this(new PageReference(parameters.get("pageId").toInt()));
+ }
+
+ public InspectorPage(PageReference reference)
+ {
add(new ApplicationView("application", Application.get()));
add(new SessionView("session", Session.get()));
- IManageablePage page = null;
- try
- {
- final int pageId = parameters.get("pageId").toInt();
- page = Session.get().getPageManager().getPage(pageId);
- }
- catch (StringValueConversionException e)
- {
- // Ignore
- }
- catch (NullPointerException e)
- {
- // Ignore
- }
- add(new EnhancedPageView("page", (Page)page));
+
+ IModel<Page> page = () -> {
+ return reference.getPage();
+ };
+
+ add(new EnhancedPageView("page", page));
add(new Image("bug", new PackageResourceReference(InspectorPage.class, "bug.png")));
add(new BookmarkablePageLink<>("allsessions", LiveSessionsPage.class));
add(new Label("wicketVersion", getApplication().getFrameworkSettings().getVersion()));
http://git-wip-us.apache.org/repos/asf/wicket/blob/bcf76f51/wicket-examples/src/main/java/org/apache/wicket/examples/frames/BodyFrame.java
----------------------------------------------------------------------
diff --git a/wicket-examples/src/main/java/org/apache/wicket/examples/frames/BodyFrame.java b/wicket-examples/src/main/java/org/apache/wicket/examples/frames/BodyFrame.java
index 3896404..f557a59 100644
--- a/wicket-examples/src/main/java/org/apache/wicket/examples/frames/BodyFrame.java
+++ b/wicket-examples/src/main/java/org/apache/wicket/examples/frames/BodyFrame.java
@@ -16,10 +16,10 @@
*/
package org.apache.wicket.examples.frames;
-import org.apache.wicket.markup.html.WebPage;
-import org.apache.wicket.request.IRequestHandler;
import org.apache.wicket.core.request.handler.PageProvider;
import org.apache.wicket.core.request.handler.RenderPageRequestHandler;
+import org.apache.wicket.markup.html.WebPage;
+import org.apache.wicket.request.IRequestHandler;
/**
@@ -41,7 +41,7 @@ public class BodyFrame extends WebPage
{
// create a new page instance, passing this 'master page' as an argument
LeftFrame leftFrame = new LeftFrame(this);
- getSession().getPageManager().touchPage(leftFrame);
+ getSession().getPageManager().addPage(leftFrame);
// get the url to that page
IRequestHandler leftFrameHandler = new RenderPageRequestHandler(new PageProvider(leftFrame));
// and create a simple component that modifies it's src attribute to
http://git-wip-us.apache.org/repos/asf/wicket/blob/bcf76f51/wicket-examples/src/test/java/org/apache/wicket/examples/StartExamples.java
----------------------------------------------------------------------
diff --git a/wicket-examples/src/test/java/org/apache/wicket/examples/StartExamples.java b/wicket-examples/src/test/java/org/apache/wicket/examples/StartExamples.java
index 18e6c26..9f08961 100644
--- a/wicket-examples/src/test/java/org/apache/wicket/examples/StartExamples.java
+++ b/wicket-examples/src/test/java/org/apache/wicket/examples/StartExamples.java
@@ -16,6 +16,7 @@
*/
package org.apache.wicket.examples;
+import java.io.File;
import java.lang.management.ManagementFactory;
import javax.management.MBeanServer;
@@ -28,6 +29,8 @@ import org.eclipse.jetty.server.SecureRequestCustomizer;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ServerConnector;
import org.eclipse.jetty.server.SslConnectionFactory;
+import org.eclipse.jetty.server.session.DefaultSessionCache;
+import org.eclipse.jetty.server.session.FileSessionDataStore;
import org.eclipse.jetty.util.resource.Resource;
import org.eclipse.jetty.util.ssl.SslContextFactory;
import org.eclipse.jetty.webapp.WebAppContext;
@@ -97,12 +100,18 @@ public class StartExamples
bb.setContextPath("/");
bb.setWar("src/main/webapp");
+ // uncomment next lines if you want to test with session persistence
+// DefaultSessionCache sessionCache = new DefaultSessionCache(bb.getSessionHandler());
+// FileSessionDataStore sessionStore = new FileSessionDataStore();
+// sessionStore.setStoreDir(new File("./jetty-session-data"));
+// sessionCache.setSessionDataStore(sessionStore);
+// bb.getSessionHandler().setSessionCache(sessionCache);
+
ServerContainer serverContainer = WebSocketServerContainerInitializer.configureContext(bb);
serverContainer.addEndpoint(new WicketServerEndpointConfig());
// uncomment next line if you want to test with JSESSIONID encoded in the urls
- // ((AbstractSessionManager)
- // bb.getSessionHandler().getSessionManager()).setUsingCookies(false);
+// ((AbstractSessionManager) bb.getSessionHandler().getSessionManager()).setUsingCookies(false);
server.setHandler(bb);
http://git-wip-us.apache.org/repos/asf/wicket/blob/bcf76f51/wicket-extensions/src/main/java/org/apache/wicket/extensions/ajax/markup/html/modal/ModalWindow.java
----------------------------------------------------------------------
diff --git a/wicket-extensions/src/main/java/org/apache/wicket/extensions/ajax/markup/html/modal/ModalWindow.java b/wicket-extensions/src/main/java/org/apache/wicket/extensions/ajax/markup/html/modal/ModalWindow.java
index a8a70ef..8302650 100644
--- a/wicket-extensions/src/main/java/org/apache/wicket/extensions/ajax/markup/html/modal/ModalWindow.java
+++ b/wicket-extensions/src/main/java/org/apache/wicket/extensions/ajax/markup/html/modal/ModalWindow.java
@@ -16,7 +16,6 @@
*/
package org.apache.wicket.extensions.ajax.markup.html.modal;
-import com.github.openjson.JSONObject;
import org.apache.wicket.Component;
import org.apache.wicket.Page;
import org.apache.wicket.WicketRuntimeException;
@@ -45,6 +44,8 @@ import org.apache.wicket.util.io.IClusterable;
import org.apache.wicket.util.lang.EnumeratedType;
import org.apache.wicket.util.string.AppendingStringBuffer;
+import com.github.openjson.JSONObject;
+
/**
* Modal window component.
* <p>
@@ -1043,7 +1044,7 @@ public class ModalWindow extends Panel
CharSequence pageUrl;
RequestCycle requestCycle = RequestCycle.get();
- page.getSession().getPageManager().touchPage(page);
+ page.getSession().getPageManager().addPage(page);
if (page.isPageStateless())
{
pageUrl = requestCycle.urlFor(page.getClass(), page.getPageParameters());
http://git-wip-us.apache.org/repos/asf/wicket/blob/bcf76f51/wicket-jmx/src/main/java/org/apache/wicket/jmx/StoreSettingsMBean.java
----------------------------------------------------------------------
diff --git a/wicket-jmx/src/main/java/org/apache/wicket/jmx/StoreSettingsMBean.java b/wicket-jmx/src/main/java/org/apache/wicket/jmx/StoreSettingsMBean.java
index 7f40a26..4e18730 100644
--- a/wicket-jmx/src/main/java/org/apache/wicket/jmx/StoreSettingsMBean.java
+++ b/wicket-jmx/src/main/java/org/apache/wicket/jmx/StoreSettingsMBean.java
@@ -16,8 +16,7 @@
*/
package org.apache.wicket.jmx;
-import org.apache.wicket.pageStore.DiskDataStore;
-import org.apache.wicket.pageStore.IDataStore;
+import org.apache.wicket.pageStore.DiskPageStore;
/**
* JMX MBean for Application's StoreSettings
@@ -26,19 +25,13 @@ public interface StoreSettingsMBean
{
/**
- * @return the number of page instances which will be stored in the http session for faster
- * retrieval
- */
- int getInmemoryCacheSize();
-
- /**
- * @return maximum page size. After this size is exceeded, the {@link DiskDataStore} will start
+ * @return maximum page size. After this size is exceeded, the {@link DiskPageStore} will start
* saving the pages at the beginning of file.
*/
long getMaxSizePerSession();
/**
- * @return the location of the folder where {@link DiskDataStore} will store the files with page
+ * @return the location of the folder where {@link DiskPageStore} will store the files with page
* instances per session
*/
String getFileStoreFolder();
http://git-wip-us.apache.org/repos/asf/wicket/blob/bcf76f51/wicket-jmx/src/main/java/org/apache/wicket/jmx/wrapper/StoreSettings.java
----------------------------------------------------------------------
diff --git a/wicket-jmx/src/main/java/org/apache/wicket/jmx/wrapper/StoreSettings.java b/wicket-jmx/src/main/java/org/apache/wicket/jmx/wrapper/StoreSettings.java
index 9a658fd..b40793e 100644
--- a/wicket-jmx/src/main/java/org/apache/wicket/jmx/wrapper/StoreSettings.java
+++ b/wicket-jmx/src/main/java/org/apache/wicket/jmx/wrapper/StoreSettings.java
@@ -37,12 +37,6 @@ public class StoreSettings implements StoreSettingsMBean
}
@Override
- public int getInmemoryCacheSize()
- {
- return application.getStoreSettings().getInmemoryCacheSize();
- }
-
- @Override
public long getMaxSizePerSession()
{
return application.getStoreSettings().getMaxSizePerSession().bytes();
http://git-wip-us.apache.org/repos/asf/wicket/blob/bcf76f51/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/AbstractWebSocketProcessor.java
----------------------------------------------------------------------
diff --git a/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/AbstractWebSocketProcessor.java b/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/AbstractWebSocketProcessor.java
index ca3569d..d3c9d4f 100644
--- a/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/AbstractWebSocketProcessor.java
+++ b/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/AbstractWebSocketProcessor.java
@@ -300,7 +300,7 @@ public abstract class AbstractWebSocketProcessor implements IWebSocketProcessor
{
if (Session.exists())
{
- Session.get().getPageManager().commitRequest();
+ Session.get().getPageManager().detach();
}
}
});
[4/5] wicket git commit: WICKET-6563 new IPageStore implementation
Posted by sv...@apache.org.
http://git-wip-us.apache.org/repos/asf/wicket/blob/bcf76f51/wicket-core/src/main/java/org/apache/wicket/pageStore/AsynchronousPageStore.java
----------------------------------------------------------------------
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 43993ba..3428d02 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
@@ -17,41 +17,43 @@
package org.apache.wicket.pageStore;
import java.io.Serializable;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;
+import org.apache.wicket.MetaDataKey;
+import org.apache.wicket.WicketRuntimeException;
import org.apache.wicket.page.IManageablePage;
import org.apache.wicket.util.lang.Args;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
- * Facade for {@link IPageStore} that does the actual saving in worker thread.
+ * Facade for {@link IPageStore} moving {@link #addPage(IPageContext, IManageablePage)} to a worker thread.
* <p>
- * Creates an {@link Entry} for each double (sessionId, page) and puts it in {@link #entries} queue
- * if there is room. Acts as producer.<br/>
- * Later {@link PageSavingRunnable} reads in blocking manner from {@link #entries} and saves each
- * entry. Acts as consumer.
- * </p>
- * It starts only one instance of {@link PageSavingRunnable} because all we need is to make the page
+ * Creates an {@link PendingAdd} for {@link #addPage(IPageContext, IManageablePage)} and puts ito a {@link #queue}.
+ * Later {@link PageAddingRunnable} reads in blocking manner from {@link #queue} and performs the add.
+ * <p>
+ * It starts only one instance of {@link PageAddingRunnable} because all we need is to make the page
* storing asynchronous. We don't want to write concurrently in the wrapped {@link IPageStore},
* though it may happen in the extreme case when the queue is full. These cases should be avoided.
*
- * Based on AsynchronousDataStore (@author Matej Knopp).
- *
+ * @author Matej Knopp
* @author manuelbarzi
*/
-public class AsynchronousPageStore implements IPageStore
+public class AsynchronousPageStore extends DelegatingPageStore
{
/** Log for reporting. */
private static final Logger log = LoggerFactory.getLogger(AsynchronousPageStore.class);
/**
- * The time to wait when adding an {@link Entry} into the entries. In millis.
+ * The time to wait when adding an {@link PendingAdd} into the entries. In millis.
*/
private static final long OFFER_WAIT = 30L;
@@ -66,20 +68,15 @@ public class AsynchronousPageStore implements IPageStore
private final Thread pageSavingThread;
/**
- * The wrapped {@link IPageStore} that actually stores that pages
- */
- private final IPageStore delegate;
-
- /**
* The queue where the entries which have to be saved are temporary stored
*/
- private final BlockingQueue<Entry> entries;
+ private final BlockingQueue<PendingAdd> queue;
/**
- * A map 'sessionId:::pageId' -> {@link Entry}. Used for fast retrieval of {@link Entry}s which
+ * A map 'sessionId:::pageId' -> {@link PendingAdd}. Used for fast retrieval of {@link PendingAdd}s which
* are not yet stored by the wrapped {@link IPageStore}
*/
- private final ConcurrentMap<String, Entry> entryMap;
+ private final ConcurrentMap<String, PendingAdd> queueMap;
/**
* Construct.
@@ -91,29 +88,18 @@ public class AsynchronousPageStore implements IPageStore
*/
public AsynchronousPageStore(final IPageStore delegate, final int capacity)
{
- this.delegate = Args.notNull(delegate, "delegate");
- entries = new LinkedBlockingQueue<>(capacity);
- entryMap = new ConcurrentHashMap<>();
+ super(delegate);
+
+ queue = new LinkedBlockingQueue<>(capacity);
+ queueMap = new ConcurrentHashMap<>();
- PageSavingRunnable savingRunnable = new PageSavingRunnable(delegate, entries, entryMap);
+ PageAddingRunnable savingRunnable = new PageAddingRunnable(delegate, queue, queueMap);
pageSavingThread = new Thread(savingRunnable, "Wicket-AsyncPageStore-PageSavingThread");
pageSavingThread.setDaemon(true);
pageSavingThread.start();
}
/**
- * Little helper
- *
- * @param sessionId
- * @param pageId
- * @return Entry
- */
- private Entry getEntry(final String sessionId, final int pageId)
- {
- return entryMap.get(getKey(sessionId, pageId));
- }
-
- /**
*
* @param pageId
* @param sessionId
@@ -125,83 +111,198 @@ public class AsynchronousPageStore implements IPageStore
}
/**
- *
- * @param entry
- * @return generated key
+ * A pending asynchronous add in the queue.
+ * <p>
+ * Used as {@link IPageContext} for the call to the delegate {@link IPageStore#addPage(IPageContext, IManageablePage)}.
*/
- private static String getKey(final Entry entry)
- {
- return getKey(entry.sessionId, entry.page.getPageId());
- }
-
- /**
- * The structure used for an entry in the queue
- */
- private static class Entry
+ private static class PendingAdd implements IPageContext
{
+ private final IPageContext context;
+
private final String sessionId;
+
private final IManageablePage page;
- public Entry(final String sessionId, final IManageablePage page)
+ /**
+ * Is this context passed to an asynchronously called {@link IPageStore#addPage(IPageContext, IManageablePage)}.
+ */
+ private boolean asynchronous = false;
+
+ /**
+ * Cache of session attributes which may filled in {@link IPageStore#canBeAsynchronous(IPageContext)},
+ * so these are available asynchronously later on.
+ */
+ private Map<String, Serializable> attributeCache = new HashMap<>();
+
+ public PendingAdd(final IPageContext context, final IManageablePage page)
{
- this.sessionId = Args.notNull(sessionId, "sessionId");
+ this.context = Args.notNull(context, "context");
this.page = Args.notNull(page, "page");
+
+ context.bind();
+ this.sessionId = context.getSessionId();
+ }
+
+ /**
+ *
+ * @param entry
+ * @return generated key
+ */
+ private String getKey()
+ {
+ return AsynchronousPageStore.getKey(sessionId, page.getPageId());
}
@Override
- public int hashCode()
+ public String toString()
{
- final int prime = 31;
- int result = 1;
- result = prime * result + page.getPageId();
- result = prime * result + sessionId.hashCode();
- return result;
+ return "Entry [sessionId=" + sessionId + ", pageId=" + page.getPageId() + "]";
}
+ /**
+ * Prevents access to request when called asynchronously.
+ */
@Override
- public boolean equals(Object obj)
+ public <T> void setRequestData(MetaDataKey<T> key, T value)
{
- if (this == obj)
- return true;
- if (obj == null)
- return false;
- if (getClass() != obj.getClass())
- return false;
- Entry other = (Entry)obj;
- if (page.getPageId() != other.page.getPageId())
- return false;
- if (!sessionId.equals(other.sessionId))
- return false;
- return true;
+ if (asynchronous) {
+ throw new WicketRuntimeException("no request available asynchronuously");
+ }
+
+ context.setRequestData(key, value);
}
+ /**
+ * Prevents access to request when called asynchronously.
+ */
@Override
- public String toString()
+ public <T> T getRequestData(MetaDataKey<T> key)
{
- return "Entry [sessionId=" + sessionId + ", pageId=" + page.getPageId() + "]";
+ if (asynchronous) {
+ throw new WicketRuntimeException("no request available asynchronuously");
+ }
+
+ return context.getRequestData(key);
}
+ /**
+ * Prevents access to request when called asynchronously.
+ * <p>
+ * All values set from {@link IPageStore#canBeAsynchronous(IPageContext)} are kept
+ * for later retrieval.
+ */
+ @Override
+ public <T extends Serializable> void setSessionAttribute(String key, T value)
+ {
+ if (asynchronous) {
+ throw new WicketRuntimeException("no session available asynchronuously");
+ }
+
+ if (value != null) {
+ attributeCache.put(key, value);
+ }
+
+ context.setSessionAttribute(key, value);
+ }
+
+ /**
+ * Prevents access to the session when called asynchronously.
+ * <p>
+ * All values set from {@link IPageStore#canBeAsynchronous(IPageContext)} are still
+ * available.
+ */
+ @SuppressWarnings("unchecked")
+ @Override
+ public <T extends Serializable> T getSessionAttribute(String key)
+ {
+ if (asynchronous) {
+ T value = (T)attributeCache.get(key);
+ if (value != null) {
+ return value;
+ }
+
+ throw new WicketRuntimeException("no session available asynchronuously");
+ }
+
+ T value = context.getSessionAttribute(key);
+ if (value != null) {
+ attributeCache.put(key, value);
+ }
+
+ return value;
+ }
+
+ /**
+ * Prevents access to the session when called asynchronously.
+ */
+ @Override
+ public <T extends Serializable> void setSessionData(MetaDataKey<T> key, T value)
+ {
+ if (asynchronous) {
+ throw new WicketRuntimeException("no session available asynchronuously");
+ }
+
+ context.setSessionData(key, value);
+ }
+
+ /**
+ * Gets data from the session.
+ */
+ @Override
+ public <T extends Serializable> T getSessionData(MetaDataKey<T> key)
+ {
+ return context.getSessionData(key);
+ }
+
+ /**
+ * Prevents access to the session when called asynchronously.
+ * <p>
+ * Has no effect when session is already bound.
+ */
+ @Override
+ public void bind()
+ {
+ if (sessionId != null) {
+ // already bound
+ return;
+ }
+
+ if (asynchronous) {
+ throw new WicketRuntimeException("no session available asynchronuously");
+ }
+
+ context.bind();
+ }
+
+ /**
+ * Get the identifier of the session, maybe <code>null</code> if not bound.
+ */
+ @Override
+ public String getSessionId()
+ {
+ return sessionId;
+ }
}
/**
- * The thread that acts as consumer of {@link Entry}ies
+ * The consumer of {@link PendingAdd}s.
*/
- private static class PageSavingRunnable implements Runnable
+ private static class PageAddingRunnable implements Runnable
{
- private static final Logger log = LoggerFactory.getLogger(PageSavingRunnable.class);
+ private static final Logger log = LoggerFactory.getLogger(PageAddingRunnable.class);
- private final BlockingQueue<Entry> entries;
+ private final BlockingQueue<PendingAdd> entries;
- private final ConcurrentMap<String, Entry> entryMap;
+ private final ConcurrentMap<String, PendingAdd> addQueue;
private final IPageStore delegate;
- private PageSavingRunnable(IPageStore delegate, BlockingQueue<Entry> entries,
- ConcurrentMap<String, Entry> entryMap)
+ private PageAddingRunnable(IPageStore delegate, BlockingQueue<PendingAdd> entries,
+ ConcurrentMap<String, PendingAdd> entryMap)
{
this.delegate = delegate;
this.entries = entries;
- this.entryMap = entryMap;
+ this.addQueue = entryMap;
}
@Override
@@ -209,21 +310,21 @@ public class AsynchronousPageStore implements IPageStore
{
while (!Thread.interrupted())
{
- Entry entry = null;
+ PendingAdd add = null;
try
{
- entry = entries.poll(POLL_WAIT, TimeUnit.MILLISECONDS);
+ add = entries.poll(POLL_WAIT, TimeUnit.MILLISECONDS);
}
catch (InterruptedException e)
{
Thread.currentThread().interrupt();
}
- if (entry != null)
+ if (add != null)
{
- log.debug("Saving asynchronously: {}...", entry);
- delegate.storePage(entry.sessionId, entry.page);
- entryMap.remove(getKey(entry));
+ log.debug("Saving asynchronously: {}...", add);
+ delegate.addPage(add, add.page);
+ addQueue.remove(add.getKey());
}
}
}
@@ -245,102 +346,85 @@ public class AsynchronousPageStore implements IPageStore
}
}
- delegate.destroy();
+ super.destroy();
}
@Override
- public IManageablePage getPage(String sessionId, int pageId)
+ public IManageablePage getPage(IPageContext context, int pageId)
{
- Entry entry = getEntry(sessionId, pageId);
+ PendingAdd entry = queueMap.get(getKey(context.getSessionId(), pageId));
if (entry != null)
{
- log.debug(
- "Returning the page of a non-stored entry with session id '{}' and page id '{}'",
- sessionId, pageId);
+ log.debug("Returning the page of a non-stored entry with page id '{}'", pageId);
return entry.page;
}
- IManageablePage page = delegate.getPage(sessionId, pageId);
+ IManageablePage page = super.getPage(context, pageId);
- log.debug("Returning the page of a stored entry with session id '{}' and page id '{}'",
- sessionId, pageId);
+ log.debug("Returning the page of a stored entry with page id '{}'", pageId);
return page;
}
@Override
- public void removePage(String sessionId, int pageId)
+ public void removePage(IPageContext context, IManageablePage page)
{
- String key = getKey(sessionId, pageId);
+ String key = getKey(context.getSessionId(), page.getPageId());
if (key != null)
{
- Entry entry = entryMap.remove(key);
+ PendingAdd entry = queueMap.remove(key);
if (entry != null)
{
- entries.remove(entry);
+ queue.remove(entry);
}
}
- delegate.removePage(sessionId, pageId);
+ super.removePage(context, page);
}
@Override
- public void storePage(String sessionId, IManageablePage page)
+ public void addPage(IPageContext context, IManageablePage page)
{
- Entry entry = new Entry(sessionId, page);
- String key = getKey(entry);
- entryMap.put(key, entry);
-
- try
- {
- if (entries.offer(entry, OFFER_WAIT, TimeUnit.MILLISECONDS))
+ PendingAdd add = new PendingAdd(context, page);
+ if (getDelegate().canBeAsynchronous(add)) {
+ add.asynchronous = true;
+
+ String key = add.getKey();
+ queueMap.put(key, add);
+ try
{
- log.debug("Offered for storing asynchronously page with id '{}' in session '{}'",
- page.getPageId(), sessionId);
+ if (queue.offer(add, OFFER_WAIT, TimeUnit.MILLISECONDS))
+ {
+ log.debug("Offered for storing asynchronously page with id '{}'", page.getPageId());
+ return;
+ }
+ else
+ {
+ log.debug("Storing synchronously page with id '{}'", page.getPageId());
+ queueMap.remove(key);
+ }
}
- else
+ catch (InterruptedException e)
{
- log.debug("Storing synchronously page with id '{}' in session '{}'",
- page.getPageId(), sessionId);
- entryMap.remove(key);
- delegate.storePage(sessionId, page);
+ log.error(e.getMessage(), e);
+ queueMap.remove(key);
}
}
- catch (InterruptedException e)
- {
- log.error(e.getMessage(), e);
- entryMap.remove(key);
- delegate.storePage(sessionId, page);
- }
- }
-
- @Override
- public void unbind(String sessionId)
- {
- delegate.unbind(sessionId);
- }
-
- @Override
- public Serializable prepareForSerialization(String sessionId, Serializable page)
- {
- return delegate.prepareForSerialization(sessionId, page);
- }
-
- @Override
- public Object restoreAfterSerialization(Serializable serializable)
- {
- return delegate.restoreAfterSerialization(serializable);
+
+ super.addPage(context, page);
}
@Override
- public IManageablePage convertToPage(Object page)
+ public void removeAllPages(IPageContext context)
{
- return delegate.convertToPage(page);
- }
-
- @Override
- public boolean canBeAsynchronous()
- {
- // should not wrap in another AsynchronousPageStore
- return false;
+ Iterator<PendingAdd> iterator = queue.iterator();
+ while (iterator.hasNext()) {
+ PendingAdd add = iterator.next();
+
+ if (add.sessionId.equals(context.getSessionId())) {
+ iterator.remove();
+ }
+ }
+
+ super.removeAllPages(context);
}
-}
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/wicket/blob/bcf76f51/wicket-core/src/main/java/org/apache/wicket/pageStore/DefaultPageContext.java
----------------------------------------------------------------------
diff --git a/wicket-core/src/main/java/org/apache/wicket/pageStore/DefaultPageContext.java b/wicket-core/src/main/java/org/apache/wicket/pageStore/DefaultPageContext.java
new file mode 100644
index 0000000..257f593
--- /dev/null
+++ b/wicket-core/src/main/java/org/apache/wicket/pageStore/DefaultPageContext.java
@@ -0,0 +1,103 @@
+/*
+ * 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.Serializable;
+
+import org.apache.wicket.MetaDataKey;
+import org.apache.wicket.Session;
+import org.apache.wicket.request.cycle.RequestCycle;
+
+/**
+ * Default page context using a {@link Session}.
+ *
+ * @author Juergen Donnerstag
+ * @author svenmeier
+ */
+public class DefaultPageContext implements IPageContext
+{
+ private Session session;
+
+ public DefaultPageContext(Session session) {
+ this.session = Session.get();
+ }
+
+ /**
+ * @see org.apache.wicket.pageStore.IPageContext#bind()
+ */
+ @Override
+ public void bind()
+ {
+ session.bind();
+ }
+
+ /**
+ * @see org.apache.wicket.pageStore.IPageContext#getSessionId()
+ */
+ @Override
+ public String getSessionId()
+ {
+ return session.getId();
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public <T extends Serializable> T getSessionAttribute(String key)
+ {
+ return (T)session.getAttribute(key);
+ }
+
+ @Override
+ public <T extends Serializable> void setSessionAttribute(String key, T value)
+ {
+ session.setAttribute(key, value);
+ }
+
+ @Override
+ public <T extends Serializable> T getSessionData(MetaDataKey<T> key)
+ {
+ return session.getMetaData(key);
+ }
+
+ @Override
+ public <T extends Serializable> void setSessionData(MetaDataKey<T> key, T value)
+ {
+ session.setMetaData(key, value);
+ }
+
+ @Override
+ public <T> T getRequestData(MetaDataKey<T> key)
+ {
+ RequestCycle requestCycle = RequestCycle.get();
+ if (requestCycle == null)
+ {
+ throw new IllegalStateException("Not a request thread.");
+ }
+ return requestCycle.getMetaData(key);
+ }
+
+ @Override
+ public <T> void setRequestData(MetaDataKey<T> key, T value)
+ {
+ RequestCycle requestCycle = RequestCycle.get();
+ if (requestCycle == null)
+ {
+ throw new IllegalStateException("Not a request thread.");
+ }
+ requestCycle.setMetaData(key, value);
+ }
+}
http://git-wip-us.apache.org/repos/asf/wicket/blob/bcf76f51/wicket-core/src/main/java/org/apache/wicket/pageStore/DefaultPageStore.java
----------------------------------------------------------------------
diff --git a/wicket-core/src/main/java/org/apache/wicket/pageStore/DefaultPageStore.java b/wicket-core/src/main/java/org/apache/wicket/pageStore/DefaultPageStore.java
deleted file mode 100644
index f324b85..0000000
--- a/wicket-core/src/main/java/org/apache/wicket/pageStore/DefaultPageStore.java
+++ /dev/null
@@ -1,469 +0,0 @@
-/*
- * 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.Serializable;
-import java.lang.ref.SoftReference;
-import java.util.Iterator;
-import java.util.concurrent.ConcurrentLinkedDeque;
-
-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.Objects;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * The {@link IPageStore} that converts {@link IManageablePage} instances to {@link SerializedPage}s
- * before passing them to the {@link IDataStore} to store them and the same in the opposite
- * direction when loading {@link SerializedPage} from the data store.
- *
- */
-public class DefaultPageStore extends AbstractCachingPageStore<DefaultPageStore.SerializedPage>
-{
- private static final Logger LOG = LoggerFactory.getLogger(DefaultPageStore.class);
-
- /**
- * Construct.
- *
- * @param pageSerializer
- * the {@link ISerializer} that will be used to convert pages from/to byte arrays
- * @param dataStore
- * the {@link IDataStore} that actually stores the pages
- * @param cacheSize
- * the number of pages to cache in memory before passing them to
- * {@link IDataStore#storeData(String, int, byte[])}
- */
- public DefaultPageStore(final ISerializer pageSerializer, final IDataStore dataStore,
- final int cacheSize)
- {
- super(pageSerializer, dataStore, new SerializedPagesCache(cacheSize));
- }
-
- @Override
- public void storePage(final String sessionId, final IManageablePage page)
- {
- SerializedPage serialized = createSerializedPage(sessionId, page);
- if (serialized != null)
- {
- int pageId = page.getPageId();
- pagesCache.storePage(sessionId, pageId, serialized);
- storePageData(sessionId, pageId, serialized.getData());
- }
- }
-
- @Override
- public IManageablePage convertToPage(final Object object)
- {
- if (object == null)
- {
- return null;
- }
- else if (object instanceof IManageablePage)
- {
- return (IManageablePage)object;
- }
- else if (object instanceof SerializedPage)
- {
- SerializedPage page = (SerializedPage)object;
- byte data[] = page.getData();
- if (data == null)
- {
- data = getPageData(page.getSessionId(), page.getPageId());
- }
- if (data != null)
- {
- return deserializePage(data);
- }
- return null;
- }
-
- String type = object.getClass().getName();
- throw new IllegalArgumentException("Unknown object type " + type);
- }
-
- /**
- * Reloads the {@link SerializedPage} from the backing {@link IDataStore} if the
- * {@link SerializedPage#data} is stripped earlier
- *
- * @param serializedPage
- * the {@link SerializedPage} with empty {@link SerializedPage#data} slot
- * @return the fully functional {@link SerializedPage}
- */
- private SerializedPage restoreStrippedSerializedPage(final SerializedPage serializedPage)
- {
- SerializedPage result = pagesCache.getPage(serializedPage.getSessionId(),
- serializedPage.getPageId());
- if (result != null)
- {
- return result;
- }
-
- byte data[] = getPageData(serializedPage.getSessionId(), serializedPage.getPageId());
- return new SerializedPage(serializedPage.getSessionId(), serializedPage.getPageId(), data);
- }
-
- @Override
- public Serializable prepareForSerialization(final String sessionId, final Serializable page)
- {
- if (dataStore.isReplicated())
- {
- return null;
- }
-
- SerializedPage result = null;
-
- if (page instanceof IManageablePage)
- {
- IManageablePage _page = (IManageablePage)page;
- result = pagesCache.getPage(sessionId, _page.getPageId());
- if (result == null)
- {
- result = createSerializedPage(sessionId, _page);
- if (result != null)
- {
- pagesCache.storePage(sessionId, _page.getPageId(), result);
- }
- }
- }
- else if (page instanceof SerializedPage)
- {
- SerializedPage _page = (SerializedPage)page;
- if (_page.getData() == null)
- {
- result = restoreStrippedSerializedPage(_page);
- }
- else
- {
- result = _page;
- }
- }
-
- if (result != null)
- {
- return result;
- }
- return page;
- }
-
- /**
- *
- * @return Always true for this implementation
- */
- protected boolean storeAfterSessionReplication()
- {
- return true;
- }
-
- @Override
- public Object restoreAfterSerialization(final Serializable serializable)
- {
- if (serializable == null)
- {
- return null;
- }
- else if (!storeAfterSessionReplication() || serializable instanceof IManageablePage)
- {
- return serializable;
- }
- else if (serializable instanceof SerializedPage)
- {
- SerializedPage page = (SerializedPage)serializable;
- if (page.getData() != null)
- {
- storePageData(page.getSessionId(), page.getPageId(), page.getData());
- return new SerializedPage(page.getSessionId(), page.getPageId(), null);
- }
- return page;
- }
-
- String type = serializable.getClass().getName();
- throw new IllegalArgumentException("Unknown object type " + type);
- }
-
- /**
- * A representation of {@link IManageablePage} that knows additionally the id of the http
- * session in which this {@link IManageablePage} instance is used. The {@link #sessionId} and
- * {@link #pageId} are used for better clustering in the {@link IDataStore} structures.
- */
- protected static class SerializedPage implements Serializable
- {
- private static final long serialVersionUID = 1L;
-
- /**
- * The id of the serialized {@link IManageablePage}
- */
- private final int pageId;
-
- /**
- * The id of the http session in which the serialized {@link IManageablePage} is used.
- */
- private final String sessionId;
-
- /**
- * The serialized {@link IManageablePage}
- */
- private final byte[] data;
-
- public SerializedPage(String sessionId, int pageId, byte[] data)
- {
- this.pageId = pageId;
- this.sessionId = sessionId;
- this.data = data;
- }
-
- public byte[] getData()
- {
- return data;
- }
-
- public int getPageId()
- {
- return pageId;
- }
-
- public String getSessionId()
- {
- return sessionId;
- }
-
- @Override
- public boolean equals(Object obj)
- {
- if (this == obj)
- {
- return true;
- }
- if ((obj instanceof SerializedPage) == false)
- {
- return false;
- }
- SerializedPage rhs = (SerializedPage)obj;
- return Objects.equal(getPageId(), rhs.getPageId()) &&
- Objects.equal(getSessionId(), rhs.getSessionId());
- }
-
- @Override
- public int hashCode()
- {
- return Objects.hashCode(getPageId(), getSessionId());
- }
- }
-
- /**
- *
- * @param sessionId
- * @param page
- * @return the serialized page information
- */
- protected SerializedPage createSerializedPage(final String sessionId, final IManageablePage page)
- {
- Args.notNull(sessionId, "sessionId");
- Args.notNull(page, "page");
-
- SerializedPage serializedPage = null;
-
- byte[] data = serializePage(page);
-
- if (data != null)
- {
- serializedPage = new SerializedPage(sessionId, page.getPageId(), data);
- }
- else if (LOG.isWarnEnabled())
- {
- LOG.warn("Page {} cannot be serialized. See previous logs for possible reasons.", page);
- }
- return serializedPage;
- }
-
- /**
- * Cache that stores serialized pages. This is important to make sure that a single page is not
- * serialized twice or more when not necessary.
- * <p>
- * For example a page is serialized during request, but it might be also later serialized on
- * session replication. The purpose of this cache is to make sure that the data obtained from
- * first serialization is reused on second serialization.
- *
- * @author Matej Knopp
- */
- static class SerializedPagesCache implements SecondLevelPageCache<String, Integer, SerializedPage>
- {
- private final int maxSize;
-
- private final ConcurrentLinkedDeque<SoftReference<SerializedPage>> cache;
-
- /**
- * Constructor.
- *
- * @param maxSize
- * The maximum number of entries to cache
- */
- public SerializedPagesCache(final int maxSize)
- {
- this.maxSize = maxSize;
- cache = new ConcurrentLinkedDeque<>();
- }
-
- /**
- *
- * @param sessionId
- * @param pageId
- * @return the removed {@link SerializedPage} or <code>null</code> - otherwise
- */
- @Override
- public SerializedPage removePage(final String sessionId, final Integer pageId)
- {
- if (maxSize > 0)
- {
- Args.notNull(sessionId, "sessionId");
- Args.notNull(pageId, "pageId");
-
- SerializedPage sample = new SerializedPage(sessionId, pageId, null);
-
- for (Iterator<SoftReference<SerializedPage>> i = cache.iterator(); i.hasNext();)
- {
- SoftReference<SerializedPage> ref = i.next();
- SerializedPage entry = ref.get();
- if (sample.equals(entry))
- {
- i.remove();
- return entry;
- }
- }
- }
- return null;
- }
-
- /**
- * Removes all {@link SerializedPage}s for the session with <code>sessionId</code> from the
- * cache.
- *
- * @param sessionId
- */
- @Override
- public void removePages(String sessionId)
- {
- if (maxSize > 0)
- {
- Args.notNull(sessionId, "sessionId");
-
- for (Iterator<SoftReference<SerializedPage>> i = cache.iterator(); i.hasNext();)
- {
- SoftReference<SerializedPage> ref = i.next();
- SerializedPage entry = ref.get();
- if (entry != null && entry.getSessionId().equals(sessionId))
- {
- i.remove();
- }
- }
- }
- }
-
- /**
- * Returns a {@link SerializedPage} by looking it up by <code>sessionId</code> and
- * <code>pageId</code>. If there is a match then it is <i>touched</i>, i.e. it is moved at
- * the top of the cache.
- *
- * @param sessionId
- * @param pageId
- * @return the found serialized page or <code>null</code> when not found
- */
- @Override
- public SerializedPage getPage(String sessionId, Integer pageId)
- {
- SerializedPage result = null;
- if (maxSize > 0)
- {
- Args.notNull(sessionId, "sessionId");
- Args.notNull(pageId, "pageId");
-
- SerializedPage sample = new SerializedPage(sessionId, pageId, null);
-
- for (Iterator<SoftReference<SerializedPage>> i = cache.iterator(); i.hasNext();)
- {
- SoftReference<SerializedPage> ref = i.next();
- SerializedPage entry = ref.get();
- if (sample.equals(entry))
- {
- i.remove();
- result = entry;
- break;
- }
- }
-
- if (result != null)
- {
- // move to top
- internalStore(result);
- }
- }
- return result;
- }
-
- /**
- * Store the serialized page in cache
- *
- * @param page
- * the data to serialize (page id, session id, bytes)
- */
- @Override
- public void storePage(String sessionId, Integer pageId, SerializedPage page)
- {
- if (maxSize > 0)
- {
- Args.notNull(sessionId, "sessionId");
- Args.notNull(pageId, "pageId");
- Args.notNull(page, "page");
-
- for (Iterator<SoftReference<SerializedPage>> i = cache.iterator(); i.hasNext();)
- {
- SoftReference<SerializedPage> r = i.next();
- SerializedPage entry = r.get();
- if (entry != null && entry.equals(page))
- {
- i.remove();
- break;
- }
- }
-
- internalStore(page);
- }
- }
-
- private void internalStore(SerializedPage page)
- {
- cache.push(new SoftReference<>(page));
- while (cache.size() > maxSize)
- {
- cache.pollLast();
- }
- }
-
- @Override
- public void destroy()
- {
- cache.clear();
- }
- }
-
- @Override
- public boolean canBeAsynchronous()
- {
- return true;
- }
-}
http://git-wip-us.apache.org/repos/asf/wicket/blob/bcf76f51/wicket-core/src/main/java/org/apache/wicket/pageStore/DelegatingPageStore.java
----------------------------------------------------------------------
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
new file mode 100644
index 0000000..304988a
--- /dev/null
+++ b/wicket-core/src/main/java/org/apache/wicket/pageStore/DelegatingPageStore.java
@@ -0,0 +1,67 @@
+/*
+ * 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;
+
+/**
+ * An {@link IPageStore} that delegates to another storage.
+ */
+public abstract class DelegatingPageStore implements IPageStore
+{
+ private IPageStore delegate;
+
+ protected DelegatingPageStore(IPageStore delegate) {
+ this.delegate = Args.notNull(delegate, "delegate");
+ }
+
+ public IPageStore getDelegate()
+ {
+ return delegate;
+ }
+
+ @Override
+ public void addPage(IPageContext context, IManageablePage page) {
+ delegate.addPage(context, page);
+ }
+
+ @Override
+ public void removePage(IPageContext context, IManageablePage page) {
+ delegate.removePage(context, page);
+ }
+
+ @Override
+ public void removeAllPages(IPageContext context) {
+ delegate.removeAllPages(context);
+ }
+
+ @Override
+ public IManageablePage getPage(IPageContext context, int id) {
+ return delegate.getPage(context, id);
+ }
+
+ @Override
+ public void detach(IPageContext context) {
+ delegate.detach(context);
+ }
+
+ @Override
+ public void destroy() {
+ delegate.destroy();
+ }
+}
http://git-wip-us.apache.org/repos/asf/wicket/blob/bcf76f51/wicket-core/src/main/java/org/apache/wicket/pageStore/DiskDataStore.java
----------------------------------------------------------------------
diff --git a/wicket-core/src/main/java/org/apache/wicket/pageStore/DiskDataStore.java b/wicket-core/src/main/java/org/apache/wicket/pageStore/DiskDataStore.java
deleted file mode 100644
index 2dd95e4..0000000
--- a/wicket-core/src/main/java/org/apache/wicket/pageStore/DiskDataStore.java
+++ /dev/null
@@ -1,589 +0,0 @@
-/*
- * 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.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.ObjectInputStream;
-import java.io.ObjectOutputStream;
-import java.io.OutputStream;
-import java.io.RandomAccessFile;
-import java.io.Serializable;
-import java.nio.ByteBuffer;
-import java.nio.channels.FileChannel;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.ConcurrentMap;
-
-import org.apache.wicket.WicketRuntimeException;
-import org.apache.wicket.pageStore.PageWindowManager.PageWindow;
-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.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * A data store implementation which stores the data on disk (in a file system)
- */
-public class DiskDataStore implements IDataStore
-{
- private static final Logger log = LoggerFactory.getLogger(DiskDataStore.class);
-
- private static final String INDEX_FILE_NAME = "DiskDataStoreIndex";
-
- private final String applicationName;
-
- private final Bytes maxSizePerPageSession;
-
- private final File fileStoreFolder;
-
- private final ConcurrentMap<String, SessionEntry> sessionEntryMap;
-
- /**
- * Construct.
- *
- * @param applicationName
- * @param fileStoreFolder
- * @param maxSizePerSession
- */
- public DiskDataStore(final String applicationName, final File fileStoreFolder,
- final Bytes maxSizePerSession)
- {
- this.applicationName = applicationName;
- this.fileStoreFolder = fileStoreFolder;
- maxSizePerPageSession = Args.notNull(maxSizePerSession, "maxSizePerSession");
- sessionEntryMap = new ConcurrentHashMap<>();
-
- try
- {
- if (this.fileStoreFolder.exists() || this.fileStoreFolder.mkdirs())
- {
- loadIndex();
- }
- else
- {
- log.warn("Cannot create file store folder for some reason.");
- }
- }
- catch (SecurityException e)
- {
- throw new WicketRuntimeException(
- "SecurityException occurred while creating DiskDataStore. Consider using a non-disk based IDataStore implementation. "
- + "See org.apache.wicket.Application.setPageManagerProvider(IPageManagerProvider)",
- e);
- }
- }
-
- /**
- * @see org.apache.wicket.pageStore.IDataStore#destroy()
- */
- @Override
- public void destroy()
- {
- log.debug("Destroying...");
- saveIndex();
- log.debug("Destroyed.");
- }
-
- /**
- * @see org.apache.wicket.pageStore.IDataStore#getData(java.lang.String, int)
- */
- @Override
- public byte[] getData(final String sessionId, final int id)
- {
- byte[] pageData = null;
- SessionEntry sessionEntry = getSessionEntry(sessionId, false);
- if (sessionEntry != null)
- {
- pageData = sessionEntry.loadPage(id);
- }
-
- if (log.isDebugEnabled())
- {
- log.debug("Returning data{} for page with id '{}' in session with id '{}'",
- pageData != null ? "" : "(null)", id, sessionId);
- }
- return pageData;
- }
-
- /**
- * @see org.apache.wicket.pageStore.IDataStore#isReplicated()
- */
- @Override
- public boolean isReplicated()
- {
- return false;
- }
-
- /**
- * @see org.apache.wicket.pageStore.IDataStore#removeData(java.lang.String, int)
- */
- @Override
- public void removeData(final String sessionId, final int id)
- {
- SessionEntry sessionEntry = getSessionEntry(sessionId, false);
- if (sessionEntry != null)
- {
- if (log.isDebugEnabled())
- {
- log.debug("Removing data for page with id '{}' in session with id '{}'", id, sessionId);
- }
- sessionEntry.removePage(id);
- }
- }
-
- /**
- * @see org.apache.wicket.pageStore.IDataStore#removeData(java.lang.String)
- */
- @Override
- public void removeData(final String sessionId)
- {
- SessionEntry sessionEntry = getSessionEntry(sessionId, false);
- if (sessionEntry != null)
- {
- log.debug("Removing data for pages in session with id '{}'", sessionId);
- synchronized (sessionEntry)
- {
- sessionEntryMap.remove(sessionEntry.sessionId);
- sessionEntry.unbind();
- }
- }
- }
-
- /**
- * @see org.apache.wicket.pageStore.IDataStore#storeData(java.lang.String, int, byte[])
- */
- @Override
- public void storeData(final String sessionId, final int id, final byte[] data)
- {
- SessionEntry sessionEntry = getSessionEntry(sessionId, true);
- if (sessionEntry != null)
- {
- log.debug("Storing data for page with id '{}' in session with id '{}'", id, sessionId);
- sessionEntry.savePage(id, data);
- }
- }
-
- /**
- *
- * @param sessionId
- * @param create
- * @return the session entry
- */
- protected SessionEntry getSessionEntry(final String sessionId, final boolean create)
- {
- if (!create)
- {
- return sessionEntryMap.get(sessionId);
- }
-
- SessionEntry entry = new SessionEntry(this, sessionId);
- SessionEntry existing = sessionEntryMap.putIfAbsent(sessionId, entry);
- return existing != null ? existing : entry;
- }
-
- /**
- * Load the index
- */
- @SuppressWarnings("unchecked")
- private void loadIndex()
- {
- File storeFolder = getStoreFolder();
- File index = new File(storeFolder, INDEX_FILE_NAME);
- if (index.exists() && index.length() > 0)
- {
- try
- {
- InputStream stream = new FileInputStream(index);
- ObjectInputStream ois = new ObjectInputStream(stream);
- try
- {
- Map<String, SessionEntry> map = (Map<String, SessionEntry>)ois.readObject();
- sessionEntryMap.clear();
- sessionEntryMap.putAll(map);
-
- for (Entry<String, SessionEntry> entry : sessionEntryMap.entrySet())
- {
- // initialize the diskPageStore reference
- SessionEntry sessionEntry = entry.getValue();
- sessionEntry.diskDataStore = this;
- }
- } finally {
- stream.close();
- ois.close();
- }
- }
- catch (Exception e)
- {
- log.error("Couldn't load DiskDataStore index from file " + index + ".", e);
- }
- }
- Files.remove(index);
- }
-
- /**
- *
- */
- private void saveIndex()
- {
- File storeFolder = getStoreFolder();
- if (storeFolder.exists())
- {
- File index = new File(storeFolder, INDEX_FILE_NAME);
- Files.remove(index);
- try
- {
- OutputStream stream = new FileOutputStream(index);
- ObjectOutputStream oos = new ObjectOutputStream(stream);
- try
- {
- Map<String, SessionEntry> map = new HashMap<>(sessionEntryMap.size());
- for (Entry<String, SessionEntry> e : sessionEntryMap.entrySet())
- {
- if (e.getValue().unbound == false)
- {
- map.put(e.getKey(), e.getValue());
- }
- }
- oos.writeObject(map);
- } finally {
- stream.close();
- oos.close();
- }
- }
- catch (Exception e)
- {
- log.error("Couldn't write DiskDataStore index to file " + index + ".", e);
- }
- }
- }
-
- /**
- *
- */
- protected static class SessionEntry implements Serializable
- {
- private static final long serialVersionUID = 1L;
-
- private final String sessionId;
- private transient DiskDataStore diskDataStore;
- private String fileName;
- private PageWindowManager manager;
- private boolean unbound = false;
-
- protected SessionEntry(DiskDataStore diskDataStore, String sessionId)
- {
- this.diskDataStore = diskDataStore;
- this.sessionId = sessionId;
- }
-
- public PageWindowManager getManager()
- {
- if (manager == null)
- {
- manager = new PageWindowManager(diskDataStore.maxSizePerPageSession.bytes());
- }
- return manager;
- }
-
- private String getFileName()
- {
- if (fileName == null)
- {
- fileName = diskDataStore.getSessionFileName(sessionId, true);
- }
- return fileName;
- }
-
- /**
- * @return session id
- */
- public String getSessionId()
- {
- return sessionId;
- }
-
- /**
- * Saves the serialized page to appropriate file.
- *
- * @param pageId
- * @param data
- */
- public synchronized void savePage(int pageId, byte data[])
- {
- if (unbound)
- {
- return;
- }
- // only save page that has some data
- if (data != null)
- {
- // allocate window for page
- PageWindow window = getManager().createPageWindow(pageId, data.length);
-
- FileChannel channel = getFileChannel(true);
- if (channel != null)
- {
- try
- {
- // write the content
- channel.write(ByteBuffer.wrap(data), window.getFilePartOffset());
- }
- catch (IOException e)
- {
- log.error("Error writing to a channel " + channel, e);
- }
- finally
- {
- IOUtils.closeQuietly(channel);
- }
- }
- else
- {
- log.warn(
- "Cannot save page with id '{}' because the data file cannot be opened.",
- pageId);
- }
- }
- }
-
- /**
- * Removes the page from pagemap file.
- *
- * @param pageId
- */
- public synchronized void removePage(int pageId)
- {
- if (unbound)
- {
- return;
- }
- getManager().removePage(pageId);
- }
-
- /**
- * Loads the part of pagemap file specified by the given PageWindow.
- *
- * @param window
- * @return serialized page data
- */
- public byte[] loadPage(PageWindow window)
- {
- byte[] result = null;
- FileChannel channel = getFileChannel(false);
- if (channel != null)
- {
- ByteBuffer buffer = ByteBuffer.allocate(window.getFilePartSize());
- try
- {
- channel.read(buffer, window.getFilePartOffset());
- if (buffer.hasArray())
- {
- result = buffer.array();
- }
- }
- catch (IOException e)
- {
- log.error("Error reading from file channel " + channel, e);
- }
- finally
- {
- IOUtils.closeQuietly(channel);
- }
- }
- return result;
- }
-
- private FileChannel getFileChannel(boolean create)
- {
- FileChannel channel = null;
- File file = new File(getFileName());
- if (create || file.exists())
- {
- String mode = create ? "rw" : "r";
- try
- {
- RandomAccessFile randomAccessFile = new RandomAccessFile(file, mode);
- channel = randomAccessFile.getChannel();
- }
- catch (FileNotFoundException fnfx)
- {
- // can happen if the file is locked. WICKET-4176
- log.error(fnfx.getMessage(), fnfx);
- }
- }
- return channel;
- }
-
- /**
- * Loads the specified page data.
- *
- * @param id
- * @return page data or null if the page is no longer in pagemap file
- */
- public synchronized byte[] loadPage(int id)
- {
- if (unbound)
- {
- return null;
- }
- byte[] result = null;
- PageWindow window = getManager().getPageWindow(id);
- if (window != null)
- {
- result = loadPage(window);
- }
- return result;
- }
-
- /**
- * Deletes all files for this session.
- */
- public synchronized void unbind()
- {
- File sessionFolder = diskDataStore.getSessionFolder(sessionId, false);
- if (sessionFolder.exists())
- {
- Files.removeFolder(sessionFolder);
- cleanup(sessionFolder);
- }
- unbound = true;
- }
-
- /**
- * deletes the sessionFolder's parent and grandparent, if (and only if) they are empty.
- *
- * @see #createPathFrom(String sessionId)
- * @param sessionFolder
- * must not be null
- */
- private void cleanup(final File sessionFolder)
- {
- File high = sessionFolder.getParentFile();
- if (high != null && high.list().length == 0)
- {
- if (Files.removeFolder(high))
- {
- File low = high.getParentFile();
- if (low != null && low.list().length == 0)
- {
- Files.removeFolder(low);
- }
- }
- }
- }
- }
-
- /**
- * Returns the file name for specified session. If the session folder (folder that contains the
- * file) does not exist and createSessionFolder is true, the folder will be created.
- *
- * @param sessionId
- * @param createSessionFolder
- * @return file name for pagemap
- */
- private String getSessionFileName(String sessionId, boolean createSessionFolder)
- {
- File sessionFolder = getSessionFolder(sessionId, createSessionFolder);
- return new File(sessionFolder, "data").getAbsolutePath();
- }
-
- /**
- * This folder contains sub-folders named as the session id for which they hold the data.
- *
- * @return the folder where the pages are stored
- */
- protected File getStoreFolder()
- {
- return new File(fileStoreFolder, applicationName + "-filestore");
- }
-
- /**
- * Returns the folder for the specified sessions. If the folder doesn't exist and the create
- * flag is set, the folder will be created.
- *
- * @param sessionId
- * @param create
- * @return folder used to store session data
- */
- protected File getSessionFolder(String sessionId, final boolean create)
- {
- File storeFolder = getStoreFolder();
-
- sessionId = sessionId.replace('*', '_');
- sessionId = sessionId.replace('/', '_');
- sessionId = sessionId.replace(':', '_');
-
- sessionId = createPathFrom(sessionId);
-
- File sessionFolder = new File(storeFolder, sessionId);
- if (create && sessionFolder.exists() == false)
- {
- Files.mkdirs(sessionFolder);
- }
- return sessionFolder;
- }
-
- /**
- * creates a three-level path from the sessionId in the format 0000/0000/<sessionId>. The two
- * prefixing directories are created from the sessionId's hashcode and thus, should be well
- * distributed.
- *
- * This is used to avoid problems with Filesystems allowing no more than 32k entries in a
- * directory.
- *
- * Note that the prefix paths are created from Integers and not guaranteed to be four chars
- * long.
- *
- * @param sessionId
- * must not be null
- * @return path in the form 0000/0000/sessionId
- */
- private String createPathFrom(final String sessionId)
- {
- int sessionIdHashCode = sessionId.hashCode();
- if (sessionIdHashCode == Integer.MIN_VALUE) {
- // Math.abs(MIN_VALUE) == MIN_VALUE, so avoid it
- sessionIdHashCode += 1;
- }
- int hash = Math.abs(sessionIdHashCode);
- String low = String.valueOf(hash % 9973);
- String high = String.valueOf((hash / 9973) % 9973);
- StringBuilder bs = new StringBuilder(sessionId.length() + 10);
- bs.append(low);
- bs.append(File.separator);
- bs.append(high);
- bs.append(File.separator);
- bs.append(sessionId);
-
- return bs.toString();
- }
-
- @Override
- public boolean canBeAsynchronous()
- {
- return true;
- }
-}
http://git-wip-us.apache.org/repos/asf/wicket/blob/bcf76f51/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
new file mode 100644
index 0000000..b810218
--- /dev/null
+++ b/wicket-core/src/main/java/org/apache/wicket/pageStore/DiskPageStore.java
@@ -0,0 +1,719 @@
+/*
+ * 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.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.OutputStream;
+import java.io.RandomAccessFile;
+import java.io.Serializable;
+import java.nio.ByteBuffer;
+import java.nio.channels.FileChannel;
+import java.util.ArrayList;
+import java.util.Collections;
+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.PageWindowManager;
+import org.apache.wicket.pageStore.disk.PageWindowManager.FileWindow;
+import org.apache.wicket.serialize.ISerializer;
+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.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * A storage of pages on disk.
+ */
+public class DiskPageStore implements IPersistentPageStore
+{
+ private static final Logger log = LoggerFactory.getLogger(DiskPageStore.class);
+
+ private static final String KEY = "wicket:DiskPageStore";
+
+ private static final String INDEX_FILE_NAME = "DiskDataStoreIndex";
+
+ /**
+ * 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;
+
+ private final File fileStoreFolder;
+
+ private final ConcurrentMap<String, DiskData> diskDatas;
+
+ public DiskPageStore(String applicationName, ISerializer serializer, File fileStoreFolder, Bytes maxSizePerSession)
+ {
+ this.applicationName = Args.notNull(applicationName, "applicationName");
+ this.serializer = Args.notNull(serializer, "serializer");
+ this.maxSizePerSession = Args.notNull(maxSizePerSession, "maxSizePerSession");
+ this.fileStoreFolder = Args.notNull(fileStoreFolder, "fileStoreFolder");
+
+ this.diskDatas = new ConcurrentHashMap<>();
+
+ try
+ {
+ if (this.fileStoreFolder.exists() || this.fileStoreFolder.mkdirs())
+ {
+ loadIndex();
+ }
+ else
+ {
+ log.warn("Cannot create file store folder for some reason.");
+ }
+ }
+ catch (SecurityException e)
+ {
+ throw new WicketRuntimeException(
+ "SecurityException occurred while creating DiskDataStore. Consider using a non-disk based IDataStore implementation. "
+ + "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);
+ }
+
+ @Override
+ public void destroy()
+ {
+ log.debug("Destroying...");
+ saveIndex();
+
+ DISK_STORES.remove(applicationName);
+
+ log.debug("Destroyed.");
+ }
+
+ @Override
+ public boolean canBeAsynchronous(IPageContext context)
+ {
+ // session attribute must be added here *before* any asynchronous calls
+ // when session is no longer available
+ getSessionAttribute(context, true);
+
+ return true;
+ }
+
+ @Override
+ public IManageablePage getPage(IPageContext context, int id)
+ {
+ IManageablePage page = null;
+
+ DiskData diskData = getDiskData(context, false);
+ if (diskData != null)
+ {
+ byte[] data = diskData.loadPage(id);
+ if (data != null) {
+ page = (IManageablePage)serializer.deserialize(data);
+ }
+ }
+
+ if (log.isDebugEnabled())
+ {
+ log.debug("Returning page with id '{}' in session with id '{}'", page != null ? "" : "(null)", id, context.getSessionId());
+ }
+
+ return page;
+ }
+
+ @Override
+ public void removePage(IPageContext context, IManageablePage page)
+ {
+ DiskData diskData = getDiskData(context, false);
+ if (diskData != null)
+ {
+ if (log.isDebugEnabled())
+ {
+ log.debug("Removing page with id '{}' in session with id '{}'", page.getPageId(), context.getSessionId());
+ }
+ diskData.removeData(page.getPageId());
+ }
+ }
+
+ @Override
+ public void removeAllPages(IPageContext context)
+ {
+ DiskData diskData = getDiskData(context, false);
+ if (diskData != null)
+ {
+ removeDiskData(diskData);
+ }
+ }
+
+ protected void removeDiskData(DiskData diskData) {
+ synchronized (diskDatas)
+ {
+ diskDatas.remove(diskData.sessionIdentifier);
+ diskData.unbind();
+ }
+ }
+
+ @Override
+ public void addPage(IPageContext context, IManageablePage page)
+ {
+ DiskData diskData = getDiskData(context, true);
+ if (diskData != null)
+ {
+ log.debug("Storing data for page with id '{}' in session with id '{}'", page.getPageId(), context.getSessionId());
+
+ byte[] data = serializer.serialize(page);
+
+ diskData.savePage(page.getPageId(), page.getClass(), data);
+ }
+ }
+
+ /**
+ *
+ * @param context
+ * @param create
+ * @return the session entry
+ */
+ protected DiskData getDiskData(final IPageContext context, final boolean create)
+ {
+ SessionAttribute attribute = getSessionAttribute(context, create);
+
+ if (!create && attribute == null) {
+ return null;
+ }
+
+ return getDiskData(attribute.identifier, create);
+ }
+
+ protected DiskData getDiskData(String sessionIdentifier, boolean create) {
+ if (!create)
+ {
+ return diskDatas.get(sessionIdentifier);
+ }
+
+ DiskData data = new DiskData(this, sessionIdentifier);
+ DiskData existing = diskDatas.putIfAbsent(sessionIdentifier, data);
+ return existing != null ? existing : data;
+ }
+
+ protected SessionAttribute getSessionAttribute(IPageContext context, boolean create)
+ {
+ context.bind();
+
+ SessionAttribute attribute = context.getSessionAttribute(KEY);
+ if (attribute == null && create) {
+ attribute = new SessionAttribute(applicationName, context.getSessionId());
+ context.setSessionAttribute(KEY, attribute);
+ }
+ return attribute;
+ }
+
+ /**
+ * Load the index
+ */
+ @SuppressWarnings("unchecked")
+ private void loadIndex()
+ {
+ File storeFolder = getStoreFolder();
+
+ File index = new File(storeFolder, INDEX_FILE_NAME);
+ if (index.exists() && index.length() > 0)
+ {
+ try
+ {
+ InputStream stream = new FileInputStream(index);
+ ObjectInputStream ois = new ObjectInputStream(stream);
+ try
+ {
+ diskDatas.clear();
+
+ for (DiskData diskData : (List<DiskData>)ois.readObject()) {
+ diskData.pageStore = this;
+ diskDatas.put(diskData.sessionIdentifier, diskData);
+ }
+ } finally {
+ stream.close();
+ ois.close();
+ }
+ }
+ catch (Exception e)
+ {
+ log.error("Couldn't load DiskDataStore index from file " + index + ".", e);
+ }
+ }
+ Files.remove(index);
+ }
+
+ /**
+ *
+ */
+ private void saveIndex()
+ {
+ File storeFolder = getStoreFolder();
+ if (storeFolder.exists())
+ {
+ File index = new File(storeFolder, INDEX_FILE_NAME);
+ Files.remove(index);
+ try
+ {
+ OutputStream stream = new FileOutputStream(index);
+ ObjectOutputStream oos = new ObjectOutputStream(stream);
+ try
+ {
+ List<DiskData> list = new ArrayList<>(diskDatas.size());
+ for (DiskData diskData : diskDatas.values())
+ {
+ if (diskData.sessionIdentifier != null)
+ {
+ list.add(diskData);
+ }
+ }
+ oos.writeObject(list);
+ } finally {
+ stream.close();
+ oos.close();
+ }
+ }
+ catch (Exception e)
+ {
+ log.error("Couldn't write DiskDataStore index to file " + index + ".", e);
+ }
+ }
+ }
+
+ @Override
+ public Set<String> getSessionIdentifiers()
+ {
+ return Collections.unmodifiableSet(diskDatas.keySet());
+ }
+
+ /**
+ *
+ * @param session key
+ * @return a list of the last N page windows
+ */
+ @Override
+ public List<IPersistedPage> getPersistentPages(String sessionIdentifier)
+ {
+ List<IPersistedPage> pages = new ArrayList<>();
+
+ DiskData diskData = getDiskData(sessionIdentifier, false);
+ if (diskData != null)
+ {
+ PageWindowManager windowManager = diskData.getManager();
+
+ pages.addAll(windowManager.getFileWindows());
+ }
+ return pages;
+ }
+
+ @Override
+ public String getSessionIdentifier(IPageContext context)
+ {
+ SessionAttribute sessionAttribute = getSessionAttribute(context, true);
+
+ return sessionAttribute.identifier;
+ }
+
+ @Override
+ public Bytes getTotalSize()
+ {
+ long size = 0;
+
+ synchronized (diskDatas)
+ {
+ for (DiskData diskData : diskDatas.values()) {
+ size = size + diskData.size();
+ }
+ }
+
+ return Bytes.bytes(size);
+ }
+
+ /**
+ * Data held on disk.
+ */
+ protected static class DiskData implements Serializable
+ {
+ private static final long serialVersionUID = 1L;
+
+ private transient DiskPageStore pageStore;
+
+ private transient String fileName;
+
+ private String sessionIdentifier;
+
+ private PageWindowManager manager;
+
+ protected DiskData(DiskPageStore pageStore, String sessionIdentifier)
+ {
+ this.pageStore = pageStore;
+
+ this.sessionIdentifier = sessionIdentifier;
+ }
+
+ public long size()
+ {
+ return manager.getTotalSize();
+ }
+
+ public PageWindowManager getManager()
+ {
+ if (manager == null)
+ {
+ manager = new PageWindowManager(pageStore.maxSizePerSession.bytes());
+ }
+ return manager;
+ }
+
+ private String getFileName()
+ {
+ if (fileName == null)
+ {
+ fileName = pageStore.getSessionFileName(sessionIdentifier, true);
+ }
+ return fileName;
+ }
+
+ /**
+ * @return session id
+ */
+ public String getKey()
+ {
+ return sessionIdentifier;
+ }
+
+ /**
+ * Saves the serialized page to appropriate file.
+ *
+ * @param pageId
+ * @param clazz
+ * @param data
+ */
+ public synchronized void savePage(int pageId, Class<? extends IManageablePage> clazz, byte data[])
+ {
+ if (sessionIdentifier == null)
+ {
+ return;
+ }
+
+ // only save page that has some data
+ if (data != null)
+ {
+ // allocate window for page
+ FileWindow window = getManager().createPageWindow(pageId, clazz, data.length);
+
+ FileChannel channel = getFileChannel(true);
+ if (channel != null)
+ {
+ try
+ {
+ // write the content
+ channel.write(ByteBuffer.wrap(data), window.getFilePartOffset());
+ }
+ catch (IOException e)
+ {
+ log.error("Error writing to a channel " + channel, e);
+ }
+ finally
+ {
+ IOUtils.closeQuietly(channel);
+ }
+ }
+ else
+ {
+ log.warn(
+ "Cannot save page with id '{}' because the data file cannot be opened.",
+ pageId);
+ }
+ }
+ }
+
+ /**
+ * Removes the page from pagemap file.
+ *
+ * @param pageId
+ */
+ public synchronized void removeData(int pageId)
+ {
+ if (sessionIdentifier == null)
+ {
+ return;
+ }
+
+ getManager().removePage(pageId);
+ }
+
+ /**
+ * Loads the part of pagemap file specified by the given PageWindow.
+ *
+ * @param window
+ * @return serialized page data
+ */
+ public byte[] loadData(FileWindow window)
+ {
+ byte[] result = null;
+ FileChannel channel = getFileChannel(false);
+ if (channel != null)
+ {
+ ByteBuffer buffer = ByteBuffer.allocate(window.getFilePartSize());
+ try
+ {
+ channel.read(buffer, window.getFilePartOffset());
+ if (buffer.hasArray())
+ {
+ result = buffer.array();
+ }
+ }
+ catch (IOException e)
+ {
+ log.error("Error reading from file channel " + channel, e);
+ }
+ finally
+ {
+ IOUtils.closeQuietly(channel);
+ }
+ }
+ return result;
+ }
+
+ private FileChannel getFileChannel(boolean create)
+ {
+ FileChannel channel = null;
+ File file = new File(getFileName());
+ if (create || file.exists())
+ {
+ String mode = create ? "rw" : "r";
+ try
+ {
+ RandomAccessFile randomAccessFile = new RandomAccessFile(file, mode);
+ channel = randomAccessFile.getChannel();
+ }
+ catch (FileNotFoundException fnfx)
+ {
+ // can happen if the file is locked. WICKET-4176
+ log.error(fnfx.getMessage(), fnfx);
+ }
+ }
+ return channel;
+ }
+
+ /**
+ * Loads the specified page data.
+ *
+ * @param id
+ * @return page data or null if the page is no longer in pagemap file
+ */
+ public synchronized byte[] loadPage(int id)
+ {
+ if (sessionIdentifier == null)
+ {
+ return null;
+ }
+
+ FileWindow window = getManager().getPageWindow(id);
+ if (window == null)
+ {
+ return null;
+ }
+
+ return loadData(window);
+ }
+
+ /**
+ * Deletes all files for this session.
+ */
+ public synchronized void unbind()
+ {
+ File sessionFolder = pageStore.getSessionFolder(sessionIdentifier, false);
+ if (sessionFolder.exists())
+ {
+ Files.removeFolder(sessionFolder);
+ cleanup(sessionFolder);
+ }
+
+ sessionIdentifier = null;
+ }
+
+ /**
+ * deletes the sessionFolder's parent and grandparent, if (and only if) they are empty.
+ *
+ * @see #createPathFrom(String sessionId)
+ * @param sessionFolder
+ * must not be null
+ */
+ private void cleanup(final File sessionFolder)
+ {
+ File high = sessionFolder.getParentFile();
+ if (high != null && high.list().length == 0)
+ {
+ if (Files.removeFolder(high))
+ {
+ File low = high.getParentFile();
+ if (low != null && low.list().length == 0)
+ {
+ Files.removeFolder(low);
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Returns the file name for specified session. If the session folder (folder that contains the
+ * file) does not exist and createSessionFolder is true, the folder will be created.
+ *
+ * @param sessionIdentifier
+ * @param createSessionFolder
+ * @return file name for pagemap
+ */
+ private String getSessionFileName(String sessionIdentifier, boolean createSessionFolder)
+ {
+ File sessionFolder = getSessionFolder(sessionIdentifier, createSessionFolder);
+ return new File(sessionFolder, "data").getAbsolutePath();
+ }
+
+ /**
+ * This folder contains sub-folders named as the session id for which they hold the data.
+ *
+ * @return the folder where the pages are stored
+ */
+ protected File getStoreFolder()
+ {
+ return new File(fileStoreFolder, applicationName + "-filestore");
+ }
+
+ /**
+ * Returns the folder for the specified sessions. If the folder doesn't exist and the create
+ * flag is set, the folder will be created.
+ *
+ * @param sessionIdentifier
+ * @param create
+ * @return folder used to store session data
+ */
+ protected File getSessionFolder(String sessionIdentifier, final boolean create)
+ {
+ File storeFolder = getStoreFolder();
+
+ sessionIdentifier = sessionIdentifier.replace('*', '_');
+ sessionIdentifier = sessionIdentifier.replace('/', '_');
+ sessionIdentifier = sessionIdentifier.replace(':', '_');
+
+ sessionIdentifier = createPathFrom(sessionIdentifier);
+
+ File sessionFolder = new File(storeFolder, sessionIdentifier);
+ if (create && sessionFolder.exists() == false)
+ {
+ Files.mkdirs(sessionFolder);
+ }
+ return sessionFolder;
+ }
+
+ /**
+ * creates a three-level path from the sessionId in the format 0000/0000/<sessionId>. The two
+ * prefixing directories are created from the sessionId's hashcode and thus, should be well
+ * distributed.
+ *
+ * This is used to avoid problems with Filesystems allowing no more than 32k entries in a
+ * directory.
+ *
+ * Note that the prefix paths are created from Integers and not guaranteed to be four chars
+ * long.
+ *
+ * @param sessionId
+ * must not be null
+ * @return path in the form 0000/0000/sessionId
+ */
+ private String createPathFrom(final String sessionId)
+ {
+ int sessionIdHashCode = sessionId.hashCode();
+ if (sessionIdHashCode == Integer.MIN_VALUE) {
+ // Math.abs(MIN_VALUE) == MIN_VALUE, so avoid it
+ sessionIdHashCode += 1;
+ }
+ int hash = Math.abs(sessionIdHashCode);
+ String low = String.valueOf(hash % 9973);
+ String high = String.valueOf((hash / 9973) % 9973);
+ StringBuilder bs = new StringBuilder(sessionId.length() + 10);
+ bs.append(low);
+ bs.append(File.separator);
+ bs.append(high);
+ bs.append(File.separator);
+ bs.append(sessionId);
+
+ return bs.toString();
+ }
+
+ /**
+ * 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
http://git-wip-us.apache.org/repos/asf/wicket/blob/bcf76f51/wicket-core/src/main/java/org/apache/wicket/pageStore/GroupingPageStore.java
----------------------------------------------------------------------
diff --git a/wicket-core/src/main/java/org/apache/wicket/pageStore/GroupingPageStore.java b/wicket-core/src/main/java/org/apache/wicket/pageStore/GroupingPageStore.java
new file mode 100644
index 0000000..1771763
--- /dev/null
+++ b/wicket-core/src/main/java/org/apache/wicket/pageStore/GroupingPageStore.java
@@ -0,0 +1,289 @@
+/*
+ * 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.Serializable;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.LinkedHashSet;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.wicket.MetaDataEntry;
+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.util.string.Strings;
+
+/**
+ * An {@link IPageStore} that groups pages.
+ *
+ * @see #getGroup(IManageablePage)
+ */
+public abstract class GroupingPageStore extends DelegatingPageStore
+{
+
+ private static final String DEFAULT_GROUP = "default";
+
+ private static final MetaDataKey<SessionData> KEY = new MetaDataKey<SessionData>()
+ {
+ private static final long serialVersionUID = 1L;
+ };
+
+ private int maxGroups;
+
+ /**
+ * Is a group of a page stable.
+ */
+ private boolean stableGroups = false;
+
+ /**
+ * @param delegate
+ * store to delegate to
+ * @param maxGroups
+ * maximum groups to keep
+ */
+ public GroupingPageStore(IPageStore delegate, int maxGroups)
+ {
+ super(delegate);
+
+ this.maxGroups = maxGroups;
+ }
+
+ /**
+ * Indicate that groups are stable, i.e. the group of a page never changes.
+ */
+ public GroupingPageStore withStableGroups()
+ {
+ stableGroups = true;
+
+ return this;
+ }
+
+ /**
+ * Get the group of a page, default is <code>"default"</code>
+ *
+ * @return group of page, must not be empty
+ */
+ protected String getGroup(IManageablePage page)
+ {
+ return DEFAULT_GROUP;
+ }
+
+ private String getGroupInternal(IManageablePage page)
+ {
+ String group = getGroup(page);
+
+ if (Strings.isEmpty(group))
+ {
+ throw new WicketRuntimeException("group must not be empy");
+ }
+
+ return group;
+ }
+
+ @Override
+ public void addPage(IPageContext context, IManageablePage page)
+ {
+ SessionData sessionData = getSessionData(context);
+
+ sessionData.addPage(context, page, getGroupInternal(page), maxGroups, stableGroups, getDelegate());
+ }
+
+ @Override
+ public void removePage(IPageContext context, IManageablePage page)
+ {
+ SessionData sessionData = getSessionData(context);
+
+ sessionData.removePage(context, page, getDelegate());
+ }
+
+ @Override
+ public void removeAllPages(IPageContext context)
+ {
+ SessionData sessionData = getSessionData(context);
+
+ sessionData.removeAllPages(context, getDelegate());
+ }
+
+ @Override
+ public IManageablePage getPage(IPageContext context, int id)
+ {
+ SessionData sessionData = getSessionData(context);
+
+ return sessionData.getPage(context, id, getDelegate());
+ }
+
+ private SessionData getSessionData(IPageContext context)
+ {
+ SessionData data = context.getSessionData(KEY);
+ if (data == null)
+ {
+ context.bind();
+ data = new SessionData();
+
+ context.setSessionData(KEY, data);
+ }
+
+ return data;
+ }
+
+ /**
+ * Data kept in the {@link Session}.
+ */
+ static class SessionData implements Serializable
+ {
+ Set<String> groups = new LinkedHashSet<>();
+
+ private Map<String, MetaDataEntry<?>[]> metaData = new HashMap<>();
+
+ public synchronized <T> void setMetaData(String group, MetaDataKey<T> key, T value)
+ {
+ metaData.put(group, key.set(metaData.get(group), value));
+ }
+
+ public synchronized <T> T getMetaData(String group, MetaDataKey<T> key)
+ {
+ return key.get(metaData.get(group));
+ }
+
+ public synchronized void addPage(IPageContext context, IManageablePage page, String group, int maxGroups, boolean stableGroups, IPageStore delegate)
+ {
+ if (stableGroups == false)
+ {
+ // group might have changed, so remove page first from all groups
+ for (String other : groups)
+ {
+ delegate.removePage(new GroupContext(context, this, other), page);
+ }
+ }
+
+ groups.add(group);
+ delegate.addPage(new GroupContext(context, this, group), page);
+
+ Iterator<String> iterator = groups.iterator();
+ int size = groups.size();
+ while (size > maxGroups)
+ {
+ String other = iterator.next();
+ iterator.remove();
+ size--;
+
+ delegate.removeAllPages(new GroupContext(context, this, other));
+ }
+ }
+
+ public IManageablePage getPage(IPageContext context, int id, IPageStore delegate)
+ {
+ for (String group : groups)
+ {
+ IManageablePage page = delegate.getPage(new GroupContext(context, this, group), id);
+ if (page != null)
+ {
+ return page;
+ }
+ }
+ return null;
+ }
+
+ public synchronized void removePage(IPageContext context, IManageablePage page, IPageStore delegate)
+ {
+ for (String group : groups)
+ {
+ delegate.removePage(new GroupContext(context, this, group), page);
+ }
+ }
+
+ public synchronized void removeAllPages(IPageContext context, IPageStore delegate)
+ {
+ for (String group : groups)
+ {
+ delegate.removeAllPages(new GroupContext(context, this, group));
+ }
+ }
+ }
+
+ /**
+ * Context passed to the delegate store to group data and attributes.
+ */
+ static class GroupContext implements IPageContext
+ {
+
+ private final IPageContext context;
+
+ private final SessionData sessionData;
+
+ private final String group;
+
+ public GroupContext(IPageContext context, SessionData sessionData, String group)
+ {
+ this.context = context;
+ this.sessionData = sessionData;
+ this.group = group;
+ }
+
+ @Override
+ public String getSessionId()
+ {
+ return context.getSessionId() + "_" + group;
+ }
+
+ @Override
+ public <T extends Serializable> void setSessionData(MetaDataKey<T> key, T value)
+ {
+ sessionData.setMetaData(group, key, value);
+ }
+
+ @Override
+ public <T extends Serializable> T getSessionData(MetaDataKey<T> key)
+ {
+ return sessionData.getMetaData(group, key);
+ }
+
+ @Override
+ public <T extends Serializable> void setSessionAttribute(String key, T value)
+ {
+ context.setSessionAttribute(key + "_" + group, value);
+ }
+
+ @Override
+ public <T extends Serializable> T getSessionAttribute(String key)
+ {
+ return context.getSessionAttribute(key + "_" + group);
+ }
+
+ @Override
+ public <T> void setRequestData(MetaDataKey<T> key, T data)
+ {
+ throw new WicketRuntimeException("no request available for group");
+ }
+
+ @Override
+ public <T> T getRequestData(MetaDataKey<T> key)
+ {
+ throw new WicketRuntimeException("no request available for group");
+ }
+
+
+ @Override
+ public void bind()
+ {
+ context.bind();
+ }
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/wicket/blob/bcf76f51/wicket-core/src/main/java/org/apache/wicket/pageStore/IDataStore.java
----------------------------------------------------------------------
diff --git a/wicket-core/src/main/java/org/apache/wicket/pageStore/IDataStore.java b/wicket-core/src/main/java/org/apache/wicket/pageStore/IDataStore.java
deleted file mode 100644
index b59176a..0000000
--- a/wicket-core/src/main/java/org/apache/wicket/pageStore/IDataStore.java
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * 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;
-
-/**
- * Data stores are used to persist (read & write) Wicket page data to a persistent store like e.g.
- * files or databases.
- *
- * @see IPageStore
- */
-public interface IDataStore
-{
- /**
- * Get data associated with the session id and page id.
- *
- * @param sessionId
- * Session ID
- * @param id
- * Page ID
- * @return All the page data persisted
- */
- byte[] getData(String sessionId, int id);
-
- /**
- * Remove all persisted data related to the session id and page id
- *
- * @param sessionId
- * Session ID
- * @param id
- * Page ID
- */
- void removeData(String sessionId, int id);
-
- /**
- * Remove all page data for the session id
- *
- * @param sessionId
- * Session ID
- */
- void removeData(String sessionId);
-
- /**
- * Store the page data
- *
- * @param sessionId
- * Session ID
- * @param id
- * Page ID
- * @param data
- * Page data
- */
- void storeData(String sessionId, int id, byte[] data);
-
- /**
- * Properly close the data store and possibly open resource handles
- */
- void destroy();
-
- /**
- *
- * @return whether the data store is replicated
- */
- boolean isReplicated();
-
- /**
- * @return whether the implementation can be wrapped in {@link AsynchronousDataStore}
- */
- boolean canBeAsynchronous();
-}
http://git-wip-us.apache.org/repos/asf/wicket/blob/bcf76f51/wicket-core/src/main/java/org/apache/wicket/pageStore/IPageContext.java
----------------------------------------------------------------------
diff --git a/wicket-core/src/main/java/org/apache/wicket/pageStore/IPageContext.java b/wicket-core/src/main/java/org/apache/wicket/pageStore/IPageContext.java
new file mode 100644
index 0000000..5b9fcfb
--- /dev/null
+++ b/wicket-core/src/main/java/org/apache/wicket/pageStore/IPageContext.java
@@ -0,0 +1,102 @@
+/*
+ * 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.Serializable;
+
+import org.apache.wicket.MetaDataKey;
+import org.apache.wicket.page.IManageablePage;
+
+/**
+ * Context of a {@link IManageablePage} when it is store in a {@link IPageStore}, decoupling it from
+ * request cycle and session.
+ *
+ * @author Matej Knopp
+ * @author svenmeier
+ */
+public interface IPageContext
+{
+ /**
+ * Set data into the current request.
+ *
+ * @param key
+ * key
+ * @param value
+ * value
+ */
+ <T> void setRequestData(MetaDataKey<T> key, T value);
+
+ /**
+ * Get data from the current request.
+ *
+ * @param key
+ * key
+ * @return value
+ */
+ <T> T getRequestData(MetaDataKey<T> key);
+
+ /**
+ * Set an attribute in the session.
+ *
+ * @param key
+ * key
+ * @param value
+ * value
+ */
+ <T extends Serializable> void setSessionAttribute(String key, T value);
+
+ /**
+ * Get an attribute from the session.
+ *
+ * @param key
+ * key
+ * @param value
+ * value
+ */
+ <T extends Serializable> T getSessionAttribute(String key);
+
+ /**
+ * Set data into the session.
+ *
+ * @param key
+ * key
+ * @param value
+ * value
+ */
+ <T extends Serializable> void setSessionData(MetaDataKey<T> key, T value);
+
+ /**
+ * Get data from the session.
+ *
+ * @param key
+ * key
+ * @return value
+ */
+ <T extends Serializable> T getSessionData(MetaDataKey<T> key);
+
+ /**
+ * Bind the current session. This make a temporary session become persistent across requests.
+ */
+ void bind();
+
+ /**
+ * Get the identifier of the session.
+ *
+ * @return session id
+ */
+ String getSessionId();
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/wicket/blob/bcf76f51/wicket-core/src/main/java/org/apache/wicket/pageStore/IPageStore.java
----------------------------------------------------------------------
diff --git a/wicket-core/src/main/java/org/apache/wicket/pageStore/IPageStore.java b/wicket-core/src/main/java/org/apache/wicket/pageStore/IPageStore.java
index ed1b9d3..8860b33 100644
--- a/wicket-core/src/main/java/org/apache/wicket/pageStore/IPageStore.java
+++ b/wicket-core/src/main/java/org/apache/wicket/pageStore/IPageStore.java
@@ -16,96 +16,79 @@
*/
package org.apache.wicket.pageStore;
-import java.io.Serializable;
-
import org.apache.wicket.page.IManageablePage;
/**
- * {@link IPageStore} role is to mediate the storing and loading of pages done by {@link IDataStore}
- * s. {@link IPageStore} may pre-process the pages before passing them to
- * {@link IDataStore#storeData(String, int, byte[])} and to post-process them after
- * {@link IDataStore#getData(String, int)}.
- *
- * @see IDataStore
+ * A store of pages
*/
public interface IPageStore
{
/**
- * Destroy the store.
- */
- void destroy();
-
- /**
- * Restores a page from the persistent layer.
+ * This method must be called before any attempt to call
+ * {@link #addPage(IPageContext, IManageablePage)} asynchronously, as done by
+ * {@link AsynchronousPageStore}.
*
- * @param sessionId
- * The session of the page that must be removed
- * @param pageId
- * The id of the page.
- * @return The page
+ * @return whether {@link #addPage(IPageContext, IManageablePage)} may be called asynchronously,
+ * default is <code>false</code>
*/
- IManageablePage getPage(String sessionId, int pageId);
+ default boolean canBeAsynchronous(IPageContext context)
+ {
+ return false;
+ }
/**
- * Removes a page from the persistent layer.
+ * Stores the page-
*
- * @param sessionId
- * The session of the page that must be removed
- * @param pageId
- * The id of the page.
+ * @param context
+ * the context of the page
+ * @param id
+ * the id of the page.
*/
- void removePage(String sessionId, int pageId);
+ void addPage(IPageContext context, IManageablePage page);
/**
- * Stores the page to a persistent layer. The page should be stored under the id and the version
- * number.
+ * Removes a page from storage.
*
- * @param sessionId
- * The session of the page that must be removed
- * @param page
- * The page to store
+ * @param context
+ * the context of the page
+ * @param id
+ * the id of the page.
*/
- void storePage(String sessionId, IManageablePage page);
+ void removePage(IPageContext context, IManageablePage page);
/**
- * The page store should cleanup all the pages for that sessionid.
+ * All pages should be removed from storage for the given context.
*
- * @param sessionId
- * The session of the page that must be removed
+ * @param context
+ * the context of the pages
*/
- void unbind(String sessionId);
+ void removeAllPages(IPageContext context);
/**
- * Process the page before the it gets serialized. The page can be either real page instance or
- * object returned by {@link #restoreAfterSerialization(Serializable)}.
+ * Restores a page from storage.
*
- * @param sessionId
- * The session of the page that must be removed
- * @param page
- * @return The Page itself or a SerializedContainer for that page
+ * @param context
+ * the context of the page
+ * @param id
+ * the id of the page.
+ * @return the page
*/
- Serializable prepareForSerialization(String sessionId, Serializable page);
+ IManageablePage getPage(IPageContext context, int id);
/**
- * This method should restore the serialized page to intermediate object that can be converted
- * to real page instance using {@link #convertToPage(Object)}.
+ * Detach from the current context.
*
- * @param serializable
- * @return Page
+ * @param context
+ * the context of the pages
*/
- Object restoreAfterSerialization(Serializable serializable);
+ default void detach(IPageContext context)
+ {
+ }
/**
- * Converts a page representation to an instance of {@link IManageablePage}
- *
- * @param page
- * some kind of page representation
- * @return page
- */
- IManageablePage convertToPage(Object page);
-
- /**
- * @return whether the implementation can be wrapped in {@link AsynchronousPageStore}
+ * Destroy the store.
*/
- boolean canBeAsynchronous();
+ default void destroy()
+ {
+ }
}
[5/5] wicket git commit: WICKET-6563 new IPageStore implementation
Posted by sv...@apache.org.
WICKET-6563 new IPageStore implementation
Project: http://git-wip-us.apache.org/repos/asf/wicket/repo
Commit: http://git-wip-us.apache.org/repos/asf/wicket/commit/bcf76f51
Tree: http://git-wip-us.apache.org/repos/asf/wicket/tree/bcf76f51
Diff: http://git-wip-us.apache.org/repos/asf/wicket/diff/bcf76f51
Branch: refs/heads/WICKET-6563
Commit: bcf76f517310ac5d27a2092595c3a925c3973067
Parents: 175734d
Author: Sven Meier <sv...@apache.org>
Authored: Mon Jun 25 17:19:41 2018 +0200
Committer: Sven Meier <sv...@apache.org>
Committed: Mon Jul 2 23:14:42 2018 +0200
----------------------------------------------------------------------
.../java/org/apache/wicket/Application.java | 30 +-
.../wicket/DefaultPageManagerProvider.java | 132 ++--
.../org/apache/wicket/IPageManagerProvider.java | 5 +-
.../src/main/java/org/apache/wicket/Page.java | 10 +-
.../main/java/org/apache/wicket/Session.java | 7 +-
.../core/request/handler/PageProvider.java | 1 -
.../handler/RenderPageRequestHandler.java | 2 +-
.../org/apache/wicket/mock/MockApplication.java | 2 +-
.../org/apache/wicket/mock/MockPageManager.java | 56 +-
.../org/apache/wicket/mock/MockPageStore.java | 60 ++
.../apache/wicket/page/AbstractPageManager.java | 121 ----
.../wicket/page/DefaultPageManagerContext.java | 101 ---
.../org/apache/wicket/page/IPageManager.java | 80 +--
.../apache/wicket/page/IPageManagerContext.java | 66 --
.../wicket/page/PageAccessSynchronizer.java | 42 +-
.../org/apache/wicket/page/PageManager.java | 88 +++
.../wicket/page/PageManagerDecorator.java | 100 ---
.../apache/wicket/page/PageStoreManager.java | 507 -------------
.../org/apache/wicket/page/RequestAdapter.java | 206 ------
.../pageStore/AbstractCachingPageStore.java | 105 ---
.../wicket/pageStore/AbstractPageStore.java | 154 ----
.../wicket/pageStore/AsynchronousDataStore.java | 353 ---------
.../wicket/pageStore/AsynchronousPageStore.java | 378 ++++++----
.../wicket/pageStore/DefaultPageContext.java | 103 +++
.../wicket/pageStore/DefaultPageStore.java | 469 ------------
.../wicket/pageStore/DelegatingPageStore.java | 67 ++
.../apache/wicket/pageStore/DiskDataStore.java | 589 ---------------
.../apache/wicket/pageStore/DiskPageStore.java | 719 +++++++++++++++++++
.../wicket/pageStore/GroupingPageStore.java | 289 ++++++++
.../org/apache/wicket/pageStore/IDataStore.java | 83 ---
.../apache/wicket/pageStore/IPageContext.java | 102 +++
.../org/apache/wicket/pageStore/IPageStore.java | 103 ++-
.../apache/wicket/pageStore/IPersistedPage.java | 44 ++
.../wicket/pageStore/IPersistentPageStore.java | 51 ++
.../wicket/pageStore/InMemoryPageStore.java | 352 +++++++++
.../wicket/pageStore/InSessionPageStore.java | 268 +++++++
.../apache/wicket/pageStore/NoopPageStore.java | 53 ++
.../wicket/pageStore/PageWindowManager.java | 506 -------------
.../wicket/pageStore/PerSessionPageStore.java | 332 ---------
.../wicket/pageStore/RequestPageStore.java | 159 ++++
.../wicket/pageStore/SecondLevelPageCache.java | 42 --
.../pageStore/disk/PageWindowManager.java | 493 +++++++++++++
.../pageStore/memory/HttpSessionDataStore.java | 186 -----
.../memory/IDataStoreEvictionStrategy.java | 35 -
.../memory/MemorySizeEvictionStrategy.java | 64 --
.../memory/PageNumberEvictionStrategy.java | 62 --
.../wicket/pageStore/memory/PageTable.java | 128 ----
.../pageStore/memory/PageTableCleaner.java | 46 --
.../apache/wicket/settings/StoreSettings.java | 26 -
.../wicket/util/tester/BaseWicketTester.java | 8 +-
.../core/request/mapper/TestMapperContext.java | 47 +-
.../DontStoreNotRenderedPageTestCase.java | 23 +-
.../html/TransparentWebMarkupContainerTest.java | 8 +-
.../wicket/page/PageAccessSynchronizerTest.java | 2 +-
.../wicket/page/PersistentPageManagerTest.java | 75 +-
.../persistent/disk/PageWindowManagerTest.java | 301 --------
.../wicket/pageStore/AbstractPageStoreTest.java | 61 +-
.../pageStore/AsynchronousDataStoreTest.java | 37 +-
.../pageStore/AsynchronousPageStoreTest.java | 135 ++--
.../wicket/pageStore/DefaultPageStoreTest.java | 31 -
.../wicket/pageStore/DiskDataStoreTest.java | 151 ++--
.../wicket/pageStore/DummyPageContext.java | 103 +++
.../wicket/pageStore/GroupingPageStoreTest.java | 112 +++
.../wicket/pageStore/InMemoryPageStoreTest.java | 31 +
.../pageStore/InSessionPageStoreTest.java | 32 +
.../apache/wicket/pageStore/NoopDataStore.java | 61 --
.../pageStore/PerSessionPageStoreTest.java | 53 --
.../pageStore/disk/PageWindowManagerTest.java | 303 ++++++++
.../memory/DummyPageManagerContext.java | 66 --
.../memory/HttpSessionDataStoreTest.java | 112 ---
.../memory/MemorySizeEvictionStrategyTest.java | 65 --
.../memory/PageNumberEvictionStrategyTest.java | 63 --
.../wicket/pageStore/memory/PageTableTest.java | 58 --
.../request/handler/PageIdPoliticTest.java | 25 +-
.../request/handler/PageProviderTest.java | 20 +-
.../wicket/versioning/InMemoryPageStore.java | 126 ----
.../wicket/versioning/PageVersioningTest.java | 28 +-
.../devutils/debugbar/DebugBarInitializer.java | 2 +-
.../devutils/debugbar/InspectorDebugPanel.java | 20 +-
.../devutils/debugbar/PageSizeDebugPanel.java | 104 ---
.../devutils/debugbar/PageStoreDebugPanel.java | 84 +++
.../devutils/debugbar/StandardDebugPanel.java | 4 +-
.../devutils/diskstore/DebugDiskDataStore.java | 100 ---
.../diskstore/DebugPageManagerProvider.java | 63 --
.../diskstore/DiskStoreBrowserPage.html | 31 -
.../diskstore/DiskStoreBrowserPage.java | 51 --
.../devutils/diskstore/PageStorePage.html | 31 +
.../devutils/diskstore/PageStorePage.java | 68 ++
.../diskstore/browser/BrowserPanel.html | 9 +-
.../diskstore/browser/BrowserPanel.java | 115 ++-
.../diskstore/browser/BrowserTable.java | 47 --
.../diskstore/browser/DataStoreHelper.java | 43 --
.../diskstore/browser/PageWindowColumn.java | 80 ---
.../browser/PageWindowDescription.java | 57 --
.../diskstore/browser/PageWindowProvider.java | 108 ---
.../browser/PersistedPagesProvider.java | 130 ++++
.../browser/SessionIdentifiersModel.java | 59 ++
.../browser/SessionsProviderModel.java | 57 --
.../devutils/inspector/EnhancedPageView.java | 37 +-
.../devutils/inspector/InspectorPage.java | 30 +-
.../wicket/examples/frames/BodyFrame.java | 6 +-
.../apache/wicket/examples/StartExamples.java | 13 +-
.../ajax/markup/html/modal/ModalWindow.java | 5 +-
.../apache/wicket/jmx/StoreSettingsMBean.java | 13 +-
.../wicket/jmx/wrapper/StoreSettings.java | 6 -
.../ws/api/AbstractWebSocketProcessor.java | 2 +-
106 files changed, 4761 insertions(+), 6728 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/wicket/blob/bcf76f51/wicket-core/src/main/java/org/apache/wicket/Application.java
----------------------------------------------------------------------
diff --git a/wicket-core/src/main/java/org/apache/wicket/Application.java b/wicket-core/src/main/java/org/apache/wicket/Application.java
index 9415afa..64bf7ac 100644
--- a/wicket-core/src/main/java/org/apache/wicket/Application.java
+++ b/wicket-core/src/main/java/org/apache/wicket/Application.java
@@ -55,10 +55,9 @@ import org.apache.wicket.markup.parser.filter.WicketMessageTagHandler;
import org.apache.wicket.markup.resolver.HtmlHeaderResolver;
import org.apache.wicket.markup.resolver.WicketContainerResolver;
import org.apache.wicket.markup.resolver.WicketMessageResolver;
-import org.apache.wicket.page.DefaultPageManagerContext;
import org.apache.wicket.page.IPageManager;
-import org.apache.wicket.page.IPageManagerContext;
-import org.apache.wicket.pageStore.IDataStore;
+import org.apache.wicket.pageStore.DefaultPageContext;
+import org.apache.wicket.pageStore.IPageContext;
import org.apache.wicket.pageStore.IPageStore;
import org.apache.wicket.protocol.http.IRequestLogger;
import org.apache.wicket.protocol.http.RequestLogger;
@@ -1355,11 +1354,6 @@ public abstract class Application implements UnboundListener, IEventSink
}
/**
- * Context for PageManager to interact with rest of Wicket
- */
- private final IPageManagerContext pageManagerContext = new DefaultPageManagerContext();
-
- /**
* Returns an unsynchronized version of page manager
*
* @return the page manager
@@ -1372,22 +1366,13 @@ public abstract class Application implements UnboundListener, IEventSink
{
if (pageManager == null)
{
- pageManager = pageManagerProvider.apply(getPageManagerContext());
+ pageManager = pageManagerProvider.get();
}
}
}
return pageManager;
}
- /**
- *
- * @return the page manager context
- */
- protected IPageManagerContext getPageManagerContext()
- {
- return pageManagerContext;
- }
-
// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
@@ -1545,7 +1530,7 @@ public abstract class Application implements UnboundListener, IEventSink
{
session = newSession(requestCycle.getRequest(), requestCycle.getResponse());
ThreadContext.setSession(session);
- internalGetPageManager().newSessionCreated();
+ internalGetPageManager().removeAllPages();
sessionListeners.onCreated(session);
}
else
@@ -1592,10 +1577,15 @@ public abstract class Application implements UnboundListener, IEventSink
@Override
public void onDetach(final RequestCycle requestCycle)
{
+ IPageManager pageManager;
+
if (Session.exists())
{
- Session.get().getPageManager().commitRequest();
+ pageManager = Session.get().getPageManager();
+ } else {
+ pageManager = internalGetPageManager();
}
+ pageManager.detach();
if (Application.exists())
{
http://git-wip-us.apache.org/repos/asf/wicket/blob/bcf76f51/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 f109472..c800935 100644
--- a/wicket-core/src/main/java/org/apache/wicket/DefaultPageManagerProvider.java
+++ b/wicket-core/src/main/java/org/apache/wicket/DefaultPageManagerProvider.java
@@ -19,22 +19,44 @@ package org.apache.wicket;
import java.io.File;
import org.apache.wicket.page.IPageManager;
-import org.apache.wicket.page.IPageManagerContext;
-import org.apache.wicket.page.PageStoreManager;
-import org.apache.wicket.pageStore.AsynchronousDataStore;
+import org.apache.wicket.page.PageManager;
import org.apache.wicket.pageStore.AsynchronousPageStore;
-import org.apache.wicket.pageStore.DefaultPageStore;
-import org.apache.wicket.pageStore.DiskDataStore;
-import org.apache.wicket.pageStore.IDataStore;
+import org.apache.wicket.pageStore.DiskPageStore;
+import org.apache.wicket.pageStore.GroupingPageStore;
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.RequestPageStore;
import org.apache.wicket.serialize.ISerializer;
import org.apache.wicket.settings.StoreSettings;
import org.apache.wicket.util.lang.Args;
import org.apache.wicket.util.lang.Bytes;
/**
- * {@link IPageManagerProvider} implementation that creates new instance of {@link IPageManager}
- * that persists the pages in {@link DiskDataStore}
+ * A provider of a {@link PageManager} with a default chain of page {@link IPageStore}s:
+ * <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 AsynchronousPageStore} moving storage of pages to a worker thread (if enabled in {@link StoreSettings#isAsynchronous()})</li>
+ * <li>{@link DiskPageStore} keeping all pages, configured according to {@link StoreSettings}</li>
+ * </ul>
+ * An alternative chain with all pages held in-memory could be:
+ * <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 InMemoryPageStore} keeping all pages</li>
+ * </ul>
+ * ... or if all pages should be kept in the session only:
+ * <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>
+ * <li>{@link NoopPageStore} discarding all exceeding pages</li>
+ * </ul>
+ * Other stores be may inserted ad libitum, e.g.
+ * <ul>
+ * <li>{@link GroupingPageStore} groups pages with their own maximum page limit</li>
+ * </ul>
*/
public class DefaultPageManagerProvider implements IPageManagerProvider
{
@@ -44,7 +66,7 @@ public class DefaultPageManagerProvider implements IPageManagerProvider
* Constructor.
*
* @param application
- * The application instance
+ * The application instance
*/
public DefaultPageManagerProvider(Application application)
{
@@ -52,53 +74,81 @@ public class DefaultPageManagerProvider implements IPageManagerProvider
}
@Override
- public IPageManager apply(IPageManagerContext pageManagerContext)
+ public IPageManager get()
{
- IDataStore dataStore = newDataStore();
+ IPageStore store = newPersistentStore();
- StoreSettings storeSettings = getStoreSettings();
+ store = newAsynchronousStore(store);
- IPageStore pageStore;
+ store = newSessionStore(store);
- if (dataStore.canBeAsynchronous() && storeSettings.isAsynchronous())
- {
- int capacity = storeSettings.getAsynchronousQueueCapacity();
- dataStore = new AsynchronousDataStore(dataStore, capacity);
-
- pageStore = newPageStore(dataStore);
-
- if (pageStore.canBeAsynchronous())
- {
- pageStore = new AsynchronousPageStore(pageStore, capacity);
- }
- }
- else
- {
- pageStore = newPageStore(dataStore);
- }
+ store = newRequestStore(store);
+
+ return new PageManager(store);
+ }
- return new PageStoreManager(application.getName(), pageStore, pageManagerContext);
+ /**
+ * Get the {@link ISerializer} to use for serializing of pages.
+ *
+ * @return how to serialize pages if needed for any {@link IPageStore}
+ */
+ protected ISerializer getSerializer()
+ {
+ return application.getFrameworkSettings().getSerializer();
+ }
+ /**
+ * Keep pages in the request until it is finished.
+ *
+ * @see RequestPageStore
+ */
+ protected IPageStore newRequestStore(IPageStore pageStore)
+ {
+ return new RequestPageStore(pageStore);
}
- protected IPageStore newPageStore(IDataStore dataStore)
+ /**
+ * After requests keep pages in the session.
+ *
+ * @see InSessionPageStore
+ */
+ protected IPageStore newSessionStore(IPageStore pageStore)
{
- int inmemoryCacheSize = getStoreSettings().getInmemoryCacheSize();
- ISerializer pageSerializer = application.getFrameworkSettings().getSerializer();
- return new DefaultPageStore(pageSerializer, dataStore, inmemoryCacheSize);
+ return new InSessionPageStore(pageStore, getSerializer(), 1);
}
- protected IDataStore newDataStore()
+ /**
+ * Store pages asynchronously into the persistent store.
+ *
+ * @see AsynchronousPageStore
+ * @see StoreSettings#isAsynchronous()
+ */
+ protected IPageStore newAsynchronousStore(IPageStore pageStore)
{
- StoreSettings storeSettings = getStoreSettings();
- Bytes maxSizePerSession = storeSettings.getMaxSizePerSession();
- File fileStoreFolder = storeSettings.getFileStoreFolder();
+ StoreSettings storeSettings = application.getStoreSettings();
- return new DiskDataStore(application.getName(), fileStoreFolder, maxSizePerSession);
+ if (storeSettings.isAsynchronous())
+ {
+ int capacity = storeSettings.getAsynchronousQueueCapacity();
+ pageStore = new AsynchronousPageStore(pageStore, capacity);
+ }
+
+ return pageStore;
}
- StoreSettings getStoreSettings()
+ /**
+ * Keep pages persistent on disk.
+ *
+ * @see DiskPageStore
+ * @see StoreSettings#getMaxSizePerSession()
+ * @see StoreSettings#getFileStoreFolder()
+ */
+ protected IPageStore newPersistentStore()
{
- return application.getStoreSettings();
+ StoreSettings storeSettings = application.getStoreSettings();
+ Bytes maxSizePerSession = storeSettings.getMaxSizePerSession();
+ File fileStoreFolder = storeSettings.getFileStoreFolder();
+
+ return new DiskPageStore(application.getName(), getSerializer(), fileStoreFolder, maxSizePerSession);
}
}
http://git-wip-us.apache.org/repos/asf/wicket/blob/bcf76f51/wicket-core/src/main/java/org/apache/wicket/IPageManagerProvider.java
----------------------------------------------------------------------
diff --git a/wicket-core/src/main/java/org/apache/wicket/IPageManagerProvider.java b/wicket-core/src/main/java/org/apache/wicket/IPageManagerProvider.java
index 557a7aa..ce40fcc 100644
--- a/wicket-core/src/main/java/org/apache/wicket/IPageManagerProvider.java
+++ b/wicket-core/src/main/java/org/apache/wicket/IPageManagerProvider.java
@@ -16,11 +16,10 @@
*/
package org.apache.wicket;
-import java.util.function.Function;
+import java.util.function.Supplier;
import org.apache.wicket.page.IPageManager;
-import org.apache.wicket.page.IPageManagerContext;
-public interface IPageManagerProvider extends Function<IPageManagerContext, IPageManager>
+public interface IPageManagerProvider extends Supplier<IPageManager>
{
}
http://git-wip-us.apache.org/repos/asf/wicket/blob/bcf76f51/wicket-core/src/main/java/org/apache/wicket/Page.java
----------------------------------------------------------------------
diff --git a/wicket-core/src/main/java/org/apache/wicket/Page.java b/wicket-core/src/main/java/org/apache/wicket/Page.java
index a1f3b29..935e1f9 100644
--- a/wicket-core/src/main/java/org/apache/wicket/Page.java
+++ b/wicket-core/src/main/java/org/apache/wicket/Page.java
@@ -275,7 +275,7 @@ public abstract class Page extends MarkupContainer
}
final IPageManager pageManager = getSession().getPageManager();
- if (!getFlag(FLAG_IS_DIRTY) && (isVersioned() && pageManager.supportsVersioning() ||
+ if (!getFlag(FLAG_IS_DIRTY) && (isVersioned() ||
// we need to get pageId for new page instances even when the page doesn't need
// versioning, otherwise pages override each other in the page store and back button
@@ -287,7 +287,7 @@ public abstract class Page extends MarkupContainer
if (isInitialization == false)
{
- pageManager.touchPage(this);
+ pageManager.addPage(this);
}
}
}
@@ -298,7 +298,7 @@ public abstract class Page extends MarkupContainer
super.onInitialize();
final IPageManager pageManager = getSession().getPageManager();
- pageManager.touchPage(this);
+ pageManager.addPage(this);
}
/**
@@ -825,7 +825,7 @@ public abstract class Page extends MarkupContainer
getSession().getSessionStore().getSessionId(RequestCycle.get().getRequest(), true);
// Add/touch the response page in the session.
- getSession().getPageManager().touchPage(this);
+ getSession().getPageManager().addPage(this);
}
if (getApplication().getDebugSettings().isOutputMarkupContainerClassName())
@@ -936,7 +936,7 @@ public abstract class Page extends MarkupContainer
setStatelessHint(false);
// make sure the page will be available on following request
- getSession().getPageManager().touchPage(this);
+ getSession().getPageManager().addPage(this);
return new PageReference(numericId);
}
http://git-wip-us.apache.org/repos/asf/wicket/blob/bcf76f51/wicket-core/src/main/java/org/apache/wicket/Session.java
----------------------------------------------------------------------
diff --git a/wicket-core/src/main/java/org/apache/wicket/Session.java b/wicket-core/src/main/java/org/apache/wicket/Session.java
index cb8f4a2..8df8577 100644
--- a/wicket-core/src/main/java/org/apache/wicket/Session.java
+++ b/wicket-core/src/main/java/org/apache/wicket/Session.java
@@ -37,6 +37,7 @@ import org.apache.wicket.feedback.FeedbackMessage;
import org.apache.wicket.feedback.FeedbackMessages;
import org.apache.wicket.page.IPageManager;
import org.apache.wicket.page.PageAccessSynchronizer;
+import org.apache.wicket.pageStore.IPageStore;
import org.apache.wicket.request.Request;
import org.apache.wicket.request.cycle.RequestCycle;
import org.apache.wicket.session.ISessionStore;
@@ -290,7 +291,7 @@ public abstract class Session implements IClusterable, IEventSink
{
if (isTemporary() == false)
{
- getPageManager().clear();
+ getPageManager().removeAllPages();
}
}
@@ -907,8 +908,8 @@ public abstract class Session implements IClusterable, IEventSink
*/
public final IPageManager getPageManager()
{
- IPageManager pageManager = Application.get().internalGetPageManager();
- return pageAccessSynchronizer.get().adapt(pageManager);
+ IPageManager manager = Application.get().internalGetPageManager();
+ return pageAccessSynchronizer.get().adapt(manager);
}
/** {@inheritDoc} */
http://git-wip-us.apache.org/repos/asf/wicket/blob/bcf76f51/wicket-core/src/main/java/org/apache/wicket/core/request/handler/PageProvider.java
----------------------------------------------------------------------
diff --git a/wicket-core/src/main/java/org/apache/wicket/core/request/handler/PageProvider.java b/wicket-core/src/main/java/org/apache/wicket/core/request/handler/PageProvider.java
index 7bd473e..bd45693 100644
--- a/wicket-core/src/main/java/org/apache/wicket/core/request/handler/PageProvider.java
+++ b/wicket-core/src/main/java/org/apache/wicket/core/request/handler/PageProvider.java
@@ -19,7 +19,6 @@ package org.apache.wicket.core.request.handler;
import org.apache.wicket.Application;
import org.apache.wicket.core.request.mapper.IPageSource;
import org.apache.wicket.core.request.mapper.StalePageException;
-import org.apache.wicket.page.IPageManager;
import org.apache.wicket.protocol.http.PageExpiredException;
import org.apache.wicket.request.IRequestHandler;
import org.apache.wicket.request.IRequestMapper;
http://git-wip-us.apache.org/repos/asf/wicket/blob/bcf76f51/wicket-core/src/main/java/org/apache/wicket/core/request/handler/RenderPageRequestHandler.java
----------------------------------------------------------------------
diff --git a/wicket-core/src/main/java/org/apache/wicket/core/request/handler/RenderPageRequestHandler.java b/wicket-core/src/main/java/org/apache/wicket/core/request/handler/RenderPageRequestHandler.java
index 156d420..642d40f 100644
--- a/wicket-core/src/main/java/org/apache/wicket/core/request/handler/RenderPageRequestHandler.java
+++ b/wicket-core/src/main/java/org/apache/wicket/core/request/handler/RenderPageRequestHandler.java
@@ -136,7 +136,7 @@ public class RenderPageRequestHandler
if (Session.exists())
{
// WICKET-5499
- Session.get().getPageManager().touchPage(pageProvider.getPageInstance());
+ Session.get().getPageManager().addPage(pageProvider.getPageInstance());
}
}
}
http://git-wip-us.apache.org/repos/asf/wicket/blob/bcf76f51/wicket-core/src/main/java/org/apache/wicket/mock/MockApplication.java
----------------------------------------------------------------------
diff --git a/wicket-core/src/main/java/org/apache/wicket/mock/MockApplication.java b/wicket-core/src/main/java/org/apache/wicket/mock/MockApplication.java
index 1c0a99d..4ae6f41 100644
--- a/wicket-core/src/main/java/org/apache/wicket/mock/MockApplication.java
+++ b/wicket-core/src/main/java/org/apache/wicket/mock/MockApplication.java
@@ -67,7 +67,7 @@ public class MockApplication extends WebApplication
// set page and session store providers
setSessionStoreProvider(MockSessionStore::new);
- setPageManagerProvider((pageManagerContext) -> new MockPageManager());
+ setPageManagerProvider(() -> new MockPageManager());
// for test cases we usually want stable resource names
getResourceSettings().setCachingStrategy(NoOpResourceCachingStrategy.INSTANCE);
http://git-wip-us.apache.org/repos/asf/wicket/blob/bcf76f51/wicket-core/src/main/java/org/apache/wicket/mock/MockPageManager.java
----------------------------------------------------------------------
diff --git a/wicket-core/src/main/java/org/apache/wicket/mock/MockPageManager.java b/wicket-core/src/main/java/org/apache/wicket/mock/MockPageManager.java
index b27dc7e..05bb520 100644
--- a/wicket-core/src/main/java/org/apache/wicket/mock/MockPageManager.java
+++ b/wicket-core/src/main/java/org/apache/wicket/mock/MockPageManager.java
@@ -21,7 +21,7 @@ import java.util.Map;
import org.apache.wicket.page.IManageablePage;
import org.apache.wicket.page.IPageManager;
-import org.apache.wicket.page.IPageManagerContext;
+import org.apache.wicket.pageStore.IPageStore;
/**
* Simple {@link IPageManager} used for testing.
@@ -32,19 +32,6 @@ public class MockPageManager implements IPageManager
{
private final Map<Integer, IManageablePage> pages = new HashMap<>();
- /**
- * Construct.
- *
- */
- public MockPageManager()
- {
- }
-
- @Override
- public void commitRequest()
- {
- }
-
@Override
public void destroy()
{
@@ -59,54 +46,29 @@ public class MockPageManager implements IPageManager
@Override
public void removePage(final IManageablePage page) {
- if (page != null) {
- pages.remove(page.getPageId());
- }
+ pages.remove(page.getPageId());
}
@Override
- public void newSessionCreated()
+ public void addPage(IManageablePage page)
{
- pages.clear();
+ pages.put(page.getPageId(), page);
}
@Override
- public void clear()
+ public void removeAllPages()
{
pages.clear();
}
- /**
- * @param context
- */
- public void setContext(IPageManagerContext context)
- {
- }
-
- @Override
- public boolean supportsVersioning()
- {
- return true;
- }
-
@Override
- public void touchPage(IManageablePage page)
+ public void detach()
{
- if (true || page.isPageStateless() == false)
- {
- pages.put(page.getPageId(), page);
- }
- }
-
- @Override
- public void untouchPage(IManageablePage page)
- {
- pages.remove(page.getPageId());
}
@Override
- public IPageManagerContext getContext()
+ public IPageStore getPageStore()
{
- return null;
+ throw new UnsupportedOperationException();
}
-}
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/wicket/blob/bcf76f51/wicket-core/src/main/java/org/apache/wicket/mock/MockPageStore.java
----------------------------------------------------------------------
diff --git a/wicket-core/src/main/java/org/apache/wicket/mock/MockPageStore.java b/wicket-core/src/main/java/org/apache/wicket/mock/MockPageStore.java
new file mode 100644
index 0000000..cb4eaec
--- /dev/null
+++ b/wicket-core/src/main/java/org/apache/wicket/mock/MockPageStore.java
@@ -0,0 +1,60 @@
+/*
+ * 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.mock;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.wicket.page.IManageablePage;
+import org.apache.wicket.pageStore.IPageContext;
+import org.apache.wicket.pageStore.IPageStore;
+
+public class MockPageStore implements IPageStore
+{
+ private final Map<Integer, IManageablePage> pages = new HashMap<>();
+
+ @Override
+ public void destroy()
+ {
+ pages.clear();
+ }
+
+ @Override
+ public IManageablePage getPage(IPageContext context, int id)
+ {
+ return pages.get(id);
+ }
+
+ @Override
+ public void removePage(IPageContext context, final IManageablePage page) {
+ if (page != null) {
+ pages.remove(page.getPageId());
+ }
+ }
+
+ @Override
+ public void removeAllPages(IPageContext context)
+ {
+ pages.clear();
+ }
+
+ @Override
+ public void addPage(IPageContext context, IManageablePage page)
+ {
+ pages.put(page.getPageId(), page);
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/wicket/blob/bcf76f51/wicket-core/src/main/java/org/apache/wicket/page/AbstractPageManager.java
----------------------------------------------------------------------
diff --git a/wicket-core/src/main/java/org/apache/wicket/page/AbstractPageManager.java b/wicket-core/src/main/java/org/apache/wicket/page/AbstractPageManager.java
deleted file mode 100644
index 03b26aa..0000000
--- a/wicket-core/src/main/java/org/apache/wicket/page/AbstractPageManager.java
+++ /dev/null
@@ -1,121 +0,0 @@
-/*
- * 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.page;
-
-import org.apache.wicket.util.lang.Args;
-
-/**
- * Convenience class for {@link IPageManager} implementations. Subclass should extend
- * {@link RequestAdapter} and override {@link #newRequestAdapter(IPageManagerContext)} method to return it's
- * {@link RequestAdapter} implementation.
- *
- * @author Matej Knopp
- */
-public abstract class AbstractPageManager implements IPageManager
-{
- private final IPageManagerContext context;
-
- /**
- * Construct.
- *
- * @param context
- */
- public AbstractPageManager(IPageManagerContext context)
- {
- this.context = Args.notNull(context, "context");
- }
-
- /**
- *
- * @param context
- * @return a new request adapter
- */
- protected abstract RequestAdapter newRequestAdapter(IPageManagerContext context);
-
- /**
- * @return The page manager context
- */
- @Override
- public IPageManagerContext getContext()
- {
- return context;
- }
-
- /**
- * @see #newRequestAdapter(IPageManagerContext)
- * @return the request adapter
- */
- protected RequestAdapter getRequestAdapter()
- {
- RequestAdapter adapter = (RequestAdapter)getContext().getRequestData();
- if (adapter == null)
- {
- adapter = newRequestAdapter(getContext());
- getContext().setRequestData(adapter);
- }
- return adapter;
- }
-
- @Override
- public void commitRequest()
- {
- getRequestAdapter().commitRequest();
- }
-
- @Override
- public IManageablePage getPage(int id)
- {
- IManageablePage page = getRequestAdapter().getPage(id);
- if (page != null)
- {
- touchPage(page);
- }
- return page;
- }
-
- @Override
- public void removePage(final IManageablePage page) {
- if (page != null)
- {
- getRequestAdapter().removePage(page);
- }
- }
-
- @Override
- public void newSessionCreated()
- {
- getRequestAdapter().newSessionCreated();
- }
-
- @Override
- public void touchPage(IManageablePage page)
- {
- if (page != null)
- {
- getRequestAdapter().touch(page);
- }
- }
-
- @Override
- public void untouchPage(IManageablePage page)
- {
- if (page != null)
- {
- getRequestAdapter().untouch(page);
- }
- }
-}
http://git-wip-us.apache.org/repos/asf/wicket/blob/bcf76f51/wicket-core/src/main/java/org/apache/wicket/page/DefaultPageManagerContext.java
----------------------------------------------------------------------
diff --git a/wicket-core/src/main/java/org/apache/wicket/page/DefaultPageManagerContext.java b/wicket-core/src/main/java/org/apache/wicket/page/DefaultPageManagerContext.java
deleted file mode 100644
index 78f4b49..0000000
--- a/wicket-core/src/main/java/org/apache/wicket/page/DefaultPageManagerContext.java
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- * 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.page;
-
-import java.io.Serializable;
-
-import org.apache.wicket.MetaDataKey;
-import org.apache.wicket.Session;
-import org.apache.wicket.request.cycle.RequestCycle;
-
-/**
- * Wicket's default page manager context
- *
- * @author Juergen Donnerstag
- */
-public class DefaultPageManagerContext implements IPageManagerContext
-{
- private static final MetaDataKey<Object> requestCycleMetaDataKey = new MetaDataKey<Object>()
- {
- private static final long serialVersionUID = 1L;
- };
-
- /**
- * @see org.apache.wicket.page.IPageManagerContext#bind()
- */
- @Override
- public void bind()
- {
- Session.get().bind();
- }
-
- /**
- * @see org.apache.wicket.page.IPageManagerContext#getRequestData()
- */
- @Override
- public Object getRequestData()
- {
- RequestCycle requestCycle = RequestCycle.get();
- if (requestCycle == null)
- {
- throw new IllegalStateException("Not a request thread.");
- }
- return requestCycle.getMetaData(requestCycleMetaDataKey);
- }
-
- /**
- * @see org.apache.wicket.page.IPageManagerContext#getSessionAttribute(java.lang.String)
- */
- @Override
- public Serializable getSessionAttribute(final String key)
- {
- return Session.get().getAttribute(key);
- }
-
- /**
- * @see org.apache.wicket.page.IPageManagerContext#getSessionId()
- */
- @Override
- public String getSessionId()
- {
- return Session.get().getId();
- }
-
- /**
- * @see org.apache.wicket.page.IPageManagerContext#setRequestData(Object)
- */
- @Override
- public void setRequestData(final Object data)
- {
- RequestCycle requestCycle = RequestCycle.get();
- if (requestCycle == null)
- {
- throw new IllegalStateException("Not a request thread.");
- }
- requestCycle.setMetaData(requestCycleMetaDataKey, data);
- }
-
- /**
- * @see org.apache.wicket.page.IPageManagerContext#setSessionAttribute(java.lang.String,
- * java.io.Serializable)
- */
- @Override
- public void setSessionAttribute(String key, Serializable value)
- {
- Session.get().setAttribute(key, value);
- }
-}
http://git-wip-us.apache.org/repos/asf/wicket/blob/bcf76f51/wicket-core/src/main/java/org/apache/wicket/page/IPageManager.java
----------------------------------------------------------------------
diff --git a/wicket-core/src/main/java/org/apache/wicket/page/IPageManager.java b/wicket-core/src/main/java/org/apache/wicket/page/IPageManager.java
index a19a0e3..9d517df 100644
--- a/wicket-core/src/main/java/org/apache/wicket/page/IPageManager.java
+++ b/wicket-core/src/main/java/org/apache/wicket/page/IPageManager.java
@@ -16,89 +16,59 @@
*/
package org.apache.wicket.page;
+import org.apache.wicket.Page;
+import org.apache.wicket.pageStore.IPageStore;
/**
- * Page manager.
- *
- * @author Matej Knopp
+ * A manager of pages - facade between {@link Page}s and {@link IPageStore}s they are stored in.
*/
public interface IPageManager
{
- /**
- *
- * @return the page manager context
- */
- IPageManagerContext getContext();
/**
- * Retrieve page instance with given id.
+ * Get a page
*
- * @param id
- * the id of the page to load
- * @return page instance or <code>null</code>
- * @throws CouldNotLockPageException if the page is already locked by another thread
- * and the lock cannot be acquired for some timeout
- */
- IManageablePage getPage(int id) throws CouldNotLockPageException;
-
- /**
- * Removes a page from the {@link org.apache.wicket.pageStore.IPageStore} and
- * {@link org.apache.wicket.pageStore.IDataStore}. Any attempt to access it later
- * will lead to {@link org.apache.wicket.protocol.http.PageExpiredException}
- *
- * @param page The page instance to remove from the stores
+ * @param pageId
+ * id of page
+ * @return page, may be <code>null</code>
*/
- void removePage(IManageablePage page);
+ IManageablePage getPage(int pageId);
/**
- * Marks page as changed.
- * <p><strong>Note:</strong>Only stateful pages are stored.</p>
+ * Remove a page
*
* @param page
- * the page that should be stored in the page stores at the end of the request.
- * @throws CouldNotLockPageException if the page is already locked by another thread
- * and the lock cannot be acquired for some timeout
- */
- void touchPage(IManageablePage page);
-
- /**
- * Marks page as non-changed.
- * Could be used in Ajax requests to avoid storing the page if no changes have happened.
- *
- * @param page
- * the page that should <strong>not</strong> be stored in the page stores at the end of the request.
- * @throws CouldNotLockPageException if the page is already locked by another thread
- * and the lock cannot be acquired for some timeout
+ * page to remove
*/
- void untouchPage(IManageablePage page);
+ void removePage(IManageablePage page);
/**
- * Returns whether this manager supports versioning. Managers that support versioning must store
- * page snapshots.
+ * Add a page.
*
- * @return whether this page manager supports versioning
+ * @param page
+ * page to add
*/
- boolean supportsVersioning();
+ void addPage(IManageablePage page);
/**
- * Commits the changes to external storage if the manager uses it.
- *
- * Should also detach all pages that were touched during this request.
+ * Remove all pages.
*/
- void commitRequest();
+ void removeAllPages();
/**
- * Invoked when new session has been created.
+ * Detach at end of request.
*/
- void newSessionCreated();
+ void detach();
/**
- * Clears all data for the current session.
+ * Destroy when application is destroyed.
*/
- void clear();
+ void destroy();
/**
- * Destroy the page manager.
+ * Get the storage of pages, optional.
+ *
+ * @return store or <code>null</code>
*/
- void destroy();
+ IPageStore getPageStore();
}
http://git-wip-us.apache.org/repos/asf/wicket/blob/bcf76f51/wicket-core/src/main/java/org/apache/wicket/page/IPageManagerContext.java
----------------------------------------------------------------------
diff --git a/wicket-core/src/main/java/org/apache/wicket/page/IPageManagerContext.java b/wicket-core/src/main/java/org/apache/wicket/page/IPageManagerContext.java
deleted file mode 100644
index d928606..0000000
--- a/wicket-core/src/main/java/org/apache/wicket/page/IPageManagerContext.java
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * 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.page;
-
-import java.io.Serializable;
-
-/**
- * Context object for {@link IPageManager}. This decouples the {@link IPageManager} from request
- * cycle and session.
- *
- * @author Matej Knopp
- */
-public interface IPageManagerContext
-{
- /**
- *
- * @param data
- */
- void setRequestData(Object data);
-
- /**
- *
- * @return request data
- */
- Object getRequestData();
-
- /**
- *
- * @param key
- * @param value
- */
- void setSessionAttribute(String key, Serializable value);
-
- /**
- *
- * @param key
- * @return The session attribute associate with the key
- */
- Serializable getSessionAttribute(String key);
-
- /**
- * Tells Wicket to bind the current session. This make a temporary session become persistent
- * across requests.
- */
- void bind();
-
- /**
- *
- * @return session id
- */
- String getSessionId();
-}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/wicket/blob/bcf76f51/wicket-core/src/main/java/org/apache/wicket/page/PageAccessSynchronizer.java
----------------------------------------------------------------------
diff --git a/wicket-core/src/main/java/org/apache/wicket/page/PageAccessSynchronizer.java b/wicket-core/src/main/java/org/apache/wicket/page/PageAccessSynchronizer.java
index d44b86a..c50fb20 100644
--- a/wicket-core/src/main/java/org/apache/wicket/page/PageAccessSynchronizer.java
+++ b/wicket-core/src/main/java/org/apache/wicket/page/PageAccessSynchronizer.java
@@ -23,6 +23,7 @@ import java.util.concurrent.ConcurrentMap;
import java.util.function.Supplier;
import org.apache.wicket.Application;
+import org.apache.wicket.pageStore.IPageStore;
import org.apache.wicket.settings.ExceptionSettings.ThreadDumpStrategy;
import org.apache.wicket.util.LazyInitializer;
import org.apache.wicket.util.lang.Threads;
@@ -230,12 +231,12 @@ public class PageAccessSynchronizer implements Serializable
/**
* Wraps a page manager with this synchronizer
*
- * @param pagemanager
+ * @param manager
* @return wrapped page manager
*/
- public IPageManager adapt(IPageManager pagemanager)
+ public IPageManager adapt(final IPageManager manager)
{
- return new PageManagerDecorator(pagemanager)
+ return new IPageManager()
{
@Override
public IManageablePage getPage(int pageId)
@@ -244,7 +245,7 @@ public class PageAccessSynchronizer implements Serializable
try
{
lockPage(pageId);
- page = super.getPage(pageId);
+ page = manager.getPage(pageId);
}
finally
{
@@ -257,13 +258,13 @@ public class PageAccessSynchronizer implements Serializable
}
@Override
- public void removePage(final IManageablePage page) {
+ public void removePage(IManageablePage page)
+ {
if (page != null)
{
try
{
- super.removePage(page);
- untouchPage(page);
+ manager.removePage(page);
}
finally
{
@@ -273,24 +274,43 @@ public class PageAccessSynchronizer implements Serializable
}
@Override
- public void touchPage(IManageablePage page)
+ public void addPage(IManageablePage page)
{
lockPage(page.getPageId());
- super.touchPage(page);
+
+ manager.addPage(page);
}
@Override
- public void commitRequest()
+ public void removeAllPages()
+ {
+ manager.removeAllPages();
+ }
+
+ @Override
+ public void detach()
{
try
{
- super.commitRequest();
+ manager.detach();
}
finally
{
unlockAllPages();
}
}
+
+ @Override
+ public IPageStore getPageStore()
+ {
+ return manager.getPageStore();
+ }
+
+ @Override
+ public void destroy()
+ {
+ manager.destroy();
+ }
};
}
http://git-wip-us.apache.org/repos/asf/wicket/blob/bcf76f51/wicket-core/src/main/java/org/apache/wicket/page/PageManager.java
----------------------------------------------------------------------
diff --git a/wicket-core/src/main/java/org/apache/wicket/page/PageManager.java b/wicket-core/src/main/java/org/apache/wicket/page/PageManager.java
new file mode 100644
index 0000000..ab58c41
--- /dev/null
+++ b/wicket-core/src/main/java/org/apache/wicket/page/PageManager.java
@@ -0,0 +1,88 @@
+/*
+ * 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.page;
+
+import org.apache.wicket.Application;
+import org.apache.wicket.Session;
+import org.apache.wicket.pageStore.DefaultPageContext;
+import org.apache.wicket.pageStore.IPageContext;
+import org.apache.wicket.pageStore.IPageStore;
+import org.apache.wicket.util.lang.Args;
+
+/**
+ * A manager of pages, i.e. a mediator between an {@link Application} and an {@link IPageStore}.
+ */
+public class PageManager implements IPageManager
+{
+ private final IPageStore store;
+
+ public PageManager(IPageStore store) {
+ this.store = Args.notNull(store, "store");
+ }
+
+ @Override
+ public IManageablePage getPage(int pageId)
+ {
+ return store.getPage(createPageContext(), pageId);
+ }
+
+ @Override
+ public void removePage(IManageablePage page)
+ {
+ store.removePage(createPageContext(), page);
+ }
+
+ @Override
+ public void addPage(IManageablePage page)
+ {
+ store.addPage(createPageContext(), page);
+ }
+
+ @Override
+ public void removeAllPages()
+ {
+ store.removeAllPages(createPageContext());
+ }
+
+ @Override
+ public void detach()
+ {
+ store.detach(createPageContext());
+ }
+
+ /**
+ * Factory method for an {@link IPageContext}, returns a {@link DefaultPageContext} by default.
+ *
+ * @return
+ */
+ protected IPageContext createPageContext()
+ {
+ return new DefaultPageContext(Session.get());
+ }
+
+ @Override
+ public void destroy()
+ {
+ store.destroy();
+ }
+
+ @Override
+ public IPageStore getPageStore()
+ {
+ return store;
+ }
+}
http://git-wip-us.apache.org/repos/asf/wicket/blob/bcf76f51/wicket-core/src/main/java/org/apache/wicket/page/PageManagerDecorator.java
----------------------------------------------------------------------
diff --git a/wicket-core/src/main/java/org/apache/wicket/page/PageManagerDecorator.java b/wicket-core/src/main/java/org/apache/wicket/page/PageManagerDecorator.java
deleted file mode 100644
index 8f719f8..0000000
--- a/wicket-core/src/main/java/org/apache/wicket/page/PageManagerDecorator.java
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- * 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.page;
-
-import org.apache.wicket.util.lang.Args;
-
-/**
- * Decorator for {@link IPageManager}
- *
- * @author igor
- */
-public class PageManagerDecorator implements IPageManager
-{
- private final IPageManager delegate;
-
- /**
- * Constructor
- *
- * @param delegate
- */
- public PageManagerDecorator(IPageManager delegate)
- {
- Args.notNull(delegate, "delegate");
- this.delegate = delegate;
- }
-
- @Override
- public IPageManagerContext getContext()
- {
- return delegate.getContext();
- }
-
- @Override
- public IManageablePage getPage(int id)
- {
- return delegate.getPage(id);
- }
-
- @Override
- public void removePage(final IManageablePage page) {
- delegate.removePage(page);
- }
-
- @Override
- public void touchPage(IManageablePage page)
- {
- delegate.touchPage(page);
- }
-
- @Override
- public void untouchPage(IManageablePage page)
- {
- delegate.untouchPage(page);
- }
-
- @Override
- public boolean supportsVersioning()
- {
- return delegate.supportsVersioning();
- }
-
- @Override
- public void commitRequest()
- {
- delegate.commitRequest();
- }
-
- @Override
- public void newSessionCreated()
- {
- delegate.newSessionCreated();
- }
-
- @Override
- public void clear()
- {
- delegate.clear();
- }
-
- @Override
- public void destroy()
- {
- delegate.destroy();
- }
-
-}
http://git-wip-us.apache.org/repos/asf/wicket/blob/bcf76f51/wicket-core/src/main/java/org/apache/wicket/page/PageStoreManager.java
----------------------------------------------------------------------
diff --git a/wicket-core/src/main/java/org/apache/wicket/page/PageStoreManager.java b/wicket-core/src/main/java/org/apache/wicket/page/PageStoreManager.java
deleted file mode 100644
index 88c1645..0000000
--- a/wicket-core/src/main/java/org/apache/wicket/page/PageStoreManager.java
+++ /dev/null
@@ -1,507 +0,0 @@
-/*
- * 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.page;
-
-import java.io.IOException;
-import java.io.ObjectInputStream;
-import java.io.ObjectOutputStream;
-import java.io.Serializable;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.ConcurrentMap;
-
-import javax.servlet.http.HttpSessionBindingEvent;
-import javax.servlet.http.HttpSessionBindingListener;
-
-import org.apache.wicket.pageStore.IPageStore;
-
-/**
- *
- */
-public class PageStoreManager extends AbstractPageManager
-{
- /**
- * A cache that holds all registered page managers. <br/>
- * applicationName -> page manager
- */
- private static final ConcurrentMap<String, PageStoreManager> MANAGERS = new ConcurrentHashMap<>();
-
- private static final String ATTRIBUTE_NAME = "wicket:persistentPageManagerData";
-
- /**
- * A flag indicating whether this session entry is being re-set in the Session.
- * <p>
- * Web containers intercept
- * {@link javax.servlet.http.HttpSession#setAttribute(String, Object)} to detect changes and
- * replicate the session. If the attribute has been already bound in the session then
- * {@link #valueUnbound(HttpSessionBindingEvent)} might get called - this flag
- * helps us to ignore the invocation in that case.
- *
- * @see #valueUnbound(HttpSessionBindingEvent)
- */
- private static final ThreadLocal<Boolean> STORING_TOUCHED_PAGES = new ThreadLocal<Boolean>()
- {
- protected Boolean initialValue()
- {
- return Boolean.FALSE;
- };
- };
-
- private final IPageStore pageStore;
-
- private final String applicationName;
-
- /**
- * Construct.
- *
- * @param applicationName
- * @param pageStore
- * @param context
- */
- public PageStoreManager(final String applicationName, final IPageStore pageStore,
- final IPageManagerContext context)
- {
- super(context);
-
- this.applicationName = applicationName;
- this.pageStore = pageStore;
-
- if (MANAGERS.containsKey(applicationName))
- {
- throw new IllegalStateException(
- "Manager for application with key '" + applicationName + "' already exists.");
- }
- MANAGERS.put(applicationName, this);
- }
-
- /**
- * Represents entry for single session. This is stored as session attribute and caches pages
- * between requests.
- *
- * @author Matej Knopp
- */
- private static class SessionEntry implements Serializable, HttpSessionBindingListener
- {
- private static final long serialVersionUID = 1L;
-
- private final String applicationName;
-
- /**
- * The id handed to the {@link IPageStore} to identify the session.
- * <p>
- * Note: If the container changes a session's id, this field remains unchanged on its
- * initial value.
- */
- private final String sessionId;
-
- private transient List<IManageablePage> sessionCache;
- private transient List<Object> afterReadObject;
-
-
- /**
- * Construct.
- *
- * @param applicationName
- * @param sessionId
- */
- public SessionEntry(String applicationName, String sessionId)
- {
- this.applicationName = applicationName;
- this.sessionId = sessionId;
- }
-
- /**
- *
- * @return page store
- */
- private IPageStore getPageStore()
- {
- PageStoreManager manager = MANAGERS.get(applicationName);
-
- if (manager == null)
- {
- return null;
- }
-
- return manager.pageStore;
- }
-
- /**
- *
- * @param id
- * @return null, if not found
- */
- private IManageablePage findPage(int id)
- {
- for (IManageablePage p : sessionCache)
- {
- if (p.getPageId() == id)
- {
- return p;
- }
- }
- return null;
- }
-
- /**
- * Add the page to cached pages if page with same id is not already there
- *
- * @param page
- */
- private void addPage(IManageablePage page)
- {
- if (page != null)
- {
- if (findPage(page.getPageId()) != null)
- {
- return;
- }
-
- sessionCache.add(page);
- }
- }
-
- private synchronized void removePage(IManageablePage page)
- {
- if (page != null)
- {
- sessionCache.remove(page);
- final IPageStore pageStore = getPageStore();
- if (pageStore != null)
- {
- pageStore.removePage(sessionId, page.getPageId());
- }
- }
- }
-
- /**
- * If the pages are stored in temporary state (after deserialization) this method convert
- * them to list of "real" pages
- */
- private void convertAfterReadObjects()
- {
- if (sessionCache == null)
- {
- sessionCache = new ArrayList<>();
- }
-
- final IPageStore pageStore = getPageStore();
- if (pageStore != null)
- {
- for (Object o : afterReadObject)
- {
- IManageablePage page = pageStore.convertToPage(o);
- addPage(page);
- }
- }
-
- afterReadObject = null;
- }
-
- /**
- *
- * @param id
- * @return manageable page
- */
- public synchronized IManageablePage getPage(int id)
- {
- // check if pages are in deserialized state
- if (afterReadObject != null && afterReadObject.isEmpty() == false)
- {
- convertAfterReadObjects();
- }
-
- IManageablePage page = null;
- // try to find page with same id
- if (sessionCache != null)
- {
- page = findPage(id);
- if (page != null)
- {
- return page;
- }
- }
-
- // not found, ask pagestore for the page
- final IPageStore pageStore = getPageStore();
- if (pageStore != null)
- {
- page = pageStore.getPage(sessionId, id);
- }
- return page;
- }
-
- /**
- * set the list of pages to remember after the request
- *
- * @param pages
- */
- public synchronized void setSessionCache(final List<IManageablePage> pages)
- {
- sessionCache = new ArrayList<>(pages);
- afterReadObject = null;
- }
-
- /**
- * Serializes all pages in this {@link SessionEntry}. If this is http worker thread then
- * there is available {@link IPageStore} which will be asked to prepare the page for
- * serialization (see DefaultPageStore$SerializePage). If there is no {@link IPageStore}
- * available (session loading/persisting in application initialization/destruction thread)
- * then the pages are serialized without any pre-processing
- *
- * @param s
- * @throws IOException
- */
- private void writeObject(final ObjectOutputStream s) throws IOException
- {
- s.defaultWriteObject();
-
- // prepare for serialization and store the pages
- List<Serializable> serializedPages = new ArrayList<Serializable>();
- if (sessionCache != null)
- {
- IPageStore pageStore = getPageStore();
- for (IManageablePage p : sessionCache)
- {
- Serializable preparedPage;
- if (pageStore != null)
- {
- preparedPage = pageStore.prepareForSerialization(sessionId, p);
- }
- else
- {
- preparedPage = p;
- }
-
- if (preparedPage != null)
- {
- serializedPages.add(preparedPage);
- }
- }
- }
- s.writeObject(serializedPages);
- }
-
- /**
- * Deserializes the pages in this {@link SessionEntry}. If this is http worker thread then
- * there is available {@link IPageStore} which will be asked to restore the page from its
- * optimized state (see DefaultPageStore$SerializePage). If there is no {@link IPageStore}
- * available (session loading/persisting in application initialization/destruction thread)
- * then the pages are deserialized without any post-processing
- *
- * @param s
- * @throws IOException
- * @throws ClassNotFoundException
- */
- @SuppressWarnings("unchecked")
- private void readObject(final ObjectInputStream s)
- throws IOException, ClassNotFoundException
- {
- s.defaultReadObject();
-
- afterReadObject = new ArrayList<>();
-
- List<Serializable> l = (List<Serializable>)s.readObject();
-
- // convert to temporary state after deserialization (will need to be processed
- // by convertAfterReadObject before the pages can be accessed)
- IPageStore pageStore = getPageStore();
- for (Serializable ser : l)
- {
- Object page;
- if (pageStore != null)
- {
- page = pageStore.restoreAfterSerialization(ser);
- }
- else
- {
- page = ser;
- }
- afterReadObject.add(page);
- }
- }
-
- @Override
- public void valueBound(HttpSessionBindingEvent event)
- {
- }
-
- @Override
- public void valueUnbound(HttpSessionBindingEvent event)
- {
- if (STORING_TOUCHED_PAGES.get())
- {
- // triggered by #storeTouchedPages(), so do not remove the data
- return;
- }
-
- // WICKET-5164 use the original sessionId
- IPageStore store = getPageStore();
- // store might be null if destroyed already
- if (store != null)
- {
- store.unbind(sessionId);
- }
- }
-
- @Override
- public boolean equals(Object o)
- {
- // see https://issues.apache.org/jira/browse/WICKET-5390
- return false;
- }
- }
-
- private String getAttributeName()
- {
- return ATTRIBUTE_NAME + " - " + applicationName;
- }
-
- /**
- * {@link RequestAdapter} for {@link PageStoreManager}
- *
- * @author Matej Knopp
- */
- protected class PersistentRequestAdapter extends RequestAdapter
- {
- /**
- * Construct.
- *
- * @param context
- */
- public PersistentRequestAdapter(IPageManagerContext context)
- {
- super(context);
- }
-
- @Override
- protected IManageablePage getPage(int id)
- {
- IManageablePage touchedPage = findPage(id);
- if (touchedPage != null)
- {
- return touchedPage;
- }
-
- // try to get session entry for this session
- SessionEntry entry = getSessionEntry(false);
-
- if (entry != null)
- {
- return entry.getPage(id);
- }
- else
- {
- return null;
- }
- }
-
- @Override
- protected void removePage(final IManageablePage page)
- {
- final SessionEntry sessionEntry = getSessionEntry(false);
- if (sessionEntry != null)
- {
- sessionEntry.removePage(page);
- }
- }
-
- /**
- *
- * @param create
- * @return Session Entry
- */
- private SessionEntry getSessionEntry(boolean create)
- {
- SessionEntry entry = (SessionEntry)getSessionAttribute(getAttributeName());
- if (entry == null && create)
- {
- bind();
- entry = new SessionEntry(applicationName, getSessionId());
- }
- return entry;
- }
-
- @Override
- protected void newSessionCreated()
- {
- // if the session is not temporary bind a session entry to it
- if (getSessionId() != null)
- {
- getSessionEntry(true);
- }
- }
-
- @Override
- protected void storeTouchedPages(final List<IManageablePage> touchedPages)
- {
- if (!touchedPages.isEmpty())
- {
- SessionEntry entry = getSessionEntry(true);
- entry.setSessionCache(touchedPages);
- for (IManageablePage page : touchedPages)
- {
- // WICKET-5103 use the same sessionId as used in
- // SessionEntry#getPage()
- pageStore.storePage(entry.sessionId, page);
- }
-
- STORING_TOUCHED_PAGES.set(true);
- try
- {
- setSessionAttribute(getAttributeName(), entry);
- }
- finally
- {
- STORING_TOUCHED_PAGES.remove();
- }
- }
- }
- }
-
- @Override
- protected RequestAdapter newRequestAdapter(IPageManagerContext context)
- {
- return new PersistentRequestAdapter(context);
- }
-
- @Override
- public boolean supportsVersioning()
- {
- return true;
- }
-
- @Override
- public void clear()
- {
- RequestAdapter requestAdapter = getRequestAdapter();
- String sessionEntryAttributeName = getAttributeName();
- Serializable sessionEntry = requestAdapter.getSessionAttribute(sessionEntryAttributeName);
- if (sessionEntry instanceof SessionEntry)
- {
- ((SessionEntry)sessionEntry).valueUnbound(null);
- }
- }
-
- @Override
- public void destroy()
- {
- MANAGERS.remove(applicationName);
- pageStore.destroy();
- }
-}
http://git-wip-us.apache.org/repos/asf/wicket/blob/bcf76f51/wicket-core/src/main/java/org/apache/wicket/page/RequestAdapter.java
----------------------------------------------------------------------
diff --git a/wicket-core/src/main/java/org/apache/wicket/page/RequestAdapter.java b/wicket-core/src/main/java/org/apache/wicket/page/RequestAdapter.java
deleted file mode 100644
index 7b8b7b9..0000000
--- a/wicket-core/src/main/java/org/apache/wicket/page/RequestAdapter.java
+++ /dev/null
@@ -1,206 +0,0 @@
-/*
- * 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.page;
-
-import java.io.Serializable;
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.List;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * Request scoped helper class for {@link IPageManager}.
- *
- * @author Matej Knopp
- */
-public abstract class RequestAdapter
-{
- private static final Logger log = LoggerFactory.getLogger(RequestAdapter.class);
-
- private final IPageManagerContext context;
-
- private final List<IManageablePage> touchedPages = new ArrayList<IManageablePage>();
-
- /**
- * Construct.
- *
- * @param context
- * The page manager context
- */
- public RequestAdapter(final IPageManagerContext context)
- {
- this.context = context;
- }
-
- /**
- * Returns the page with specified id. The page is then cached by {@link RequestAdapter} during
- * the rest of request processing.
- *
- * @param id
- * @return page instance or <code>null</code> if the page does not exist.
- */
- protected abstract IManageablePage getPage(int id);
-
- /**
- * Removes a page from the cache and the stores ({@link org.apache.wicket.pageStore.IPageStore} and
- * {@link org.apache.wicket.pageStore.IDataStore}). Any attempt to access it later
- * will lead to {@link org.apache.wicket.protocol.http.PageExpiredException}
- *
- * @param page The page instance to remove
- */
- protected abstract void removePage(final IManageablePage page);
-
- /**
- * Store the list of stateful pages.
- *
- * @param touchedPages
- */
- protected abstract void storeTouchedPages(List<IManageablePage> touchedPages);
-
- /**
- * Notification on new session being created.
- */
- protected abstract void newSessionCreated();
-
- /**
- * Bind the session
- *
- * @see IPageManagerContext#bind()
- */
- protected void bind()
- {
- context.bind();
- }
-
- /**
- * @see IPageManagerContext#setSessionAttribute(String, Serializable)
- *
- * @param key
- * @param value
- */
- public void setSessionAttribute(String key, Serializable value)
- {
- context.setSessionAttribute(key, value);
- }
-
- /**
- * @see IPageManagerContext#getSessionAttribute(String)
- *
- * @param key
- * @return the session attribute
- */
- public Serializable getSessionAttribute(final String key)
- {
- return context.getSessionAttribute(key);
- }
-
- /**
- * @see IPageManagerContext#getSessionId()
- *
- * @return session id
- */
- public String getSessionId()
- {
- return context.getSessionId();
- }
-
- /**
- *
- * @param id
- * @return null, if not found
- */
- protected IManageablePage findPage(final int id)
- {
- for (IManageablePage page : touchedPages)
- {
- if (page.getPageId() == id)
- {
- return page;
- }
- }
- return null;
- }
-
- /**
- * Touches a page, so it will be stored in the page stores
- * at the end of the request cycle
- *
- * @param page The page to mark as dirty
- */
- protected void touch(final IManageablePage page)
- {
- if (findPage(page.getPageId()) == null)
- {
- touchedPages.add(page);
- }
- }
-
- /**
- * @param page The page to unmark as dirty, so it won't be stored
- * at the end of the request cycle
- */
- protected void untouch(final IManageablePage page)
- {
- Iterator<IManageablePage> iterator = touchedPages.iterator();
- while (iterator.hasNext())
- {
- IManageablePage touchedPage = iterator.next();
- if (touchedPage.getPageId() == page.getPageId())
- {
- iterator.remove();
- break;
- }
- }
- }
-
- /**
- *
- */
- protected void commitRequest()
- {
- // store pages that are not stateless
- if (touchedPages.isEmpty() == false)
- {
- List<IManageablePage> statefulPages = new ArrayList<IManageablePage>(
- touchedPages.size());
- for (IManageablePage page : touchedPages)
- {
- boolean isPageStateless;
- try
- {
- isPageStateless = page.isPageStateless();
- }
- catch (Exception x)
- {
- log.warn("An error occurred while checking whether a page is stateless. Assuming it is stateful.", x);
- isPageStateless = false;
- }
- if (isPageStateless == false)
- {
- statefulPages.add(page);
- }
- }
-
- if (statefulPages.isEmpty() == false)
- {
- storeTouchedPages(statefulPages);
- }
- }
- }
-}
http://git-wip-us.apache.org/repos/asf/wicket/blob/bcf76f51/wicket-core/src/main/java/org/apache/wicket/pageStore/AbstractCachingPageStore.java
----------------------------------------------------------------------
diff --git a/wicket-core/src/main/java/org/apache/wicket/pageStore/AbstractCachingPageStore.java b/wicket-core/src/main/java/org/apache/wicket/pageStore/AbstractCachingPageStore.java
deleted file mode 100644
index 86b8d82..0000000
--- a/wicket-core/src/main/java/org/apache/wicket/pageStore/AbstractCachingPageStore.java
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
- * 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;
-
-/**
- * An abstract {@link org.apache.wicket.pageStore.IPageStore} that uses
- * {@link org.apache.wicket.pageStore.SecondLevelPageCache} to cache the stored pages in memory
- *
- * @param <P>
- * The type of the page to be stored
- */
-public abstract class AbstractCachingPageStore<P> extends AbstractPageStore
-{
- /**
- * The cache implementation
- */
- protected final SecondLevelPageCache<String, Integer, P> pagesCache;
-
- /**
- * Constructor.
- *
- * @param pageSerializer
- * The serializer that will convert pages to/from byte[]
- * @param dataStore
- * The third level page cache
- * @param pagesCache
- * The cache to use as a second level store
- */
- protected AbstractCachingPageStore(ISerializer pageSerializer, IDataStore dataStore,
- SecondLevelPageCache<String, Integer, P> pagesCache)
- {
- super(pageSerializer, dataStore);
-
- this.pagesCache = Args.notNull(pagesCache, "pagesCache");
- }
-
- @Override
- public IManageablePage getPage(final String sessionId, final int pageId)
- {
- P fromCache = pagesCache.getPage(sessionId, pageId);
- if (fromCache != null)
- {
- return convertToPage(fromCache);
- }
-
- byte[] data = getPageData(sessionId, pageId);
- if (data != null)
- {
- return deserializePage(data);
- }
- return null;
- }
-
- @Override
- public void removePage(final String sessionId, final int pageId)
- {
- pagesCache.removePage(sessionId, pageId);
- removePageData(sessionId, pageId);
- }
-
- @SuppressWarnings("unchecked")
- @Override
- public void storePage(final String sessionId, final IManageablePage page)
- {
- byte[] data = serializePage(page);
- if (data != null)
- {
- int pageId = page.getPageId();
- pagesCache.storePage(sessionId, pageId, (P) page);
- storePageData(sessionId, pageId, data);
- }
- }
-
- @Override
- public void unbind(final String sessionId)
- {
- removePageData(sessionId);
- pagesCache.removePages(sessionId);
- }
-
- @Override
- public void destroy()
- {
- super.destroy();
- pagesCache.destroy();
- }
-}
http://git-wip-us.apache.org/repos/asf/wicket/blob/bcf76f51/wicket-core/src/main/java/org/apache/wicket/pageStore/AbstractPageStore.java
----------------------------------------------------------------------
diff --git a/wicket-core/src/main/java/org/apache/wicket/pageStore/AbstractPageStore.java b/wicket-core/src/main/java/org/apache/wicket/pageStore/AbstractPageStore.java
deleted file mode 100644
index 07f97d5..0000000
--- a/wicket-core/src/main/java/org/apache/wicket/pageStore/AbstractPageStore.java
+++ /dev/null
@@ -1,154 +0,0 @@
-/*
- * 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.Serializable;
-
-import org.apache.wicket.page.IManageablePage;
-import org.apache.wicket.serialize.ISerializer;
-import org.apache.wicket.util.lang.Args;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- *
- */
-public abstract class AbstractPageStore implements IPageStore
-{
- private static final Logger LOG = LoggerFactory.getLogger(AbstractPageStore.class);
-
- protected final IDataStore dataStore;
-
- /**
- * The {@link org.apache.wicket.serialize.ISerializer} that will be used to convert pages from/to byte arrays
- */
- protected final ISerializer pageSerializer;
-
- protected AbstractPageStore(final ISerializer pageSerializer, final IDataStore dataStore)
- {
- Args.notNull(pageSerializer, "pageSerializer");
- Args.notNull(dataStore, "dataStore");
-
- this.pageSerializer = pageSerializer;
- this.dataStore = dataStore;
- }
-
- @Override
- public void destroy()
- {
- dataStore.destroy();
- }
-
- @Override
- public Serializable prepareForSerialization(final String sessionId, final Serializable page)
- {
- if (dataStore.isReplicated())
- {
- return null;
- }
-
- return page;
- }
-
- @Override
- public Object restoreAfterSerialization(final Serializable serializable)
- {
- return serializable;
- }
-
- /**
- * @param sessionId
- * The id of the http session
- * @param pageId
- * The id of page which serialized data should be got
- * @return page data
- * @see org.apache.wicket.pageStore.IDataStore#getData(String, int)
- */
- protected byte[] getPageData(final String sessionId, final int pageId)
- {
- return dataStore.getData(sessionId, pageId);
- }
-
- /**
- * @param sessionId
- * The id of the http session
- * @param pageId
- * The id of page which serialized data should be removed
- * @see org.apache.wicket.pageStore.IDataStore#removeData(String, int)
- */
- protected void removePageData(final String sessionId, final int pageId)
- {
- dataStore.removeData(sessionId, pageId);
- }
-
- /**
- * @param sessionId
- * The id of the http session for which all data should be removed
- * @see org.apache.wicket.pageStore.IDataStore#removeData(String)
- */
- protected void removePageData(final String sessionId)
- {
- dataStore.removeData(sessionId);
- }
-
- /**
- * @param sessionId
- * The id of the http session
- * @param pageId
- * The id of the page to store
- * @param data
- * The serialized view of the page
- * @see org.apache.wicket.pageStore.IDataStore#storeData(String, int, byte[])
- */
- protected void storePageData(final String sessionId, final int pageId, final byte[] data)
- {
- dataStore.storeData(sessionId, pageId, data);
- }
-
- /**
- * Serializes the passed page to byte[]
- *
- * @param page
- * The page to serialize
- * @return the serialized view of the passed page
- */
- protected byte[] serializePage(final IManageablePage page)
- {
- Args.notNull(page, "page");
-
- byte[] data = pageSerializer.serialize(page);
-
- if (data == null && LOG.isWarnEnabled())
- {
- LOG.warn("Page {} cannot be serialized. See previous logs for possible reasons.", page);
- }
- return data;
- }
-
- /**
- *
- * @param data
- * The serialized view of the page
- * @return page data deserialized
- */
- protected IManageablePage deserializePage(final byte[] data)
- {
- Args.notNull(data, "data");
-
- return (IManageablePage) pageSerializer.deserialize(data);
- }
-}
http://git-wip-us.apache.org/repos/asf/wicket/blob/bcf76f51/wicket-core/src/main/java/org/apache/wicket/pageStore/AsynchronousDataStore.java
----------------------------------------------------------------------
diff --git a/wicket-core/src/main/java/org/apache/wicket/pageStore/AsynchronousDataStore.java b/wicket-core/src/main/java/org/apache/wicket/pageStore/AsynchronousDataStore.java
deleted file mode 100644
index 7ccd689..0000000
--- a/wicket-core/src/main/java/org/apache/wicket/pageStore/AsynchronousDataStore.java
+++ /dev/null
@@ -1,353 +0,0 @@
-/*
- * 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.util.Iterator;
-import java.util.concurrent.BlockingQueue;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.ConcurrentMap;
-import java.util.concurrent.LinkedBlockingQueue;
-import java.util.concurrent.TimeUnit;
-
-import org.apache.wicket.util.lang.Args;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * Facade for {@link IDataStore} that does the actual saving in worker thread.
- * <p>
- * Creates an {@link Entry} for each triple (sessionId, pageId, data) and puts it in
- * {@link #entries} queue if there is room. Acts as producer.<br/>
- * Later {@link PageSavingRunnable} reads in blocking manner from {@link #entries} and saves each
- * entry. Acts as consumer.
- * </p>
- * It starts only one instance of {@link PageSavingRunnable} because all we need is to make the page
- * storing asynchronous. We don't want to write concurrently in the wrapped {@link IDataStore},
- * though it may happen in the extreme case when the queue is full. These cases should be avoided.
- *
- * @author Matej Knopp
- */
-public class AsynchronousDataStore implements IDataStore
-{
- /** Log for reporting. */
- private static final Logger log = LoggerFactory.getLogger(AsynchronousDataStore.class);
-
- /**
- * The time to wait when adding an {@link Entry} into the entries. In millis.
- */
- private static final long OFFER_WAIT = 30L;
-
- /**
- * The time to wait for an entry to save with the wrapped {@link IDataStore}. In millis.
- */
- private static final long POLL_WAIT = 1000L;
-
- /**
- * The page saving thread.
- */
- private final Thread pageSavingThread;
-
- /**
- * The wrapped {@link IDataStore} that actually stores that pages
- */
- private final IDataStore dataStore;
-
- /**
- * The queue where the entries which have to be saved are temporary stored
- */
- private final BlockingQueue<Entry> entries;
-
- /**
- * A map 'sessionId:::pageId' -> {@link Entry}. Used for fast retrieval of {@link Entry}s which
- * are not yet stored by the wrapped {@link IDataStore}
- */
- private final ConcurrentMap<String, Entry> entryMap;
-
- /**
- * Construct.
- *
- * @param dataStore
- * the wrapped {@link IDataStore} that actually saved the data
- * @param capacity
- * the capacity of the queue that delays the saving
- */
- public AsynchronousDataStore(final IDataStore dataStore, final int capacity)
- {
- this.dataStore = dataStore;
- entries = new LinkedBlockingQueue<>(capacity);
- entryMap = new ConcurrentHashMap<>();
-
- PageSavingRunnable savingRunnable = new PageSavingRunnable(dataStore, entries, entryMap);
- pageSavingThread = new Thread(savingRunnable, "Wicket-AsyncDataStore-PageSavingThread");
- pageSavingThread.setDaemon(true);
- pageSavingThread.start();
- }
-
- @Override
- public void destroy()
- {
- if (pageSavingThread.isAlive())
- {
- pageSavingThread.interrupt();
- try
- {
- pageSavingThread.join();
- } catch (InterruptedException e)
- {
- log.error(e.getMessage(), e);
- }
- }
-
- dataStore.destroy();
- }
-
- /**
- * Little helper
- *
- * @param sessionId
- * @param id
- * @return Entry
- */
- private Entry getEntry(final String sessionId, final int id)
- {
- return entryMap.get(getKey(sessionId, id));
- }
-
- @Override
- public byte[] getData(final String sessionId, final int id)
- {
- Entry entry = getEntry(sessionId, id);
- if (entry != null)
- {
- log.debug(
- "Returning the data of a non-stored entry with sessionId '{}' and pageId '{}'",
- sessionId, id);
- return entry.data;
- }
- byte[] data = dataStore.getData(sessionId, id);
-
- log.debug("Returning the data of a stored entry with sessionId '{}' and pageId '{}'",
- sessionId, id);
-
- return data;
- }
-
- @Override
- public boolean isReplicated()
- {
- return dataStore.isReplicated();
- }
-
- @Override
- public void removeData(final String sessionId, final int id)
- {
- String key = getKey(sessionId, id);
- if (key != null)
- {
- Entry entry = entryMap.remove(key);
- if (entry != null)
- {
- entries.remove(entry);
- }
- }
-
- dataStore.removeData(sessionId, id);
- }
-
- @Override
- public void removeData(final String sessionId)
- {
- for (Iterator<Entry> itor = entries.iterator(); itor.hasNext();)
- {
- Entry entry = itor.next();
- if (entry != null) // this check is not needed in JDK6
- {
- String entrySessionId = entry.sessionId;
-
- if (sessionId.equals(entrySessionId))
- {
- entryMap.remove(getKey(entry));
- itor.remove();
- }
- }
- }
-
- dataStore.removeData(sessionId);
- }
-
- /**
- * Save the entry in the queue if there is a room or directly pass it to the wrapped
- * {@link IDataStore} if there is no such
- *
- * @see org.apache.wicket.pageStore.IDataStore#storeData(java.lang.String, int, byte[])
- */
- @Override
- public void storeData(final String sessionId, final int id, final byte[] data)
- {
- Entry entry = new Entry(sessionId, id, data);
- String key = getKey(entry);
- entryMap.put(key, entry);
-
- try
- {
- boolean added = entries.offer(entry, OFFER_WAIT, TimeUnit.MILLISECONDS);
-
- if (added == false)
- {
- log.debug("Storing synchronously page with id '{}' in session '{}'", id, sessionId);
- entryMap.remove(key);
- dataStore.storeData(sessionId, id, data);
- }
- }
- catch (InterruptedException e)
- {
- log.error(e.getMessage(), e);
- entryMap.remove(key);
- dataStore.storeData(sessionId, id, data);
- }
- }
-
- /**
- *
- * @param pageId
- * @param sessionId
- * @return generated key
- */
- private static String getKey(final String sessionId, final int pageId)
- {
- return pageId + ":::" + sessionId;
- }
-
- /**
- *
- * @param entry
- * @return generated key
- */
- private static String getKey(final Entry entry)
- {
- return getKey(entry.sessionId, entry.pageId);
- }
-
- /**
- * The structure used for an entry in the queue
- */
- private static class Entry
- {
- private final String sessionId;
- private final int pageId;
- private final byte data[];
-
- public Entry(final String sessionId, final int pageId, final byte data[])
- {
- this.sessionId = Args.notNull(sessionId, "sessionId");
- this.pageId = pageId;
- this.data = Args.notNull(data, "data");
- }
-
- @Override
- public int hashCode()
- {
- final int prime = 31;
- int result = 1;
- result = prime * result + pageId;
- result = prime * result + ((sessionId == null) ? 0 : sessionId.hashCode());
- return result;
- }
-
- @Override
- public boolean equals(Object obj)
- {
- if (this == obj)
- return true;
- if (obj == null)
- return false;
- if (getClass() != obj.getClass())
- return false;
- Entry other = (Entry)obj;
- if (pageId != other.pageId)
- return false;
- if (sessionId == null)
- {
- if (other.sessionId != null)
- return false;
- }
- else if (!sessionId.equals(other.sessionId))
- return false;
- return true;
- }
-
- @Override
- public String toString()
- {
- return "Entry [sessionId=" + sessionId + ", pageId=" + pageId + "]";
- }
-
- }
-
- /**
- * The thread that acts as consumer of {@link Entry}ies
- */
- private static class PageSavingRunnable implements Runnable
- {
- private static final Logger log = LoggerFactory.getLogger(PageSavingRunnable.class);
-
- private final BlockingQueue<Entry> entries;
-
- private final ConcurrentMap<String, Entry> entryMap;
-
- private final IDataStore dataStore;
-
- private PageSavingRunnable(IDataStore dataStore, BlockingQueue<Entry> entries,
- ConcurrentMap<String, Entry> entryMap)
- {
- this.dataStore = dataStore;
- this.entries = entries;
- this.entryMap = entryMap;
- }
-
- @Override
- public void run()
- {
- while (!Thread.interrupted())
- {
- Entry entry = null;
- try
- {
- entry = entries.poll(POLL_WAIT, TimeUnit.MILLISECONDS);
- }
- catch (InterruptedException e)
- {
- Thread.currentThread().interrupt();
- }
-
- if (entry != null)
- {
- log.debug("Saving asynchronously: {}...", entry);
- dataStore.storeData(entry.sessionId, entry.pageId, entry.data);
- entryMap.remove(getKey(entry));
- }
- }
- }
- }
-
- @Override
- public final boolean canBeAsynchronous()
- {
- // should not wrap in another AsynchronousDataStore
- return false;
- }
-}
[3/5] wicket git commit: WICKET-6563 new IPageStore implementation
Posted by sv...@apache.org.
http://git-wip-us.apache.org/repos/asf/wicket/blob/bcf76f51/wicket-core/src/main/java/org/apache/wicket/pageStore/IPersistedPage.java
----------------------------------------------------------------------
diff --git a/wicket-core/src/main/java/org/apache/wicket/pageStore/IPersistedPage.java b/wicket-core/src/main/java/org/apache/wicket/pageStore/IPersistedPage.java
new file mode 100644
index 0000000..8a03507
--- /dev/null
+++ b/wicket-core/src/main/java/org/apache/wicket/pageStore/IPersistedPage.java
@@ -0,0 +1,44 @@
+/*
+ * 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.Serializable;
+
+import org.apache.wicket.util.lang.Bytes;
+
+/**
+ * Information about a persisted page in an {@link IPersistentPageStore}.
+ *
+ * @see IPersistentPageStore#getPersistentPages(String, int)
+ */
+public interface IPersistedPage extends Serializable
+{
+ /**
+ * Id of page.
+ */
+ int getPageId();
+
+ /**
+ * Size of page.
+ */
+ Bytes getPageSize();
+
+ /**
+ * Type of page.
+ */
+ String getPageType();
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/wicket/blob/bcf76f51/wicket-core/src/main/java/org/apache/wicket/pageStore/IPersistentPageStore.java
----------------------------------------------------------------------
diff --git a/wicket-core/src/main/java/org/apache/wicket/pageStore/IPersistentPageStore.java b/wicket-core/src/main/java/org/apache/wicket/pageStore/IPersistentPageStore.java
new file mode 100644
index 0000000..b42746d
--- /dev/null
+++ b/wicket-core/src/main/java/org/apache/wicket/pageStore/IPersistentPageStore.java
@@ -0,0 +1,51 @@
+/*
+ * 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.util.List;
+import java.util.Set;
+
+import org.apache.wicket.util.lang.Bytes;
+
+/**
+ * A store that can provide information about stored pages.
+ */
+public interface IPersistentPageStore extends IPageStore
+{
+
+ /**
+ * Get the identifier for pages stored for the given context.
+ */
+ String getSessionIdentifier(IPageContext context);
+
+ /**
+ * Get the identifiers for all pages stored in all contexts.
+ */
+ Set<String> getSessionIdentifiers();
+
+ /**
+ * Get information about all persisted pages with the given session identifier.
+ */
+ List<IPersistedPage> getPersistentPages(String sessionIdentifier);
+
+ /**
+ * Get total size of all stored pages.
+ *
+ * @return
+ */
+ Bytes getTotalSize();
+}
http://git-wip-us.apache.org/repos/asf/wicket/blob/bcf76f51/wicket-core/src/main/java/org/apache/wicket/pageStore/InMemoryPageStore.java
----------------------------------------------------------------------
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
new file mode 100644
index 0000000..fc11901
--- /dev/null
+++ b/wicket-core/src/main/java/org/apache/wicket/pageStore/InMemoryPageStore.java
@@ -0,0 +1,352 @@
+/*
+ * 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.Serializable;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+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;
+
+/**
+ * A storage of pages in memory.
+ */
+public class InMemoryPageStore implements IPersistentPageStore
+{
+
+ /**
+ * 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;
+
+ /**
+ * @param applicationName
+ * {@link Application#getName()}
+ * @param maxPages
+ * max pages per session
+ */
+ public InMemoryPageStore(String applicationName, int maxPages)
+ {
+ this.applicationName = Args.notNull(applicationName, "applicationName");
+ this.maxPages = maxPages;
+
+ IN_MEMORY_STORES.put(applicationName, this);
+ }
+
+ /**
+ *
+ *
+ * @return <code>true</code> always
+ */
+ @Override
+ public boolean canBeAsynchronous(IPageContext context)
+ {
+ // session attribute must be added here *before* any asynchronous calls
+ // when session is no longer available
+ getSessionAttribute(context, true);
+
+ return true;
+ }
+
+ protected SessionAttribute getSessionAttribute(IPageContext context, boolean create)
+ {
+ context.bind();
+
+ 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)
+ {
+ MemoryData data = getMemoryData(context, false);
+ if (data == null)
+ {
+ return null;
+ }
+
+ return data.get(id);
+ }
+
+ @Override
+ public void removePage(IPageContext context, final IManageablePage page)
+ {
+ MemoryData data = getMemoryData(context, false);
+
+ if (data != null)
+ {
+ synchronized (data)
+ {
+ data.remove(page);
+ }
+ }
+ }
+
+ @Override
+ public void removeAllPages(IPageContext context)
+ {
+ MemoryData data = getMemoryData(context, false);
+
+ if (data != null)
+ {
+ synchronized (data)
+ {
+ data.removeAll();
+ }
+ }
+ }
+
+ @Override
+ public void addPage(IPageContext context, IManageablePage page)
+ {
+ MemoryData data = getMemoryData(context, true);
+
+ data.add(page, maxPages);
+ }
+
+ @Override
+ public String getSessionIdentifier(IPageContext context)
+ {
+ return context.getSessionId();
+ }
+
+ @Override
+ public Set<String> getSessionIdentifiers()
+ {
+ return datas.keySet();
+ }
+
+ @Override
+ public List<IPersistedPage> getPersistentPages(String sessionIdentifier)
+ {
+ MemoryData data = datas.get(sessionIdentifier);
+ if (data == null)
+ {
+ return new ArrayList<>();
+ }
+
+ synchronized (data)
+ {
+ return StreamSupport.stream(data.spliterator(), false)
+ .map(page -> new MermoryPersistedPage(page, getSize(page)))
+ .collect(Collectors.toList());
+ }
+ }
+
+ @Override
+ public Bytes getTotalSize()
+ {
+ int size = 0;
+
+ for (MemoryData data : datas.values())
+ {
+ synchronized (data)
+ {
+ for (IManageablePage page : data)
+ {
+ size += getSize(page);
+ }
+ }
+ }
+
+ return Bytes.bytes(size);
+ }
+
+ protected long getSize(IManageablePage page)
+ {
+ return WicketObjects.sizeof(page);
+ }
+
+ private MemoryData getMemoryData(IPageContext context, boolean create)
+ {
+ SessionAttribute attribute = getSessionAttribute(context, create);
+
+ if (!create)
+ {
+ if (attribute == null) {
+ return null;
+ } else {
+ return datas.get(attribute.identifier);
+ }
+ }
+
+ MemoryData data = new MemoryData();
+ MemoryData existing = datas.putIfAbsent(attribute.identifier, data);
+ return existing != null ? existing : data;
+ }
+
+ private void removeMemoryData(String identifier)
+ {
+ datas.remove(identifier);
+ }
+
+ /**
+ * Data kept in memory.
+ */
+ static class MemoryData implements Iterable<IManageablePage>
+ {
+ private LinkedHashMap<Integer, IManageablePage> pages = new LinkedHashMap<>();
+
+ @Override
+ public Iterator<IManageablePage> iterator()
+ {
+ return pages.values().iterator();
+ }
+
+ public synchronized void add(IManageablePage page, int maxPages)
+ {
+ 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)
+ {
+ pages.remove(page.getPageId());
+ }
+
+ public void removeAll()
+ {
+ pages.clear();
+ }
+
+ public IManageablePage get(int id)
+ {
+ IManageablePage page = pages.get(id);
+
+ 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 MermoryPersistedPage implements IPersistedPage
+ {
+
+ private final int id;
+
+ private final String type;
+
+ private final long size;
+
+ public MermoryPersistedPage(IManageablePage page, long size)
+ {
+ this.id = page.getPageId();
+ this.type = page.getClass().getName();
+ 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
http://git-wip-us.apache.org/repos/asf/wicket/blob/bcf76f51/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
new file mode 100644
index 0000000..3914464
--- /dev/null
+++ b/wicket-core/src/main/java/org/apache/wicket/pageStore/InSessionPageStore.java
@@ -0,0 +1,268 @@
+/*
+ * 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.IOException;
+import java.io.ObjectOutputStream;
+import java.io.Serializable;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.Map.Entry;
+
+import javax.servlet.http.HttpSession;
+
+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;
+
+/**
+ * A store keeping a configurable maximum of pages in the session, delegating all or excessive pages
+ * to another store.
+ */
+public class InSessionPageStore extends DelegatingPageStore
+{
+
+ private static final MetaDataKey<SessionData> KEY = new MetaDataKey<SessionData>()
+ {
+ private static final long serialVersionUID = 1L;
+ };
+
+ private ISerializer serializer;
+
+ private int maxPages;
+
+ private boolean delegateAll = false;
+
+ /**
+ * Use this constructor, if sessions are never serialized.
+ *
+ * @param delegate
+ * store to delegate to
+ * @param maxPages
+ * maximum pages to keep in session
+ */
+ public InSessionPageStore(IPageStore delegate, int maxPages)
+ {
+ this(delegate, new ISerializer()
+ {
+ @Override
+ public byte[] serialize(Object object)
+ {
+ throw new WicketRuntimeException("InSessionPageStore not configured for serialization");
+ }
+
+ @Override
+ public Object deserialize(byte[] data)
+ {
+ throw new WicketRuntimeException("InSessionPageStore not configured for serialization");
+ }
+ }, maxPages);
+ }
+
+ /**
+ * @param delegate
+ * store to delegate to
+ * @param serializer
+ * serializer to use if session gets persisted
+ * @param maxPages
+ * maximum pages to keep in session
+ */
+ public InSessionPageStore(IPageStore delegate, ISerializer serializer, int maxPages)
+ {
+ super(delegate);
+
+ this.serializer = Args.notNull(serializer, "serializer");
+
+ 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)
+ {
+ IManageablePage page = getSessionData(context).get(id);
+ if (page != null)
+ {
+ return page;
+ }
+
+ return super.getPage(context, id);
+ }
+
+ @Override
+ public void addPage(IPageContext context, IManageablePage page)
+ {
+ SessionData data = getSessionData(context);
+
+ data.addAndDelegate(context, page, maxPages, delegateAll, getDelegate());
+ }
+
+ @Override
+ public void removePage(IPageContext context, IManageablePage page)
+ {
+ getSessionData(context).remove(page);
+
+ super.removePage(context, page);
+ }
+
+ @Override
+ public void removeAllPages(IPageContext context)
+ {
+ getSessionData(context).removeAll();
+
+ super.removeAllPages(context);
+ }
+
+ private SessionData getSessionData(IPageContext context)
+ {
+ SessionData data = context.getSessionData(KEY);
+ if (data == null)
+ {
+ context.bind();
+ data = new SessionData();
+
+ context.setSessionData(KEY, data);
+ }
+
+ // data might be deserialized so initialize again
+ data.init(serializer);
+
+ return data;
+ }
+
+ /**
+ * Data kept in the {@link Session}, might get serialized along with its containing
+ * {@link HttpSession}.
+ */
+ static class SessionData implements Serializable
+ {
+
+ transient ISerializer serializer;
+
+ /**
+ * Pages, may partly be serialized.
+ */
+ private LinkedHashMap<Integer, Serializable> pages = new LinkedHashMap<>();
+
+ /**
+ * 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.
+ */
+ public void init(ISerializer serializer)
+ {
+ this.serializer = Args.notNull(serializer, "serializer");
+ }
+
+ public synchronized void addAndDelegate(IPageContext context, IManageablePage page,
+ int maxPages, boolean delegateAll, IPageStore delegate)
+ {
+ pages.remove(page.getPageId());
+ pages.put(page.getPageId(), 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
+ {
+ // 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);
+ }
+ }
+ }
+
+ public synchronized void remove(IManageablePage page)
+ {
+ pages.remove(page.getPageId());
+ }
+
+ public synchronized void removeAll()
+ {
+ pages.clear();
+ }
+
+ public synchronized IManageablePage get(int id)
+ {
+ Serializable serializable = pages.get(id);
+
+ if (serializable instanceof byte[])
+ {
+ if (serializer == null)
+ {
+ throw new IllegalStateException("SessionData#init() was not called");
+ }
+ serializable = (Serializable)serializer.deserialize((byte[])serializable);
+
+ pages.put(id, serializable);
+ }
+
+ return (IManageablePage)serializable;
+ }
+
+ /**
+ * Serialize pages before writing to output.
+ */
+ private void writeObject(final ObjectOutputStream output) throws IOException
+ {
+ // serialize pages if not already
+ for (Entry<Integer, Serializable> entry : pages.entrySet())
+ {
+ if (entry.getValue() instanceof IManageablePage)
+ {
+ if (serializer == null)
+ {
+ throw new IllegalStateException("SessionData#init() was not called");
+ }
+ entry.setValue(serializer.serialize(entry.getValue()));
+ }
+ }
+
+ output.defaultWriteObject();
+ }
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/wicket/blob/bcf76f51/wicket-core/src/main/java/org/apache/wicket/pageStore/NoopPageStore.java
----------------------------------------------------------------------
diff --git a/wicket-core/src/main/java/org/apache/wicket/pageStore/NoopPageStore.java b/wicket-core/src/main/java/org/apache/wicket/pageStore/NoopPageStore.java
new file mode 100644
index 0000000..846c858
--- /dev/null
+++ b/wicket-core/src/main/java/org/apache/wicket/pageStore/NoopPageStore.java
@@ -0,0 +1,53 @@
+/*
+ * 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;
+
+/**
+ * A non-storage of pages.
+ */
+public class NoopPageStore implements IPageStore
+{
+
+ @Override
+ public boolean canBeAsynchronous(IPageContext context)
+ {
+ return true;
+ }
+
+ @Override
+ public void addPage(IPageContext context, IManageablePage page)
+ {
+ }
+
+ @Override
+ public void removePage(IPageContext context, IManageablePage page)
+ {
+ }
+
+ @Override
+ public void removeAllPages(IPageContext context)
+ {
+ }
+
+ @Override
+ public IManageablePage getPage(IPageContext context, int id)
+ {
+ return null;
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/wicket/blob/bcf76f51/wicket-core/src/main/java/org/apache/wicket/pageStore/PageWindowManager.java
----------------------------------------------------------------------
diff --git a/wicket-core/src/main/java/org/apache/wicket/pageStore/PageWindowManager.java b/wicket-core/src/main/java/org/apache/wicket/pageStore/PageWindowManager.java
deleted file mode 100644
index f194710..0000000
--- a/wicket-core/src/main/java/org/apache/wicket/pageStore/PageWindowManager.java
+++ /dev/null
@@ -1,506 +0,0 @@
-/*
- * 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.Serializable;
-import java.util.ArrayList;
-import java.util.List;
-
-import org.apache.wicket.util.collections.IntHashMap;
-
-/**
- * Manages positions and size of serialized pages in the pagemap file.
- * <p>
- * The pages are stored inside the file in a cyclic way. Newer pages are placed after older ones,
- * until the maximum file size is reached. After that, the next page is stored in the beginning of
- * the file.
- *
- * @author Matej Knopp
- */
-public class PageWindowManager implements Serializable
-{
- private static final long serialVersionUID = 1L;
-
- /**
- * Contains information about a page inside the file.
- *
- * @author Matej Knopp
- */
- private static class PageWindowInternal implements Serializable
- {
- private static final long serialVersionUID = 1L;
-
- /** id of page or -1 if the window is empty */
- private int pageId;
-
- /** offset in the file where the serialized page data begins */
- private int filePartOffset;
-
- /** size of serialized page data */
- private int filePartSize;
- }
-
- /** list of PageWindowInternal objects */
- private final List<PageWindowInternal> windows = new ArrayList<PageWindowInternal>();
-
- /**
- * map from page id to list of pagewindow indices (referring to the windows list) - to improve
- * searching speed the index must be cleaned when the instances in the windows list change their
- * indexes (e.g. items are shifted on page window removal)
- */
- private IntHashMap<Integer> idToWindowIndex = null;
-
- /**
- * Inversed index of #idToWindowIndex
- */
- private IntHashMap<Integer> windowIndexToPageId = null;
-
- /** index of last added page */
- private int indexPointer = -1;
-
- private int totalSize = 0;
-
- /**
- * Maximum page size. After this size is exceeded, the pages will be saved starting at the
- * beginning of file.
- */
- private final long maxSize;
-
- /**
- *
- * @param pageId
- * @param windowIndex
- */
- private void putWindowIndex(int pageId, int windowIndex)
- {
- if (idToWindowIndex != null && pageId != -1 && windowIndex != -1)
- {
- Integer oldPageId = windowIndexToPageId.remove(windowIndex);
- if (oldPageId != null)
- {
- idToWindowIndex.remove(oldPageId);
- }
- idToWindowIndex.put(pageId, windowIndex);
- windowIndexToPageId.put(windowIndex, pageId);
- }
- }
-
- /**
- *
- * @param pageId
- */
- private void removeWindowIndex(int pageId)
- {
- Integer windowIndex = idToWindowIndex.remove(pageId);
- if (windowIndex != null)
- {
- windowIndexToPageId.remove(windowIndex);
- }
- }
-
- /**
- *
- */
- private void rebuildIndices()
- {
- idToWindowIndex = null;
- idToWindowIndex = new IntHashMap<Integer>();
- windowIndexToPageId = null;
- windowIndexToPageId = new IntHashMap<Integer>();
- for (int i = 0; i < windows.size(); ++i)
- {
- PageWindowInternal window = windows.get(i);
- putWindowIndex(window.pageId, i);
- }
- }
-
- /**
- * Returns the index of the given page in the {@link #windows} list.
- *
- * @param pageId
- * @return window index
- */
- private int getWindowIndex(int pageId)
- {
- if (idToWindowIndex == null)
- {
- rebuildIndices();
- }
-
- Integer result = idToWindowIndex.get(pageId);
- return result != null ? result : -1;
- }
-
- /**
- * Increments the {@link #indexPointer}. If the maximum file size has been reached, the
- * {@link #indexPointer} is set to 0.
- *
- * @return new index pointer
- */
- private int incrementIndexPointer()
- {
- if ((maxSize > 0) && (totalSize >= maxSize) && (indexPointer == windows.size() - 1))
- {
- indexPointer = 0;
- }
- else
- {
- ++indexPointer;
- }
- return indexPointer;
- }
-
- /**
- * Returns the offset in file of the window on given index. The offset is counted by getting the
- * previous page offset and adding the previous page size to it.
- *
- * @param index
- * @return window file offset
- */
- private int getWindowFileOffset(int index)
- {
- if (index > 0)
- {
- PageWindowInternal window = windows.get(index - 1);
- return window.filePartOffset + window.filePartSize;
- }
- return 0;
- }
-
- /**
- * Splits the window with given index to two windows. First of those will have size specified by
- * the argument, the other one will fill up the rest of the original window.
- *
- * @param index
- * @param size
- */
- private void splitWindow(int index, int size)
- {
- PageWindowInternal window = windows.get(index);
- int delta = window.filePartSize - size;
-
- if (index == windows.size() - 1)
- {
- // if this is last window
- totalSize -= delta;
- window.filePartSize = size;
- }
- else if (window.filePartSize != size)
- {
- PageWindowInternal newWindow = new PageWindowInternal();
- newWindow.pageId = -1;
- window.filePartSize = size;
-
- windows.add(index + 1, newWindow);
-
- newWindow.filePartOffset = getWindowFileOffset(index + 1);
- newWindow.filePartSize = delta;
- }
-
- idToWindowIndex = null;
- windowIndexToPageId = null;
- }
-
- /**
- * Merges the window with given index with the next window. The resulting window will have size
- * of the two windows summed together.
- *
- * @param index
- */
- private void mergeWindowWithNext(int index)
- {
- if (index < windows.size() - 1)
- {
- PageWindowInternal window = windows.get(index);
- PageWindowInternal next = windows.get(index + 1);
- window.filePartSize += next.filePartSize;
-
- windows.remove(index + 1);
- idToWindowIndex = null; // reset index
- windowIndexToPageId = null;
- }
- }
-
- /**
- * Adjusts the window on given index to the specified size. If the new size is smaller than the
- * window size, the window will be split. Otherwise the window will be merged with as many
- * subsequent window as necessary. In case the window is last window in the file, the size will
- * be adjusted without splitting or merging.
- *
- * @param index
- * @param size
- */
- private void adjustWindowSize(int index, int size)
- {
- PageWindowInternal window = windows.get(index);
-
- // last window, just adjust size
- if (index == windows.size() - 1)
- {
- int delta = size - window.filePartSize;
- totalSize += delta;
- window.filePartSize = size;
- }
- else
- {
- // merge as many times as necessary
- while (window.filePartSize < size && index < windows.size() - 1)
- {
- mergeWindowWithNext(index);
- }
-
- // done merging - do we have enough room ?
- if (window.filePartSize < size)
- {
- // no, this is the last window
- int delta = size - window.filePartSize;
- totalSize += delta;
- window.filePartSize = size;
- }
- else
- {
- // yes, we might want to split the window, so that we don't lose
- // space when the created window was too big
- splitWindow(index, size);
- }
- }
-
- window.pageId = -1;
- }
-
- /**
- * Allocates window on given index with to size. If the index is pointing to existing window,
- * the window size will be adjusted. Otherwise a new window with appropriated size will be
- * created.
- *
- * @param index
- * @param size
- * @return page window
- */
- private PageWindowInternal allocatePageWindow(int index, int size)
- {
- final PageWindowInternal window;
-
- // new window
- if (index == windows.size())
- {
- // new page window
- window = new PageWindowInternal();
- window.filePartOffset = getWindowFileOffset(index);
- totalSize += size;
- window.filePartSize = size;
- windows.add(window);
- }
- else
- {
- // get the window
- window = windows.get(index);
-
- // adjust if necessary
- if (window.filePartSize != size)
- {
- adjustWindowSize(index, size);
- }
- }
-
- return window;
- }
-
- /**
- * Public (read only) version of page window.
- *
- * @author Matej Knopp
- */
- public static class PageWindow
- {
- private final PageWindowInternal pageWindowInternal;
-
- /**
- * Construct.
- *
- * @param pageWindowInternal
- */
- private PageWindow(PageWindowInternal pageWindowInternal)
- {
- this.pageWindowInternal = pageWindowInternal;
- }
-
- /**
- * @return page Id
- */
- public int getPageId()
- {
- return pageWindowInternal.pageId;
- }
-
- /**
- * @return offset in the pagemap file where the serialized page data starts
- */
- public int getFilePartOffset()
- {
- return pageWindowInternal.filePartOffset;
- }
-
- /**
- * @return size of the serialized page data
- */
- public int getFilePartSize()
- {
- return pageWindowInternal.filePartSize;
- }
- }
-
- /**
- * Creates and returns a new page window for given page.
- *
- * @param pageId
- * @param size
- * @return page window
- */
- public synchronized PageWindow createPageWindow(int pageId, int size)
- {
- int index = getWindowIndex(pageId);
-
- // if we found the page window, mark it as invalid
- if (index != -1)
- {
- removeWindowIndex(pageId);
- (windows.get(index)).pageId = -1;
- }
-
- // if we are not going to reuse a page window (because it's not on
- // indexPointer position or because we didn't find it), increment the
- // indexPointer
- if (index == -1 || index != indexPointer)
- {
- index = incrementIndexPointer();
- }
-
- PageWindowInternal window = allocatePageWindow(index, size);
- window.pageId = pageId;
-
- putWindowIndex(pageId, index);
- return new PageWindow(window);
- }
-
- /**
- * Returns the page window for given page or null if no window was found.
- *
- * @param pageId
- * @return page window or null
- */
- public synchronized PageWindow getPageWindow(int pageId)
- {
- int index = getWindowIndex(pageId);
- if (index != -1)
- {
- return new PageWindow(windows.get(index));
- }
- return null;
- }
-
- /**
- * Removes the page window for given page.
- *
- * @param pageId
- */
- public synchronized void removePage(int pageId)
- {
- int index = getWindowIndex(pageId);
- if (index != -1)
- {
- PageWindowInternal window = windows.get(index);
- removeWindowIndex(pageId);
- if (index == windows.size() - 1)
- {
- windows.remove(index);
- totalSize -= window.filePartSize;
- if (indexPointer == index)
- {
- --indexPointer;
- }
- }
- else
- {
- window.pageId = -1;
- }
- }
- }
-
- /**
- * Returns last n saved page windows.
- *
- * @param count
- * @return list of page windows
- */
- public synchronized List<PageWindow> getLastPageWindows(int count)
- {
- List<PageWindow> result = new ArrayList<PageWindow>();
-
- // start from current index to 0
- int currentIndex = indexPointer;
-
- do
- {
- if (currentIndex == -1)
- {
- break;
- }
-
- if (currentIndex < windows.size())
- {
- PageWindowInternal window = windows.get(currentIndex);
- if (window.pageId != -1)
- {
- result.add(new PageWindow(window));
- }
- }
-
- --currentIndex;
- if (currentIndex == -1)
- {
- // rewind to the last entry and collect all entries until current index
- currentIndex = windows.size() - 1;
- }
- }
- while (result.size() < count && currentIndex != indexPointer);
-
- return result;
- }
-
- /**
- * Creates a new PageWindowManager.
- *
- * @param maxSize
- * maximum page size. After this size is exceeded, the pages will be saved starting
- * at the beginning of file
- */
- public PageWindowManager(long maxSize)
- {
- this.maxSize = maxSize;
- }
-
- /**
- * Returns the size of all saved pages
- *
- * @return total size
- */
- public synchronized int getTotalSize()
- {
- return totalSize;
- }
-}
http://git-wip-us.apache.org/repos/asf/wicket/blob/bcf76f51/wicket-core/src/main/java/org/apache/wicket/pageStore/PerSessionPageStore.java
----------------------------------------------------------------------
diff --git a/wicket-core/src/main/java/org/apache/wicket/pageStore/PerSessionPageStore.java b/wicket-core/src/main/java/org/apache/wicket/pageStore/PerSessionPageStore.java
deleted file mode 100644
index 4a21f4c..0000000
--- a/wicket-core/src/main/java/org/apache/wicket/pageStore/PerSessionPageStore.java
+++ /dev/null
@@ -1,332 +0,0 @@
-/*
- * 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.lang.ref.SoftReference;
-import java.util.Comparator;
-import java.util.Iterator;
-import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.ConcurrentMap;
-import java.util.concurrent.ConcurrentSkipListMap;
-
-import org.apache.wicket.page.IManageablePage;
-import org.apache.wicket.serialize.ISerializer;
-import org.apache.wicket.util.lang.Args;
-
-/**
- * A page store that uses a SecondLevelPageCache with the last N used page instances
- * per session.
- *
- * <strong>Note</strong>: the size of the cache depends on the {@code cacheSize} constructor
- * parameter multiplied by the number of the active http sessions.
- *
- * It depends on the application use cases but usually a reasonable value of
- * {@code cacheSize} would be just a few pages (2-3). If the application don't expect many
- * active http sessions and the work flow involves usage of the browser/application history
- * then the {@code cacheSize} value may be increased to a bigger value.
- */
-public class PerSessionPageStore extends AbstractCachingPageStore<IManageablePage>
-{
- /**
- * Constructor.
- *
- * @param pageSerializer
- * the {@link org.apache.wicket.serialize.ISerializer} that will be used to convert pages from/to byte arrays
- * @param dataStore
- * the {@link org.apache.wicket.pageStore.IDataStore} that actually stores the pages
- * @param cacheSize
- * the number of pages to cache in memory before passing them to
- * {@link org.apache.wicket.pageStore.IDataStore#storeData(String, int, byte[])}
- */
- public PerSessionPageStore(final ISerializer pageSerializer, final IDataStore dataStore,
- final int cacheSize)
- {
- super(pageSerializer, dataStore, new PagesCache(cacheSize));
- }
-
- @Override
- public IManageablePage convertToPage(final Object object)
- {
- if (object == null)
- {
- return null;
- }
- else if (object instanceof IManageablePage)
- {
- return (IManageablePage)object;
- }
-
- String type = object.getClass().getName();
- throw new IllegalArgumentException("Unknown object type: " + type);
- }
-
- /**
- * An implementation of SecondLevelPageCache that stores the last used N live page instances
- * per http session.
- */
- protected static class PagesCache implements SecondLevelPageCache<String, Integer, IManageablePage>
- {
- /**
- * Helper class used to compare the page entries in the cache by their
- * access time
- */
- private static class PageValue
- {
- /**
- * The id of the cached page
- */
- private final int pageId;
-
- /**
- * The last time this page has been used/accessed.
- */
- private long accessTime;
-
- private PageValue(IManageablePage page)
- {
- this(page.getPageId());
- }
-
- private PageValue(int pageId)
- {
- this.pageId = pageId;
- touch();
- }
-
- /**
- * Updates the access time with the current time
- */
- private void touch()
- {
- accessTime = System.nanoTime();
- }
-
- @Override
- public boolean equals(Object o)
- {
- if (this == o) return true;
- if (o == null || getClass() != o.getClass()) return false;
-
- PageValue pageValue = (PageValue) o;
-
- return pageId == pageValue.pageId;
- }
-
- @Override
- public int hashCode()
- {
- return pageId;
- }
- }
-
- private static class PageComparator implements Comparator<PageValue>
- {
- @Override
- public int compare(PageValue p1, PageValue p2)
- {
- return Long.compare(p1.accessTime, p2.accessTime);
- }
- }
-
- private final int maxEntriesPerSession;
-
- private final ConcurrentMap<String, SoftReference<ConcurrentSkipListMap<PageValue, IManageablePage>>> cache;
-
- /**
- * Constructor.
- *
- * @param maxEntriesPerSession
- * The number of cache entries per session
- */
- public PagesCache(final int maxEntriesPerSession)
- {
- this.maxEntriesPerSession = maxEntriesPerSession;
- cache = new ConcurrentHashMap<>();
- }
-
- /**
- *
- * @param sessionId
- * The id of the http session
- * @param pageId
- * The id of the page to remove from the cache
- * @return the removed {@link org.apache.wicket.page.IManageablePage} or <code>null</code> - otherwise
- */
- @Override
- public IManageablePage removePage(final String sessionId, final Integer pageId)
- {
- IManageablePage result = null;
-
- if (maxEntriesPerSession > 0)
- {
- Args.notNull(sessionId, "sessionId");
- Args.notNull(pageId, "pageId");
-
- SoftReference<ConcurrentSkipListMap<PageValue, IManageablePage>> pagesPerSession = cache.get(sessionId);
- if (pagesPerSession != null)
- {
- ConcurrentMap<PageValue, IManageablePage> pages = pagesPerSession.get();
- if (pages != null)
- {
- PageValue sample = new PageValue(pageId);
- Iterator<Map.Entry<PageValue, IManageablePage>> iterator = pages.entrySet().iterator();
- while (iterator.hasNext())
- {
- Map.Entry<PageValue, IManageablePage> entry = iterator.next();
- if (sample.equals(entry.getKey()))
- {
- result = entry.getValue();
- iterator.remove();
- break;
- }
- }
- }
- }
- }
-
- return result;
- }
-
- /**
- * Removes all {@link org.apache.wicket.page.IManageablePage}s for the session
- * with <code>sessionId</code> from the cache.
- *
- * @param sessionId
- * The id of the expired http session
- */
- @Override
- public void removePages(String sessionId)
- {
- Args.notNull(sessionId, "sessionId");
-
- if (maxEntriesPerSession > 0)
- {
- cache.remove(sessionId);
- }
- }
-
- /**
- * Returns a {@link org.apache.wicket.page.IManageablePage} by looking it up by <code>sessionId</code> and
- * <code>pageId</code>. If there is a match then it is <i>touched</i>, i.e. it is moved at
- * the top of the cache.
- *
- * @param sessionId
- * The id of the http session
- * @param pageId
- * The id of the page to find
- * @return the found serialized page or <code>null</code> when not found
- */
- @Override
- public IManageablePage getPage(String sessionId, Integer pageId)
- {
- IManageablePage result = null;
-
- if (maxEntriesPerSession > 0)
- {
- Args.notNull(sessionId, "sessionId");
- Args.notNull(pageId, "pageId");
-
- SoftReference<ConcurrentSkipListMap<PageValue, IManageablePage>> pagesPerSession = cache.get(sessionId);
- if (pagesPerSession != null)
- {
- ConcurrentSkipListMap<PageValue, IManageablePage> pages = pagesPerSession.get();
- if (pages != null)
- {
- PageValue sample = new PageValue(pageId);
- for (Map.Entry<PageValue, IManageablePage> entry : pages.entrySet())
- {
- if (sample.equals(entry.getKey()))
- {
- // touch the entry
- entry.getKey().touch();
- result = entry.getValue();
- break;
- }
- }
- }
- }
- }
- return result;
- }
-
- /**
- * Store the serialized page in cache
- *
- * @param page
- * the data to serialize (page id, session id, bytes)
- */
- @Override
- public void storePage(String sessionId, Integer pageId, IManageablePage page)
- {
- if (maxEntriesPerSession > 0)
- {
- Args.notNull(sessionId, "sessionId");
- Args.notNull(pageId, "pageId");
-
- SoftReference<ConcurrentSkipListMap<PageValue, IManageablePage>> pagesPerSession = cache.get(sessionId);
- if (pagesPerSession == null)
- {
- ConcurrentSkipListMap<PageValue, IManageablePage> pages = new ConcurrentSkipListMap<>(new PageComparator());
- pagesPerSession = new SoftReference<>(pages);
- SoftReference<ConcurrentSkipListMap<PageValue, IManageablePage>> old = cache.putIfAbsent(sessionId, pagesPerSession);
- if (old != null)
- {
- pagesPerSession = old;
- }
- }
-
- ConcurrentSkipListMap<PageValue, IManageablePage> pages = pagesPerSession.get();
- if (pages == null)
- {
- pages = new ConcurrentSkipListMap<>();
- pagesPerSession = new SoftReference<>(pages);
- SoftReference<ConcurrentSkipListMap<PageValue, IManageablePage>> old = cache.putIfAbsent(sessionId, pagesPerSession);
- if (old != null)
- {
- pages = old.get();
- }
- }
-
- if (pages != null)
- {
- removePage(sessionId, pageId);
-
- PageValue pv = new PageValue(page);
- pages.put(pv, page);
-
- while (pages.size() > maxEntriesPerSession)
- {
- pages.pollFirstEntry();
- }
- }
- }
- }
-
- @Override
- public void destroy()
- {
- cache.clear();
- }
- }
-
- @Override
- public boolean canBeAsynchronous()
- {
- return false; // NOTE: not analyzed neither tested yet, this page store being wrapped by asynchronous one
- }
-}
http://git-wip-us.apache.org/repos/asf/wicket/blob/bcf76f51/wicket-core/src/main/java/org/apache/wicket/pageStore/RequestPageStore.java
----------------------------------------------------------------------
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
new file mode 100644
index 0000000..2420768
--- /dev/null
+++ b/wicket-core/src/main/java/org/apache/wicket/pageStore/RequestPageStore.java
@@ -0,0 +1,159 @@
+/*
+ * 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.util.LinkedHashMap;
+import java.util.Map;
+
+import org.apache.wicket.MetaDataKey;
+import org.apache.wicket.page.IManageablePage;
+import org.apache.wicket.request.cycle.RequestCycle;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Buffer pages till the end of the request, when they are delegated to another store in
+ * the reverse order they where accessed.
+ */
+public class RequestPageStore extends DelegatingPageStore
+{
+
+ private static final Logger log = LoggerFactory.getLogger(RequestPageStore.class);
+
+ private static final MetaDataKey<RequestData> KEY = new MetaDataKey<>()
+ {
+ private static final long serialVersionUID = 1L;
+ };
+
+ public RequestPageStore(IPageStore delegate)
+ {
+ super(delegate);
+ }
+
+ @Override
+ public IManageablePage getPage(IPageContext context, int id)
+ {
+ IManageablePage page = getRequestData(context).get(id);
+ if (page != null)
+ {
+ return page;
+ }
+
+ return super.getPage(context, id);
+ }
+
+ @Override
+ public void addPage(IPageContext context, IManageablePage page)
+ {
+ getRequestData(context).add(page);
+ }
+
+ @Override
+ public void removePage(IPageContext context, IManageablePage page)
+ {
+ getRequestData(context).remove(page);
+
+ super.removePage(context, page);
+ }
+
+ @Override
+ public void removeAllPages(IPageContext context)
+ {
+ getRequestData(context).removeAll();
+
+ super.removeAllPages(context);
+ }
+
+ @Override
+ public void detach(IPageContext context)
+ {
+ RequestData requestData = getRequestData(context);
+ for (IManageablePage page : requestData.pages())
+ {
+ boolean isPageStateless;
+ try
+ {
+ isPageStateless = page.isPageStateless();
+ }
+ catch (Exception x)
+ {
+ log.warn("An error occurred while checking whether a page is stateless. Assuming it is stateful.", x);
+ isPageStateless = false;
+ }
+
+ if (isPageStateless == false)
+ {
+ super.addPage(context, page);
+ }
+ }
+ requestData.removeAll();
+
+ super.detach(context);
+ }
+
+ private RequestData getRequestData(IPageContext context)
+ {
+ RequestData requestData = context.getRequestData(KEY);
+ if (requestData == null)
+ {
+ requestData = new RequestData();
+
+ context.setRequestData(KEY, requestData);
+ }
+ return requestData;
+ }
+
+ /**
+ * Data kept in the {@link RequestCycle}.
+ */
+ static class RequestData
+ {
+ private Map<Integer, IManageablePage> pages = new LinkedHashMap<>();
+
+ public void add(IManageablePage page)
+ {
+ pages.remove(page.getPageId());
+
+ pages.put(page.getPageId(), page);
+ }
+
+ public Iterable<IManageablePage> pages()
+ {
+ return pages.values();
+ }
+
+ public IManageablePage get(int id) {
+ IManageablePage page = pages.get(id);
+
+ if (page != null) {
+ pages.put(id, page);
+ }
+
+ return page;
+ }
+
+ public void remove(IManageablePage page)
+ {
+ pages.remove(page.getPageId());
+ }
+
+ public void removeAll()
+ {
+ pages.clear();
+ }
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/wicket/blob/bcf76f51/wicket-core/src/main/java/org/apache/wicket/pageStore/SecondLevelPageCache.java
----------------------------------------------------------------------
diff --git a/wicket-core/src/main/java/org/apache/wicket/pageStore/SecondLevelPageCache.java b/wicket-core/src/main/java/org/apache/wicket/pageStore/SecondLevelPageCache.java
deleted file mode 100644
index 3d30857..0000000
--- a/wicket-core/src/main/java/org/apache/wicket/pageStore/SecondLevelPageCache.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * 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;
-
-/**
- * An application scoped cache that holds the last N used pages in the application.
- * Acts as a second level cache between the Http Session (first level) and the
- * disk (third level cache).
- *
- * @param <S>
- * The type of the session identifier
- * @param <PI>
- * The type of the page identifier
- * @param <P>
- * The type of the stored page
- */
-public interface SecondLevelPageCache<S, PI, P>
-{
- P removePage(S session, PI pageId);
-
- void removePages(S session);
-
- P getPage(S session, PI pageId);
-
- void storePage(S session, PI pageId, P page);
-
- void destroy();
-}
http://git-wip-us.apache.org/repos/asf/wicket/blob/bcf76f51/wicket-core/src/main/java/org/apache/wicket/pageStore/disk/PageWindowManager.java
----------------------------------------------------------------------
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
new file mode 100644
index 0000000..5f59d34
--- /dev/null
+++ b/wicket-core/src/main/java/org/apache/wicket/pageStore/disk/PageWindowManager.java
@@ -0,0 +1,493 @@
+/*
+ * 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.disk;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.wicket.pageStore.IPersistedPage;
+import org.apache.wicket.util.collections.IntHashMap;
+import org.apache.wicket.util.lang.Bytes;
+
+/**
+ * Manages positions and size of chunks of data in a file.
+ * <p>
+ * The data is stored inside the file in a cyclic way. Newer pages are placed after older ones,
+ * until the maximum file size is reached. After that, the next page is stored in the beginning of
+ * the file.
+ *
+ * @author Matej Knopp
+ */
+public class PageWindowManager implements Serializable
+{
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * Contains information about a page inside the file.
+ *
+ * @author Matej Knopp
+ */
+ public static class FileWindow implements IPersistedPage, Serializable
+ {
+ private static final long serialVersionUID = 1L;
+
+ /** id of data or -1 if the window is empty */
+ private int id;
+
+ private String type;
+
+ /** offset in the file where the serialized page data begins */
+ private int filePartOffset;
+
+ /** size of serialized page data */
+ private int filePartSize;
+
+ @Override
+ public int getPageId()
+ {
+ return id;
+ }
+
+ @Override
+ public String getPageType() {
+ return type;
+ }
+
+ @Override
+ public Bytes getPageSize()
+ {
+ return Bytes.bytes(filePartSize);
+ }
+
+ public int getFilePartOffset()
+ {
+ return filePartOffset;
+ }
+
+ public int getFilePartSize()
+ {
+ return filePartSize;
+ }
+ }
+
+ private final List<FileWindow> windows = new ArrayList<FileWindow>();
+
+ /**
+ * map from page id to list of pagewindow indices (referring to the windows list) - to improve
+ * searching speed the index must be cleaned when the instances in the windows list change their
+ * indexes (e.g. items are shifted on page window removal)
+ */
+ private IntHashMap<Integer> idToWindowIndex = null;
+
+ /**
+ * Inversed index of #idToWindowIndex
+ */
+ private IntHashMap<Integer> windowIndexToPageId = null;
+
+ /** index of last added page */
+ private int indexPointer = -1;
+
+ private int totalSize = 0;
+
+ /**
+ * Maximum page size. After this size is exceeded, the pages will be saved starting at the
+ * beginning of file.
+ */
+ private final long maxSize;
+
+ /**
+ *
+ * @param pageId
+ * @param windowIndex
+ */
+ private void putWindowIndex(int pageId, int windowIndex)
+ {
+ if (idToWindowIndex != null && pageId != -1 && windowIndex != -1)
+ {
+ Integer oldPageId = windowIndexToPageId.remove(windowIndex);
+ if (oldPageId != null)
+ {
+ idToWindowIndex.remove(oldPageId);
+ }
+ idToWindowIndex.put(pageId, windowIndex);
+ windowIndexToPageId.put(windowIndex, pageId);
+ }
+ }
+
+ /**
+ *
+ * @param pageId
+ */
+ private void removeWindowIndex(int pageId)
+ {
+ Integer windowIndex = idToWindowIndex.remove(pageId);
+ if (windowIndex != null)
+ {
+ windowIndexToPageId.remove(windowIndex);
+ }
+ }
+
+ /**
+ *
+ */
+ private void rebuildIndices()
+ {
+ idToWindowIndex = null;
+ idToWindowIndex = new IntHashMap<Integer>();
+ windowIndexToPageId = null;
+ windowIndexToPageId = new IntHashMap<Integer>();
+ for (int i = 0; i < windows.size(); ++i)
+ {
+ FileWindow window = windows.get(i);
+ putWindowIndex(window.id, i);
+ }
+ }
+
+ /**
+ * Returns the index of the given page in the {@link #windows} list.
+ *
+ * @param pageId
+ * @return window index
+ */
+ private int getWindowIndex(int pageId)
+ {
+ if (idToWindowIndex == null)
+ {
+ rebuildIndices();
+ }
+
+ Integer result = idToWindowIndex.get(pageId);
+ return result != null ? result : -1;
+ }
+
+ /**
+ * Increments the {@link #indexPointer}. If the maximum file size has been reached, the
+ * {@link #indexPointer} is set to 0.
+ *
+ * @return new index pointer
+ */
+ private int incrementIndexPointer()
+ {
+ if ((maxSize > 0) && (totalSize >= maxSize) && (indexPointer == windows.size() - 1))
+ {
+ indexPointer = 0;
+ }
+ else
+ {
+ ++indexPointer;
+ }
+ return indexPointer;
+ }
+
+ /**
+ * Returns the offset in file of the window on given index. The offset is counted by getting the
+ * previous page offset and adding the previous page size to it.
+ *
+ * @param index
+ * @return window file offset
+ */
+ private int getWindowFileOffset(int index)
+ {
+ if (index > 0)
+ {
+ FileWindow window = windows.get(index - 1);
+ return window.filePartOffset + window.filePartSize;
+ }
+ return 0;
+ }
+
+ /**
+ * Splits the window with given index to two windows. First of those will have size specified by
+ * the argument, the other one will fill up the rest of the original window.
+ *
+ * @param index
+ * @param size
+ */
+ private void splitWindow(int index, int size)
+ {
+ FileWindow window = windows.get(index);
+ int delta = window.filePartSize - size;
+
+ if (index == windows.size() - 1)
+ {
+ // if this is last window
+ totalSize -= delta;
+ window.filePartSize = size;
+ }
+ else if (window.filePartSize != size)
+ {
+ FileWindow newWindow = new FileWindow();
+ newWindow.id = -1;
+ window.filePartSize = size;
+
+ windows.add(index + 1, newWindow);
+
+ newWindow.filePartOffset = getWindowFileOffset(index + 1);
+ newWindow.filePartSize = delta;
+ }
+
+ idToWindowIndex = null;
+ windowIndexToPageId = null;
+ }
+
+ /**
+ * Merges the window with given index with the next window. The resulting window will have size
+ * of the two windows summed together.
+ *
+ * @param index
+ */
+ private void mergeWindowWithNext(int index)
+ {
+ if (index < windows.size() - 1)
+ {
+ FileWindow window = windows.get(index);
+ FileWindow next = windows.get(index + 1);
+ window.filePartSize += next.filePartSize;
+
+ windows.remove(index + 1);
+ idToWindowIndex = null; // reset index
+ windowIndexToPageId = null;
+ }
+ }
+
+ /**
+ * Adjusts the window on given index to the specified size. If the new size is smaller than the
+ * window size, the window will be split. Otherwise the window will be merged with as many
+ * subsequent window as necessary. In case the window is last window in the file, the size will
+ * be adjusted without splitting or merging.
+ *
+ * @param index
+ * @param size
+ */
+ private void adjustWindowSize(int index, int size)
+ {
+ FileWindow window = windows.get(index);
+
+ // last window, just adjust size
+ if (index == windows.size() - 1)
+ {
+ int delta = size - window.filePartSize;
+ totalSize += delta;
+ window.filePartSize = size;
+ }
+ else
+ {
+ // merge as many times as necessary
+ while (window.filePartSize < size && index < windows.size() - 1)
+ {
+ mergeWindowWithNext(index);
+ }
+
+ // done merging - do we have enough room ?
+ if (window.filePartSize < size)
+ {
+ // no, this is the last window
+ int delta = size - window.filePartSize;
+ totalSize += delta;
+ window.filePartSize = size;
+ }
+ else
+ {
+ // yes, we might want to split the window, so that we don't lose
+ // space when the created window was too big
+ splitWindow(index, size);
+ }
+ }
+
+ window.id = -1;
+ }
+
+ /**
+ * Allocates window on given index with to size. If the index is pointing to existing window,
+ * the window size will be adjusted. Otherwise a new window with appropriated size will be
+ * created.
+ *
+ * @param index
+ * @param size
+ * @return page window
+ */
+ private FileWindow allocatePageWindow(int index, int size)
+ {
+ final FileWindow window;
+
+ // new window
+ if (index == windows.size())
+ {
+ // new page window
+ window = new FileWindow();
+ window.filePartOffset = getWindowFileOffset(index);
+ totalSize += size;
+ window.filePartSize = size;
+ windows.add(window);
+ }
+ else
+ {
+ // get the window
+ window = windows.get(index);
+
+ // adjust if necessary
+ if (window.filePartSize != size)
+ {
+ adjustWindowSize(index, size);
+ }
+ }
+
+ return window;
+ }
+
+ /**
+ * Creates and returns a new page window for given page.
+ *
+ * @param pageId
+ * @param type
+ * @param size
+ * @return page window
+ */
+ public synchronized FileWindow createPageWindow(int pageId, Class<?> type, int size)
+ {
+ int index = getWindowIndex(pageId);
+
+ // if we found the page window, mark it as invalid
+ if (index != -1)
+ {
+ removeWindowIndex(pageId);
+ (windows.get(index)).id = -1;
+ }
+
+ // if we are not going to reuse a page window (because it's not on
+ // indexPointer position or because we didn't find it), increment the
+ // indexPointer
+ if (index == -1 || index != indexPointer)
+ {
+ index = incrementIndexPointer();
+ }
+
+ FileWindow window = allocatePageWindow(index, size);
+ window.id = pageId;
+ window.type = type.getName();
+
+ putWindowIndex(pageId, index);
+ return window;
+ }
+
+ /**
+ * Returns the page window for given page or null if no window was found.
+ *
+ * @param pageId
+ * @return page window or null
+ */
+ public synchronized FileWindow getPageWindow(int pageId)
+ {
+ int index = getWindowIndex(pageId);
+ if (index != -1)
+ {
+ return windows.get(index);
+ }
+ return null;
+ }
+
+ /**
+ * Removes the page window for given page.
+ *
+ * @param pageId
+ */
+ public synchronized void removePage(int pageId)
+ {
+ int index = getWindowIndex(pageId);
+ if (index != -1)
+ {
+ FileWindow window = windows.get(index);
+ removeWindowIndex(pageId);
+ if (index == windows.size() - 1)
+ {
+ windows.remove(index);
+ totalSize -= window.filePartSize;
+ if (indexPointer == index)
+ {
+ --indexPointer;
+ }
+ }
+ else
+ {
+ window.id = -1;
+ }
+ }
+ }
+
+ /**
+ * Returns last n saved page windows.
+ *
+ * @return list of page windows
+ */
+ public synchronized List<FileWindow> getFileWindows()
+ {
+ List<FileWindow> result = new ArrayList<FileWindow>();
+
+ // start from current index to 0
+ int currentIndex = indexPointer;
+
+ do
+ {
+ if (currentIndex == -1)
+ {
+ break;
+ }
+
+ if (currentIndex < windows.size())
+ {
+ FileWindow window = windows.get(currentIndex);
+ if (window.id != -1)
+ {
+ result.add(window);
+ }
+ }
+
+ --currentIndex;
+ if (currentIndex == -1)
+ {
+ // rewind to the last entry and collect all entries until current index
+ currentIndex = windows.size() - 1;
+ }
+ }
+ while (currentIndex != indexPointer);
+
+ return result;
+ }
+
+ /**
+ * Creates a new PageWindowManager.
+ *
+ * @param maxSize
+ * maximum page size. After this size is exceeded, the pages will be saved starting
+ * at the beginning of file
+ */
+ public PageWindowManager(long maxSize)
+ {
+ this.maxSize = maxSize;
+ }
+
+ /**
+ * Returns the size of all saved pages
+ *
+ * @return total size
+ */
+ public synchronized int getTotalSize()
+ {
+ return totalSize;
+ }
+}
http://git-wip-us.apache.org/repos/asf/wicket/blob/bcf76f51/wicket-core/src/main/java/org/apache/wicket/pageStore/memory/HttpSessionDataStore.java
----------------------------------------------------------------------
diff --git a/wicket-core/src/main/java/org/apache/wicket/pageStore/memory/HttpSessionDataStore.java b/wicket-core/src/main/java/org/apache/wicket/pageStore/memory/HttpSessionDataStore.java
deleted file mode 100644
index fcc4f7a..0000000
--- a/wicket-core/src/main/java/org/apache/wicket/pageStore/memory/HttpSessionDataStore.java
+++ /dev/null
@@ -1,186 +0,0 @@
-/*
- * 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.memory;
-
-import javax.servlet.http.HttpSession;
-
-import org.apache.wicket.Session;
-import org.apache.wicket.page.IPageManagerContext;
-import org.apache.wicket.pageStore.IDataStore;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * A {@link IDataStore} which stores the pages in the {@link HttpSession}. Uses
- * {@link IDataStoreEvictionStrategy} to keep the memory footprint reasonable.
- *
- * <p>
- * Usage:
- *
- * <pre>
- * <!--@formatter:off-->
- * MyApp#init()
- * {
- *
- * setPageManagerProvider(new DefaultPageManagerProvider(this)
- * {
- * protected IDataStore newDataStore()
- * {
- * return new HttpSessionDataStore(pageManagerContext, new PageNumberEvictionStrategy(20));
- * }
- * }
- * }
- * <!--@formatter:on-->
- * </pre>
- */
-public class HttpSessionDataStore implements IDataStore
-{
- private static final Logger LOG = LoggerFactory.getLogger(HttpSessionDataStore.class);
-
- /** the session attribute key. auto-prefixed with application.getSessionAttributePrefix() */
- private static final String PAGE_TABLE_KEY = "page:store:memory";
-
- private final IPageManagerContext pageManagerContext;
-
- private final IDataStoreEvictionStrategy evictionStrategy;
-
- /**
- * Construct.
- *
- * @param pageManagerContext
- * @param evictionStrategy
- */
- public HttpSessionDataStore(IPageManagerContext pageManagerContext,
- IDataStoreEvictionStrategy evictionStrategy)
- {
- this.pageManagerContext = pageManagerContext;
- this.evictionStrategy = evictionStrategy;
- }
-
- /**
- * @param sessionId
- * Ignored. Only pages from the current http session can be read
- * @see org.apache.wicket.pageStore.IDataStore#getData(java.lang.String, int)
- */
- @Override
- public byte[] getData(String sessionId, int pageId)
- {
- PageTable pageTable = getPageTable(false, false);
- byte[] pageAsBytes = null;
- if (pageTable != null)
- {
- pageAsBytes = pageTable.getPage(pageId);
- }
-
- if (LOG.isDebugEnabled())
- {
- int bytesLength = pageAsBytes != null ? pageAsBytes.length : -1;
- LOG.debug("Loaded '{}' bytes for page with id '{}' in session '{}'",
- bytesLength, pageId, sessionId);
- }
-
-
- return pageAsBytes;
- }
-
- @Override
- public void removeData(String sessionId, int pageId)
- {
- PageTable pageTable = getPageTable(false, true);
- if (pageTable != null)
- {
- byte[] bytes = pageTable.removePage(pageId);
-
- if (LOG.isDebugEnabled() && bytes != null)
- {
- LOG.debug("Removed page '{}' in session '{}'", pageId, sessionId);
- }
- }
- }
-
- @Override
- public void removeData(String sessionId)
- {
- PageTable pageTable = getPageTable(false, true);
- if (pageTable != null)
- {
- pageTable.clear();
- LOG.debug("Removed all pages in session '{}'", sessionId);
- }
- }
-
- @Override
- public void storeData(String sessionId, int pageId, byte[] pageAsBytes)
- {
- PageTable pageTable = getPageTable(true, true);
- if (pageTable != null)
- {
- pageTable.storePage(pageId, pageAsBytes);
- if (LOG.isDebugEnabled())
- {
- LOG.debug("Stored '{}' bytes for page '{}' in session '{}'",
- pageAsBytes.length, pageId, sessionId);
- }
- evictionStrategy.evict(pageTable);
- }
- else
- {
- LOG.error("Cannot store the data for page with id '{}' in session with id '{}'",
- pageId, sessionId);
- }
- }
-
- @Override
- public void destroy()
- {
- // do nothing
- // this is application lifecycle thread (WicketFilter#destroy())
- // so there is no reachable http session
- }
-
- @Override
- public boolean isReplicated()
- {
- return true;
- }
-
- private PageTable getPageTable(boolean create, boolean rewriteToSession)
- {
- PageTable pageTable = null;
- if (Session.exists())
- {
- pageTable = (PageTable)pageManagerContext.getSessionAttribute(PAGE_TABLE_KEY);
- if (pageTable == null && create)
- {
- pageTable = new PageTable();
- pageManagerContext.setSessionAttribute(PAGE_TABLE_KEY, pageTable);
- } else if (rewriteToSession) {
- pageManagerContext.setSessionAttribute(PAGE_TABLE_KEY, pageTable);
- }
- }
- return pageTable;
- }
-
- @Override
- public final boolean canBeAsynchronous()
- {
- // HttpSessionDataStore needs access to the current http session
- // and this is not possible in AsychronousDataStore
- return false;
- }
-
-}
http://git-wip-us.apache.org/repos/asf/wicket/blob/bcf76f51/wicket-core/src/main/java/org/apache/wicket/pageStore/memory/IDataStoreEvictionStrategy.java
----------------------------------------------------------------------
diff --git a/wicket-core/src/main/java/org/apache/wicket/pageStore/memory/IDataStoreEvictionStrategy.java b/wicket-core/src/main/java/org/apache/wicket/pageStore/memory/IDataStoreEvictionStrategy.java
deleted file mode 100644
index 6b6e556..0000000
--- a/wicket-core/src/main/java/org/apache/wicket/pageStore/memory/IDataStoreEvictionStrategy.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * 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.memory;
-
-
-/**
- * An eviction strategy that decides whether the in-memory data structure used as page store should
- * be compacted
- */
-@FunctionalInterface
-public interface IDataStoreEvictionStrategy
-{
-
- /**
- * Called after each {@link org.apache.wicket.pageStore.IDataStore#storeData(String, int, byte[])} call.
- *
- * @param pageTable
- * the in-memory data store with <strong>all</strong> pages
- */
- void evict(PageTable pageTable);
-}
http://git-wip-us.apache.org/repos/asf/wicket/blob/bcf76f51/wicket-core/src/main/java/org/apache/wicket/pageStore/memory/MemorySizeEvictionStrategy.java
----------------------------------------------------------------------
diff --git a/wicket-core/src/main/java/org/apache/wicket/pageStore/memory/MemorySizeEvictionStrategy.java b/wicket-core/src/main/java/org/apache/wicket/pageStore/memory/MemorySizeEvictionStrategy.java
deleted file mode 100644
index 92f985b..0000000
--- a/wicket-core/src/main/java/org/apache/wicket/pageStore/memory/MemorySizeEvictionStrategy.java
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * 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.memory;
-
-import org.apache.wicket.util.lang.Args;
-import org.apache.wicket.util.lang.Bytes;
-import org.apache.wicket.core.util.lang.WicketObjects;
-
-/**
- * An eviction strategy that keeps the data store size up to configured bytes
- */
-public class MemorySizeEvictionStrategy implements IDataStoreEvictionStrategy
-{
-
- private final Bytes maxBytes;
-
- /**
- * Construct.
- *
- * @param maxBytes
- * the maximum size of the data store
- */
- public MemorySizeEvictionStrategy(Bytes maxBytes)
- {
- Args.notNull(maxBytes, "maxBytes");
-
- this.maxBytes = maxBytes;
- }
-
- /**
- *
- * @see IDataStoreEvictionStrategy#evict(org.apache.wicket.pageStore.memory.PageTable)
- */
- @Override
- public void evict(PageTable pageTable)
- {
-
- long storeCurrentSize = WicketObjects.sizeof(pageTable);
-
- if (storeCurrentSize > maxBytes.bytes())
- {
- PageTableCleaner cleaner = new PageTableCleaner();
- cleaner.drop(pageTable, 1);
-
- // recurse until enough space is cleaned
- evict(pageTable);
- }
- }
-
-}
http://git-wip-us.apache.org/repos/asf/wicket/blob/bcf76f51/wicket-core/src/main/java/org/apache/wicket/pageStore/memory/PageNumberEvictionStrategy.java
----------------------------------------------------------------------
diff --git a/wicket-core/src/main/java/org/apache/wicket/pageStore/memory/PageNumberEvictionStrategy.java b/wicket-core/src/main/java/org/apache/wicket/pageStore/memory/PageNumberEvictionStrategy.java
deleted file mode 100644
index 9857a6b..0000000
--- a/wicket-core/src/main/java/org/apache/wicket/pageStore/memory/PageNumberEvictionStrategy.java
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * 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.memory;
-
-
-/**
- * An eviction strategy which decides whether to evict entries from the in-memory data store
- * depending on the number of stored paged per session
- */
-public class PageNumberEvictionStrategy implements IDataStoreEvictionStrategy
-{
-
- private final int pagesNumber;
-
- /**
- * Construct.
- *
- * @param pagesNumber
- * the maximum number of pages the data store can hold
- */
- public PageNumberEvictionStrategy(int pagesNumber)
- {
- if (pagesNumber < 1)
- {
- throw new IllegalArgumentException("'pagesNumber' must be greater than 0.");
- }
-
- this.pagesNumber = pagesNumber;
- }
-
- /**
- *
- * @see IDataStoreEvictionStrategy#evict(org.apache.wicket.pageStore.memory.PageTable)
- */
- @Override
- public void evict(PageTable pageTable)
- {
- int size = pageTable.size();
- int pagesToDrop = size - pagesNumber;
-
- if (pagesToDrop > 0)
- {
- PageTableCleaner cleaner = new PageTableCleaner();
- cleaner.drop(pageTable, pagesToDrop);
- }
- }
-
-}
http://git-wip-us.apache.org/repos/asf/wicket/blob/bcf76f51/wicket-core/src/main/java/org/apache/wicket/pageStore/memory/PageTable.java
----------------------------------------------------------------------
diff --git a/wicket-core/src/main/java/org/apache/wicket/pageStore/memory/PageTable.java b/wicket-core/src/main/java/org/apache/wicket/pageStore/memory/PageTable.java
deleted file mode 100644
index dfad4af..0000000
--- a/wicket-core/src/main/java/org/apache/wicket/pageStore/memory/PageTable.java
+++ /dev/null
@@ -1,128 +0,0 @@
-/*
- * 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.memory;
-
-import java.util.Iterator;
-import java.util.Queue;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.ConcurrentLinkedQueue;
-import java.util.concurrent.ConcurrentMap;
-
-import org.apache.wicket.util.io.IClusterable;
-
-/**
- * A structure that holds page id => pageAsBytes.
- *
- * <p>
- * Additionally it has an index of the least recently used pages
- */
-public class PageTable implements IClusterable
-{
- private static final long serialVersionUID = 1L;
-
- /**
- * Holds the index of last/least recently used page ids. The most recently used page id is in
- * the tail, the least recently used is in the head.
- */
- /*
- * Can be replaced later with PriorityQueue to deal with lightweight (Ajax) and heavyweight
- * pages
- */
- private final Queue<Integer> index;
-
- /**
- * The actual container for the pages.
- *
- * <p>
- * page id => page as bytes
- */
- private final ConcurrentMap<Integer, byte[]> pages;
-
- public PageTable()
- {
- pages = new ConcurrentHashMap<>();
- index = new ConcurrentLinkedQueue<>();
- }
-
- public void storePage(Integer pageId, byte[] pageAsBytes)
- {
- synchronized (index)
- {
- pages.put(pageId, pageAsBytes);
-
- updateIndex(pageId);
- }
- }
-
- public byte[] getPage(final Integer pageId)
- {
- synchronized (index)
- {
- updateIndex(pageId);
-
- return pages.get(pageId);
- }
- }
-
- public byte[] removePage(Integer pageId)
- {
- synchronized (index)
- {
- index.remove(pageId);
-
- return pages.remove(pageId);
- }
- }
-
- public void clear()
- {
- synchronized (index)
- {
- index.clear();
- pages.clear();
- }
- }
-
- public int size()
- {
- return pages.size();
- }
-
- public Integer getOldest()
- {
- return index.peek();
- }
-
- public Iterator<Integer> indexIterator()
- {
- return index.iterator();
- }
-
- /**
- * Updates the index of last/least recently used pages by removing the page id from the index
- * (in case it is already in) and (re-)adding it at the head
- *
- * @param pageId
- * the id of a recently used page
- */
- private void updateIndex(Integer pageId)
- {
- index.remove(pageId);
- index.offer(pageId);
- }
-
-}
http://git-wip-us.apache.org/repos/asf/wicket/blob/bcf76f51/wicket-core/src/main/java/org/apache/wicket/pageStore/memory/PageTableCleaner.java
----------------------------------------------------------------------
diff --git a/wicket-core/src/main/java/org/apache/wicket/pageStore/memory/PageTableCleaner.java b/wicket-core/src/main/java/org/apache/wicket/pageStore/memory/PageTableCleaner.java
deleted file mode 100644
index 2c9a9cb..0000000
--- a/wicket-core/src/main/java/org/apache/wicket/pageStore/memory/PageTableCleaner.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * 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.memory;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * Helper class that knows how to remove the nth oldest pages from {@link PageTable}
- */
-public class PageTableCleaner
-{
- private static final Logger LOG = LoggerFactory.getLogger(PageTableCleaner.class);
-
- /**
- * Removes {@code pagesNumber} of pages from the {@link PageTable pageTable}
- *
- * @param pageTable
- * the {@link PageTable} to clean
- * @param pagesNumber
- * the number of pages to remove
- */
- public void drop(final PageTable pageTable, final int pagesNumber)
- {
- for (int i = 0; i < pagesNumber; i++)
- {
- Integer pageIdOfTheOldest = pageTable.getOldest();
- pageTable.removePage(pageIdOfTheOldest);
- LOG.debug("Evicted page with id '{}' from the HttpSessionDataStore");
- }
- }
-}
http://git-wip-us.apache.org/repos/asf/wicket/blob/bcf76f51/wicket-core/src/main/java/org/apache/wicket/settings/StoreSettings.java
----------------------------------------------------------------------
diff --git a/wicket-core/src/main/java/org/apache/wicket/settings/StoreSettings.java b/wicket-core/src/main/java/org/apache/wicket/settings/StoreSettings.java
index 8852208..63a5499 100644
--- a/wicket-core/src/main/java/org/apache/wicket/settings/StoreSettings.java
+++ b/wicket-core/src/main/java/org/apache/wicket/settings/StoreSettings.java
@@ -50,8 +50,6 @@ public class StoreSettings
private static final int DEFAULT_ASYNCHRONOUS_QUEUE_CAPACITY = 100;
- private int inmemoryCacheSize = DEFAULT_CACHE_SIZE;
-
private Bytes maxSizePerSession = DEFAULT_MAX_SIZE_PER_SESSION;
private File fileStoreFolder = null;
@@ -70,30 +68,6 @@ public class StoreSettings
}
/**
- * @return the number of page instances which will be stored in the application scoped cache for
- * faster retrieval
- */
- public int getInmemoryCacheSize()
- {
- return inmemoryCacheSize;
- }
-
- /**
- * Sets the maximum number of page instances which will be stored in the application scoped
- * second level cache for faster retrieval
- *
- * @param inmemoryCacheSize
- * the maximum number of page instances which will be held in the application scoped
- * cache
- * @return {@code this} object for chaining
- */
- public StoreSettings setInmemoryCacheSize(int inmemoryCacheSize)
- {
- this.inmemoryCacheSize = inmemoryCacheSize;
- return this;
- }
-
- /**
* @return maximum page size. After this size is exceeded,
* the {@link org.apache.wicket.pageStore.DiskDataStore} will start saving the
* pages at the beginning of file.
http://git-wip-us.apache.org/repos/asf/wicket/blob/bcf76f51/wicket-core/src/main/java/org/apache/wicket/util/tester/BaseWicketTester.java
----------------------------------------------------------------------
diff --git a/wicket-core/src/main/java/org/apache/wicket/util/tester/BaseWicketTester.java b/wicket-core/src/main/java/org/apache/wicket/util/tester/BaseWicketTester.java
index 54e7808..4012a5f 100644
--- a/wicket-core/src/main/java/org/apache/wicket/util/tester/BaseWicketTester.java
+++ b/wicket-core/src/main/java/org/apache/wicket/util/tester/BaseWicketTester.java
@@ -92,11 +92,11 @@ import org.apache.wicket.markup.html.list.ListView;
import org.apache.wicket.markup.parser.XmlPullParser;
import org.apache.wicket.markup.parser.XmlTag;
import org.apache.wicket.mock.MockApplication;
-import org.apache.wicket.mock.MockPageManager;
+import org.apache.wicket.mock.MockPageStore;
import org.apache.wicket.mock.MockRequestParameters;
import org.apache.wicket.model.PropertyModel;
import org.apache.wicket.page.IPageManager;
-import org.apache.wicket.page.IPageManagerContext;
+import org.apache.wicket.page.PageManager;
import org.apache.wicket.protocol.http.AjaxEnclosureListener;
import org.apache.wicket.protocol.http.IMetaDataBufferingWebResponse;
import org.apache.wicket.protocol.http.WebApplication;
@@ -2926,9 +2926,9 @@ public class BaseWicketTester
private static class TestPageManagerProvider implements IPageManagerProvider
{
@Override
- public IPageManager apply(IPageManagerContext pageManagerContext)
+ public IPageManager get()
{
- return new MockPageManager();
+ return new PageManager(new MockPageStore());
}
}
[2/5] wicket git commit: WICKET-6563 new IPageStore implementation
Posted by sv...@apache.org.
http://git-wip-us.apache.org/repos/asf/wicket/blob/bcf76f51/wicket-core/src/test/java/org/apache/wicket/core/request/mapper/TestMapperContext.java
----------------------------------------------------------------------
diff --git a/wicket-core/src/test/java/org/apache/wicket/core/request/mapper/TestMapperContext.java b/wicket-core/src/test/java/org/apache/wicket/core/request/mapper/TestMapperContext.java
index a1b960d..c1d7737 100644
--- a/wicket-core/src/test/java/org/apache/wicket/core/request/mapper/TestMapperContext.java
+++ b/wicket-core/src/test/java/org/apache/wicket/core/request/mapper/TestMapperContext.java
@@ -20,19 +20,20 @@ import org.apache.wicket.MockPage;
import org.apache.wicket.WicketRuntimeException;
import org.apache.wicket.core.request.handler.PageProvider;
import org.apache.wicket.markup.MarkupParser;
-import org.apache.wicket.page.IPageManagerContext;
-import org.apache.wicket.page.PageStoreManager;
-import org.apache.wicket.pageStore.DefaultPageStore;
-import org.apache.wicket.pageStore.IDataStore;
-import org.apache.wicket.pageStore.IPageStore;
-import org.apache.wicket.pageStore.memory.DummyPageManagerContext;
+import org.apache.wicket.mock.MockPageStore;
+import org.apache.wicket.page.IPageManager;
+import org.apache.wicket.page.PageManager;
+import org.apache.wicket.pageStore.DummyPageContext;
+import org.apache.wicket.pageStore.IPageContext;
+import org.apache.wicket.pageStore.InMemoryPageStore;
+import org.apache.wicket.pageStore.RequestPageStore;
+import org.apache.wicket.pageStore.InSessionPageStore;
import org.apache.wicket.request.component.IRequestablePage;
import org.apache.wicket.request.mapper.parameter.PageParameters;
import org.apache.wicket.request.resource.ResourceReference;
import org.apache.wicket.request.resource.ResourceReference.Key;
import org.apache.wicket.request.resource.ResourceReferenceRegistry;
import org.apache.wicket.serialize.java.JavaSerializer;
-import org.apache.wicket.versioning.InMemoryPageStore;
/**
* Simple {@link IMapperContext} implementation for testing purposes
@@ -43,10 +44,10 @@ public class TestMapperContext implements IMapperContext
{
private static final String APP_NAME = "test_app";
private static int count;
- IDataStore dataStore;
- IPageStore pageStore;
- IPageManagerContext pageManagerContext;
- PageStoreManager pageManager;
+
+ InSessionPageStore pageStore;
+ DummyPageContext pageContext;
+ IPageManager pageManager;
private String appName;
private boolean createMockPageIfInstanceNotFound = true;
@@ -56,10 +57,18 @@ public class TestMapperContext implements IMapperContext
public TestMapperContext()
{
appName = APP_NAME + count++;
- dataStore = new InMemoryPageStore();
- pageStore = new DefaultPageStore(new JavaSerializer(appName), dataStore, 4);
- pageManagerContext = new DummyPageManagerContext();
- pageManager = new PageStoreManager(appName, pageStore, pageManagerContext);
+
+ pageContext = new DummyPageContext();
+
+ InMemoryPageStore inMemoryPageStore = new InMemoryPageStore(appName, Integer.MAX_VALUE);
+ pageStore = new InSessionPageStore(inMemoryPageStore, new JavaSerializer(appName), 4);
+ pageManager = new PageManager(new RequestPageStore(pageStore)) {
+ @Override
+ protected IPageContext createPageContext()
+ {
+ return pageContext;
+ }
+ };
}
/**
@@ -67,17 +76,17 @@ public class TestMapperContext implements IMapperContext
*/
public void cleanSessionCache()
{
- getPageManager().getContext().setRequestData(null);
+ pageContext.clearRequest();
MockPage other = new MockPage();
other.setPageId(Integer.MAX_VALUE);
- getPageManager().touchPage(other);
- getPageManager().commitRequest();
+ getPageManager().addPage(other);
+ pageManager.detach();
}
/**
* @return pageManager
*/
- public PageStoreManager getPageManager()
+ public IPageManager getPageManager()
{
return pageManager;
}
http://git-wip-us.apache.org/repos/asf/wicket/blob/bcf76f51/wicket-core/src/test/java/org/apache/wicket/dontstoreunrendered/DontStoreNotRenderedPageTestCase.java
----------------------------------------------------------------------
diff --git a/wicket-core/src/test/java/org/apache/wicket/dontstoreunrendered/DontStoreNotRenderedPageTestCase.java b/wicket-core/src/test/java/org/apache/wicket/dontstoreunrendered/DontStoreNotRenderedPageTestCase.java
index fe1875b..f49a384 100644
--- a/wicket-core/src/test/java/org/apache/wicket/dontstoreunrendered/DontStoreNotRenderedPageTestCase.java
+++ b/wicket-core/src/test/java/org/apache/wicket/dontstoreunrendered/DontStoreNotRenderedPageTestCase.java
@@ -22,8 +22,6 @@ import org.apache.wicket.application.IComponentInstantiationListener;
import org.apache.wicket.behavior.Behavior;
import org.apache.wicket.mock.MockPageManager;
import org.apache.wicket.page.IManageablePage;
-import org.apache.wicket.page.IPageManager;
-import org.apache.wicket.page.IPageManagerContext;
import org.apache.wicket.protocol.http.WebApplication;
import org.apache.wicket.util.tester.WicketTestCase;
import org.apache.wicket.util.tester.WicketTester;
@@ -55,21 +53,16 @@ public abstract class DontStoreNotRenderedPageTestCase extends WicketTestCase
@Override
protected IPageManagerProvider newTestPageManagerProvider()
{
- return new IPageManagerProvider()
- {
- @Override
- public IPageManager apply(IPageManagerContext context)
+ return () -> {
+ return new MockPageManager()
{
- return new MockPageManager()
+ @Override
+ public void addPage(IManageablePage page)
{
- @Override
- public void touchPage(IManageablePage page)
- {
- Assert.assertFalse("PageB should not be touched!", page instanceof PageB);
- super.touchPage(page);
- }
- };
- }
+ Assert.assertFalse("PageB should not be touched!", page instanceof PageB);
+ super.addPage(page);
+ }
+ };
};
}
};
http://git-wip-us.apache.org/repos/asf/wicket/blob/bcf76f51/wicket-core/src/test/java/org/apache/wicket/markup/html/TransparentWebMarkupContainerTest.java
----------------------------------------------------------------------
diff --git a/wicket-core/src/test/java/org/apache/wicket/markup/html/TransparentWebMarkupContainerTest.java b/wicket-core/src/test/java/org/apache/wicket/markup/html/TransparentWebMarkupContainerTest.java
index 39586e0..6ec0066 100644
--- a/wicket-core/src/test/java/org/apache/wicket/markup/html/TransparentWebMarkupContainerTest.java
+++ b/wicket-core/src/test/java/org/apache/wicket/markup/html/TransparentWebMarkupContainerTest.java
@@ -34,7 +34,7 @@ import org.apache.wicket.markup.html.panel.Fragment;
import org.apache.wicket.mock.MockPageManager;
import org.apache.wicket.page.IManageablePage;
import org.apache.wicket.page.IPageManager;
-import org.apache.wicket.page.IPageManagerContext;
+import org.apache.wicket.pageStore.IPageContext;
import org.apache.wicket.request.mapper.parameter.PageParameters;
import org.apache.wicket.util.resource.IResourceStream;
import org.apache.wicket.util.resource.StringResourceStream;
@@ -117,15 +117,15 @@ public class TransparentWebMarkupContainerTest extends WicketTestCase
return new IPageManagerProvider()
{
@Override
- public IPageManager apply(IPageManagerContext context)
+ public IPageManager get()
{
return new MockPageManager()
{
@Override
- public void touchPage(IManageablePage page)
+ public void addPage(IManageablePage page)
{
page = WicketObjects.cloneObject(page);
- super.touchPage(page);
+ super.addPage(page);
}
};
}
http://git-wip-us.apache.org/repos/asf/wicket/blob/bcf76f51/wicket-core/src/test/java/org/apache/wicket/page/PageAccessSynchronizerTest.java
----------------------------------------------------------------------
diff --git a/wicket-core/src/test/java/org/apache/wicket/page/PageAccessSynchronizerTest.java b/wicket-core/src/test/java/org/apache/wicket/page/PageAccessSynchronizerTest.java
index e2053df..eeb9ba3 100644
--- a/wicket-core/src/test/java/org/apache/wicket/page/PageAccessSynchronizerTest.java
+++ b/wicket-core/src/test/java/org/apache/wicket/page/PageAccessSynchronizerTest.java
@@ -324,7 +324,7 @@ public class PageAccessSynchronizerTest extends Assert
int pageId = 1;
IManageablePage page = new MockPage(pageId);
- synchronizedPageManager.touchPage(page);
+ synchronizedPageManager.addPage(page);
synchronizedPageManager.getPage(pageId);
PageLock pageLock2 = locks.get(Integer.valueOf(pageId));
assertNotNull(pageLock2);
http://git-wip-us.apache.org/repos/asf/wicket/blob/bcf76f51/wicket-core/src/test/java/org/apache/wicket/page/PersistentPageManagerTest.java
----------------------------------------------------------------------
diff --git a/wicket-core/src/test/java/org/apache/wicket/page/PersistentPageManagerTest.java b/wicket-core/src/test/java/org/apache/wicket/page/PersistentPageManagerTest.java
index 23fe264..cb39d94 100644
--- a/wicket-core/src/test/java/org/apache/wicket/page/PersistentPageManagerTest.java
+++ b/wicket-core/src/test/java/org/apache/wicket/page/PersistentPageManagerTest.java
@@ -19,19 +19,19 @@ package org.apache.wicket.page;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
-import java.io.ByteArrayInputStream;
import java.io.IOException;
-import java.io.ObjectInputStream;
import java.io.Serializable;
+import java.util.concurrent.atomic.AtomicReference;
import org.apache.wicket.Application;
+import org.apache.wicket.MetaDataKey;
import org.apache.wicket.ThreadContext;
-import org.apache.wicket.pageStore.DefaultPageStore;
-import org.apache.wicket.pageStore.IDataStore;
+import org.apache.wicket.pageStore.DummyPageContext;
+import org.apache.wicket.pageStore.IPageContext;
import org.apache.wicket.pageStore.IPageStore;
-import org.apache.wicket.pageStore.memory.DummyPageManagerContext;
+import org.apache.wicket.pageStore.InSessionPageStore;
+import org.apache.wicket.pageStore.NoopPageStore;
import org.apache.wicket.serialize.java.JavaSerializer;
-import org.apache.wicket.versioning.InMemoryPageStore;
import org.junit.Assert;
import org.junit.Test;
@@ -58,44 +58,43 @@ public class PersistentPageManagerTest
ThreadContext.detach();
// create IPageManager (with IPageStore) and store a page instance
- IPageManager pageManager = newPersistentPageManager(APP_NAME);
+ final AtomicReference<Object> sessionData = new AtomicReference<Object>(null);
+
+ IPageManager pageManager = createPageManager(APP_NAME, sessionData);
+
+ // add a page
TestPage toSerializePage = new TestPage();
- pageManager.touchPage(toSerializePage);
- pageManager.commitRequest();
+ pageManager.addPage(toSerializePage);
+ pageManager.detach();
// get the stored SessionEntry
- Serializable sessionEntry = pageManager.getContext().getSessionAttribute(null);
+ assertNotNull(sessionData.get());
// destroy the manager and the store
pageManager.destroy();
// simulate persisting of the http sessions initiated by the web container
- byte[] serializedSessionEntry = new JavaSerializer(APP_NAME).serialize(sessionEntry);
+ byte[] serializedSessionData = new JavaSerializer(APP_NAME).serialize(sessionData.get());
assertNotNull("Wicket needs to be able to serialize the session entry",
- serializedSessionEntry);
-
- // simulate loading of the persisted http session initiated by the web container
- // when starting an application
- ObjectInputStream in = new ObjectInputStream(new ByteArrayInputStream(
- serializedSessionEntry));
+ serializedSessionData);
// WicketFilter is not initialized so there is no Application available yet
Assert.assertFalse("Worker thread should be unaware of Wicket application",
Application.exists());
- assertEquals(APP_NAME, in.readObject());
+ // simulate loading of the persisted http session initiated by the web container
+ // when starting an application
+ sessionData.set(new JavaSerializer(APP_NAME).deserialize(serializedSessionData));
// without available IPageStore the read SessionEntry holds
// the IManageablePage itself, not SerializedPage
- Serializable loadedSessionEntry = (Serializable)in.readObject();
assertNotNull(
"Wicket needs to be able to deserialize the session entry regardless the application availability",
- loadedSessionEntry);
+ sessionData.get());
// provide new IPageStore which will read IManageablePage's or SerializedPage's
// from the SessionEntry's
- IPageManager newPageManager = newPersistentPageManager(APP_NAME);
- newPageManager.getContext().setSessionAttribute(null, loadedSessionEntry);
+ IPageManager newPageManager = createPageManager(APP_NAME, sessionData);
TestPage deserializedPage = (TestPage)newPageManager.getPage(toSerializePage.getPageId());
assertNotNull(deserializedPage);
@@ -104,12 +103,34 @@ public class PersistentPageManagerTest
newPageManager.destroy();
}
- private PageStoreManager newPersistentPageManager(String appName)
+ /**
+ * Create a manager that stores session data in the given atomic reference.
+ */
+ private IPageManager createPageManager(String appName, AtomicReference<Object> sessionData)
{
- IDataStore dataStore = new InMemoryPageStore();
- IPageStore pageStore = new DefaultPageStore(new JavaSerializer(appName), dataStore, 4);
- IPageManagerContext pageManagerContext = new DummyPageManagerContext();
- return new PageStoreManager(appName, pageStore, pageManagerContext);
+ IPageStore store = new InSessionPageStore(new NoopPageStore(), new JavaSerializer(APP_NAME), Integer.MAX_VALUE);
+
+ return new PageManager(store) {
+ @Override
+ protected IPageContext createPageContext()
+ {
+ return new DummyPageContext() {
+ @Override
+ public <T extends Serializable> void setSessionData(MetaDataKey<T> key, T value)
+ {
+ super.setSessionData(key, value);
+
+ sessionData.set(value);
+ }
+
+ @Override
+ public <T extends Serializable> T getSessionData(MetaDataKey<T> key)
+ {
+ return (T)sessionData.get();
+ }
+ };
+ }
+ };
}
private static class TestPage implements IManageablePage
http://git-wip-us.apache.org/repos/asf/wicket/blob/bcf76f51/wicket-core/src/test/java/org/apache/wicket/page/persistent/disk/PageWindowManagerTest.java
----------------------------------------------------------------------
diff --git a/wicket-core/src/test/java/org/apache/wicket/page/persistent/disk/PageWindowManagerTest.java b/wicket-core/src/test/java/org/apache/wicket/page/persistent/disk/PageWindowManagerTest.java
deleted file mode 100644
index 1270800..0000000
--- a/wicket-core/src/test/java/org/apache/wicket/page/persistent/disk/PageWindowManagerTest.java
+++ /dev/null
@@ -1,301 +0,0 @@
-/*
- * 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.page.persistent.disk;
-
-import java.security.SecureRandom;
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-
-import org.apache.wicket.pageStore.PageWindowManager;
-import org.apache.wicket.pageStore.PageWindowManager.PageWindow;
-import org.junit.Assert;
-import org.junit.Test;
-
-/**
- * @author Matej Knopp
- */
-public class PageWindowManagerTest extends Assert
-{
- /**
- * https://issues.apache.org/jira/browse/WICKET-4572
- */
- @Test
- public void removeObsoleteIndices()
- {
- int page0id = 0,
- page1id = 1,
- page2id = 2;
- int maxSize = 10;
-
- PageWindowManager manager = new PageWindowManager(maxSize);
-
- // Add few pages.
- // All of them fully occupy the max space in the pageWindowManager.
- // So adding N+1st page removes the Nth page.
- manager.createPageWindow(page0id, maxSize);
- PageWindow page0Window = manager.getPageWindow(page0id);
- assertWindow(page0Window, page0id, page0Window.getFilePartOffset(), page0Window.getFilePartSize());
-
- manager.createPageWindow(page1id, maxSize);
- PageWindow page1Window = manager.getPageWindow(page1id);
- assertWindow(page1Window, page1id, page1Window.getFilePartOffset(), page1Window.getFilePartSize());
-
- // Try to get a page which has been lost with the adding of page1
- assertNull("Page0 must be lost when Page1 has been added.", manager.getPageWindow(page0id));
-
- manager.createPageWindow(page2id, maxSize);
- PageWindow page2Window = manager.getPageWindow(page2id);
- assertWindow(page2Window, page2id, page2Window.getFilePartOffset(), page2Window.getFilePartSize());
-
- // Try to get a page which has been lost with the adding of page2
- assertNull("Page1 must be lost when Page2 has been added.", manager.getPageWindow(page1id));
- }
-
- /**
- *
- */
- @Test
- public void addRemove()
- {
- PageWindowManager manager = new PageWindowManager(300);
- PageWindow window;
-
- window = manager.createPageWindow(1, 50);
- assertWindow(window, 1, 0, 50);
-
- window = manager.createPageWindow(2, 40);
- assertWindow(window, 2, 50, 40);
-
- assertEquals(manager.getTotalSize(), 90);
-
- window = manager.createPageWindow(2, 30);
- assertWindow(window, 2, 50, 30);
- assertEquals(manager.getTotalSize(), 80);
-
- manager.removePage(2);
- assertEquals(manager.getTotalSize(), 50);
-
- window = manager.createPageWindow(3, 30);
- assertWindow(window, 3, 50, 30);
- assertEquals(manager.getTotalSize(), 80);
- }
-
- /**
- *
- */
- @Test
- public void pageWindowCycle()
- {
- PageWindowManager manager = new PageWindowManager(100);
- PageWindow window;
-
- window = manager.createPageWindow(1, 30);
-
- window = manager.createPageWindow(2, 30);
-
- window = manager.createPageWindow(3, 30);
-
- assertWindow(window, 3, 60, 30);
-
- window = manager.createPageWindow(4, 30);
-
- assertWindow(window, 4, 90, 30);
-
- // should start at the beginging
-
- window = manager.createPageWindow(5, 20);
-
- assertWindow(window, 5, 0, 20);
-
- assertNull(manager.getPageWindow(1));
-
- window = manager.getPageWindow(2);
- assertWindow(window, 2, 30, 30);
-
- window = manager.createPageWindow(6, 10);
-
- assertWindow(window, 6, 20, 10);
-
- window = manager.getPageWindow(2);
- assertWindow(window, 2, 30, 30);
-
- window = manager.createPageWindow(6, 30);
- assertWindow(window, 6, 20, 30);
-
- assertNull(manager.getPageWindow(2));
- assertNotNull(manager.getPageWindow(3));
-
- window = manager.createPageWindow(6, 60);
- assertWindow(window, 6, 20, 60);
-
- assertNull(manager.getPageWindow(3));
-
- window = manager.createPageWindow(7, 20);
- assertWindow(window, 7, 80, 20);
-
- assertNotNull(manager.getPageWindow(7));
-
- // should start at the beginning again
-
- window = manager.createPageWindow(8, 10);
- assertWindow(window, 8, 0, 10);
-
- assertNull(manager.getPageWindow(5));
- assertNotNull(manager.getPageWindow(6));
-
- window = manager.createPageWindow(9, 20);
- assertWindow(window, 9, 10, 20);
-
- assertNull(manager.getPageWindow(6));
- assertNotNull(manager.getPageWindow(7));
-
- window = manager.createPageWindow(10, 20);
- assertWindow(window, 10, 30, 20);
-
- assertNull(manager.getPageWindow(6));
- assertNotNull(manager.getPageWindow(7));
-
- // make sure when replacing a page that's not last the old "instance" is
- // not valid anymore
-
- manager.createPageWindow(8, 10);
-
- window = manager.getPageWindow(8);
- assertWindow(window, 8, 50, 10);
- }
-
-
- private void assertWindow(PageWindow window, int pageId, int filePartOffset, int filePartSize)
- {
- assertTrue(window.getPageId() == pageId && window.getFilePartOffset() == filePartOffset &&
- window.getFilePartSize() == filePartSize);
- }
-
- /** how many operations to execute */
- private static final int EXECUTIONS = 10000;
-
- /** used to wait the executions */
- private static final CountDownLatch LATCH = new CountDownLatch(EXECUTIONS);
-
- private final PageWindowManager pageWindowManager = new PageWindowManager(1000L);
-
- /** the execution types */
- private final Runnable[] TASKS = new Runnable[]
- {
- new CreatePageWindowTask(pageWindowManager),
- new GetPageWindowTask(pageWindowManager),
- new RemovePageInSessionTask(pageWindowManager)
- };
-
- private static final SecureRandom RND = new SecureRandom();
-
- /**
- * Executes random mutator and accessor operations on {@link org.apache.wicket.pageStore.AsynchronousDataStore} validating
- * that the used data structures can be used simultaneously.
- *
- * @throws Exception
- */
- @Test
- public void randomOperations() throws Exception
- {
- ExecutorService executorService = Executors.newFixedThreadPool(50);
-
- for (int i = 0; i < EXECUTIONS; i++)
- {
- Runnable task = TASKS[RND.nextInt(TASKS.length)];
- executorService.submit(task);
- }
- LATCH.await();
- executorService.shutdown();
- }
-
- private static abstract class AbstractTask implements Runnable
- {
- /** the ids for the stored/removed pages */
- private static final int[] PAGE_IDS = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
-
- protected final PageWindowManager pageWindowManager;
-
- private AbstractTask(PageWindowManager pageWindowManager)
- {
- this.pageWindowManager = pageWindowManager;
- }
-
- protected abstract void r();
-
- @Override
- public void run()
- {
- try
- {
- r();
- }
- finally
- {
- LATCH.countDown();
- }
- }
-
- protected int getPageId()
- {
- return PAGE_IDS[RND.nextInt(PAGE_IDS.length)];
- }
- }
-
- private static class CreatePageWindowTask extends AbstractTask
- {
- private CreatePageWindowTask(PageWindowManager pageWindowManager)
- {
- super(pageWindowManager);
- }
-
- @Override
- public void r()
- {
- pageWindowManager.createPageWindow(getPageId(), 1000);
- }
- }
-
- private static class GetPageWindowTask extends AbstractTask
- {
- private GetPageWindowTask(PageWindowManager pageWindowManager)
- {
- super(pageWindowManager);
- }
-
- @Override
- public void r()
- {
- pageWindowManager.getPageWindow(getPageId());
- }
- }
-
- private static class RemovePageInSessionTask extends AbstractTask
- {
- private RemovePageInSessionTask(PageWindowManager pageWindowManager)
- {
- super(pageWindowManager);
- }
-
- @Override
- public void r()
- {
- pageWindowManager.removePage(getPageId());
- }
- }
-}
http://git-wip-us.apache.org/repos/asf/wicket/blob/bcf76f51/wicket-core/src/test/java/org/apache/wicket/pageStore/AbstractPageStoreTest.java
----------------------------------------------------------------------
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 0ab35fd..d662b5a 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
@@ -29,17 +29,16 @@ public abstract class AbstractPageStoreTest extends Assert
protected final String sessionId = "1234567890";
protected final int pageId = 123;
protected final ISerializer serializer = new JavaSerializer(getClass().getName());
- protected final IDataStore dataStore = new NoopDataStore();
protected int maxEntries = 1;
protected IPageStore pageStore = null;
@Before
public void before()
{
- pageStore = createPageStore(serializer, dataStore, maxEntries);
+ pageStore = createPageStore(serializer, maxEntries);
}
- protected abstract IPageStore createPageStore(ISerializer serializer, IDataStore dataStore, int maxEntries);
+ protected abstract IPageStore createPageStore(ISerializer serializer, int maxEntries);
@After
public void after()
@@ -57,9 +56,11 @@ public abstract class AbstractPageStoreTest extends Assert
@Test
public void storePage()
{
- pageStore.storePage(sessionId, new MockPage(pageId));
+ IPageContext context = new DummyPageContext(sessionId);
+
+ pageStore.addPage(context, new MockPage(pageId));
- assertNotNull(pageStore.getPage(sessionId, pageId));
+ assertNotNull(pageStore.getPage(context, pageId));
}
/**
@@ -68,46 +69,51 @@ public abstract class AbstractPageStoreTest extends Assert
@Test
public void storePage2()
{
+ IPageContext context = new DummyPageContext(sessionId);
int maxEntries = 10;
- pageStore = createPageStore(serializer, dataStore, maxEntries);
+ pageStore = createPageStore(serializer, maxEntries);
- pageStore.storePage(sessionId, new MockPage(pageId));
- pageStore.storePage(sessionId, new MockPage(pageId));
+ pageStore.addPage(context, new MockPage(pageId));
+ pageStore.addPage(context, new MockPage(pageId));
- assertNotNull(pageStore.getPage(sessionId, pageId));
+ assertNotNull(pageStore.getPage(context, pageId));
- pageStore.removePage(sessionId, pageId);
+ pageStore.removePage(context, new MockPage(pageId));
- assertNull(pageStore.getPage(sessionId, pageId));
+ assertNull(pageStore.getPage(context, pageId));
}
@Test
public void removePage()
{
- pageStore.storePage(sessionId, new MockPage(pageId));
+ IPageContext context = new DummyPageContext(sessionId);
+
+ pageStore.addPage(context, new MockPage(pageId));
- assertNotNull(pageStore.getPage(sessionId, pageId));
+ assertNotNull(pageStore.getPage(context, pageId));
- pageStore.removePage(sessionId, pageId);
+ pageStore.removePage(context, new MockPage(pageId));
- assertNull(pageStore.getPage(sessionId, pageId));
+ assertNull(pageStore.getPage(context, pageId));
}
/**
- * Verify that at most {@code maxEntries} per session can be put in the cache
+ * Verify that at most {@code maxEntries} per session can be put in the store
*/
@Test
public void maxSizeSameSession()
{
- pageStore.storePage(sessionId, new MockPage(pageId));
+ IPageContext context = new DummyPageContext(sessionId);
+
+ pageStore.addPage(context, new MockPage(pageId));
- assertNotNull(pageStore.getPage(sessionId, pageId));
+ assertNotNull(pageStore.getPage(context, pageId));
int pageId2 = 234;
- pageStore.storePage(sessionId, new MockPage(pageId2));
- assertNull(pageStore.getPage(sessionId, pageId));
- assertNotNull(pageStore.getPage(sessionId, pageId2));
+ pageStore.addPage(context, new MockPage(pageId2));
+ assertNull(pageStore.getPage(context, pageId));
+ assertNotNull(pageStore.getPage(context, pageId2));
}
/**
@@ -117,15 +123,16 @@ public abstract class AbstractPageStoreTest extends Assert
@Test
public void maxSizeDifferentSessions()
{
- String sessionId2 = "0987654321";
+ IPageContext context = new DummyPageContext(sessionId);
+ IPageContext context2 = new DummyPageContext("0987654321");
- pageStore.storePage(sessionId, new MockPage(pageId));
+ pageStore.addPage(context, new MockPage(pageId));
- assertNotNull(pageStore.getPage(sessionId, pageId));
+ assertNotNull(pageStore.getPage(context, pageId));
- pageStore.storePage(sessionId2, new MockPage(pageId));
+ pageStore.addPage(context2, new MockPage(pageId));
- assertNull(pageStore.getPage(sessionId, pageId));
- assertNotNull(pageStore.getPage(sessionId2, pageId));
+ assertNotNull(pageStore.getPage(context, pageId));
+ assertNotNull(pageStore.getPage(context2, pageId));
}
}
http://git-wip-us.apache.org/repos/asf/wicket/blob/bcf76f51/wicket-core/src/test/java/org/apache/wicket/pageStore/AsynchronousDataStoreTest.java
----------------------------------------------------------------------
diff --git a/wicket-core/src/test/java/org/apache/wicket/pageStore/AsynchronousDataStoreTest.java b/wicket-core/src/test/java/org/apache/wicket/pageStore/AsynchronousDataStoreTest.java
index 7f5b2c1..7c0b0a7 100644
--- a/wicket-core/src/test/java/org/apache/wicket/pageStore/AsynchronousDataStoreTest.java
+++ b/wicket-core/src/test/java/org/apache/wicket/pageStore/AsynchronousDataStoreTest.java
@@ -21,7 +21,8 @@ import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
-import org.apache.wicket.versioning.InMemoryPageStore;
+import org.apache.wicket.MockPage;
+import org.apache.wicket.page.IManageablePage;
import org.junit.Test;
/**
@@ -29,17 +30,13 @@ import org.junit.Test;
*/
public class AsynchronousDataStoreTest
{
-// private static final IDataStore WRAPPED_DATA_STORE = new DiskDataStore("asyncDataStoreApp", new StoreSettings(null).getFileStoreFolder(), Bytes.kilobytes(1));
- private static final IDataStore WRAPPED_DATA_STORE = new InMemoryPageStore();
+ private static final IPageStore WRAPPED_PAGE_STORE = new InMemoryPageStore("test", Integer.MAX_VALUE);
/** the data store under test */
- private static final IDataStore DATA_STORE = new AsynchronousDataStore(WRAPPED_DATA_STORE, 100);
-
- /** the data for each page */
- private static final byte[] DATA = new byte[] { 1, 2, 3 };
+ private static final IPageStore ASYNC_PAGE_STORE = new AsynchronousPageStore(WRAPPED_PAGE_STORE, 100);
/** the used jsessionid's */
- private static final String[] SESSIONS = new String[] { "s1", "s2", "s3" };
+ private static final IPageContext[] CONTEXT = new IPageContext[] { createContext("s1"), createContext("s2"), createContext("s3")};
/** the ids for the stored/removed pages */
private static final int[] PAGE_IDS = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
@@ -74,7 +71,12 @@ public class AsynchronousDataStoreTest
}
LATCH.await();
executorService.shutdown();
- DATA_STORE.destroy();
+ ASYNC_PAGE_STORE.destroy();
+ }
+
+ private static IPageContext createContext(String sessionId)
+ {
+ return new DummyPageContext(sessionId);
}
private static abstract class AbstractTask implements Runnable
@@ -94,15 +96,20 @@ public class AsynchronousDataStoreTest
}
}
- protected String getSessionId()
+ protected IPageContext getPageContext()
{
- return SESSIONS[RND.nextInt(SESSIONS.length)];
+ return CONTEXT[RND.nextInt(CONTEXT.length)];
}
protected int getPageId()
{
return PAGE_IDS[RND.nextInt(PAGE_IDS.length)];
}
+
+ protected IManageablePage getPage()
+ {
+ return new MockPage(getPageId());
+ }
}
private static class StoreTask extends AbstractTask
@@ -110,7 +117,7 @@ public class AsynchronousDataStoreTest
@Override
public void r()
{
- DATA_STORE.storeData(getSessionId(), getPageId(), DATA);
+ ASYNC_PAGE_STORE.addPage(getPageContext(), getPage());
}
}
@@ -119,7 +126,7 @@ public class AsynchronousDataStoreTest
@Override
public void r()
{
- DATA_STORE.getData(getSessionId(), getPageId());
+ ASYNC_PAGE_STORE.getPage(getPageContext(), getPageId());
}
}
@@ -128,7 +135,7 @@ public class AsynchronousDataStoreTest
@Override
public void r()
{
- DATA_STORE.removeData(getSessionId(), getPageId());
+ ASYNC_PAGE_STORE.removePage(getPageContext(), getPage());
}
}
@@ -137,7 +144,7 @@ public class AsynchronousDataStoreTest
@Override
public void r()
{
- DATA_STORE.removeData(getSessionId());
+ ASYNC_PAGE_STORE.removeAllPages(getPageContext());
}
}
}
http://git-wip-us.apache.org/repos/asf/wicket/blob/bcf76f51/wicket-core/src/test/java/org/apache/wicket/pageStore/AsynchronousPageStoreTest.java
----------------------------------------------------------------------
diff --git a/wicket-core/src/test/java/org/apache/wicket/pageStore/AsynchronousPageStoreTest.java b/wicket-core/src/test/java/org/apache/wicket/pageStore/AsynchronousPageStoreTest.java
index 4b17f69..1752e50 100644
--- a/wicket-core/src/test/java/org/apache/wicket/pageStore/AsynchronousPageStoreTest.java
+++ b/wicket-core/src/test/java/org/apache/wicket/pageStore/AsynchronousPageStoreTest.java
@@ -17,21 +17,19 @@
package org.apache.wicket.pageStore;
import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertTrue;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.spy;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
+import static org.junit.Assert.fail;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicBoolean;
-import com.google.common.base.Stopwatch;
import org.apache.commons.lang3.RandomUtils;
+import org.apache.wicket.mock.MockPageStore;
import org.apache.wicket.page.IManageablePage;
import org.apache.wicket.serialize.ISerializer;
import org.apache.wicket.serialize.java.DeflatedJavaSerializer;
@@ -43,6 +41,8 @@ import org.junit.experimental.categories.Category;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import com.google.common.base.Stopwatch;
+
/**
* AsynchronousPageStoreTest
@@ -155,31 +155,50 @@ public class AsynchronousPageStoreTest
@Test
public void storeReturnsSameInstanceOnClosePageRequest() throws InterruptedException
{
+ final Semaphore semaphore = new Semaphore(0);
+
+ IPageStore store = new NoopPageStore() {
+
+ @Override
+ public synchronized void addPage(IPageContext context, IManageablePage page)
+ {
+ try
+ {
+ semaphore.acquire();
+ }
+ catch (InterruptedException e)
+ {
+ }
+
+ super.addPage(context, page);
+ }
+
+ @Override
+ public IManageablePage getPage(IPageContext context, int id)
+ {
+ fail();
+ return null;
+ }
+ };
- ISerializer serializer = new DeflatedJavaSerializer("applicationKey");
- // ISerializer serializer = new DummySerializer();
-
- IDataStore dataStore = new DiskDataStore("applicationName", new File("./target"),
- Bytes.bytes(10000l));
-
- // IPageStore pageStore = new DummyPageStore(new File("target/store"));
- IPageStore pageStore = spy(new DefaultPageStore(serializer, dataStore, 0));
-
- IPageStore asyncPageStore = new AsynchronousPageStore(pageStore, 100);
+ IPageStore asyncPageStore = new AsynchronousPageStore(store, 100);
int pageId = 0;
+
String sessionId = "sessionId";
+
+ IPageContext context = new DummyPageContext(sessionId);
DummyPage page = new DummyPage(pageId, 1000, 1000, sessionId);
- asyncPageStore.storePage(sessionId, page);
-
- Thread.sleep(500);
+ asyncPageStore.addPage(context, page);
- IManageablePage pageBack = asyncPageStore.getPage(sessionId, pageId);
+ IManageablePage pageBack = asyncPageStore.getPage(context, pageId);
- verify(pageStore, never()).getPage(sessionId, pageId);
+ semaphore.release();
assertEquals(page, pageBack);
+
+ store.destroy();
}
/**
@@ -191,31 +210,55 @@ public class AsynchronousPageStoreTest
@Test
public void storeReturnsRestoredInstanceOnDistantPageRequest() throws InterruptedException
{
+ final Semaphore semaphore = new Semaphore(0);
+
+ final AtomicBoolean got = new AtomicBoolean(false);
+
+ IPageStore store = new MockPageStore() {
+
+ @Override
+ public synchronized void addPage(IPageContext context, IManageablePage page)
+ {
+ super.addPage(context, page);
+
+ semaphore.release();
+ }
+
+ @Override
+ public IManageablePage getPage(IPageContext context, int id)
+ {
+ got.set(true);
+
+ return super.getPage(context, id);
+ }
+ };
- ISerializer serializer = new DeflatedJavaSerializer("applicationKey");
- // ISerializer serializer = new DummySerializer();
-
- IDataStore dataStore = new DiskDataStore("applicationName", new File("./target"),
- Bytes.bytes(10000l));
-
- // IPageStore pageStore = new DummyPageStore(new File("target/store"));
- IPageStore pageStore = spy(new DefaultPageStore(serializer, dataStore, 0));
-
- IPageStore asyncPageStore = new AsynchronousPageStore(pageStore, 100);
+ IPageStore asyncPageStore = new AsynchronousPageStore(store, 100);
int pageId = 0;
+
String sessionId = "sessionId";
+
+ IPageContext context = new DummyPageContext(sessionId);
DummyPage page = new DummyPage(pageId, 1000, 1000, sessionId);
- asyncPageStore.storePage(sessionId, page);
+ asyncPageStore.addPage(context, page);
- Thread.sleep(1500);
+ try
+ {
+ semaphore.acquire();
+ }
+ catch (InterruptedException e)
+ {
+ }
- IManageablePage pageBack = asyncPageStore.getPage(sessionId, pageId);
+ IManageablePage pageBack = asyncPageStore.getPage(context, pageId);
- verify(pageStore, times(1)).getPage(sessionId, pageId);
+ semaphore.release();
- assertNotEquals(page, pageBack);
+ assertEquals(page, pageBack);
+
+ store.destroy();
}
/**
@@ -315,18 +358,13 @@ public class AsynchronousPageStoreTest
// ISerializer serializer = new DummySerializer();
ISerializer serializer = new DeflatedJavaSerializer("applicationKey");
- IDataStore dataStore = new DiskDataStore("applicationName", new File("./target"),
- Bytes.bytes(10000l));
-
- // IPageStore pageStore = new DummyPageStore(new File("target/store")) {
- IPageStore pageStore = new DefaultPageStore(serializer, dataStore, 0)
- {
-
+ IPageStore pageStore = new DiskPageStore("applicationName", serializer, new File("./target"),
+ Bytes.bytes(10000l)) {
@Override
- public void storePage(String sessionId, IManageablePage page)
+ public void addPage(IPageContext context, IManageablePage page)
{
- super.storePage(sessionId, page);
+ super.addPage(context, page);
lock.countDown();
}
@@ -341,20 +379,21 @@ public class AsynchronousPageStoreTest
for (int i = 1; i <= sessions; i++)
{
String sessionId = String.valueOf(i);
+ IPageContext context = new DummyPageContext(sessionId);
Metrics metrics = new Metrics();
stopwatch.reset();
DummyPage page = new DummyPage(pageId, around(writeMillis), around(readMillis),
sessionId);
stopwatch.start();
- asyncPageStore.storePage(sessionId, page);
+ asyncPageStore.addPage(context, page);
metrics.storedPage = page;
metrics.storingMillis = stopwatch.elapsed(TimeUnit.MILLISECONDS);
stopwatch.reset();
stopwatch.start();
metrics.restoredPage = DummyPage.class
- .cast(asyncPageStore.getPage(sessionId, pageId));
+ .cast(asyncPageStore.getPage(context, pageId));
metrics.restoringMillis = stopwatch.elapsed(TimeUnit.MILLISECONDS);
results.add(metrics);
@@ -363,6 +402,8 @@ public class AsynchronousPageStoreTest
lock.await(pages * sessions * (writeMillis + readMillis), TimeUnit.MILLISECONDS);
+ pageStore.destroy();
+
return results;
}
http://git-wip-us.apache.org/repos/asf/wicket/blob/bcf76f51/wicket-core/src/test/java/org/apache/wicket/pageStore/DefaultPageStoreTest.java
----------------------------------------------------------------------
diff --git a/wicket-core/src/test/java/org/apache/wicket/pageStore/DefaultPageStoreTest.java b/wicket-core/src/test/java/org/apache/wicket/pageStore/DefaultPageStoreTest.java
deleted file mode 100644
index 2ffa376..0000000
--- a/wicket-core/src/test/java/org/apache/wicket/pageStore/DefaultPageStoreTest.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * 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.serialize.ISerializer;
-
-/**
- * Tests for DefaultPageStore
- */
-public class DefaultPageStoreTest extends AbstractPageStoreTest
-{
- @Override
- protected IPageStore createPageStore(ISerializer serializer, IDataStore dataStore, int maxEntries)
- {
- return new DefaultPageStore(serializer, dataStore, maxEntries);
- }
-}
http://git-wip-us.apache.org/repos/asf/wicket/blob/bcf76f51/wicket-core/src/test/java/org/apache/wicket/pageStore/DiskDataStoreTest.java
----------------------------------------------------------------------
diff --git a/wicket-core/src/test/java/org/apache/wicket/pageStore/DiskDataStoreTest.java b/wicket-core/src/test/java/org/apache/wicket/pageStore/DiskDataStoreTest.java
index e69ead6..933870e 100644
--- a/wicket-core/src/test/java/org/apache/wicket/pageStore/DiskDataStoreTest.java
+++ b/wicket-core/src/test/java/org/apache/wicket/pageStore/DiskDataStoreTest.java
@@ -16,6 +16,7 @@
*/
package org.apache.wicket.pageStore;
+import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
@@ -26,6 +27,8 @@ import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
+import org.apache.wicket.page.IManageablePage;
+import org.apache.wicket.serialize.java.JavaSerializer;
import org.apache.wicket.settings.StoreSettings;
import org.apache.wicket.util.SlowTests;
import org.apache.wicket.util.lang.Bytes;
@@ -36,6 +39,7 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
+ * Test for {@link DiskDataStore}.
*/
@Category(SlowTests.class)
public class DiskDataStoreTest extends Assert
@@ -59,20 +63,33 @@ public class DiskDataStoreTest extends Assert
private static final int SLEEP_MAX = 10;
private static final int THREAD_COUNT = 20;
private static final int READ_MODULO = 100;
+
+ private static final ConcurrentHashMap<String, IPageContext> contexts = new ConcurrentHashMap<>();
+
+ private static IPageContext getContext(String sessionId) {
+ IPageContext context = new DummyPageContext();
+
+ IPageContext existing = contexts.putIfAbsent(sessionId, context);
+ return existing != null ? existing : context;
+ }
- private static class File
+ private static class TaskPage implements IManageablePage
{
private final String sessionId;
- private final int id;
+
+ private int id;
- private byte first;
- private byte last;
- private int length;
+ private byte[] data;
- public File(String sessionId, int id)
+ public TaskPage(String sessionId, int id)
{
this.sessionId = sessionId;
+
this.id = id;
+
+ int length = FILE_SIZE_MIN + random.nextInt(FILE_SIZE_MAX - FILE_SIZE_MIN);
+ data = new byte[length];
+ random.nextBytes(data);
}
public String getSessionId()
@@ -80,51 +97,54 @@ public class DiskDataStoreTest extends Assert
return sessionId;
}
- public int getId()
+ public boolean check(TaskPage other)
{
- return id;
- }
-
- public byte[] generateData()
- {
- length = FILE_SIZE_MIN + random.nextInt(FILE_SIZE_MAX - FILE_SIZE_MIN);
- byte data[] = new byte[length];
- random.nextBytes(data);
- first = data[0];
- last = data[data.length - 1];
- return data;
- }
-
- public boolean checkData(byte data[])
- {
- if (data == null)
- {
- log.error("data[] should never be null");
- return false;
- }
- if (data.length != length)
+ if (other.data.length != other.data.length)
{
log.error("data.length != length");
return false;
}
- if (first != data[0])
+ if (other.id != other.id)
{
- log.error("first != data[0]");
+ log.error("data.id != id");
return false;
}
- if (last != data[data.length - 1])
+ if (other.sessionId != other.sessionId)
{
- log.error("last != data[data.length - 1]");
+ log.error("data.sessionId != sessionId");
return false;
}
return true;
}
+
+ @Override
+ public boolean isPageStateless()
+ {
+ return false;
+ }
+
+ @Override
+ public int getPageId()
+ {
+ return id;
+ }
+
+ @Override
+ public void detach()
+ {
+ }
+
+ @Override
+ public boolean setFreezePageId(boolean freeze)
+ {
+ return false;
+ }
}
private final Map<String, AtomicInteger> sessionCounter = new ConcurrentHashMap<String, AtomicInteger>();
- private final ConcurrentLinkedQueue<File> filesToSave = new ConcurrentLinkedQueue<File>();
- private final ConcurrentLinkedQueue<File> filesToRead1 = new ConcurrentLinkedQueue<File>();
- private final ConcurrentLinkedQueue<File> filesToRead2 = new ConcurrentLinkedQueue<File>();
+ private final ConcurrentLinkedQueue<TaskPage> pagesToSave = new ConcurrentLinkedQueue<TaskPage>();
+ private final ConcurrentLinkedQueue<TaskPage> filesToRead1 = new ConcurrentLinkedQueue<TaskPage>();
+ private final ConcurrentLinkedQueue<TaskPage> filesToRead2 = new ConcurrentLinkedQueue<TaskPage>();
private final AtomicInteger read1Count = new AtomicInteger(0);
private final AtomicInteger read2Count = new AtomicInteger(0);
@@ -164,15 +184,15 @@ public class DiskDataStoreTest extends Assert
for (int i = 0; i < FILES_COUNT; ++i)
{
String session = randomSessionId();
- File file = new File(session, nextSessionId(session));
+ TaskPage file = new TaskPage(session, nextSessionId(session));
long now = System.nanoTime();
- filesToSave.add(file);
+ pagesToSave.add(file);
long duration = System.nanoTime() - now;
saveTime.addAndGet((int)duration);
}
}
- private IDataStore dataStore;
+ private IPageStore pageStore;
/**
* Stores RuntimeException into a field.
@@ -205,21 +225,20 @@ public class DiskDataStoreTest extends Assert
@Override
protected void doRun()
{
- File file;
+ TaskPage page;
- while ((file = filesToSave.poll()) != null || saveCount.get() < FILES_COUNT)
+ while ((page = pagesToSave.poll()) != null || saveCount.get() < FILES_COUNT)
{
- if (file != null)
+ if (page != null)
{
- byte data[] = file.generateData();
- dataStore.storeData(file.getSessionId(), file.getId(), data);
+ pageStore.addPage(getContext(page.getSessionId()), page);
if (saveCount.get() % READ_MODULO == 0)
{
- filesToRead1.add(file);
+ filesToRead1.add(page);
}
saveCount.incrementAndGet();
- bytesWritten.addAndGet(data.length);
+ bytesWritten.addAndGet(page.data.length);
}
try
@@ -242,20 +261,20 @@ public class DiskDataStoreTest extends Assert
@Override
protected void doRun()
{
- File file;
- while ((file = filesToRead1.poll()) != null || !saveDone.get())
+ TaskPage page;
+ while ((page = filesToRead1.poll()) != null || !saveDone.get())
{
- if (file != null)
+ if (page != null)
{
- byte bytes[] = dataStore.getData(file.getSessionId(), file.getId());
- if (file.checkData(bytes) == false)
+ TaskPage other = (TaskPage)pageStore.getPage(getContext(page.getSessionId()), page.getPageId());
+ if (page.check(other) == false)
{
failures.incrementAndGet();
log.error("Detected error number: " + failures.get());
}
- filesToRead2.add(file);
+ filesToRead2.add(page);
read1Count.incrementAndGet();
- bytesRead.addAndGet(bytes.length);
+ bytesRead.addAndGet(other.data.length);
}
try
@@ -277,19 +296,19 @@ public class DiskDataStoreTest extends Assert
@Override
protected void doRun()
{
- File file;
- while ((file = filesToRead2.poll()) != null || !read1Done.get())
+ TaskPage page;
+ while ((page = filesToRead2.poll()) != null || !read1Done.get())
{
- if (file != null)
+ if (page != null)
{
- byte bytes[] = dataStore.getData(file.getSessionId(), file.getId());
- if (file.checkData(bytes) == false)
+ TaskPage other = (TaskPage)pageStore.getPage(getContext(page.getSessionId()), page.getPageId());
+ if (page.check(other) == false)
{
failures.incrementAndGet();
log.error("Detected error number: " + failures.get());
}
read2Count.incrementAndGet();
- bytesRead.addAndGet(bytes.length);
+ bytesRead.addAndGet(other.data.length);
}
try
@@ -356,7 +375,7 @@ public class DiskDataStoreTest extends Assert
for (String s : sessionCounter.keySet())
{
- dataStore.removeData(s);
+ pageStore.removeAllPages(getContext(s));
}
}
@@ -369,15 +388,15 @@ public class DiskDataStoreTest extends Assert
generateFiles();
StoreSettings storeSettings = new StoreSettings(null);
- java.io.File fileStoreFolder = storeSettings.getFileStoreFolder();
-
- dataStore = new DiskDataStore("app1", fileStoreFolder, MAX_SIZE_PER_SESSION);
+ File fileStoreFolder = storeSettings.getFileStoreFolder();
int asynchronousQueueCapacity = storeSettings.getAsynchronousQueueCapacity();
- dataStore = new AsynchronousDataStore(dataStore, asynchronousQueueCapacity);
+
+ pageStore = new DiskPageStore("app1", new JavaSerializer("app1"), fileStoreFolder, MAX_SIZE_PER_SESSION);
+ pageStore = new AsynchronousPageStore(pageStore, asynchronousQueueCapacity);
doTestDataStore();
- dataStore.destroy();
+ pageStore.destroy();
}
/**
@@ -391,7 +410,7 @@ public class DiskDataStoreTest extends Assert
{
StoreSettings storeSettings = new StoreSettings(null);
java.io.File fileStoreFolder = storeSettings.getFileStoreFolder();
- DiskDataStore store = new DiskDataStore("sessionFolderName", fileStoreFolder, MAX_SIZE_PER_SESSION);
+ DiskPageStore store = new DiskPageStore("sessionFolderName", new JavaSerializer("sessionFolderName"), fileStoreFolder, MAX_SIZE_PER_SESSION);
String sessionId = "abcdefg";
java.io.File sessionFolder = store.getSessionFolder(sessionId, true);
@@ -401,7 +420,7 @@ public class DiskDataStoreTest extends Assert
assertTrue(absolutePath.contains("1279"));
assertTrue(absolutePath.contains("abcdefg"));
- DiskDataStore.SessionEntry sessionEntry = new DiskDataStore.SessionEntry(store, sessionId);
+ DiskPageStore.DiskData sessionEntry = new DiskPageStore.DiskData(store, sessionId);
sessionEntry.unbind();
// assert that the 'sessionId' folder and the parents two levels up are removed
assertFalse(sessionFolder.getParentFile().getParentFile().exists());
http://git-wip-us.apache.org/repos/asf/wicket/blob/bcf76f51/wicket-core/src/test/java/org/apache/wicket/pageStore/DummyPageContext.java
----------------------------------------------------------------------
diff --git a/wicket-core/src/test/java/org/apache/wicket/pageStore/DummyPageContext.java b/wicket-core/src/test/java/org/apache/wicket/pageStore/DummyPageContext.java
new file mode 100644
index 0000000..0cd0b08
--- /dev/null
+++ b/wicket-core/src/test/java/org/apache/wicket/pageStore/DummyPageContext.java
@@ -0,0 +1,103 @@
+/*
+ * 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.Serializable;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.wicket.MetaDataEntry;
+import org.apache.wicket.MetaDataKey;
+import org.apache.wicket.pageStore.IPageContext;
+
+/**
+ * Dummy implementation of a page context - suitable for a single session only.
+ */
+public class DummyPageContext implements IPageContext
+{
+
+ final String sessionId;
+
+ MetaDataEntry<?>[] requestData;
+
+ MetaDataEntry<?>[] sessionData;
+
+ Map<String, Object> sessionAttributes = new HashMap<>();
+
+ public DummyPageContext()
+ {
+ this("dummy_id");
+ }
+
+ public DummyPageContext(String sessionId)
+ {
+ this.sessionId = sessionId;
+ }
+
+ @Override
+ public <T> void setRequestData(MetaDataKey<T> key, T value)
+ {
+ requestData = key.set(requestData, value);
+ }
+
+ @Override
+ public <T> T getRequestData(MetaDataKey<T> key)
+ {
+ return key.get(requestData);
+ }
+
+ @Override
+ public <T extends Serializable> void setSessionAttribute(String key, T value)
+ {
+ sessionAttributes.put(key, value);
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public <T extends Serializable> T getSessionAttribute(String key)
+ {
+ return (T)sessionAttributes.get(key);
+ }
+
+ @Override
+ public <T extends Serializable> void setSessionData(MetaDataKey<T> key, T value)
+ {
+ sessionData = key.set(sessionData, value);
+ }
+
+ @Override
+ public <T extends Serializable> T getSessionData(MetaDataKey<T> key)
+ {
+ return key.get(sessionData);
+ }
+
+ @Override
+ public void bind()
+ {
+ }
+
+ @Override
+ public String getSessionId()
+ {
+ return sessionId;
+ }
+
+ public void clearRequest()
+ {
+ requestData = null;
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/wicket/blob/bcf76f51/wicket-core/src/test/java/org/apache/wicket/pageStore/GroupingPageStoreTest.java
----------------------------------------------------------------------
diff --git a/wicket-core/src/test/java/org/apache/wicket/pageStore/GroupingPageStoreTest.java b/wicket-core/src/test/java/org/apache/wicket/pageStore/GroupingPageStoreTest.java
new file mode 100644
index 0000000..b863074
--- /dev/null
+++ b/wicket-core/src/test/java/org/apache/wicket/pageStore/GroupingPageStoreTest.java
@@ -0,0 +1,112 @@
+/*
+ * 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 static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import java.io.Serializable;
+
+import org.apache.wicket.MetaDataKey;
+import org.apache.wicket.MockPage;
+import org.apache.wicket.mock.MockPageStore;
+import org.apache.wicket.page.IManageablePage;
+import org.junit.Test;
+
+/**
+ * Test for {@link GroupingPageStore}.
+ *
+ * @author svenmeier
+ */
+public class GroupingPageStoreTest
+{
+
+ private static MetaDataKey<Serializable> KEY = new MetaDataKey<Serializable>()
+ {
+ };
+
+ private static Serializable VALUE = new Serializable()
+ {
+ };
+
+ @Test
+ public void test()
+ {
+ String sessionId = "foo";
+
+ IPageStore store = new MockPageStore() {
+
+ public void addPage(IPageContext context, IManageablePage page) {
+
+ context.setSessionAttribute("attribute", "value");
+ context.setSessionData(KEY, VALUE);
+
+ assertEquals(sessionId + "_" + group(page), context.getSessionId());
+
+ super.addPage(context, page);
+ }
+
+ @Override
+ public void removeAllPages(IPageContext context)
+ {
+ assertEquals(sessionId + "_group0", context.getSessionId());
+
+ super.removeAllPages(context);
+ }
+ };
+
+ IPageStore groupingStore = new GroupingPageStore(store, 2) {
+ @Override
+ protected String getGroup(IManageablePage page)
+ {
+ return group(page);
+ }
+ };
+
+ DummyPageContext context = new DummyPageContext(sessionId) {
+ @Override
+ public <T extends Serializable> void setSessionData(MetaDataKey<T> key, T value)
+ {
+ assertFalse("session not set directly in session", value == VALUE);
+
+ super.setSessionData(key, value);
+ }
+
+ @Override
+ public <T extends Serializable> void setSessionAttribute(String key, T value)
+ {
+ assertTrue("key starts with group", key.startsWith("attribute_group"));
+
+ super.setSessionAttribute(key, value);
+ }
+ };
+
+ groupingStore.addPage(context, new MockPage(0));
+ groupingStore.addPage(context, new MockPage(1));
+ groupingStore.addPage(context, new MockPage(10));
+ groupingStore.addPage(context, new MockPage(11));
+ groupingStore.addPage(context, new MockPage(2));
+ groupingStore.addPage(context, new MockPage(21));
+
+ }
+
+ protected String group(IManageablePage page)
+ {
+ return "group" + page.getPageId() / 10;
+ }
+}
http://git-wip-us.apache.org/repos/asf/wicket/blob/bcf76f51/wicket-core/src/test/java/org/apache/wicket/pageStore/InMemoryPageStoreTest.java
----------------------------------------------------------------------
diff --git a/wicket-core/src/test/java/org/apache/wicket/pageStore/InMemoryPageStoreTest.java b/wicket-core/src/test/java/org/apache/wicket/pageStore/InMemoryPageStoreTest.java
new file mode 100644
index 0000000..ab1dcec
--- /dev/null
+++ b/wicket-core/src/test/java/org/apache/wicket/pageStore/InMemoryPageStoreTest.java
@@ -0,0 +1,31 @@
+/*
+ * 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.serialize.ISerializer;
+
+/**
+ * Tests for {@link InMemoryPageStore}
+ */
+public class InMemoryPageStoreTest extends AbstractPageStoreTest
+{
+ @Override
+ protected IPageStore createPageStore(ISerializer serializer, int maxEntries)
+ {
+ return new InMemoryPageStore("test", maxEntries);
+ }
+}
http://git-wip-us.apache.org/repos/asf/wicket/blob/bcf76f51/wicket-core/src/test/java/org/apache/wicket/pageStore/InSessionPageStoreTest.java
----------------------------------------------------------------------
diff --git a/wicket-core/src/test/java/org/apache/wicket/pageStore/InSessionPageStoreTest.java b/wicket-core/src/test/java/org/apache/wicket/pageStore/InSessionPageStoreTest.java
new file mode 100644
index 0000000..4fa2f4e
--- /dev/null
+++ b/wicket-core/src/test/java/org/apache/wicket/pageStore/InSessionPageStoreTest.java
@@ -0,0 +1,32 @@
+/*
+ * 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.serialize.ISerializer;
+
+/**
+ * Test for {@link InSessionPageStore}.
+ */
+public class InSessionPageStoreTest extends AbstractPageStoreTest
+{
+ @Override
+ protected IPageStore createPageStore(ISerializer serializer, int maxEntries)
+ {
+ return new InSessionPageStore(new NoopPageStore(), serializer, maxEntries);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/wicket/blob/bcf76f51/wicket-core/src/test/java/org/apache/wicket/pageStore/NoopDataStore.java
----------------------------------------------------------------------
diff --git a/wicket-core/src/test/java/org/apache/wicket/pageStore/NoopDataStore.java b/wicket-core/src/test/java/org/apache/wicket/pageStore/NoopDataStore.java
deleted file mode 100644
index 0cadaee..0000000
--- a/wicket-core/src/test/java/org/apache/wicket/pageStore/NoopDataStore.java
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * 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;
-
-/**
- * An implementation of IDataStore that does nothing
- */
-public class NoopDataStore implements IDataStore
-{
- @Override
- public byte[] getData(String sessionId, int id)
- {
- return null;
- }
-
- @Override
- public void removeData(String sessionId, int id)
- {
- }
-
- @Override
- public void removeData(String sessionId)
- {
- }
-
- @Override
- public void storeData(String sessionId, int id, byte[] data)
- {
- }
-
- @Override
- public void destroy()
- {
- }
-
- @Override
- public boolean isReplicated()
- {
- return false;
- }
-
- @Override
- public boolean canBeAsynchronous()
- {
- return false;
- }
-}
http://git-wip-us.apache.org/repos/asf/wicket/blob/bcf76f51/wicket-core/src/test/java/org/apache/wicket/pageStore/PerSessionPageStoreTest.java
----------------------------------------------------------------------
diff --git a/wicket-core/src/test/java/org/apache/wicket/pageStore/PerSessionPageStoreTest.java b/wicket-core/src/test/java/org/apache/wicket/pageStore/PerSessionPageStoreTest.java
deleted file mode 100644
index 0cd4a2a..0000000
--- a/wicket-core/src/test/java/org/apache/wicket/pageStore/PerSessionPageStoreTest.java
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * 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.MockPage;
-import org.apache.wicket.serialize.ISerializer;
-import org.junit.Test;
-
-/**
- * Tests for PerSessionPageStore
- */
-public class PerSessionPageStoreTest extends AbstractPageStoreTest
-{
- @Override
- protected IPageStore createPageStore(ISerializer serializer, IDataStore dataStore, int maxEntries)
- {
- return new PerSessionPageStore(serializer, dataStore, maxEntries);
- }
-
- /**
- * Verify that it is OK to store more pages than {@code maxEntries}
- * if they are in different sessions
- */
- @Test
- @Override
- public void maxSizeDifferentSessions()
- {
- String sessionId2 = "0987654321";
-
- pageStore.storePage(sessionId, new MockPage(pageId));
-
- assertNotNull(pageStore.getPage(sessionId, pageId));
-
- pageStore.storePage(sessionId2, new MockPage(pageId));
-
- assertNotNull(pageStore.getPage(sessionId, pageId));
- assertNotNull(pageStore.getPage(sessionId2, pageId));
- }
-}
http://git-wip-us.apache.org/repos/asf/wicket/blob/bcf76f51/wicket-core/src/test/java/org/apache/wicket/pageStore/disk/PageWindowManagerTest.java
----------------------------------------------------------------------
diff --git a/wicket-core/src/test/java/org/apache/wicket/pageStore/disk/PageWindowManagerTest.java b/wicket-core/src/test/java/org/apache/wicket/pageStore/disk/PageWindowManagerTest.java
new file mode 100644
index 0000000..57ce54d
--- /dev/null
+++ b/wicket-core/src/test/java/org/apache/wicket/pageStore/disk/PageWindowManagerTest.java
@@ -0,0 +1,303 @@
+/*
+ * 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.disk;
+
+import java.security.SecureRandom;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+
+import org.apache.wicket.markup.html.WebPage;
+import org.apache.wicket.pageStore.disk.PageWindowManager.FileWindow;
+import org.junit.Assert;
+import org.junit.Test;
+
+/**
+ * Test for {@link PageWindowManager}.
+ *
+ * @author Matej Knopp
+ */
+public class PageWindowManagerTest extends Assert
+{
+ /**
+ * https://issues.apache.org/jira/browse/WICKET-4572
+ */
+ @Test
+ public void removeObsoleteIndices()
+ {
+ int page0id = 0,
+ page1id = 1,
+ page2id = 2;
+ int maxSize = 10;
+
+ PageWindowManager manager = new PageWindowManager(maxSize);
+
+ // Add few pages.
+ // All of them fully occupy the max space in the pageWindowManager.
+ // So adding N+1st page removes the Nth page.
+ manager.createPageWindow(page0id, WebPage.class, maxSize);
+ FileWindow page0Window = manager.getPageWindow(page0id);
+ assertWindow(page0Window, page0id, page0Window.getFilePartOffset(), page0Window.getFilePartSize());
+
+ manager.createPageWindow(page1id, WebPage.class, maxSize);
+ FileWindow page1Window = manager.getPageWindow(page1id);
+ assertWindow(page1Window, page1id, page1Window.getFilePartOffset(), page1Window.getFilePartSize());
+
+ // Try to get a page which has been lost with the adding of page1
+ assertNull("Page0 must be lost when Page1 has been added.", manager.getPageWindow(page0id));
+
+ manager.createPageWindow(page2id, WebPage.class, maxSize);
+ FileWindow page2Window = manager.getPageWindow(page2id);
+ assertWindow(page2Window, page2id, page2Window.getFilePartOffset(), page2Window.getFilePartSize());
+
+ // Try to get a page which has been lost with the adding of page2
+ assertNull("Page1 must be lost when Page2 has been added.", manager.getPageWindow(page1id));
+ }
+
+ /**
+ *
+ */
+ @Test
+ public void addRemove()
+ {
+ PageWindowManager manager = new PageWindowManager(300);
+ FileWindow window;
+
+ window = manager.createPageWindow(1, WebPage.class, 50);
+ assertWindow(window, 1, 0, 50);
+
+ window = manager.createPageWindow(2, WebPage.class, 40);
+ assertWindow(window, 2, 50, 40);
+
+ assertEquals(manager.getTotalSize(), 90);
+
+ window = manager.createPageWindow(2, WebPage.class, 30);
+ assertWindow(window, 2, 50, 30);
+ assertEquals(manager.getTotalSize(), 80);
+
+ manager.removePage(2);
+ assertEquals(manager.getTotalSize(), 50);
+
+ window = manager.createPageWindow(3, WebPage.class, 30);
+ assertWindow(window, 3, 50, 30);
+ assertEquals(manager.getTotalSize(), 80);
+ }
+
+ /**
+ *
+ */
+ @Test
+ public void pageWindowCycle()
+ {
+ PageWindowManager manager = new PageWindowManager(100);
+ FileWindow window;
+
+ window = manager.createPageWindow(1, WebPage.class, 30);
+
+ window = manager.createPageWindow(2, WebPage.class, 30);
+
+ window = manager.createPageWindow(3, WebPage.class, 30);
+
+ assertWindow(window, 3, 60, 30);
+
+ window = manager.createPageWindow(4, WebPage.class, 30);
+
+ assertWindow(window, 4, 90, 30);
+
+ // should start at the beginging
+
+ window = manager.createPageWindow(5, WebPage.class, 20);
+
+ assertWindow(window, 5, 0, 20);
+
+ assertNull(manager.getPageWindow(1));
+
+ window = manager.getPageWindow(2);
+ assertWindow(window, 2, 30, 30);
+
+ window = manager.createPageWindow(6, WebPage.class, 10);
+
+ assertWindow(window, 6, 20, 10);
+
+ window = manager.getPageWindow(2);
+ assertWindow(window, 2, 30, 30);
+
+ window = manager.createPageWindow(6, WebPage.class, 30);
+ assertWindow(window, 6, 20, 30);
+
+ assertNull(manager.getPageWindow(2));
+ assertNotNull(manager.getPageWindow(3));
+
+ window = manager.createPageWindow(6, WebPage.class, 60);
+ assertWindow(window, 6, 20, 60);
+
+ assertNull(manager.getPageWindow(3));
+
+ window = manager.createPageWindow(7, WebPage.class, 20);
+ assertWindow(window, 7, 80, 20);
+
+ assertNotNull(manager.getPageWindow(7));
+
+ // should start at the beginning again
+
+ window = manager.createPageWindow(8, WebPage.class, 10);
+ assertWindow(window, 8, 0, 10);
+
+ assertNull(manager.getPageWindow(5));
+ assertNotNull(manager.getPageWindow(6));
+
+ window = manager.createPageWindow(9, WebPage.class, 20);
+ assertWindow(window, 9, 10, 20);
+
+ assertNull(manager.getPageWindow(6));
+ assertNotNull(manager.getPageWindow(7));
+
+ window = manager.createPageWindow(10, WebPage.class, 20);
+ assertWindow(window, 10, 30, 20);
+
+ assertNull(manager.getPageWindow(6));
+ assertNotNull(manager.getPageWindow(7));
+
+ // make sure when replacing a page that's not last the old "instance" is
+ // not valid anymore
+
+ manager.createPageWindow(8, WebPage.class, 10);
+
+ window = manager.getPageWindow(8);
+ assertWindow(window, 8, 50, 10);
+ }
+
+
+ private void assertWindow(FileWindow window, int pageId, int filePartOffset, int filePartSize)
+ {
+ assertTrue(window.getPageId() == pageId && window.getFilePartOffset() == filePartOffset &&
+ window.getFilePartSize() == filePartSize);
+ }
+
+ /** how many operations to execute */
+ private static final int EXECUTIONS = 10000;
+
+ /** used to wait the executions */
+ private static final CountDownLatch LATCH = new CountDownLatch(EXECUTIONS);
+
+ private final PageWindowManager pageWindowManager = new PageWindowManager(1000L);
+
+ /** the execution types */
+ private final Runnable[] TASKS = new Runnable[]
+ {
+ new CreatePageWindowTask(pageWindowManager),
+ new GetPageWindowTask(pageWindowManager),
+ new RemovePageInSessionTask(pageWindowManager)
+ };
+
+ private static final SecureRandom RND = new SecureRandom();
+
+ /**
+ * Executes random mutator and accessor operations on {@link org.apache.wicket.pageStore.AsynchronousDataStore} validating
+ * that the used data structures can be used simultaneously.
+ *
+ * @throws Exception
+ */
+ @Test
+ public void randomOperations() throws Exception
+ {
+ ExecutorService executorService = Executors.newFixedThreadPool(50);
+
+ for (int i = 0; i < EXECUTIONS; i++)
+ {
+ Runnable task = TASKS[RND.nextInt(TASKS.length)];
+ executorService.submit(task);
+ }
+ LATCH.await();
+ executorService.shutdown();
+ }
+
+ private static abstract class AbstractTask implements Runnable
+ {
+ /** the ids for the stored/removed pages */
+ private static final int[] PAGE_IDS = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
+
+ protected final PageWindowManager pageWindowManager;
+
+ private AbstractTask(PageWindowManager pageWindowManager)
+ {
+ this.pageWindowManager = pageWindowManager;
+ }
+
+ protected abstract void r();
+
+ @Override
+ public void run()
+ {
+ try
+ {
+ r();
+ }
+ finally
+ {
+ LATCH.countDown();
+ }
+ }
+
+ protected int getPageId()
+ {
+ return PAGE_IDS[RND.nextInt(PAGE_IDS.length)];
+ }
+ }
+
+ private static class CreatePageWindowTask extends AbstractTask
+ {
+ private CreatePageWindowTask(PageWindowManager pageWindowManager)
+ {
+ super(pageWindowManager);
+ }
+
+ @Override
+ public void r()
+ {
+ pageWindowManager.createPageWindow(getPageId(), WebPage.class, 1000);
+ }
+ }
+
+ private static class GetPageWindowTask extends AbstractTask
+ {
+ private GetPageWindowTask(PageWindowManager pageWindowManager)
+ {
+ super(pageWindowManager);
+ }
+
+ @Override
+ public void r()
+ {
+ pageWindowManager.getPageWindow(getPageId());
+ }
+ }
+
+ private static class RemovePageInSessionTask extends AbstractTask
+ {
+ private RemovePageInSessionTask(PageWindowManager pageWindowManager)
+ {
+ super(pageWindowManager);
+ }
+
+ @Override
+ public void r()
+ {
+ pageWindowManager.removePage(getPageId());
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/wicket/blob/bcf76f51/wicket-core/src/test/java/org/apache/wicket/pageStore/memory/DummyPageManagerContext.java
----------------------------------------------------------------------
diff --git a/wicket-core/src/test/java/org/apache/wicket/pageStore/memory/DummyPageManagerContext.java b/wicket-core/src/test/java/org/apache/wicket/pageStore/memory/DummyPageManagerContext.java
deleted file mode 100644
index 99d4c90..0000000
--- a/wicket-core/src/test/java/org/apache/wicket/pageStore/memory/DummyPageManagerContext.java
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * 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.memory;
-
-import java.io.Serializable;
-
-import org.apache.wicket.page.IPageManagerContext;
-
-/**
- */
-public class DummyPageManagerContext implements IPageManagerContext
-{
-
- Serializable attribute = null;
- Object requestData;
-
- @Override
- public void setRequestData(Object data)
- {
- requestData = data;
- }
-
- @Override
- public Object getRequestData()
- {
- return requestData;
- }
-
- @Override
- public void setSessionAttribute(String key, Serializable value)
- {
- attribute = value;
- }
-
- @Override
- public Serializable getSessionAttribute(String key)
- {
- return attribute;
- }
-
- @Override
- public void bind()
- {
- }
-
- @Override
- public String getSessionId()
- {
- return "dummy_id";
- }
-
-}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/wicket/blob/bcf76f51/wicket-core/src/test/java/org/apache/wicket/pageStore/memory/HttpSessionDataStoreTest.java
----------------------------------------------------------------------
diff --git a/wicket-core/src/test/java/org/apache/wicket/pageStore/memory/HttpSessionDataStoreTest.java b/wicket-core/src/test/java/org/apache/wicket/pageStore/memory/HttpSessionDataStoreTest.java
deleted file mode 100644
index 10b5268..0000000
--- a/wicket-core/src/test/java/org/apache/wicket/pageStore/memory/HttpSessionDataStoreTest.java
+++ /dev/null
@@ -1,112 +0,0 @@
-/*
- * 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.memory;
-
-import static org.junit.Assert.assertArrayEquals;
-
-import org.apache.wicket.util.tester.WicketTestCase;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-
-/**
- */
-public class HttpSessionDataStoreTest extends WicketTestCase
-{
- final String sessionId = "anything";
-
- final int pageId = 1;
-
- final byte[] PAGE1 = new byte[] { 1 };
- final byte[] PAGE2 = new byte[] { 2 };
-
- HttpSessionDataStore store;
-
- /**
- * before()
- */
- @Before
- public void before()
- {
- store = new HttpSessionDataStore(new DummyPageManagerContext(), new NoopEvictionStrategy());
- }
-
- /**
- * after()
- */
- @After
- public void after()
- {
- store.destroy();
- }
-
- /**
- * storePage()
- */
- @Test
- public void storePage()
- {
- assertNull(store.getData(sessionId, pageId));
-
- store.storeData(sessionId, pageId, PAGE1);
- assertArrayEquals(PAGE1, store.getData(sessionId, pageId));
- }
-
- /**
- * removePage1()
- */
- @Test
- public void removePage1()
- {
- assertNull(store.getData(sessionId, pageId));
-
- store.storeData(sessionId, pageId, PAGE1);
-
- assertNotNull(store.getData(sessionId, pageId));
-
- store.removeData(sessionId, pageId);
-
- assertNull(store.getData(sessionId, pageId));
- }
-
- /**
- * removePage2()
- */
- @Test
- public void removePage2()
- {
- assertNull(store.getData(sessionId, pageId));
-
- store.storeData(sessionId, pageId, PAGE1);
-
- assertNotNull(store.getData(sessionId, pageId));
-
- store.removeData(sessionId);
-
- assertNull(store.getData(sessionId, pageId));
- }
-
-
- private static final class NoopEvictionStrategy implements IDataStoreEvictionStrategy
- {
-
- @Override
- public void evict(PageTable pageTable)
- {
- }
- }
-}
http://git-wip-us.apache.org/repos/asf/wicket/blob/bcf76f51/wicket-core/src/test/java/org/apache/wicket/pageStore/memory/MemorySizeEvictionStrategyTest.java
----------------------------------------------------------------------
diff --git a/wicket-core/src/test/java/org/apache/wicket/pageStore/memory/MemorySizeEvictionStrategyTest.java b/wicket-core/src/test/java/org/apache/wicket/pageStore/memory/MemorySizeEvictionStrategyTest.java
deleted file mode 100644
index 50033fa..0000000
--- a/wicket-core/src/test/java/org/apache/wicket/pageStore/memory/MemorySizeEvictionStrategyTest.java
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * 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.memory;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-
-import org.apache.wicket.util.lang.Bytes;
-import org.apache.wicket.core.util.lang.WicketObjects;
-import org.junit.Test;
-
-/***/
-public class MemorySizeEvictionStrategyTest
-{
- final byte[] PAGE1 = new byte[] { 1 };
- final byte[] PAGE2 = new byte[] { 2, 3 };
-
- /***/
- @Test
- public void evict()
- {
- PageTable pageTable = new PageTable();
-
- long sizeOfEmptyPageTable = WicketObjects.sizeof(pageTable);
-
- // evict to empty page table
- MemorySizeEvictionStrategy strategy = new MemorySizeEvictionStrategy(
- Bytes.bytes(sizeOfEmptyPageTable));
- pageTable.storePage(PAGE1.length, PAGE1);
- assertEquals(1, pageTable.size());
- strategy.evict(pageTable);
- assertEquals(0, pageTable.size());
- long currentSize = WicketObjects.sizeof(pageTable);
- assertTrue("Current size: |" + currentSize + "|, strategy size: |" + sizeOfEmptyPageTable +
- "|", currentSize <= sizeOfEmptyPageTable);
-
- // evict to page table with size: empty + PAGE2
- pageTable.storePage(PAGE2.length, PAGE2);
- long sizeOfWithPage2 = WicketObjects.sizeof(pageTable);
- strategy = new MemorySizeEvictionStrategy(Bytes.bytes(sizeOfWithPage2));
- pageTable.storePage(PAGE1.length, PAGE1);
- assertEquals(2, pageTable.size());
- strategy.evict(pageTable);
- // the following assertion depends on the fact that PAGE2 has
- // bigger size than PAGE1
- assertEquals(1, pageTable.size());
- currentSize = WicketObjects.sizeof(pageTable);
- assertTrue("Current size: |" + currentSize + "|, strategy size: |" + sizeOfWithPage2 + "|",
- currentSize <= sizeOfWithPage2);
- }
-}
http://git-wip-us.apache.org/repos/asf/wicket/blob/bcf76f51/wicket-core/src/test/java/org/apache/wicket/pageStore/memory/PageNumberEvictionStrategyTest.java
----------------------------------------------------------------------
diff --git a/wicket-core/src/test/java/org/apache/wicket/pageStore/memory/PageNumberEvictionStrategyTest.java b/wicket-core/src/test/java/org/apache/wicket/pageStore/memory/PageNumberEvictionStrategyTest.java
deleted file mode 100644
index d3bf35b..0000000
--- a/wicket-core/src/test/java/org/apache/wicket/pageStore/memory/PageNumberEvictionStrategyTest.java
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * 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.memory;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
-
-import org.junit.Test;
-
-/***/
-public class PageNumberEvictionStrategyTest
-{
-
- final byte[] PAGE1 = new byte[] { 1 };
- final byte[] PAGE2 = new byte[] { 2, 3 };
-
- /***/
- @Test
- public void evict()
- {
- // evict to page table with one page only
- PageNumberEvictionStrategy strategy = new PageNumberEvictionStrategy(1);
-
- PageTable pageTable = new PageTable();
-
- pageTable.storePage(PAGE1.length, PAGE1);
- assertEquals(1, pageTable.size());
- strategy.evict(pageTable);
- assertEquals(1, pageTable.size());
- assertNotNull(pageTable.getPage(PAGE1.length));
-
- pageTable.storePage(PAGE2.length, PAGE2);
- assertEquals(2, pageTable.size());
- strategy.evict(pageTable);
- assertEquals(1, pageTable.size());
- assertNotNull(pageTable.getPage(PAGE2.length));
- assertNull(pageTable.getPage(PAGE1.length));
- }
-
- /**
- * The number of pages must be at least '1'
- */
- @Test(expected = IllegalArgumentException.class)
- public void greaterThanZero()
- {
- new PageNumberEvictionStrategy(0);
- }
-}
http://git-wip-us.apache.org/repos/asf/wicket/blob/bcf76f51/wicket-core/src/test/java/org/apache/wicket/pageStore/memory/PageTableTest.java
----------------------------------------------------------------------
diff --git a/wicket-core/src/test/java/org/apache/wicket/pageStore/memory/PageTableTest.java b/wicket-core/src/test/java/org/apache/wicket/pageStore/memory/PageTableTest.java
deleted file mode 100644
index 062068f..0000000
--- a/wicket-core/src/test/java/org/apache/wicket/pageStore/memory/PageTableTest.java
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * 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.memory;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNull;
-
-import org.junit.Test;
-
-/***/
-public class PageTableTest
-{
-
- final byte[] data = new byte[] { 1 };
-
- /***/
- @Test
- public void getOldest()
- {
- PageTable pageTable = new PageTable();
-
- assertNull(pageTable.getOldest());
-
- pageTable.storePage(1, data);
- // index: 1
- assertEquals(Integer.valueOf(1), pageTable.getOldest());
-
- pageTable.storePage(2, data);
- // index: 2, 1
- assertEquals(Integer.valueOf(1), pageTable.getOldest());
-
- pageTable.storePage(3, data);
- // index: 3, 2, 1
- assertEquals(Integer.valueOf(1), pageTable.getOldest());
-
- pageTable.getPage(1);
- // index: 1, 3, 2
- assertEquals(Integer.valueOf(2), pageTable.getOldest());
-
- pageTable.removePage(2);
- // index: 1, 3
- assertEquals(Integer.valueOf(3), pageTable.getOldest());
- }
-}