/* * Copyright 2013 Red Hat Inc. and/or its affiliates and other contributors. * * 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. */ package org.switchyard.as7.extension.cluster; import java.io.File; import java.lang.reflect.InvocationTargetException; import java.net.InetAddress; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import javax.naming.NamingException; import javax.xml.namespace.QName; import org.apache.catalina.Container; import org.apache.catalina.Host; import org.apache.catalina.Loader; import org.apache.catalina.Wrapper; import org.apache.catalina.connector.Connector; import org.apache.catalina.core.StandardContext; import org.apache.catalina.startup.ContextConfig; import org.apache.coyote.http11.Http11Protocol; import org.apache.tomcat.InstanceManager; import org.jboss.as.server.ServerEnvironment; import org.jboss.as.web.deployment.WebCtxLoader; import org.jboss.logging.Logger; import org.switchyard.ServiceDomain; import org.switchyard.as7.extension.ExtensionLogger; import org.switchyard.as7.extension.ExtensionMessages; import org.switchyard.as7.extension.util.ServerUtil; import org.switchyard.component.sca.RemoteEndpointPublisher; import org.switchyard.component.sca.SwitchYardRemotingServlet; /** * Publishes standalone HTTP endpoint. */ public class RemoteEndpointListener implements RemoteEndpointPublisher { private static final String SERVER_TEMP_DIR = System.getProperty(ServerEnvironment.SERVER_TEMP_DIR); private static final String SERVLET_NAME = "SwitchYardRemotingServlet"; private static Logger _log = Logger.getLogger(RemoteEndpointListener.class); private String _contextName; private StandardContext _serverContext; private Map<QName, ServiceDomain> _services = new ConcurrentHashMap<QName, ServiceDomain>(); private boolean _disableRemoteTransaction = false; private boolean _started; /** * Constructor. */ public RemoteEndpointListener() { } @Override public void init(String context) { _contextName = context; } @Override public synchronized void start() throws Exception { // If the remote listener is already started, just return. if (_started) { return; } Host host = ServerUtil.getDefaultHost().getHost(); _serverContext = (StandardContext) host.findChild("/" + _contextName); if (_serverContext == null) { _serverContext = new StandardContext(); _serverContext.setPath("/" + _contextName); File docBase = new File(SERVER_TEMP_DIR, _contextName); if (!docBase.exists()) { if (!docBase.mkdirs()) { throw ExtensionMessages.MESSAGES.unableToCreateTempDirectory(docBase.getPath()); } } _serverContext.setDocBase(docBase.getPath()); _serverContext.addLifecycleListener(new ContextConfig()); final Loader loader = new WebCtxLoader(Thread.currentThread().getContextClassLoader()); loader.setContainer(host); _serverContext.setLoader(loader); _serverContext.setInstanceManager(new LocalInstanceManager()); Wrapper wrapper = _serverContext.createWrapper(); wrapper.setName(SERVLET_NAME); wrapper.setServletClass(SwitchYardRemotingServlet.class.getName()); wrapper.setLoadOnStartup(1); _serverContext.addChild(wrapper); _serverContext.addServletMapping("/*", SERVLET_NAME); host.addChild(_serverContext); _serverContext.create(); _serverContext.start(); SwitchYardRemotingServlet remotingServlet = (SwitchYardRemotingServlet) wrapper.getServlet(); remotingServlet.setEndpointPublisher(this); _log.info("Published Remote Service Endpoint " + _serverContext.getPath()); _started = true; } else { throw ExtensionMessages.MESSAGES.contextAlreadyExists(_contextName); } } @Override public synchronized void stop() throws Exception { if (_serverContext != null) { // Destroy the web context unless if it is default if (!_serverContext.getPath().equals("/")) { try { Container container = _serverContext.getParent(); container.removeChild(_serverContext); _serverContext.stop(); _serverContext.destroy(); _log.info("Destroyed HTTP context " + _serverContext.getPath()); } catch (Exception e) { ExtensionLogger.ROOT_LOGGER.unableToDestroyWebContext(_contextName, e); } } } } /** * Return the address. * * @return An address string */ public String getAddress() { String hostAddress = null; Connector connector = ServerUtil.getDefaultConnector(); if (connector.getProtocolHandler() instanceof Http11Protocol) { Http11Protocol protocol = (Http11Protocol) connector.getProtocolHandler(); InetAddress address = protocol.getAddress(); hostAddress = address.getHostAddress(); } else { ExtensionLogger.ROOT_LOGGER.unableToDetermineHostAddress(); hostAddress = ServerUtil.getDefaultHost().getHost().findAliases()[0]; } return connector.getScheme() + "://" + hostAddress + ":" + connector.getPort() + "/" + _contextName; } private static class LocalInstanceManager implements InstanceManager { LocalInstanceManager() { } @Override public Object newInstance(String className) throws IllegalAccessException, InvocationTargetException, NamingException, InstantiationException, ClassNotFoundException { return Class.forName(className).newInstance(); } @Override public Object newInstance(String fqcn, ClassLoader classLoader) throws IllegalAccessException, InvocationTargetException, NamingException, InstantiationException, ClassNotFoundException { return Class.forName(fqcn, false, classLoader).newInstance(); } @Override public Object newInstance(Class<?> c) throws IllegalAccessException, InvocationTargetException, NamingException, InstantiationException { return c.newInstance(); } @Override public void newInstance(Object o) throws IllegalAccessException, InvocationTargetException, NamingException { throw new IllegalStateException(); } @Override public void destroyInstance(Object o) throws IllegalAccessException, InvocationTargetException { } } @Override public void addService(QName serviceName, ServiceDomain domain) { _services.put(serviceName, domain); } @Override public void removeService(QName serviceName, ServiceDomain domain) { _services.remove(serviceName); } @Override public ServiceDomain getDomain(QName serviceName) { return _services.get(serviceName); } @Override public RemoteEndpointPublisher setDisableRemoteTransaction(boolean disable) { _disableRemoteTransaction = disable; return this; } @Override public boolean isDisableRemoteTransaction() { return _disableRemoteTransaction; } }