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