Author: ehillenius
Date: Wed Feb  7 23:13:43 2007
New Revision: 504808

URL: http://svn.apache.org/viewvc?view=rev&rev=504808
Log:
WICKET-265

Added:
    
incubator/wicket/branches/wicket-1.x/wicket/src/main/java/wicket/util/io/DebuggingObjectOutputStream.java
Modified:
    
incubator/wicket/branches/wicket-1.x/wicket/src/main/java/wicket/protocol/http/FilePageStore.java
    
incubator/wicket/branches/wicket-1.x/wicket/src/main/java/wicket/protocol/http/HttpSessionStore.java

Modified: 
incubator/wicket/branches/wicket-1.x/wicket/src/main/java/wicket/protocol/http/FilePageStore.java
URL: 
http://svn.apache.org/viewvc/incubator/wicket/branches/wicket-1.x/wicket/src/main/java/wicket/protocol/http/FilePageStore.java?view=diff&rev=504808&r1=504807&r2=504808
==============================================================================
--- 
incubator/wicket/branches/wicket-1.x/wicket/src/main/java/wicket/protocol/http/FilePageStore.java
 (original)
+++ 
incubator/wicket/branches/wicket-1.x/wicket/src/main/java/wicket/protocol/http/FilePageStore.java
 Wed Feb  7 23:13:43 2007
@@ -30,8 +30,10 @@
 
 import wicket.Application;
 import wicket.Page;
+import wicket.WicketRuntimeException;
 import wicket.protocol.http.SecondLevelCacheSessionStore.IPageStore;
 import wicket.util.concurrent.ConcurrentHashMap;
+import wicket.util.io.DebuggingObjectOutputStream;
 import wicket.util.lang.Objects;
 
 /**
@@ -49,9 +51,9 @@
        protected static Log log = LogFactory.getLog(FilePageStore.class);
 
        private final File defaultWorkDir;
-       
+
        private final ConcurrentHashMap storePageMap;
-       
+
        private final PageSavingThread thread;
 
        private final String appName;
@@ -61,13 +63,15 @@
         */
        public FilePageStore()
        {
-               
this((File)((WebApplication)Application.get()).getServletContext()
-                               .getAttribute("javax.servlet.context.tempdir"));
+               
this((File)((WebApplication)Application.get()).getServletContext().getAttribute(
+                               "javax.servlet.context.tempdir"));
        }
 
        /**
         * Construct.
-        * @param dir The directory to save to.
+        * 
+        * @param dir
+        *            The directory to save to.
         */
        public FilePageStore(File dir)
        {
@@ -75,10 +79,10 @@
                storePageMap = new ConcurrentHashMap();
                thread = new PageSavingThread();
                appName = Application.get().getApplicationKey();
-               Thread t = new Thread(thread,"FilePageStoreThread-" +appName);
+               Thread t = new Thread(thread, "FilePageStoreThread-" + appName);
                t.setDaemon(true);
                t.start();
-               
+
        }
 
        /**
@@ -118,9 +122,11 @@
                                        if (page != null && 
log.isDebugEnabled())
                                        {
                                                long t3 = 
System.currentTimeMillis();
-                                               log.debug("restoring page " + 
page.getClass() + "[" + page.getNumericId() + ","
-                                                               + 
page.getCurrentVersionNumber() + "] size: " + pageData.length +  " for session 
" + sessionId + " took "
-                                                               + (t2 - t1) + " 
miliseconds to read in and " + (t3-t2) + " miliseconds to deserialize");
+                                               log.debug("restoring page " + 
page.getClass() + "[" + page.getNumericId()
+                                                               + "," + 
page.getCurrentVersionNumber() + "] size: "
+                                                               + 
pageData.length + " for session " + sessionId + " took "
+                                                               + (t2 - t1) + " 
miliseconds to read in and " + (t3 - t2)
+                                                               + " miliseconds 
to deserialize");
                                        }
 
                                        return page;
@@ -157,7 +163,8 @@
        {
                synchronized (storePageMap)
                {
-                       storePageMap.put(new 
SessionPageKey(sessionId,page.getNumericId(),page.getCurrentVersionNumber(),true),
 page);
+                       storePageMap.put(new SessionPageKey(sessionId, 
page.getNumericId(), page
+                                       .getCurrentVersionNumber(), true), 
page);
                        storePageMap.notifyAll();
                }
        }
@@ -170,13 +177,15 @@
        {
                synchronized (storePageMap)
                {
-                       storePageMap.put(new 
SessionPageKey(sessionId,page.getNumericId(),page.getCurrentVersionNumber()), 
page);
+                       storePageMap.put(new SessionPageKey(sessionId, 
page.getNumericId(), page
+                                       .getCurrentVersionNumber()), page);
                        storePageMap.notifyAll();
                }
        }
 
        /**
-        * @see 
wicket.protocol.http.SecondLevelCacheSessionStore.IPageStore#pageAccessed(java.lang.String,
 wicket.Page)
+        * @see 
wicket.protocol.http.SecondLevelCacheSessionStore.IPageStore#pageAccessed(java.lang.String,
+        *      wicket.Page)
         */
        public void pageAccessed(String sessionId, Page page)
        {
@@ -192,24 +201,26 @@
                thread.stop();
        }
 
