blob: 5b5b43cec22c4ae695b38f721fb649a11a7ae511 [file] [log] [blame]
/*
* 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.protocol.StanzaProcessor;
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.
* This endpoint creates an (embedded) servlet container answering HTTP.
* <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;
private StanzaProcessor stanzaProcessor;
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;
}
@Override
public void setStanzaProcessor(StanzaProcessor stanzaProcessor) {
this.stanzaProcessor = stanzaProcessor;
}
/**
* 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 #setSSLCertificateKeystore(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.inject(serverRuntimeContext, stanzaProcessor);
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);
}
}
}