You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by kk...@apache.org on 2014/06/30 13:01:45 UTC

svn commit: r1606680 - in /tomcat/trunk: java/org/apache/catalina/mapper/Mapper.java test/org/apache/catalina/mapper/TestMapper.java

Author: kkolinko
Date: Mon Jun 30 11:01:45 2014
New Revision: 1606680

URL: http://svn.apache.org/r1606680
Log:
Add a collection of aliases to MappedHost object to simplify enumeration.
This adds some cost to addHost/removeHost[Alias], but simplifies addContextVersion/removeContextVersion().
Require that addContextVersion(), removeContextVersion() methods were called on a real host. Ignore them on an alias.

Modified:
    tomcat/trunk/java/org/apache/catalina/mapper/Mapper.java
    tomcat/trunk/test/org/apache/catalina/mapper/TestMapper.java

Modified: tomcat/trunk/java/org/apache/catalina/mapper/Mapper.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/mapper/Mapper.java?rev=1606680&r1=1606679&r2=1606680&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/mapper/Mapper.java (original)
+++ tomcat/trunk/java/org/apache/catalina/mapper/Mapper.java Mon Jun 30 11:01:45 2014
@@ -16,8 +16,13 @@
  */
 package org.apache.catalina.mapper;
 
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.List;
 import java.util.Map;
 import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.CopyOnWriteArrayList;
 
 import org.apache.catalina.Context;
 import org.apache.catalina.Host;
