org.wildfly.extension.camel.undertow.CamelUndertowHostService Maven / Gradle / Ivy
/*
* #%L
* Wildfly Camel :: Subsystem
* %%
* Copyright (C) 2013 - 2014 RedHat
* %%
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* #L%
*/
package org.wildfly.extension.camel.undertow;
import java.net.InetAddress;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URL;
import org.apache.camel.component.undertow.HttpHandlerRegistrationInfo;
import org.apache.camel.component.undertow.UndertowHost;
import org.jboss.as.network.NetworkUtils;
import org.jboss.as.network.SocketBinding;
import org.jboss.gravia.runtime.ModuleContext;
import org.jboss.gravia.runtime.Runtime;
import org.jboss.gravia.runtime.ServiceRegistration;
import org.jboss.gravia.utils.IllegalStateAssertion;
import org.jboss.msc.service.AbstractService;
import org.jboss.msc.service.ServiceBuilder;
import org.jboss.msc.service.ServiceController;
import org.jboss.msc.service.ServiceName;
import org.jboss.msc.service.ServiceTarget;
import org.jboss.msc.service.StartContext;
import org.jboss.msc.service.StartException;
import org.jboss.msc.service.StopContext;
import org.jboss.msc.value.InjectedValue;
import org.wildfly.extension.camel.CamelConstants;
import org.wildfly.extension.camel.parser.SubsystemRuntimeState;
import org.wildfly.extension.gravia.GraviaConstants;
import org.wildfly.extension.undertow.AbstractUndertowEventListener;
import org.wildfly.extension.undertow.Host;
import org.wildfly.extension.undertow.ListenerService;
import org.wildfly.extension.undertow.UndertowEventListener;
import org.wildfly.extension.undertow.UndertowService;
import io.undertow.Handlers;
import io.undertow.server.HttpHandler;
import io.undertow.server.handlers.PathTemplateHandler;
import io.undertow.servlet.api.Deployment;
/**
* The {@link UndertowHost} service
*
* @author [email protected]
* @since 19-Apr-2013
*/
public class CamelUndertowHostService extends AbstractService {
private static final ServiceName SERVICE_NAME = CamelConstants.CAMEL_BASE_NAME.append("Undertow");
private final InjectedValue injectedHttpSocketBinding = new InjectedValue<>();
private final InjectedValue injectedUndertowService = new InjectedValue<>();
private final InjectedValue injectedDefaultHost = new InjectedValue<>();
private final InjectedValue injectedRuntime = new InjectedValue();
private final SubsystemRuntimeState runtimeState;
private ServiceRegistration registration;
private UndertowEventListener eventListener;
private UndertowHost undertowHost;
public static ServiceController addService(ServiceTarget serviceTarget, SubsystemRuntimeState runtimeState) {
CamelUndertowHostService service = new CamelUndertowHostService(runtimeState);
ServiceBuilder builder = serviceTarget.addService(SERVICE_NAME, service);
builder.addDependency(GraviaConstants.RUNTIME_SERVICE_NAME, Runtime.class, service.injectedRuntime);
builder.addDependency(UndertowService.UNDERTOW, UndertowService.class, service.injectedUndertowService);
builder.addDependency(SocketBinding.JBOSS_BINDING_NAME.append("http"), SocketBinding.class, service.injectedHttpSocketBinding);
builder.addDependency(UndertowService.virtualHostName("default-server", "default-host"), Host.class, service.injectedDefaultHost);
return builder.install();
}
// Hide ctor
private CamelUndertowHostService(SubsystemRuntimeState runtimeState) {
this.runtimeState = runtimeState;
}
@Override
public void start(StartContext startContext) throws StartException {
runtimeState.setHttpHost(getConnectionURL());
eventListener = new CamelUndertowEventListener();
injectedUndertowService.getValue().registerListener(eventListener);
undertowHost = new WildFlyUndertowHost(injectedDefaultHost.getValue());
ModuleContext syscontext = injectedRuntime.getValue().getModuleContext();
registration = syscontext.registerService(UndertowHost.class, undertowHost, null);
}
private URL getConnectionURL() throws StartException {
SocketBinding socketBinding = injectedHttpSocketBinding.getValue();
InetAddress address = socketBinding.getNetworkInterfaceBinding().getAddress();
/* Derive the address from network interfaces
if (address.getHostAddress().equals("127.0.0.1")) {
InetAddress derived = null;
try {
List nets = Collections.list(NetworkInterface.getNetworkInterfaces());
for (int i = 0; derived == null && i < nets.size(); i++) {
for (InetAddress aux : Collections.list(nets.get(i).getInetAddresses())) {
if (!aux.getHostAddress().equals("127.0.0.1")) {
derived = aux;
break;
}
}
}
} catch (SocketException ex) {
throw new StartException(ex);
}
IllegalStateAssertion.assertNotNull(derived, "Cannot derive internet address from interfaces");
address = derived;
}
*/
URL result;
try {
String hostAddress = NetworkUtils.formatPossibleIpv6Address(address.getHostAddress());
result = new URL(socketBinding.getName() + "://" + hostAddress + ":" + socketBinding.getPort());
} catch (MalformedURLException ex) {
throw new StartException(ex);
}
return result;
}
@Override
public void stop(StopContext context) {
injectedUndertowService.getValue().unregisterListener(eventListener);
registration.unregister();
}
@Override
public UndertowHost getValue() throws IllegalStateException {
return undertowHost;
}
class WildFlyUndertowHost implements UndertowHost {
private static final String REST_PATH_PLACEHOLDER = "{";
private final Host defaultHost;
WildFlyUndertowHost(Host host) {
this.defaultHost = host;
}
@Override
public void validateEndpointURI(URI httpURI) {
// Camel HTTP endpoint port defaults are 0 or -1
boolean portMatched = httpURI.getPort() == 0 || httpURI.getPort() == -1;
// If a port was specified, verify that undertow has a listener configured for it
if (!portMatched) {
for (ListenerService> service : defaultHost.getServer().getListeners()) {
InjectedValue binding = service.getBinding();
if (binding != null) {
if (binding.getValue().getPort() == httpURI.getPort()) {
portMatched = true;
break;
}
}
}
}
IllegalStateAssertion.assertEquals("localhost", httpURI.getHost(), "Cannot bind to host other than 'localhost': " + httpURI);
IllegalStateAssertion.assertTrue(portMatched, "Cannot bind to specific port: " + httpURI);
}
@Override
public void registerHandler(HttpHandlerRegistrationInfo reginfo, HttpHandler handler) {
String path = reginfo.getUri().getPath();
if (path.contains(REST_PATH_PLACEHOLDER)) {
String pathPrefix = path.substring(0, path.indexOf(REST_PATH_PLACEHOLDER));
String remaining = path.substring(path.indexOf(REST_PATH_PLACEHOLDER));
PathTemplateHandler pathTemplateHandler = Handlers.pathTemplate();
pathTemplateHandler.add(remaining, handler);
defaultHost.registerHandler(pathPrefix, pathTemplateHandler);
} else {
if (reginfo.isMatchOnUriPrefix()) {
defaultHost.registerHandler(path, handler);
} else {
defaultHost.registerHandler(path, Handlers.path(handler));
}
}
}
@Override
public void unregisterHandler(HttpHandlerRegistrationInfo reginfo) {
String path = reginfo.getUri().getPath();
if (path.contains(REST_PATH_PLACEHOLDER)) {
defaultHost.unregisterHandler(path.substring(0, path.indexOf(REST_PATH_PLACEHOLDER)));
} else {
defaultHost.unregisterHandler(path);
}
}
}
class CamelUndertowEventListener extends AbstractUndertowEventListener {
@Override
public void onDeploymentStart(Deployment dep, Host host) {
runtimeState.addHttpContext(dep.getServletContext().getContextPath());
}
@Override
public void onDeploymentStop(Deployment dep, Host host) {
runtimeState.removeHttpContext(dep.getServletContext().getContextPath());
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy