Author: ivaynberg
Date: Thu Nov 16 12:10:12 2006
New Revision: 475905

URL: http://svn.apache.org/viewvc?view=rev&rev=475905
Log:
optimize non-case-sensitive mount resolution

did you guys ever have a little johan sitting on your shoulder whispering 
optimization theories?

Modified:
    
incubator/wicket/branches/wicket-1.x/wicket/src/main/java/wicket/protocol/http/request/WebRequestCodingStrategy.java

Modified: 
incubator/wicket/branches/wicket-1.x/wicket/src/main/java/wicket/protocol/http/request/WebRequestCodingStrategy.java
URL: 
http://svn.apache.org/viewvc/incubator/wicket/branches/wicket-1.x/wicket/src/main/java/wicket/protocol/http/request/WebRequestCodingStrategy.java?view=diff&rev=475905&r1=475904&r2=475905
==============================================================================
--- 
incubator/wicket/branches/wicket-1.x/wicket/src/main/java/wicket/protocol/http/request/WebRequestCodingStrategy.java
 (original)
+++ 
incubator/wicket/branches/wicket-1.x/wicket/src/main/java/wicket/protocol/http/request/WebRequestCodingStrategy.java
 Thu Nov 16 12:10:12 2006
@@ -19,10 +19,10 @@
 
 import java.io.UnsupportedEncodingException;
 import java.net.URLEncoder;
+import java.util.Collection;
 import java.util.Comparator;
 import java.util.Iterator;
 import java.util.Map;
-import java.util.SortedMap;
 import java.util.TreeMap;
 import java.util.Map.Entry;
 
@@ -131,34 +131,6 @@
        /** settings for the coding strategy */
        private final Settings settings;
 
-
-       /** Comparator implementation that sorts longest strings first */
-       private static final Comparator lengthComparator = new Comparator()
-       {
-               public int compare(Object o1, Object o2)
-               {
-                       // longer first
-                       if (o1 == o2)
-                       {
-                               return 0;
-                       }
-                       else if (o1 == null)
-                       {
-                               return 1;
-                       }
-                       else if (o2 == null)
-                       {
-                               return -1;
-                       }
-                       else
-                       {
-                               String lhs = (String)o1;
-                               String rhs = (String)o2;
-                               return 0 - lhs.compareTo(rhs);
-                       }
-               }
-       };
-
        /** log. */
        private static final Log log = 
LogFactory.getLog(WebRequestCodingStrategy.class);
 
@@ -178,8 +150,7 @@
         * match the longest possible path first.
         * </p>
         */
-       private final SortedMap/* <String,IRequestTargetUrlCodingStrategy> 
*/mountsOnPath = new TreeMap(
-                       lengthComparator);
+       private final MountsMap mountsOnPath;
 
        /** cached url prefix. */
        private CharSequence urlPrefix;
@@ -204,6 +175,7 @@
                        throw new IllegalArgumentException("Argument 
[[settings]] cannot be null");
                }
                this.settings = settings;
+               mountsOnPath = new MountsMap(settings.areMountsCaseSensitive());
        }
 
 
@@ -305,49 +277,26 @@
         */
        public IRequestTargetUrlCodingStrategy[] listMounts()
        {
-               return 
(IRequestTargetUrlCodingStrategy[])mountsOnPath.values().toArray(
+               return 
(IRequestTargetUrlCodingStrategy[])mountsOnPath.strategies().toArray(
                                new 
IRequestTargetUrlCodingStrategy[mountsOnPath.size()]);
        }
 
        /**
         * @see 
wicket.request.IRequestTargetMounter#urlCodingStrategyForPath(java.lang.String)
         */
-       public final IRequestTargetUrlCodingStrategy 
urlCodingStrategyForPath(final String path)
+       public final IRequestTargetUrlCodingStrategy 
urlCodingStrategyForPath(String path)
        {
                if (path == null)
                {
-                       return 
(IRequestTargetUrlCodingStrategy)mountsOnPath.get(null);
+                       return 
(IRequestTargetUrlCodingStrategy)mountsOnPath.strategyForMount(null);
                }
                else if (!path.equals("/")) // ignore root paths.. is this the 
right
                // path?
                {
-                       for (final Iterator it = 
mountsOnPath.entrySet().iterator(); it.hasNext();)
+                       IRequestTargetUrlCodingStrategy strategy = 
mountsOnPath.strategyForPath(path);
+                       if (strategy != null)
                        {
-                               final Map.Entry entry = (Entry)it.next();
-                               final String key = (String)entry.getKey();
-                               boolean match = false;
-                               if (!settings.areMountsCaseSensitive())
-                               {
-                                       if (path.length() >= key.length())
-                                       {
-                                               String mount = 
path.substring(0, key.length());
-                                               if (mount.equalsIgnoreCase(key))
-                                               {
-                                                       match = true;
-                                               }
-                                       }
-                               }
-                               else
-                               {
-                                       if (path.startsWith(key))
-                                       {
-                                               match = true;
-                                       }
-                               }
-                               if (match)
-                               {
-                                       return 
(IRequestTargetUrlCodingStrategy)entry.getValue();
-                               }
+                               return strategy;
                        }
                }
                return null;
@@ -379,12 +328,12 @@
                        path = "/" + path;
                }
 
-               if (mountsOnPath.containsKey(path))
+               if (mountsOnPath.strategyForMount(path) != null)
                {
                        throw new WicketRuntimeException(path + " is already 
mounted for "
-                                       + mountsOnPath.get(path));
+                                       + mountsOnPath.strategyForMount(path));
                }
