Skip to content

Commit

Permalink
Merge pull request #279 from rhusar/MODCLUSTER-457
Browse files Browse the repository at this point in the history
MODCLUSTER-457 Expose Tomcat configuration to explicitly specify a connector to register with the proxy
  • Loading branch information
pferraro committed Aug 10, 2017
2 parents 9baba25 + d9e5ec1 commit 06754fc
Show file tree
Hide file tree
Showing 40 changed files with 424 additions and 256 deletions.

This file was deleted.

@@ -0,0 +1,98 @@
/*
* JBoss, Home of Professional Open Source.
* Copyright 2017, Red Hat Middleware LLC, and individual contributors
* as indicated by the @author tags. See the copyright.txt file in the
* distribution for a full listing of individual contributors.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.jboss.modcluster.container.tomcat;

import java.net.InetAddress;
import java.net.UnknownHostException;

import org.apache.catalina.Engine;
import org.jboss.modcluster.ModClusterLogger;
import org.jboss.modcluster.container.Connector;

/**
* Connector provider implementation that picks a connector based on configured {@code connectorPort=".."} and/or {@code connectorAddress=".."}.
* Should multiple or no connectors match the defined values a {@link RuntimeException} is thrown.
*
* @author Radoslav Husar
*/
public class ConfigurableProxyConnectorProvider implements ProxyConnectorProvider {

private final TomcatConnectorConfiguration connectorConfiguration;

public ConfigurableProxyConnectorProvider(TomcatConnectorConfiguration connectorConfiguration) {
this.connectorConfiguration = connectorConfiguration;
}

@Override
public Connector createProxyConnector(ConnectorFactory factory, Engine engine) {
// Resolve configuration parameters *after* it was set by Tomcat modeler
String connectorAddress = connectorConfiguration.getConnectorAddress();
Integer connectorPort = connectorConfiguration.getConnectorPort();

// Iterate entire collection of connectors once, ensuring that exactly only *one* matches the given host:port configuration
org.apache.catalina.connector.Connector candidate = null;

for (org.apache.catalina.connector.Connector connector : engine.getService().findConnectors()) {
if (connectorPort == null || connectorPort.equals(connector.getPort())) {

String resolvedConfiguredAddress = null;
String addressInTomcat = null;

if (connector != null) {
// Resolve the connector's address in use
Object addressObj = connector.getProperty("address");
if (addressObj instanceof InetAddress) {
addressInTomcat = ((InetAddress) addressObj).getHostAddress();
} else if (addressObj != null) {
addressInTomcat = addressObj.toString();
}

// Resolve configured address
try {
resolvedConfiguredAddress = InetAddress.getByName(connectorAddress).getHostAddress();
} catch (UnknownHostException e) {
throw ModClusterLogger.LOGGER.connectorAddressUnknownHost(connectorAddress);
}
}

if (connectorAddress == null || resolvedConfiguredAddress.equalsIgnoreCase(addressInTomcat)) {
if (candidate == null) {
candidate = connector;
} else {
throw ModClusterLogger.LOGGER.connectorMatchesMultiple(format(connectorAddress, connectorPort));
}
}

}
}

if (candidate == null) {
throw ModClusterLogger.LOGGER.connectorNoMatch(format(connectorAddress, connectorPort));
}

return factory.createConnector(candidate);
}

private static String format(String connectorAddress, Integer connectorPort) {
return (connectorAddress == null ? "*" : connectorAddress) + ":" + (connectorPort == null ? "*" : connectorPort);
}
}
Expand Up @@ -28,5 +28,5 @@
* @author Paul Ferraro
*/
public interface LifecycleListenerFactory {
LifecycleListener createListener(ContainerEventHandler handler);
LifecycleListener createListener(ContainerEventHandler handler, TomcatConnectorConfiguration connectorConfiguration);
}
Expand Up @@ -63,7 +63,7 @@
*
* @author Paul Ferraro
*/
public class ModClusterListener extends ModClusterConfig implements LifecycleListener, LoadBalanceFactorProviderFactory, ModClusterServiceMBean {
public class ModClusterListener extends ModClusterConfig implements TomcatConnectorConfiguration, LifecycleListener, LoadBalanceFactorProviderFactory, ModClusterServiceMBean {
private static final Logger log = Logger.getLogger(ModClusterListener.class);

private final ModClusterServiceMBean service;
Expand All @@ -78,7 +78,7 @@ public ModClusterListener() {
ModClusterService service = new ModClusterService(this, this);

this.service = service;
this.listener = ServiceLoaderTomcatFactory.load(LifecycleListenerFactory.class, TomcatEventHandlerAdapterFactory.class).createListener(service);
this.listener = ServiceLoaderTomcatFactory.load(LifecycleListenerFactory.class, TomcatEventHandlerAdapterFactory.class).createListener(service, this);
}

protected ModClusterListener(ModClusterServiceMBean mbean, LifecycleListener listener) {
Expand Down Expand Up @@ -356,6 +356,30 @@ public boolean stopContext(String host, String path, long timeout) {
return this.service.stopContext(host, path, timeout, TimeUnit.SECONDS);
}

// ---------------------- Tomcat connector configuration ----------------------

private String connectorAddress;

@Override
public String getConnectorAddress() {
return connectorAddress;
}

public void setConnectorAddress(String connectorAddress) {
this.connectorAddress = connectorAddress;
}

private Integer connectorPort;

@Override
public Integer getConnectorPort() {
return connectorPort;
}

public void setConnectorPort(int connectorPort) {
this.connectorPort = connectorPort;
}

// ---------------------------------------- String-based Tomcat modeler and server.xml methods ----------------------------------------

public String getAdvertiseGroupAddress() {
Expand Down
@@ -0,0 +1,45 @@
/*
* JBoss, Home of Professional Open Source.
* Copyright 2017, Red Hat Middleware LLC, and individual contributors
* as indicated by the @author tags. See the copyright.txt file in the
* distribution for a full listing of individual contributors.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.jboss.modcluster.container.tomcat;

/**
* Tomcat-specific configuration for selecting a connector to register with the proxy.
*
* @author Radoslav Husar
*/
public interface TomcatConnectorConfiguration {

/**
* Returns optional connector address.
*
* @return connector address
*/
String getConnectorAddress();

/**
* Returns optional connector port.
*
* @return connector port
*/
Integer getConnectorPort();

}
Expand Up @@ -24,8 +24,6 @@
import java.beans.PropertyChangeEvent;
import java.lang.management.ManagementFactory;
import java.util.concurrent.atomic.AtomicBoolean;

import javax.management.MBeanServer;
import javax.management.MalformedObjectNameException;
import javax.management.ObjectName;

Expand Down Expand Up @@ -59,21 +57,8 @@ public class TomcatEventHandlerAdapter implements TomcatEventHandler {

private volatile int statusCount = 0;

/**
* Constructs a new CatalinaEventHandlerAdapter using the specified event handler.
*
* @param eventHandler an event handler
*/
public TomcatEventHandlerAdapter(ContainerEventHandler eventHandler) {
this(eventHandler, ManagementFactory.getPlatformMBeanServer());
}

public TomcatEventHandlerAdapter(ContainerEventHandler eventHandler, MBeanServer mbeanServer) {
this(eventHandler, new JMXServerProvider(mbeanServer, toObjectName("Catalina:type=Server")), new AutoProxyConnectorProvider());
}

public TomcatEventHandlerAdapter(ContainerEventHandler eventHandler, Server server) {
this(eventHandler, new SimpleServerProvider(server), new AutoProxyConnectorProvider());
public TomcatEventHandlerAdapter(ContainerEventHandler eventHandler, TomcatConnectorConfiguration connectorConfiguration) {
this(eventHandler, new JMXServerProvider(ManagementFactory.getPlatformMBeanServer(), toObjectName("Catalina:type=Server")), new ConfigurableProxyConnectorProvider(connectorConfiguration));
}

public TomcatEventHandlerAdapter(ContainerEventHandler eventHandler, Server server, Connector connector) {
Expand All @@ -94,12 +79,10 @@ public TomcatEventHandlerAdapter(ContainerEventHandler eventHandler, ServerProvi
public void start() {
Server server = this.serverProvider.getServer();

if (!(server instanceof Lifecycle)) throw new IllegalStateException();
if (server == null) throw new IllegalStateException();

Lifecycle lifecycle = (Lifecycle) server;

if (!this.containsListener(lifecycle)) {
lifecycle.addLifecycleListener(this);
if (!this.containsListener(server)) {
server.addLifecycleListener(this);
}

if (this.init.compareAndSet(false, true)) {
Expand All @@ -115,11 +98,9 @@ public void start() {
public void stop() {
Server server = this.serverProvider.getServer();

if (!(server instanceof Lifecycle)) throw new IllegalStateException();

Lifecycle lifecycle = (Lifecycle) server;
if (server == null) throw new IllegalStateException();

lifecycle.removeLifecycleListener(this);
server.removeLifecycleListener(this);

if (this.init.get() && this.start.compareAndSet(true, false)) {
this.eventHandler.stop(this.factory.createServer(server));
Expand Down Expand Up @@ -281,13 +262,13 @@ protected void addListeners(Server server) {
for (Service service : server.findServices()) {
Container engine = service.getContainer();
engine.addContainerListener(this);
((Lifecycle) engine).addLifecycleListener(this);
engine.addLifecycleListener(this);

for (Container host : engine.findChildren()) {
host.addContainerListener(this);

for (Container context : host.findChildren()) {
((Lifecycle) context).addLifecycleListener(this);
context.addLifecycleListener(this);
context.addPropertyChangeListener(this);
}
}
Expand All @@ -299,13 +280,13 @@ protected void removeListeners(Server server) {
for (Service service : server.findServices()) {
Container engine = service.getContainer();
engine.removeContainerListener(this);
((Lifecycle) engine).removeLifecycleListener(this);
engine.removeLifecycleListener(this);

for (Container host : engine.findChildren()) {
host.removeContainerListener(this);

for (Container context : host.findChildren()) {
((Lifecycle) context).removeLifecycleListener(this);
context.removeLifecycleListener(this);
context.removePropertyChangeListener(this);
}
}
Expand Down
Expand Up @@ -26,11 +26,10 @@

/**
* @author Radoslav Husar
* @version Jun 2016
*/
public class TomcatEventHandlerAdapterFactory implements LifecycleListenerFactory {
@Override
public LifecycleListener createListener(ContainerEventHandler handler) {
return new TomcatEventHandlerAdapter(handler);
public LifecycleListener createListener(ContainerEventHandler handler, TomcatConnectorConfiguration connectorConfiguration) {
return new TomcatEventHandlerAdapter(handler, connectorConfiguration);
}
}
Expand Up @@ -16,6 +16,14 @@
description="Object name of the container"
type="javax.management.ObjectName"/>

<attribute name="connectorAddress"
description="Address of a defined Tomcat connector to register with the proxy."
type="java.lang.String"/>

<attribute name="connectorPort"
description="Port of a defined Tomcat connector to register with the proxy."
type="int"/>

<attribute name="proxyConfiguration"
description="Get the mod_cluster configuration, per proxy"
type="java.util.Map"
Expand Down

0 comments on commit 06754fc

Please sign in to comment.