You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@wicket.apache.org by iv...@apache.org on 2008/06/16 17:42:20 UTC

svn commit: r668201 - /wicket/trunk/wicket/src/main/java/org/apache/wicket/Localizer.java

Author: ivaynberg
Date: Mon Jun 16 08:42:19 2008
New Revision: 668201

URL: http://svn.apache.org/viewvc?rev=668201&view=rev
Log:
WICKET-1667, WICKET-1697: localizer memory leak fixes

Modified:
    wicket/trunk/wicket/src/main/java/org/apache/wicket/Localizer.java

Modified: wicket/trunk/wicket/src/main/java/org/apache/wicket/Localizer.java
URL: http://svn.apache.org/viewvc/wicket/trunk/wicket/src/main/java/org/apache/wicket/Localizer.java?rev=668201&r1=668200&r2=668201&view=diff
==============================================================================
--- wicket/trunk/wicket/src/main/java/org/apache/wicket/Localizer.java (original)
+++ wicket/trunk/wicket/src/main/java/org/apache/wicket/Localizer.java Mon Jun 16 08:42:19 2008
@@ -16,12 +16,16 @@
  */
 package org.apache.wicket;
 
+import java.util.HashMap;
 import java.util.Iterator;
 import java.util.Locale;
 import java.util.Map;
 import java.util.MissingResourceException;
 import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.locks.ReadWriteLock;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
 
+import org.apache.wicket.markup.repeater.AbstractRepeater;
 import org.apache.wicket.model.IModel;
 import org.apache.wicket.resource.loader.IStringResourceLoader;
 import org.apache.wicket.settings.IResourceSettings;
@@ -57,6 +61,8 @@
 	/** Cache properties */
 	private Map<String, String> cache = newCache();
 
+	private final ClassMetaDatabase metaDatabase = new ClassMetaDatabase();
+
 	/**
 	 * Create the utils instance class backed by the configuration information contained within the
 	 * supplied application object.
@@ -331,11 +337,26 @@
 			Component<?> cursor = component;
 			while (cursor != null)
 			{
-				buffer.append("-").append(cursor.getClass().getName());
-				buffer.append(":").append(cursor.getId());
-				cursor = cursor.getParent();
+				buffer.append("-").append(metaDatabase.id(cursor.getClass()));
+
 				if (cursor instanceof Page)
+				{
 					break;
+				}
+
+				if (cursor.getParent() != null && !(cursor.getParent() instanceof AbstractRepeater))
+				{
+					/*
+					 * only append component id if parent is not a repeater because
+					 * 
+					 * (a) these ids are irrelevant when generating resource cache keys
+					 * 
+					 * (b) they cause a lot of redundant keys to be generated
+					 */
+					buffer.append(":").append(cursor.getId());
+				}
+				cursor = cursor.getParent();
+
 			}
 
 			buffer.append("-").append(component.getLocale());
@@ -399,4 +420,57 @@
 	{
 		return new ConcurrentHashMap<String, String>();
 	}
+
+	/**
+	 * Database that maps class names to an integer id. This is used to make localizer keys shorter
+	 * because sometimes they can contain a large number of class names.
+	 * 
+	 * @author igor.vaynberg
+	 */
+	private static class ClassMetaDatabase
+	{
+		private final Map<String, Long> nameToId = new HashMap<String, Long>();
+		private final ReadWriteLock nameToIdLock = new ReentrantReadWriteLock();
+		private long nameCounter = 0;
+
+		/**
+		 * Returns a unique id that represents this class' name. This can be used for compressing
+		 * class names. Notice this id should not be used across cluster nodes.
+		 * 
+		 * @param clazz
+		 * @return long id of class name
+		 */
+		public long id(Class<?> clazz)
+		{
+			final String name = clazz.getName();
+			nameToIdLock.readLock().lock();
+			try
+			{
+				Long id = nameToId.get(name);
+				if (id == null)
+				{
+					nameToIdLock.readLock().unlock();
+					nameToIdLock.writeLock().lock();
+					try
+					{
+						nameToId.put(name, nameCounter);
+						id = nameCounter;
+						nameCounter++;
+					}
+					finally
+					{
+						nameToIdLock.readLock().lock();
+						nameToIdLock.writeLock().unlock();
+					}
+				}
+				return id;
+			}
+			finally
+			{
+				nameToIdLock.readLock().unlock();
+			}
+		}
+	}
+
+
 }
\ No newline at end of file