-               mountsOnPath.put(path, encoder);
+               mountsOnPath.mount(path, encoder);
        }
 
        /**
@@ -427,7 +376,7 @@
                        path = "/" + path;
                }
 
-               mountsOnPath.remove(path);
+               mountsOnPath.unmount(path);
        }
 
        /**
@@ -881,7 +830,7 @@
        {
                // TODO Post 1.2: Performance: Optimize algorithm if possible 
and/ or
                // cache lookup results
-               for (Iterator i = mountsOnPath.values().iterator(); 
i.hasNext();)
+               for (Iterator i = mountsOnPath.strategies().iterator(); 
i.hasNext();)
                {
                        IRequestTargetUrlCodingStrategy encoder = 
(IRequestTargetUrlCodingStrategy)i.next();
                        if (encoder.matches(requestTarget))
@@ -961,5 +910,165 @@
                        }
                }
                return urlPrefix;
+       }
+
+       /**
+        * Map used to store mount paths and their corresponding url coding
+        * strategies.
+        * 
+        * @author ivaynberg
+        */
+       private static class MountsMap
+       {
+               private static final long serialVersionUID = 1L;
+
+               /** case sensitive flag */
+               private final boolean caseSensitiveMounts;
+
+               /** backing map */
+               private final TreeMap map;
+
+               /**
+                * Constructor
+                * 
+                * @param caseSensitiveMounts
+                *            whether or not keys of this map are case-sensitive
+                */
+               public MountsMap(boolean caseSensitiveMounts)
+               {
+                       map = new TreeMap(LENGTH_COMPARATOR);
+                       this.caseSensitiveMounts = caseSensitiveMounts;
+               }
+
+               /**
+                * Checks if the specified path matches any mount, and if so 
returns the
+                * coding strategy for that mount. Returns null if the path 
doesnt match
+                * any mounts.
+                * 
+                * NOTE: path here is not the mount - it is the full url path
+                * 
+                * @param path
+                *            non-null url path
+                * @return coding strategy or null
+                */
+               public IRequestTargetUrlCodingStrategy strategyForPath(String 
path)
+               {
+                       if (path == null)
+                       {
+                               throw new IllegalArgumentException("Argument 
[[path]] cannot be null");
+                       }
+                       if (caseSensitiveMounts == false)
+                       {
+                               path = path.toLowerCase();
+                       }
+                       for (final Iterator it = map.entrySet().iterator(); 
it.hasNext();)
+                       {
+                               final Map.Entry entry = (Entry)it.next();
+                               final String key = (String)entry.getKey();
+                               if (path.startsWith(key))
+                               {
+                                       return 
(IRequestTargetUrlCodingStrategy)entry.getValue();
+                               }
+                       }
+                       return null;
+               }
+
+
+               /**
+                * @return number of mounts in the map
+                */
+               public int size()
+               {
+                       return map.size();
+               }
+
+               /**
+                * @return collection of coding strategies associated with 
every mount
+                */
+               public Collection strategies()
+               {
+                       return map.values();
+               }
+
+
+               /**
+                * Removes mount from the map
+                * 
+                * @param mount
+                */
+               public void unmount(String mount)
+               {
+                       if (caseSensitiveMounts == false && mount != null)
+                       {
+                               mount = mount.toLowerCase();
+                       }
+
+                       map.remove(mount);
+               }
+
+
+               /**
+                * Gets the coding strategy for the specified mount path
+                * 
+                * @param mount
+                *            mount paht
+                * @return associated coding strategy or null if none
+                */
+               public IRequestTargetUrlCodingStrategy strategyForMount(String 
mount)
+               {
+                       if (caseSensitiveMounts == false && mount != null)
+                       {
+                               mount = mount.toLowerCase();
+                       }
+
+                       return (IRequestTargetUrlCodingStrategy)map.get(mount);
+               }
+
+               /**
+                * Associates a mount with a coding strategy
+                * 
+                * @param mount
+                * @param encoder
+                * @return previous coding strategy associated with the mount, 
or null
+                *         if none
+                */
+               public IRequestTargetUrlCodingStrategy mount(String mount,
+                               IRequestTargetUrlCodingStrategy encoder)
+               {
+                       if (caseSensitiveMounts == false && mount != null)
+                       {
+                               mount = mount.toLowerCase();
+                       }
+                       return (IRequestTargetUrlCodingStrategy)map.put(mount, 
encoder);
+               }
+
+
+               /** Comparator implementation that sorts longest strings first 
*/
+               private static final Comparator LENGTH_COMPARATOR = new 
Comparator()
+               {
+                       public int compare(Object o1, Object o2)
+                       {
+                               // longer first
+                               if (o1 == o2)
+                               {
+                                       return 0;
+                               }
+                               else if (o1 == null)
+                               {
+                                       return 1;
+                               }
+                               else if (o2 == null)
+                               {
+                                       return -1;
+                               }
+                               else
+                               {
+                                       String lhs = (String)o1;
+                                       String rhs = (String)o2;
+                                       return 0 - lhs.compareTo(rhs);
+                               }
+                       }
+               };
+
        }
 }


Reply via email to