-       private void testMap(String sessionId, int id , int versionNumber)
+       private void testMap(String sessionId, int id, int versionNumber)
        {
-               SessionPageKey curentKey = new 
SessionPageKey(sessionId,id,versionNumber);
+               SessionPageKey curentKey = new SessionPageKey(sessionId, id, 
versionNumber);
                Object key = storePageMap.get(curentKey);
                while (key != null)
                {
-                       if( log.isDebugEnabled())
+                       if (log.isDebugEnabled())
                        {
-                               log.debug("The page " + id + ":" + 
versionNumber+" for session " + sessionId + 
-                                               " wasn't saved yet. blocking 
for 200ms");
+                               log.debug("The page " + id + ":" + 
versionNumber + " for session " + sessionId
+                                               + " wasn't saved yet. blocking 
for 200ms");
                        }
                        synchronized (key)
                        {
                                try
                                {
                                        // for now i just wait 200ms and then 
try again.
-                                       // i could use synchronized() and then 
notifyAll in the saving thread.
-                                       // But maybe it is really busy and we 
should just block for 200ms
+                                       // i could use synchronized() and then 
notifyAll in the
+                                       // saving thread.
+                                       // But maybe it is really busy and we 
should just block for
+                                       // 200ms
                                        key.wait(200);
                                }
                                catch (InterruptedException ex)
@@ -229,7 +240,7 @@
        {
                synchronized (storePageMap)
                {
-                       SessionPageKey key = new 
SessionPageKey(sessionId,-1,-1,true);
+                       SessionPageKey key = new SessionPageKey(sessionId, -1, 
-1, true);
                        storePageMap.put(key, key);
                        storePageMap.notifyAll();
                }
@@ -255,8 +266,7 @@
         */
        private File getPageFile(int id, int versionNumber, File sessionDir)
        {
-               return new File(sessionDir, appName + "-page-" + id
-                               + "-version-" + versionNumber);
+               return new File(sessionDir, appName + "-page-" + id + 
"-version-" + versionNumber);
        }
 
        private class SessionPageKey
@@ -270,7 +280,7 @@
                {
                        this(sessionId, id, versionNumber, false);
                }
-               
+
                SessionPageKey(String sessionId, int id, int versionNumber, 
boolean remove)
                {
                        this.sessionId = sessionId;
@@ -278,7 +288,7 @@
                        this.versionNumber = versionNumber;
                        this.remove = remove;
                }
-               
+
                /**
                 * @see java.lang.Object#hashCode()
                 */
@@ -286,7 +296,7 @@
                {
                        return sessionId.hashCode() + id + versionNumber;
                }
-               
+
                /**
                 * @see java.lang.Object#equals(java.lang.Object)
                 */
@@ -295,17 +305,17 @@
                        if (obj instanceof SessionPageKey)
                        {
                                SessionPageKey key = (SessionPageKey)obj;
-                               return id == key.id && versionNumber == 
key.versionNumber && 
-                                       sessionId.equals(key.sessionId) && 
remove == key.remove;
+                               return id == key.id && versionNumber == 
key.versionNumber
+                                               && 
sessionId.equals(key.sessionId) && remove == key.remove;
                        }
                        return false;
                }
        }
-       
+
        private class PageSavingThread implements Runnable
        {
                private volatile boolean stop = false;
-               
+
                /**
                 * Stops this thread.
                 */
@@ -317,12 +327,13 @@
                                storePageMap.notifyAll();
                        }
                }
+
                /**
                 * @see java.lang.Runnable#run()
                 */
                public void run()
                {
-                       while(!stop)
+                       while (!stop)
                        {
                                Iterator iterator = null;
                                try
@@ -332,29 +343,33 @@
                                        {
                                                synchronized (storePageMap)
                                                {
-                                                       if(stop) return;
+                                                       if (stop)
+                                                               return;
                                                        storePageMap.wait();
                                                }
                                                continue;
                                        }
-                                       while(iterator.hasNext())
+                                       while (iterator.hasNext())
                                        {
                                                SessionPageKey key = 
(SessionPageKey)iterator.next();
                                                Object value = 
storePageMap.get(key);
-                                               if (value == null) continue;
-                                               if(key.remove)
+                                               if (value == null)
+                                                       continue;
+                                               if (key.remove)
                                                {
                                                        if (key.id == -1)
                                                        {
                                                                
removeSession(key.sessionId);
-                                                               // now remove 
any other pending save for that page.
+                                                               // now remove 
any other pending save for that
+                                                               // page.
                                                                
removeSessionFromPendingMap(key.sessionId);
                                                        }
                                                        else
                                                        {
                                                                
removePage(key.sessionId, key.id, key.versionNumber);
-                                                               // now remove 
any other pending save for that page.
-                                                               
removePageFromPendingMap(key.sessionId,key.id);
+                                                               // now remove 
any other pending save for that
+                                                               // page.
+                                                               
removePageFromPendingMap(key.sessionId, key.id);
                                                        }
                                                }
                                                else
@@ -363,16 +378,17 @@
                                                }
                                                iterator.remove();
                                        }
-                               } 
+                               }
                                catch (Exception e)
                                {
                                        log.error("Error in page save thread", 
e);
                                        // removing the one that did fail...
-                                       if(iterator != null) iterator.remove();
+                                       if (iterator != null)
+                                               iterator.remove();
                                }
                        }
                }
