All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.wicket.page.PageStoreManager Maven / Gradle / Ivy

Go to download

Pax Wicket Service is an OSGi extension of the Wicket framework, allowing for dynamic loading and unloading of Wicket components and pageSources.

There is a newer version: 5.0.0
Show newest version
/*
 * 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 org.apache.wicket.pageStore.IPageStore;

/**
 * 
 */
public class PageStoreManager extends AbstractPageManager
{
	/**
	 * A cache that holds all registered page managers. 
* applicationName -> page manager */ private static final ConcurrentMap managers = new ConcurrentHashMap(); 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 { private static final long serialVersionUID = 1L; private final String applicationName; private final String sessionId; private transient List sessionCache; private transient List 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); } } /** * 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(); } for (Object o : afterReadObject) { IManageablePage page = getPageStore().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(); } // try to find page with same id if (sessionCache != null) { IManageablePage page = findPage(id); if (page != null) { return page; } } // not found, ask pagestore for the page return getPageStore().getPage(sessionId, id); } /** * set the list of pages to remember after the request * * @param pages */ public synchronized void setSessionCache(final List 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 serializedPages = new ArrayList(); 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 l = (List)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); } } } /** * {@link RequestAdapter} for {@link PageStoreManager} * * @author Matej Knopp */ protected class PersistentRequestAdapter extends RequestAdapter { private static final String ATTRIBUTE_NAME = "wicket:persistentPageManagerData"; private String getAttributeName() { return ATTRIBUTE_NAME + " - " + applicationName; } /** * Construct. * * @param context */ public PersistentRequestAdapter(IPageManagerContext context) { super(context); } /** * @see org.apache.wicket.page.RequestAdapter#getPage(int) */ @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; } } /** * * @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()); } if (entry != null) { synchronized (entry) { setSessionAttribute(getAttributeName(), entry); } } return entry; } /** * @see org.apache.wicket.page.RequestAdapter#newSessionCreated() */ @Override protected void newSessionCreated() { // if the session is not temporary bind a session entry to it if (getSessionId() != null) { getSessionEntry(true); } } /** * @see org.apache.wicket.page.RequestAdapter#storeTouchedPages(java.util.List) */ @Override protected void storeTouchedPages(final List touchedPages) { if (!touchedPages.isEmpty()) { SessionEntry entry = getSessionEntry(true); entry.setSessionCache(touchedPages); for (IManageablePage page : touchedPages) { pageStore.storePage(getSessionId(), page); } } } } /** * @see org.apache.wicket.page.AbstractPageManager#newRequestAdapter(org.apache.wicket.page.IPageManagerContext) */ @Override protected RequestAdapter newRequestAdapter(IPageManagerContext context) { return new PersistentRequestAdapter(context); } /** * @see org.apache.wicket.page.AbstractPageManager#supportsVersioning() */ @Override public boolean supportsVersioning() { return true; } /** * @see org.apache.wicket.page.AbstractPageManager#sessionExpired(java.lang.String) */ @Override public void sessionExpired(String sessionId) { pageStore.unbind(sessionId); } /** * @see org.apache.wicket.page.IPageManager#destroy() */ public void destroy() { managers.remove(applicationName); pageStore.destroy(); } }