@@ -82,6 +87,7 @@ public final class Mapper {
      * Add a new host to the mapper.
      *
      * @param name Virtual host name
+     * @param aliases Alias names for the virtual host
      * @param host Host object
      */
     public synchronized void addHost(String name, String[] aliases,
@@ -97,9 +103,14 @@ public final class Mapper {
             // Do not add aliases, as removeHost(hostName) won't be able to remove them
             return;
         }
+        List<MappedHost> newAliases = new ArrayList<>(aliases.length);
         for (String alias : aliases) {
-            addHostAliasImpl(alias, newHost);
+            MappedHost newAlias = new MappedHost(alias, newHost);
+            if (addHostAliasImpl(newAlias)) {
+                newAliases.add(newAlias);
+            }
         }
+        newHost.addAliases(newAliases);
     }
 
 
@@ -114,21 +125,15 @@ public final class Mapper {
         if (host == null || host.isAlias()) {
             return;
         }
-        Host object = host.object;
-        MappedHost[] newHosts = new MappedHost[hosts.length - 1];
-        if (removeMap(hosts, newHosts, name)) {
-            hosts = newHosts;
-
-            // Remove all aliases (they will map to the same host object)
-            for (int i = 0; i < newHosts.length; i++) {
-                if (newHosts[i].object == object) {
-                    MappedHost[] newHosts2 = new MappedHost[hosts.length - 1];
-                    if (removeMap(hosts, newHosts2, newHosts[i].name)) {
-                        hosts = newHosts2;
-                    }
-                }
+        MappedHost[] newHosts = hosts.clone();
+        // Remove real host and all its aliases
+        int j = 0;
+        for (int i = 0; i < newHosts.length; i++) {
+            if (newHosts[i].getRealHost() != host) {
+                newHosts[j++] = newHosts[i];
             }
         }
+        hosts = Arrays.copyOf(newHosts, j);
     }
 
     /**
@@ -143,24 +148,28 @@ public final class Mapper {
             // just in case...
             return;
         }
-        addHostAliasImpl(alias, realHost);
+        MappedHost newAlias = new MappedHost(alias, realHost);
+        if (addHostAliasImpl(newAlias)) {
+            realHost.addAlias(newAlias);
+        }
     }
 
-    private void addHostAliasImpl(String alias, MappedHost realHost) {
-        MappedHost newHost = new MappedHost(alias, realHost);
+    private boolean addHostAliasImpl(MappedHost newAlias) {
         MappedHost[] newHosts = new MappedHost[hosts.length + 1];
-        if (insertMap(hosts, newHosts, newHost)) {
+        if (insertMap(hosts, newHosts, newAlias)) {
             hosts = newHosts;
+            return true;
         } else {
-            MappedHost duplicate = hosts[find(hosts, alias)];
-            if (duplicate.object == realHost.object) {
+            MappedHost duplicate = hosts[find(hosts, newAlias.name)];
+            if (duplicate.getRealHost() == newAlias.getRealHost()) {
                 // A duplicate Alias for the same Host.
                 // A harmless redundancy. E.g.
                 // <Host name="localhost"><Alias>localhost</Alias></Host>
-                return;
+                return false;
             }
-            log.error(sm.getString("mapper.duplicateHostAlias", alias,
-                    realHost.getRealHostName(), duplicate.getRealHostName()));
+            log.error(sm.getString("mapper.duplicateHostAlias", newAlias.name,
+                    newAlias.getRealHostName(), duplicate.getRealHostName()));
+            return false;
         }
     }
 
@@ -177,6 +186,7 @@ public final class Mapper {
         MappedHost[] newHosts = new MappedHost[hosts.length - 1];
         if (removeMap(hosts, newHosts, alias)) {
             hosts = newHosts;
+            hostMapping.getRealHost().removeAlias(hostMapping);
         }
 
     }
@@ -188,12 +198,9 @@ public final class Mapper {
     private void updateContextList(MappedHost realHost,
             ContextList newContextList) {
 
-        // The real host and all the aliases map to the same host object
-        Host object = realHost.object;
-        for (MappedHost host : hosts) {
-            if (host.object == object) {
-                host.contextList = newContextList;
-            }
+        realHost.contextList = newContextList;
+        for (MappedHost alias : realHost.getAliases()) {
+            alias.contextList = newContextList;
         }
     }
 
@@ -221,6 +228,10 @@ public final class Mapper {
                 return;
             }
         }
+        if (mappedHost.isAlias()) {
+            log.error("No host found: " + hostName);
+            return;
+        }
         int slashCount = slashCount(path);
         synchronized (mappedHost) {
             ContextVersion newContextVersion = new ContextVersion(version,
@@ -264,7 +275,7 @@ public final class Mapper {
         contextObjectToContextVersionMap.remove(ctxt);
 
         MappedHost host = exactFind(hosts, hostName);
-        if (host == null) {
+        if (host == null || host.isAlias()) {
             return;
         }
 
@@ -1434,16 +1445,28 @@ public final class Mapper {
 
     protected static final class MappedHost extends MapElement<Host> {
 
-        private final MappedHost realHost;
         public volatile ContextList contextList;
 
         /**
+         * Link to the "real" MappedHost, shared by all aliases.
+         */
+        private final MappedHost realHost;
+
+        /**
+         * Links to all registered aliases, for easy enumeration. This field
+         * is available only in the "real" MappedHost. In an alias this field
+         * is <code>null</code>.
+         */
+        private final List<MappedHost> aliases;
+
+        /**
          * Constructor used for the primary Host
          */
         public MappedHost(String name, Host host) {
             super(name, host);
             realHost = this;
             contextList = new ContextList();
+            aliases = new CopyOnWriteArrayList<>();
         }
 
         /**
@@ -1453,6 +1476,7 @@ public final class Mapper {
             super(alias, realHost.object);
             this.realHost = realHost;
             this.contextList = realHost.contextList;
+            this.aliases = null;
         }
 
         public boolean isAlias() {
@@ -1466,6 +1490,22 @@ public final class Mapper {
         public String getRealHostName() {
             return realHost.name;
         }
+
+        public Collection<MappedHost> getAliases() {
+            return aliases;
+        }
+
+        public void addAlias(MappedHost alias) {
+            aliases.add(alias);
+        }
+
+        public void addAliases(Collection<? extends MappedHost> c) {
+            aliases.addAll(c);
+        }
+
+        public void removeAlias(MappedHost alias) {
+            aliases.remove(alias);
+        }
     }
 
 

Modified: tomcat/trunk/test/org/apache/catalina/mapper/TestMapper.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/test/org/apache/catalina/mapper/TestMapper.java?rev=1606680&r1=1606679&r2=1606680&view=diff
==============================================================================
--- tomcat/trunk/test/org/apache/catalina/mapper/TestMapper.java (original)
+++ tomcat/trunk/test/org/apache/catalina/mapper/TestMapper.java Mon Jun 30 11:01:45 2014
@@ -21,6 +21,7 @@ import java.util.concurrent.atomic.Atomi
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertSame;
 import static org.junit.Assert.assertTrue;
 
 import org.junit.Before;
@@ -182,10 +183,18 @@ public class TestMapper extends LoggingB
         Mapper.MappedHost aliasMapping = mapper.hosts[iowPos + 1];
         assertEquals("iowejoiejfoiew_alias", aliasMapping.name);
         assertTrue(aliasMapping.isAlias());
-        assertEquals(hostMapping.object, aliasMapping.object);
+        assertSame(hostMapping.object, aliasMapping.object);
+
+        assertEquals("iowejoiejfoiew", hostMapping.getRealHostName());
+        assertEquals("iowejoiejfoiew", aliasMapping.getRealHostName());
+        assertSame(hostMapping, hostMapping.getRealHost());
+        assertSame(hostMapping, aliasMapping.getRealHost());
 
         mapper.removeHost("iowejoiejfoiew");
         assertEquals(14, mapper.hosts.length); // Both host and alias removed
+        for (Mapper.MappedHost host : mapper.hosts) {
+            assertTrue(host.name, !host.name.startsWith("iowejoiejfoiew"));
+        }
     }
 
     @Test
@@ -246,7 +255,7 @@ public class TestMapper extends LoggingB
         final Context context3 = createContext("foo#bar#bla");
         final Context context4 = createContext("foo#bar#bla#baz");
 
-        mapper.addHost("localhost", new String[0], host);
+        mapper.addHost("localhost", new String[] { "alias" }, host);
         mapper.setDefaultHostName("localhost");
 
         mapper.addContextVersion("localhost", host, "", "0", contextRoot,
@@ -278,6 +287,8 @@ public class TestMapper extends LoggingB
         MappingData mappingData = new MappingData();
         MessageBytes hostMB = MessageBytes.newInstance();
         hostMB.setString("localhost");
+        MessageBytes aliasMB = MessageBytes.newInstance();
+        aliasMB.setString("alias");
         MessageBytes uriMB = MessageBytes.newInstance();
         char[] uri = "/foo/bar/bla/bobou/foo".toCharArray();
         uriMB.setChars(uri, 0, uri.length);
@@ -285,12 +296,22 @@ public class TestMapper extends LoggingB
         mapper.map(hostMB, uriMB, null, mappingData);
         assertEquals("/foo/bar/bla", mappingData.contextPath.toString());
 
+        mappingData.recycle();
+        uriMB.setChars(uri, 0, uri.length);
+        mapper.map(aliasMB, uriMB, null, mappingData);
+        assertEquals("/foo/bar/bla", mappingData.contextPath.toString());
+
         t.start();
         while (running.get()) {
             mappingData.recycle();
             uriMB.setChars(uri, 0, uri.length);
             mapper.map(hostMB, uriMB, null, mappingData);
             assertEquals("/foo/bar/bla", mappingData.contextPath.toString());
+
+            mappingData.recycle();
+            uriMB.setChars(uri, 0, uri.length);
+            mapper.map(aliasMB, uriMB, null, mappingData);
+            assertEquals("/foo/bar/bla", mappingData.contextPath.toString());
         }
     }
 



---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org