Author: knopp
Date: Tue Mar 31 20:49:14 2009
New Revision: 760608
URL: http://svn.apache.org/viewvc?rev=760608&view=rev
Log: (empty)
Added:
wicket/sandbox/knopp/experimental/wicket-ng/src/main/java/org/apache/wicket/page/persistent/disk/DiskDataStore.java
(with props)
Modified:
wicket/sandbox/knopp/experimental/wicket-ng/src/main/java/org/apache/wicket/protocol/http/WebApplication.java
wicket/sandbox/knopp/experimental/wicket-ng/src/main/java/org/apache/wicket/protocol/http/WicketFilter.java
Added:
wicket/sandbox/knopp/experimental/wicket-ng/src/main/java/org/apache/wicket/page/persistent/disk/DiskDataStore.java
URL:
http://svn.apache.org/viewvc/wicket/sandbox/knopp/experimental/wicket-ng/src/main/java/org/apache/wicket/page/persistent/disk/DiskDataStore.java?rev=760608&view=auto
==============================================================================
---
wicket/sandbox/knopp/experimental/wicket-ng/src/main/java/org/apache/wicket/page/persistent/disk/DiskDataStore.java
(added)
+++
wicket/sandbox/knopp/experimental/wicket-ng/src/main/java/org/apache/wicket/page/persistent/disk/DiskDataStore.java
Tue Mar 31 20:49:14 2009
@@ -0,0 +1,375 @@
+package org.apache.wicket.page.persistent.disk;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.Serializable;
+import java.nio.ByteBuffer;
+import java.nio.channels.FileChannel;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+
+import org.apache.wicket.Application;
+import org.apache.wicket.WicketRuntimeException;
+import org.apache.wicket.page.persistent.DataStore;
+import org.apache.wicket.page.persistent.disk.PageWindowManager.PageWindow;
+import org.apache.wicket.protocol.http.WebApplication;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class DiskDataStore implements DataStore
+{
+ private final String applicationName;
+ private final int maxSizePerPageSession;
+ private final FileChannelPool fileChannelPool;
+ private final File fileStoreFolder;
+ private final ConcurrentMap<String, SessionEntry> sessionEntryMap = new
ConcurrentHashMap<String, SessionEntry>();
+
+ public DiskDataStore(String applicationName, File fileStoreFolder, int
maxSizePerSession,
+ int fileChannelPoolCapacity)
+ {
+ this.applicationName = applicationName;
+ this.fileStoreFolder = fileStoreFolder;
+ this.maxSizePerPageSession = maxSizePerSession;
+ this.fileChannelPool = new
FileChannelPool(fileChannelPoolCapacity);
+ }
+
+ public DiskDataStore(String applicationName, int maxSizePerSession, int
fileChannelPoolCapacity)
+ {
+ this(applicationName, getDefaultFileStoreFolder(),
maxSizePerSession, fileChannelPoolCapacity);
+ }
+
+ public void destroy()
+ {
+ fileChannelPool.destroy();
+ }
+
+ public byte[] getData(String sessionId, int id)
+ {
+ SessionEntry sessionEntry = getSessionEntry(sessionId, false);
+ if (sessionEntry != null)
+ {
+ return sessionEntry.loadPage(id);
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ public boolean isReplicated()
+ {
+ return false;
+ }
+
+ public void removeData(String sessionId, int id)
+ {
+ SessionEntry sessionEntry = getSessionEntry(sessionId, false);
+ if (sessionEntry != null)
+ {
+ sessionEntry.removePage(id);
+ }
+ }
+
+ public void removeData(String sessionId)
+ {
+ SessionEntry sessionEntry = getSessionEntry(sessionId, false);
+ if (sessionEntry != null)
+ {
+ synchronized (sessionEntry)
+ {
+ sessionEntryMap.remove(sessionEntry);
+ sessionEntry.unbind();
+ }
+ }
+ }
+
+ public void storeData(String sessionId, int id, byte[] data)
+ {
+ SessionEntry sessionEntry = getSessionEntry(sessionId, false);
+ if (sessionEntry != null)
+ {
+ sessionEntry.savePage(id, data);
+ }
+ }
+
+ private SessionEntry getSessionEntry(String sessionId, boolean create)
+ {
+ if (!create)
+ {
+ return sessionEntryMap.get(sessionId);
+ }
+ else
+ {
+ SessionEntry entry = new SessionEntry(this, sessionId);
+ entry = sessionEntryMap.putIfAbsent(sessionId, entry);
+ return entry;
+ }
+ }
+
+ 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;
+ }
+
+ private PageWindowManager getManager()
+ {
+ if (manager == null)
+ {
+ manager = new
PageWindowManager(diskDataStore.maxSizePerPageSession);;
+ }
+ 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 page
+ */
+ 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);
+
+ // take the filechannel from the pool
+ FileChannel channel =
diskDataStore.fileChannelPool.getFileChannel(getFileName(), true);
+ try
+ {
+ // write the content
+ channel.write(ByteBuffer.wrap(data),
window.getFilePartOffset());
+ }
+ catch (IOException e)
+ {
+ log.error("Error writing to a channel "
+ channel, e);
+ }
+ finally
+ {
+ // return the "borrowed" file channel
+
diskDataStore.fileChannelPool.returnFileChannel(channel);
+ }
+ }
+ }
+
+ /**
+ * Removes the page from pagemap file.
+ *
+ * @param pageMapName
+ * @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
+ * @param pageMapFileName
+ * @return serialized page data
+ */
+ public byte[] loadPage(PageWindow window)
+ {
+ byte[] result = null;
+ FileChannel channel =
diskDataStore.fileChannelPool.getFileChannel(getFileName(), 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
+ {
+
diskDataStore.fileChannelPool.returnFileChannel(channel);
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Loads the specified page data.
+ *
+ * @param pageMapName
+ * @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()
+ {
+
diskDataStore.fileChannelPool.closeAndDeleteFileChannel(getFileName());
+ File sessionFolder =
diskDataStore.getSessionFolder(sessionId, false);
+ if (sessionFolder.exists())
+ {
+ sessionFolder.delete();
+ }
+ unbound = true;
+ }
+ }
+
+ /**
+ * 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 pageMapName
+ * @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();
+ }
+
+ private static File getDefaultFileStoreFolder()
+ {
+ File dir = null;
+
+ if (Application.exists())
+ {
+ dir = (File) ((WebApplication)
Application.get()).getServletContext().getAttribute(
+ "javax.servlet.context.tempdir");
+ }
+
+ if (dir != null)
+ {
+ return dir;
+ }
+ else
+ {
+ try
+ {
+ return File.createTempFile("file-prefix",
null).getParentFile();
+ }
+ catch (IOException e)
+ {
+ throw new WicketRuntimeException(e);
+ }
+ }
+ }
+
+ private File getStoreFolder()
+ {
+ File storeFolder = new File(fileStoreFolder, applicationName +
"-filestore");
+ return storeFolder;
+ }
+
+ /**
+ * 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, boolean create)
+ {
+ File storeFolder = getStoreFolder();
+
+ sessionId = sessionId.replace('*', '_');
+ sessionId = sessionId.replace('/', '_');
+ sessionId = sessionId.replace(':', '_');
+
+ File sessionFolder = new File(storeFolder, sessionId);
+ if (create && sessionFolder.exists() == false)
+ {
+ mkdirs(sessionFolder);
+ }
+ return sessionFolder;
+ }
+
+ /**
+ * Utility method for creating a directory
+ *
+ * @param file
+ */
+ private void mkdirs(File file)
+ {
+ // for some reason, simple file.mkdirs sometimes fails under
heavy load
+ for (int j = 0; j < 5; ++j)
+ {
+ for (int i = 0; i < 10; ++i)
+ {
+ if (file.mkdirs())
+ {
+ return;
+ }
+ }
+ try
+ {
+ Thread.sleep(100);
+ }
+ catch (InterruptedException ignore)
+ {
+ }
+ }
+ log.error("Failed to make directory " + file);
+ }
+
+ private static final Logger log =
LoggerFactory.getLogger(DiskDataStore.class);
+
+}
Propchange:
wicket/sandbox/knopp/experimental/wicket-ng/src/main/java/org/apache/wicket/page/persistent/disk/DiskDataStore.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Modified:
wicket/sandbox/knopp/experimental/wicket-ng/src/main/java/org/apache/wicket/protocol/http/WebApplication.java
URL:
http://svn.apache.org/viewvc/wicket/sandbox/knopp/experimental/wicket-ng/src/main/java/org/apache/wicket/protocol/http/WebApplication.java?rev=760608&r1=760607&r2=760608&view=diff
==============================================================================
---
wicket/sandbox/knopp/experimental/wicket-ng/src/main/java/org/apache/wicket/protocol/http/WebApplication.java
(original)
+++
wicket/sandbox/knopp/experimental/wicket-ng/src/main/java/org/apache/wicket/protocol/http/WebApplication.java
Tue Mar 31 20:49:14 2009
@@ -19,6 +19,8 @@
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
+import javax.servlet.ServletContext;
+
import org.apache.wicket.Application;
import org.apache.wicket.DefaultPageFactory;
import org.apache.wicket.IPage;
@@ -235,4 +237,28 @@
String key = sessionId + url.toString();
storedResponses.put(key, response);
}
+
+ /**
+ * Gets the servlet context for this application. Use this to get
references to absolute paths,
+ * global web.xml parameters (<context-param>), etc.
+ *
+ * @return The servlet context for this application
+ */
+ public ServletContext getServletContext()
+ {
+ if (wicketFilter != null)
+ {
+ return
wicketFilter.getFilterConfig().getServletContext();
+ }
+ throw new IllegalStateException("servletContext is not set yet.
Any code in your"
+ + " Application object that uses the wicket filter
instance should be put"
+ + " in the init() method instead of your constructor");
+ }
+
+ public void setWicketFilter(WicketFilter wicketFilter)
+ {
+ this.wicketFilter = wicketFilter;
+ }
+
+ private WicketFilter wicketFilter;
}
Modified:
wicket/sandbox/knopp/experimental/wicket-ng/src/main/java/org/apache/wicket/protocol/http/WicketFilter.java
URL:
http://svn.apache.org/viewvc/wicket/sandbox/knopp/experimental/wicket-ng/src/main/java/org/apache/wicket/protocol/http/WicketFilter.java?rev=760608&r1=760607&r2=760608&view=diff
==============================================================================
---
wicket/sandbox/knopp/experimental/wicket-ng/src/main/java/org/apache/wicket/protocol/http/WicketFilter.java
(original)
+++
wicket/sandbox/knopp/experimental/wicket-ng/src/main/java/org/apache/wicket/protocol/http/WicketFilter.java
Tue Mar 31 20:49:14 2009
@@ -218,6 +218,7 @@
IWebApplicationFactory factory = getApplicationFactory();
webApplication = factory.createApplication(this);
webApplication.setName(filterConfig.getFilterName());
+ webApplication.setWicketFilter(this);
initFilterPath();