/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you 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.apache.vysper.xmpp.extension.xep0124; import java.io.IOException; import java.util.List; import org.apache.vysper.xmpp.server.Endpoint; import org.apache.vysper.xmpp.server.ServerRuntimeContext; import org.eclipse.jetty.server.Connector; import org.eclipse.jetty.server.Handler; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.server.nio.SelectChannelConnector; import org.eclipse.jetty.server.ssl.SslSelectChannelConnector; import org.eclipse.jetty.servlet.ServletContextHandler; import org.eclipse.jetty.servlet.ServletHolder; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * Allows HTTP clients to communicate via the BOSH protocol with Vysper. * <p> * See http://xmpp.org/extensions/xep-0124.html and * http://xmpp.org/extensions/xep-0206.html * * @author The Apache MINA Project (dev@mina.apache.org) */ public class BoshEndpoint implements Endpoint { protected final static Logger logger = LoggerFactory.getLogger(BoshEndpoint.class); protected ServerRuntimeContext serverRuntimeContext; protected int port = 8080; protected Server server; protected boolean isSSLEnabled; protected String sslKeystorePath; protected String sslKeystorePassword; protected List<String> accessControlAllowOrigin; protected String contextPath = "/"; public void setServerRuntimeContext(ServerRuntimeContext serverRuntimeContext) { this.serverRuntimeContext = serverRuntimeContext; } /** * Setter for the listen port * @param port */ public void setPort(int port) { this.port = port; } /** * Configures the SSL keystore * <p> * Required if SSL is enabled. Also, setting the keystore password is * required. * @see #setSSLCertificateKeystorePassword * @param keystorePath the path to the Java keystore */ public void setSSLCertificateKeystore(String keystorePath) { sslKeystorePath = keystorePath; } /** * Configures the SSL keystore password. * <p> * Required if SSL is enabled. Also, the keystore must be set using * {@link #setSSLCertificateKeystore(String)} } * The password is used both for accessing the keystore and for recovering * the key from the keystore. The unique password is a limitation, you * cannot use different passwords for the keystore and for the key. * * @param password the password used as the keystore password and also used * when recovering the key from the keystore */ public void setSSLCertificateKeystorePassword(String password) { sslKeystorePassword = password; } /** * Enables/disables SSL for this endpoint. * <p> * If SSL is enabled it requires SSL certificate information that can be * configured with {@link #setSSLCertificateInfo(String, String)} * @param value */ public void setSSLEnabled(boolean value) { isSSLEnabled = value; } /** * Get the list of domains allowed to access this endpoint * @return The list of allowed domains */ public List<String> getAccessControlAllowOrigin() { return accessControlAllowOrigin; } /** * Set the list of domains allowed to access this endpoint * @param accessControlAllowOrigin The list of allowed domains */ public void setAccessControlAllowOrigin(List<String> accessControlAllowOrigin) { this.accessControlAllowOrigin = accessControlAllowOrigin; } /** * Determines the context URI where the BOSH transport will be accessible. * The default is as 'root context' under '/'. * @param contextPath */ public void setContextPath(String contextPath) { if (contextPath == null) contextPath = "/"; this.contextPath = contextPath; } /** * create a basic Jetty server including a connector on the configured port * override in subclass to create a different kind of setup or to reuse an existing instance * @return */ protected Server createJettyServer() { Server server = new Server(); Connector connector; if (isSSLEnabled) { SslSelectChannelConnector sslConnector = new SslSelectChannelConnector(); sslConnector.setKeystore(sslKeystorePath); sslConnector.setPassword(sslKeystorePassword); sslConnector.setKeyPassword(sslKeystorePassword); connector = sslConnector; } else { connector = new SelectChannelConnector(); } connector.setPort(port); server.setConnectors(new Connector[] { connector }); return server; } /** * create handler for BOSH. * for a different handler setup, override in a subclass. * for more than one handler, add them to a org.eclipse.jetty.server.handler.ContextHandlerCollection * and return the collection * @return */ protected Handler createHandler() { ServletContextHandler boshContext = new ServletContextHandler(ServletContextHandler.SESSIONS); boshContext.setContextPath(contextPath); BoshServlet boshServlet = new BoshServlet(); boshServlet.setServerRuntimeContext(serverRuntimeContext); boshServlet.setAccessControlAllowOrigin(accessControlAllowOrigin); boshContext.addServlet(new ServletHolder(boshServlet), "/"); return boshContext; } /** * @throws IOException * @throws RuntimeException a wrapper of the possible * {@link java.lang.Exception} that Jetty can throw at start-up */ public void start() throws IOException { server = createJettyServer(); Handler handler = createHandler(); server.setHandler(handler); try { server.start(); } catch (Exception e) { throw new RuntimeException(e); } } public void stop() { try { server.stop(); } catch (Exception e) { logger.warn("Could not stop the Jetty server", e); } } }