Index: VERSION.txt
===================================================================
--- VERSION.txt	(revision 3699)
+++ VERSION.txt	(working copy)
@@ -26,6 +26,7 @@
  + JETTY-716 Fixed NPE on empty cometd message
  + JETTY-718 during ssl unwrap, return true if some bytes were read, even if underflow
  + JETTY-720 fix HttpExchange.waitForStatus
+ + JETTY-721 Support wildcard in VirtualHosts configuration
  + JETTY-723 jetty.sh does not check if TMP already is set
  + JETTY-724 better handle EBCDIC default JVM encoding
  + JETTY-728 Improve Terracotta integration and performances
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 3699)
+++ modules/server/jetty/src/test/java/org/mortbay/jetty/handler/ContextHandlerTest.java	(working copy)
@@ -155,6 +155,9 @@
         try
         {
             server.start();
+            checkWildcardHost(true,server,null,new String[] {"example.com", ".example.com", "vhost.example.com"});
+            checkWildcardHost(false,server,new String[] {null},new String[] {"example.com", ".example.com", "vhost.example.com"});
+            
             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"});
             
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 3699)
+++ modules/server/jetty/src/main/java/org/mortbay/jetty/handler/ContextHandler.java	(working copy)
@@ -224,7 +224,7 @@
      * matching virtual host name.
      * @param vhosts Array of virtual hosts that this context responds to. A
      * null host name or null/empty array means any hostname is acceptable.
-     * Host names may String representation of IP addresses. Host names may
+     * Host names may be String representation of IP addresses. Host names may
      * start with '*.' to wildcard one level of names.
      */
     public void setVirtualHosts( String[] vhosts )
Index: modules/extra/jetty-rewrite/src/test/java/org/mortbay/jetty/handler/rewrite/VirtualHostRuleContainerTest.java
===================================================================
--- modules/extra/jetty-rewrite/src/test/java/org/mortbay/jetty/handler/rewrite/VirtualHostRuleContainerTest.java	(revision 3699)
+++ modules/extra/jetty-rewrite/src/test/java/org/mortbay/jetty/handler/rewrite/VirtualHostRuleContainerTest.java	(working copy)
@@ -140,7 +140,42 @@
         assertEquals("{_fooContainerRule: vhosts[cheese.com, foo.com], Host: foo.com}: apply _fooRule", "/cheese/fooRule", _request.getRequestURI());
     }
     
+    public void testWildcardVirtualHosts() throws Exception
+    {
+        checkWildcardHost(true,null,new String[] {"foo.com", ".foo.com", "vhost.foo.com"});
+        checkWildcardHost(true,new String[] {null},new String[] {"foo.com", ".foo.com", "vhost.foo.com"});
+
+        checkWildcardHost(true,new String[] {"foo.com", "*.foo.com"}, new String[] {"foo.com", ".foo.com", "vhost.foo.com"});
+        checkWildcardHost(false,new String[] {"foo.com", "*.foo.com"}, new String[] {"badfoo.com", ".badfoo.com", "vhost.badfoo.com"});
+        
+        checkWildcardHost(false,new String[] {"*."}, new String[] {"anything.anything"});
+        
+        checkWildcardHost(true,new String[] {"*.foo.com"}, new String[] {"vhost.foo.com", ".foo.com"});
+        checkWildcardHost(false,new String[] {"*.foo.com"}, new String[] {"vhost.www.foo.com", "foo.com", "www.vhost.foo.com"});
+
+        checkWildcardHost(true,new String[] {"*.sub.foo.com"}, new String[] {"vhost.sub.foo.com", ".sub.foo.com"});
+        checkWildcardHost(false,new String[] {"*.sub.foo.com"}, new String[] {".foo.com", "sub.foo.com", "vhost.foo.com"});
+        
+        checkWildcardHost(false,new String[] {"foo.*.com","foo.com.*"}, new String[] {"foo.vhost.com", "foo.com.vhost", "foo.com"});                    
+    }
     
+    private void checkWildcardHost(boolean succeed, String[] ruleHosts, String[] requestHosts) throws Exception
+    {
+        _fooContainerRule.setVirtualHosts(ruleHosts);
+        _handler.setRules(new Rule[] { _fooContainerRule });
+
+        for(String host: requestHosts)
+        {
+            _request.setServerName(host);
+            _request.setRequestURI("/cheese/bar");
+            handleRequest();
+            if(succeed)
+                assertEquals("{_fooContainerRule, Host: "+host+"}: should apply _fooRule", "/cheese/fooRule", _request.getRequestURI());
+            else
+                assertEquals("{_fooContainerRule, Host: "+host+"}: should not apply _fooRule", "/cheese/bar", _request.getRequestURI());
+        }
+    }
+
     private void handleRequest() throws Exception
     {
         _server.handle("/cheese/bar", _request, _response, 0);
Index: modules/extra/jetty-rewrite/src/main/java/org/mortbay/jetty/handler/rewrite/VirtualHostRuleContainer.java
===================================================================
--- modules/extra/jetty-rewrite/src/main/java/org/mortbay/jetty/handler/rewrite/VirtualHostRuleContainer.java	(revision 3699)
+++ modules/extra/jetty-rewrite/src/main/java/org/mortbay/jetty/handler/rewrite/VirtualHostRuleContainer.java	(working copy)
@@ -85,10 +85,9 @@
             String requestHost = normalizeHostname( request.getServerName() );
             for( String ruleHost : _virtualHosts )
             {
-                if(ruleHost == null || requestHost.equalsIgnoreCase(ruleHost))
-                {
+                if(ruleHost == null || ruleHost.equalsIgnoreCase(requestHost)
+                        || (ruleHost.startsWith("*.") && ruleHost.regionMatches(true,2,requestHost,requestHost.indexOf(".")+1,ruleHost.length()-2)))
                     return apply(target, request, response);
-                }
             }
         }
         else
