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-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org