Index: modules/server/jetty/src/main/java/org/mortbay/jetty/handler/ContextHandler.java
===================================================================
--- modules/server/jetty/src/main/java/org/mortbay/jetty/handler/ContextHandler.java	(revision 3691)
+++ modules/server/jetty/src/main/java/org/mortbay/jetty/handler/ContextHandler.java	(working copy)
@@ -676,7 +676,15 @@
                 
                 // TODO non-linear lookup
                 for (int i=0;!match && i<_vhosts.length;i++)
-                    match=_vhosts[i]!=null && _vhosts[i].equalsIgnoreCase(vhost);
+                {
+                    String contextVhost = _vhosts[i];
+                    if(contextVhost==null) continue;
+                    if(contextVhost.startsWith("*.")) {
+                        // wildcard only at the beginning, and only for one additional subdomain level
+                        match=contextVhost.regionMatches(true,2,vhost,vhost.indexOf(".")+1,contextVhost.length()-2);
+                    } else
+                        match=contextVhost.equalsIgnoreCase(vhost);
+                }
                 if (!match)
                     return;
             }
Index: modules/server/jetty/src/test/java/org/mortbay/jetty/handler/ContextHandlerTest.java
===================================================================
--- modules/server/jetty/src/test/java/org/mortbay/jetty/handler/ContextHandlerTest.java	(revision 3691)
+++ modules/server/jetty/src/test/java/org/mortbay/jetty/handler/ContextHandlerTest.java	(working copy)
@@ -138,7 +138,61 @@
         }
 
     }
+    
+    public void testVirtualHostWildcard() throws Exception
+    {
+        Server server = new Server();
+        LocalConnector connector = new LocalConnector();
+        server.setConnectors(new Connector[] { connector });
 
+        ContextHandler context = new ContextHandler("/");
+        
+        IsHandledHandler handler = new IsHandledHandler();
+        context.setHandler(handler);
+
+        server.addHandler(context);
+
+        try
+        {
+            server.start();
+            checkWildcardHost(true,server,new String[] {"example.com", "*.example.com"}, new String[] {"example.com", ".example.com", "vhost.example.com"});
+            checkWildcardHost(false,server,new String[] {"example.com", "*.example.com"}, new String[] {"badexample.com", ".badexample.com", "vhost.badexample.com"});
+            
+            checkWildcardHost(false,server,new String[] {"*."}, new String[] {"anything.anything"});
+            
+            checkWildcardHost(true,server,new String[] {"*.example.com"}, new String[] {"vhost.example.com", ".example.com"});
+            checkWildcardHost(false,server,new String[] {"*.example.com"}, new String[] {"vhost.www.example.com", "example.com", "www.vhost.example.com"});
+
+            checkWildcardHost(true,server,new String[] {"*.sub.example.com"}, new String[] {"vhost.sub.example.com", ".sub.example.com"});
+            checkWildcardHost(false,server,new String[] {"*.sub.example.com"}, new String[] {".example.com", "sub.example.com", "vhost.example.com"});
+            
+            checkWildcardHost(false,server,new String[] {"example.*.com","example.com.*"}, new String[] {"example.vhost.com", "example.com.vhost", "example.com"});            
+        }
+        finally
+        {
+            server.stop();
+        }
+    }
+
+    private void checkWildcardHost(boolean succeed, Server server, String[] contextHosts, String[] requestHosts) throws Exception
+    {
+        LocalConnector connector = (LocalConnector)server.getConnectors()[0];
+        ContextHandler context = (ContextHandler)server.getHandler();
+        context.setVirtualHosts(contextHosts);
+        
+        IsHandledHandler handler = (IsHandledHandler)context.getHandler();
+        for(String host : requestHosts)
+        {
+            connector.getResponses("GET / HTTP/1.1\n" + "Host: "+host+"\n\n");
+            if(succeed) 
+                assertTrue("'"+host+"' should have been handled.",handler.isHandled());
+            else
+                assertFalse("'"+host + "' should not have been handled.", handler.isHandled());
+            handler.reset();
+        }
+
+    }
+    
     public static final class IsHandledHandler extends AbstractHandler
     {
         private boolean handled;