-               
+
                /**
                 * @param sessionId
                 * @param id
@@ -380,10 +396,10 @@
                private void removePageFromPendingMap(String sessionId, int id)
                {
                        Iterator iterator = storePageMap.keySet().iterator();
-                       while(iterator.hasNext())
+                       while (iterator.hasNext())
                        {
                                SessionPageKey key = 
(SessionPageKey)iterator.next();
-                               if(key.sessionId == sessionId && key.id == id)
+                               if (key.sessionId == sessionId && key.id == id)
                                {
                                        iterator.remove();
                                }
@@ -393,23 +409,24 @@
                private void removeSessionFromPendingMap(String sessionId)
                {
                        Iterator iterator = storePageMap.keySet().iterator();
-                       while(iterator.hasNext())
+                       while (iterator.hasNext())
                        {
                                SessionPageKey key = 
(SessionPageKey)iterator.next();
-                               if(key.sessionId == sessionId)
+                               if (key.sessionId == sessionId)
                                {
                                        iterator.remove();
                                }
                        }
                }
+
                private void removePage(String sessionId, int id, int 
currentVersionNumber)
                {
                        File sessionDir = new File(getWorkDir(), sessionId);
                        if (sessionDir.exists())
                        {
-                               while(currentVersionNumber >= 0)
+                               while (currentVersionNumber >= 0)
                                {
-                                       File pageFile = 
getPageFile(id,currentVersionNumber,sessionDir);
+                                       File pageFile = getPageFile(id, 
currentVersionNumber, sessionDir);
                                        if (pageFile.exists())
                                        {
                                                pageFile.delete();
@@ -419,7 +436,7 @@
                        }
 
                }
-               
+
                private void removeSession(String sessionId)
                {
                        File sessionDir = new File(getWorkDir(), sessionId);
@@ -439,7 +456,7 @@
                                }
                        }
                }
-               
+
                /**
                 * @param sessionId
                 * @param page
@@ -448,7 +465,8 @@
                {
                        File sessionDir = new File(getWorkDir(), sessionId);
                        sessionDir.mkdirs();
-                       File pageFile = getPageFile(page.getNumericId(), 
page.getCurrentVersionNumber(), sessionDir);
+                       File pageFile = getPageFile(page.getNumericId(), 
page.getCurrentVersionNumber(),
+                                       sessionDir);
 
                        FileOutputStream fos = null;
                        long t1 = System.currentTimeMillis();
@@ -474,8 +492,17 @@
                        }
                        catch (Exception e)
                        {
-                               log.error("Error saving page " + 
page.getClass() + "["+ page.getId() + "," + page.getCurrentVersionNumber()
-                                               + "] for the sessionid " + 
sessionId, e);
+                               // trigger serialization again, but this time 
gather some more info
+                               try
+                               {
+                                       new 
DebuggingObjectOutputStream().writeObject(page);
+                               }
+                               catch (Exception e1)
+                               {
+                                       log.error("Error saving page " + 
page.getClass() + "[" + page.getId() + ","
+                                                       + 
page.getCurrentVersionNumber() + "] for the sessionid " + sessionId
+                                                       + ": " + 
e1.getMessage(), e1);
+                               }
                        }
                        finally
                        {
@@ -494,9 +521,10 @@
                        if (log.isDebugEnabled())
                        {
                                long t3 = System.currentTimeMillis();
-                               log.debug("storing page " + page.getClass() + 
"["+ page.getNumericId() + ","
-                                               + 
page.getCurrentVersionNumber() + "] size: " + length + " for session " + 
sessionId + " took "
-                                               + (t2 - t1) + " miliseconds to 
serialize and " + (t3-t2) + " miliseconds to save");
+                               log.debug("storing page " + page.getClass() + 
"[" + page.getNumericId() + ","
+                                               + 
page.getCurrentVersionNumber() + "] size: " + length + " for session "
+                                               + sessionId + " took " + (t2 - 
t1) + " miliseconds to serialize and "
+                                               + (t3 - t2) + " miliseconds to 
save");
                        }
                }
        }

Modified: 
incubator/wicket/branches/wicket-1.x/wicket/src/main/java/wicket/protocol/http/HttpSessionStore.java
URL: 
http://svn.apache.org/viewvc/incubator/wicket/branches/wicket-1.x/wicket/src/main/java/wicket/protocol/http/HttpSessionStore.java?view=diff&rev=504808&r1=504807&r2=504808
==============================================================================
--- 
incubator/wicket/branches/wicket-1.x/wicket/src/main/java/wicket/protocol/http/HttpSessionStore.java
 (original)
+++ 
incubator/wicket/branches/wicket-1.x/wicket/src/main/java/wicket/protocol/http/HttpSessionStore.java
 Wed Feb  7 23:13:43 2007
@@ -17,6 +17,7 @@
 package wicket.protocol.http;
 
 import java.io.ByteArrayOutputStream;
+import java.io.IOException;
 import java.io.ObjectOutputStream;
 import java.util.ArrayList;
 import java.util.Enumeration;
@@ -30,6 +31,7 @@
 import wicket.Request;
 import wicket.Session;
 import wicket.WicketRuntimeException;
+import wicket.util.io.DebuggingObjectOutputStream;
 import wicket.util.lang.Bytes;
 
 /**
@@ -139,9 +141,20 @@
                        }
                        catch (Exception e)
                        {
+                               // trigger serialization again, but this time 
gather some more info
+                               try
+                               {
+                                       new 
DebuggingObjectOutputStream().writeObject(value);
+                               }
+                               catch (IOException e1)
+                               {
+                                       throw new RuntimeException(e1);
+                               }
+                               // this should never happen
                                throw new WicketRuntimeException(
-                                               "Internal error cloning object. 
Make sure all dependent objects implement Serializable. Class="
-                                                               + valueTypeName 
+ ",attribute=" + name + ", value=" + value, e);
+                                               "first pass of serialization 
failed, but the second one "
+                                                               + "(that should 
gather extended information) passed? Please "
+                                                               + "report this 
error to the Wicket team", e);
                        }
                }
 

Added: 
incubator/wicket/branches/wicket-1.x/wicket/src/main/java/wicket/util/io/DebuggingObjectOutputStream.java
URL: 
http://svn.apache.org/viewvc/incubator/wicket/branches/wicket-1.x/wicket/src/main/java/wicket/util/io/DebuggingObjectOutputStream.java?view=auto&rev=504808
==============================================================================
--- 
incubator/wicket/branches/wicket-1.x/wicket/src/main/java/wicket/util/io/DebuggingObjectOutputStream.java
 (added)
+++ 
incubator/wicket/branches/wicket-1.x/wicket/src/main/java/wicket/util/io/DebuggingObjectOutputStream.java
 Wed Feb  7 23:13:43 2007
@@ -0,0 +1,213 @@
+/*
+ * 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 wicket.util.io;
+
+import java.io.IOException;
+import java.io.NotSerializableException;
+import java.io.ObjectOutputStream;
+import java.io.Serializable;
+import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
+import java.util.HashSet;
+import java.util.LinkedList;
+
+import wicket.Component;
+import wicket.WicketRuntimeException;
+
+/**
+ * Captures information about what it is trying to stream with the sole purpose
+ * of finding out what the object hierarchy looks like of an object that can't
+ * be serialized.
+ * <p>
+ * If you have an object you want to analyze for this, call:
+ * <code>new DebuggingObjectOutputStream().writeObject(value);</code> and
+ * catch the [EMAIL PROTECTED] WicketRuntimeException}.
+ * </p>
+ * <p>
+ * There's no point using this class if you are not trying to diagnose a
+ * serialization issue.
+ * </p>
+ * 
+ * @author Al Maw
+ */
+public class DebuggingObjectOutputStream extends ObjectOutputStream
+{
+       private static final long serialVersionUID = 1L;
+
+       /** stack for string representations of objects that are handled. */
+       private final LinkedList stack = new LinkedList();
+
+       /** set for checking circular references. */
+       private final HashSet set = new HashSet();
+
+       /**
+        * Creates an ObjectOutputStream. Doesn't write anywhere
+        * 
+        * @throws IOException
+        *             IOException if an I/O error occurs while writing stream
+        *             header
+        */
+       public DebuggingObjectOutputStream() throws IOException
+       {
+               super();
+       }
+
+       /**
+        * Dump with identation.
+        * 
+        * @param type
+        *            the type that couldn't be serialized
+        * @return A very pretty dump
+        */
+       private String getPrettyPrintedStack(String type)
+       {
+               set.clear();
+               StringBuffer result = new StringBuffer();
+               StringBuffer spaces = new StringBuffer();
+               result.append("Unable to serialize class: ");
+               result.append(type);
+               result.append("\nField hierarchy is:");
+               while (!stack.isEmpty())
+               {
+                       spaces.append("  ");
+                       
result.append("\n").append(spaces).append(stack.removeFirst());
+               }
+               result.append(" <----- field that is not serializable");
+               return result.toString();
+       }
+
+       /**
+        * @see java.io.ObjectOutputStream#writeObjectOverride(java.lang.Object)
+        * @throws IOException
+        *             never actually happens
+        * @throws WicketRuntimeException
+        *             on a serialization exception
+        */
+       protected final void writeObjectOverride(Object obj) throws IOException
+       {
+               if (obj == null)
+               {
+                       return;
+               }
+               // Check for circular reference.
+               if (set.contains(obj))
+               {
+                       return;
+               }
+               if (stack.isEmpty())
+               {
+                       stack.add("Class " + obj.getClass().getName());
+               }
+               set.add(obj);
+               Field[] fields = obj.getClass().getDeclaredFields();
+               for (int i = 0; i < fields.length; i++)
+               {
+                       fields[i].setAccessible(true);
+                       StringBuffer buffer = new StringBuffer();
+                       Field f = fields[i];
+                       int m = f.getModifiers();
+                       if (fields[i].getType().isPrimitive() || 
Modifier.isTransient(m)
+                                       || Modifier.isStatic(m))
+                       {
+                               continue;
+                       }
+
+                       if (Modifier.isPrivate(m))
+                       {
+                               buffer.append("private ");
+                       }
+                       if (Modifier.isProtected(m))
+                       {
+                               buffer.append("protected ");
+                       }
+                       if (Modifier.isPublic(m))
+                       {
+                               buffer.append("public ");
+                       }
+                       if (Modifier.isAbstract(m))
+                       {
+                               buffer.append("abstract ");
+                       }
+                       if (Modifier.isFinal(m))
+                       {
+                               buffer.append("final ");
+                       }
+                       if (Modifier.isStatic(m))
+                       {
+                               buffer.append("static ");
+                       }
+                       if (Modifier.isVolatile(m))
+                       {
+                               buffer.append("volatile ");
+                       }
+                       buffer.append(f.getType().getName()).append("");
+                       buffer.append(" ").append(f.getName()).append(" => ");
+
+                       // now that we have the reference, try to get the 
actual value
+                       try
+                       {
+                               Object val = f.get(obj);
+                               if (val != null)
+                               {
+                                       buffer.append(val.getClass().getName());
+                                       if (val instanceof Component)
+                                       {
+                                               buffer.append(" 
[path=").append(((Component)val).getPath()).append("]");
+                                       }
+                               }
+                               else
+                               {
+                                       buffer.append(" null");
+                               }
+                       }
+                       catch (IllegalArgumentException e)
+                       {
+                               buffer.append("? 
(").append(e.getMessage()).append(")");
+                       }
+                       catch (IllegalAccessException e)
+                       {
+                               buffer.append("? 
(").append(e.getMessage()).append(")");
+                       }
+
+                       stack.add(buffer.toString());
+                       if 
(Serializable.class.isAssignableFrom(fields[i].getType()))
+                       {
+                               try
+                               {
+                                       writeObjectOverride(fields[i].get(obj));
+                               }
+                               catch (IllegalAccessException e)
+                               {
+                                       throw new 
WicketRuntimeException(getPrettyPrintedStack(fields[i].getType()
+                                                       .getName()), e);
+                               }
+                       }
+                       else
+                       {
+                               throw new 
WicketRuntimeException(getPrettyPrintedStack(
+                                               
fields[i].getType().getName()).toString(), new NotSerializableException(
+                                               fields[i].getType().getName()));
+                       }
+                       stack.removeLast();
+               }
+               if (stack.size() == 1)
+               {
+                       set.clear();
+                       stack.removeLast();
+               }
+       }
+}
\ No newline at end of file


Reply via email to