/* (c) 2016 Open Source Geospatial Foundation - all rights reserved
* This code is licensed under the GPL 2.0 license, available at the root
* application directory.
*/
package org.geoserver.wps.remote.plugin.server;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.apache.vysper.stanzasession.StanzaSessionFactory;
import org.apache.vysper.storage.StorageProviderRegistry;
import org.apache.vysper.xmpp.addressing.Entity;
import org.apache.vysper.xmpp.addressing.EntityImpl;
import org.apache.vysper.xmpp.authorization.AccountManagement;
import org.apache.vysper.xmpp.authorization.Anonymous;
import org.apache.vysper.xmpp.authorization.External;
import org.apache.vysper.xmpp.authorization.Plain;
import org.apache.vysper.xmpp.authorization.SASLMechanism;
import org.apache.vysper.xmpp.cryptography.BogusTrustManagerFactory;
import org.apache.vysper.xmpp.cryptography.FileBasedTLSContextFactory;
import org.apache.vysper.xmpp.delivery.OfflineStanzaReceiver;
import org.apache.vysper.xmpp.delivery.StanzaRelayBroker;
import org.apache.vysper.xmpp.delivery.inbound.DeliveringExternalInboundStanzaRelay;
import org.apache.vysper.xmpp.delivery.inbound.DeliveringInternalInboundStanzaRelay;
import org.apache.vysper.xmpp.modules.Module;
import org.apache.vysper.xmpp.modules.extension.xep0045_muc.MUCModule;
import org.apache.vysper.xmpp.modules.extension.xep0045_muc.model.Conference;
import org.apache.vysper.xmpp.modules.extension.xep0045_muc.model.Room;
import org.apache.vysper.xmpp.modules.extension.xep0045_muc.model.RoomType;
import org.apache.vysper.xmpp.modules.extension.xep0133_service_administration.ServiceAdministrationModule;
import org.apache.vysper.xmpp.modules.extension.xep0160_offline_storage.OfflineStorageProvider;
import org.apache.vysper.xmpp.modules.roster.RosterModule;
import org.apache.vysper.xmpp.modules.servicediscovery.ServiceDiscoveryModule;
import org.apache.vysper.xmpp.protocol.HandlerDictionary;
import org.apache.vysper.xmpp.server.DefaultServerRuntimeContext;
import org.apache.vysper.xmpp.server.Endpoint;
import org.apache.vysper.xmpp.server.ServerFeatures;
import org.apache.vysper.xmpp.server.ServerRuntimeContext;
import org.apache.vysper.xmpp.state.resourcebinding.ResourceRegistry;
import org.geoserver.platform.GeoServerExtensions;
import org.geoserver.platform.GeoServerResourceLoader;
import org.geoserver.platform.resource.Resources;
import org.geoserver.wps.remote.RemoteProcessFactoryConfiguration;
import org.geoserver.wps.remote.RemoteProcessFactoryConfigurationWatcher;
import org.springframework.core.io.Resource;
/**
* @author Alessio Fabiani, GeoSolutions S.A.S.
*
*/
public class XMPPServerEmbedded {
/**
* Common logger for test cases
*/
static final Logger LOGGER =
org.geotools.util.logging.Logging.getLogger(XMPPServerEmbedded.class);
private final List<SASLMechanism> saslMechanisms = new ArrayList<SASLMechanism>();
private String serverDomain;
private DefaultServerRuntimeContext serverRuntimeContext;
private StorageProviderRegistry storageProviderRegistry;
private RemoteProcessFactoryConfigurationWatcher remoteProcessFactoryConfigurationWatcher;
private RemoteProcessFactoryConfiguration configuration;
private final List<Module> listOfModules = new ArrayList<Module>();
private File certificateFile = null;
private String certificatePassword = null;
private Collection<Endpoint> endpoints = new ArrayList<Endpoint>();
public XMPPServerEmbedded(RemoteProcessFactoryConfigurationWatcher remoteProcessFactoryConfigurationWatcher) {
this.serverDomain = remoteProcessFactoryConfigurationWatcher.getConfiguration().get("xmpp_domain");
this.remoteProcessFactoryConfigurationWatcher = remoteProcessFactoryConfigurationWatcher;
this.configuration = this.remoteProcessFactoryConfigurationWatcher.getConfiguration();
// default list of SASL mechanisms
saslMechanisms.add(new Plain());
saslMechanisms.add(new External());
saslMechanisms.add(new Anonymous());
}
public void setCertificateFile(Resource certificateFile) throws IOException {
this.certificateFile = certificateFile.getFile();
}
public void setCertificatePassword(String certificatePassword) {
this.certificatePassword = certificatePassword;
}
public void setEndpoints(Collection<Endpoint> endpoints) {
this.endpoints = endpoints;
}
public void setModules(Collection<Module> modules) {
listOfModules.addAll(modules);
}
public void setStorageProviderRegistry(StorageProviderRegistry storageProviderRegistry) {
this.storageProviderRegistry = storageProviderRegistry;
}
public ServerRuntimeContext getServerRuntimeContext() {
return serverRuntimeContext;
}
public void addEndpoint(Endpoint endpoint) {
endpoints.add(endpoint);
}
public void init() throws Exception {
final String xmppDomain = configuration.get("xmpp_domain");
final String xmppUserName = configuration.get("xmpp_manager_username");
final String xmppUserPassword = configuration.get("xmpp_manager_password");
final String xmppServerEmbedded = configuration.get("xmpp_server_embedded");
checkSecured(configuration);
if (xmppServerEmbedded != null && Boolean.valueOf(xmppServerEmbedded.trim())) {
// /
LOGGER.info("initializing embedded vysper server...");
// Admin User
final Entity adminJID = EntityImpl.parseUnchecked(xmppUserName + "@" + xmppDomain);
final AccountManagement accountManagement =
(AccountManagement) storageProviderRegistry.retrieve(AccountManagement.class);
if (!accountManagement.verifyAccountExists(adminJID)) {
accountManagement.addUser(adminJID, xmppUserPassword);
}
// Add Endpoints
if (endpoints == null || endpoints.size() == 0) {
XMPPBoshEndpoint boshEndpoint = new XMPPBoshEndpoint();
boshEndpoint.setPort(Integer.parseInt(configuration.get("xmpp_port")));
if (certificateFile != null && certificatePassword != null) {
boshEndpoint.setSSLCertificateKeystore(certificateFile.getAbsolutePath());
boshEndpoint.setSSLCertificateKeystorePassword(certificatePassword);
boshEndpoint.setSSLEnabled(true);
} else {
boshEndpoint.setSSLEnabled(false);
}
addEndpoint(boshEndpoint);
}
addEndpoint(new StanzaSessionFactory());
// Start Server
List<HandlerDictionary> dictionaries = new ArrayList<HandlerDictionary>();
addCoreDictionaries(dictionaries);
ResourceRegistry resourceRegistry = new ResourceRegistry();
EntityImpl serverEntity = new EntityImpl(null, serverDomain, null);
OfflineStanzaReceiver offlineReceiver = (OfflineStanzaReceiver) storageProviderRegistry.retrieve(OfflineStorageProvider.class);
DeliveringInternalInboundStanzaRelay internalStanzaRelay = new DeliveringInternalInboundStanzaRelay(serverEntity,
resourceRegistry, accountManagement,offlineReceiver);
DeliveringExternalInboundStanzaRelay externalStanzaRelay = new DeliveringExternalInboundStanzaRelay();
StanzaRelayBroker stanzaRelayBroker = new StanzaRelayBroker();
stanzaRelayBroker.setInternalRelay(internalStanzaRelay);
stanzaRelayBroker.setExternalRelay(externalStanzaRelay);
ServerFeatures serverFeatures = new ServerFeatures();
serverFeatures.setAuthenticationMethods(saslMechanisms);
serverRuntimeContext = new DefaultServerRuntimeContext(serverEntity, stanzaRelayBroker, serverFeatures,
dictionaries, resourceRegistry);
serverRuntimeContext.setStorageProviderRegistry(storageProviderRegistry);
serverRuntimeContext.addModule(new ServiceDiscoveryModule());
serverRuntimeContext.addModule(new RosterModule());
stanzaRelayBroker.setServerRuntimeContext(serverRuntimeContext);
internalStanzaRelay.setServerRuntimeContext(serverRuntimeContext);
externalStanzaRelay.setServerRuntimeContext(serverRuntimeContext);
// Add SSL Certificates
if (certificateFile != null && certificatePassword != null) {
FileBasedTLSContextFactory tlsContextFactory = new FileBasedTLSContextFactory(certificateFile);
tlsContextFactory.setPassword(certificatePassword);
tlsContextFactory.setTrustManagerFactory(new BogusTrustManagerFactory());
serverRuntimeContext.setTlsContextFactory(tlsContextFactory);
}
// /
start();
// Add Modules
if (listOfModules != null) {
for (Module module : listOfModules) {
addModule(module);
}
}
final ServiceAdministrationModule serviceAdministrationModule = new ServiceAdministrationModule();
// unless admin user account with a secure password is added, this will be not become effective
serviceAdministrationModule.setAddAdminJIDs(Arrays.asList(adminJID));
addModule(serviceAdministrationModule);
// add management channels and rooms
Conference conference = new Conference(configuration.get("xmpp_bus"));
Entity managementRoomJID = EntityImpl.parseUnchecked(configuration.get("xmpp_management_channel") + "@" + configuration.get("xmpp_bus") + "." + xmppDomain);
Room management = conference.createRoom(managementRoomJID, configuration.get("xmpp_management_channel"), RoomType.PasswordProtected);
management.setPassword(configuration.get("xmpp_management_channel_pwd"));
final String[] serviceChannels = configuration.get("xmpp_service_channels").split(",");
if (serviceChannels != null) {
for (String channel : serviceChannels) {
Entity serviceRoomJID = EntityImpl.parseUnchecked(channel + "@" + configuration.get("xmpp_bus") + "." + xmppDomain);
conference.createRoom(serviceRoomJID, channel, RoomType.Public);
}
}
addModule(new MUCModule(configuration.get("xmpp_bus"), conference));
// /
Thread.sleep(3000);
LOGGER.info("embedded vysper server is running...");
}
}
public void start() throws Exception {
if (endpoints.size() == 0)
throw new IllegalStateException("server must have at least one endpoint");
for (Endpoint endpoint : endpoints) {
endpoint.setServerRuntimeContext(serverRuntimeContext);
endpoint.start();
}
}
public void stop() {
for (Endpoint endpoint : endpoints) {
endpoint.stop();
}
serverRuntimeContext.getServerConnectorRegistry().close();
}
public void addModule(Module module) {
serverRuntimeContext.addModule(module);
}
private void addCoreDictionaries(List<HandlerDictionary> dictionaries) {
dictionaries.add(new org.apache.vysper.xmpp.modules.core.base.BaseStreamStanzaDictionary());
dictionaries.add(new org.apache.vysper.xmpp.modules.core.starttls.StartTLSStanzaDictionary());
dictionaries.add(new org.apache.vysper.xmpp.modules.core.sasl.SASLStanzaDictionary());
dictionaries.add(new org.apache.vysper.xmpp.modules.core.bind.BindResourceDictionary());
dictionaries.add(new org.apache.vysper.xmpp.modules.core.session.SessionStanzaDictionary());
dictionaries.add(new org.apache.vysper.xmpp.modules.core.compatibility.jabber_iq_auth.JabberIQAuthDictionary());
}
private void checkSecured(RemoteProcessFactoryConfiguration configuration) {
final String xmppServerEmbeddedSecure = configuration.get("xmpp_server_embedded_secure");
final String xmppServerEmbeddedCertFile = configuration.get("xmpp_server_embedded_certificate_file");
final String xmppServerEmbeddedCertPwd = configuration.get("xmpp_server_embedded_certificate_password");
if (xmppServerEmbeddedSecure != null && Boolean.valueOf(xmppServerEmbeddedSecure.trim())) {
// Override XML properties
if (xmppServerEmbeddedCertFile != null && xmppServerEmbeddedCertPwd != null) {
final org.geoserver.platform.resource.Resource certFileResource =
Resources.fromURL(xmppServerEmbeddedCertFile.trim());
if (certFileResource != null) {
this.certificateFile = certFileResource.file();
this.certificatePassword = xmppServerEmbeddedCertPwd.trim();
} else {
// Get the Resource loader
GeoServerResourceLoader loader = GeoServerExtensions.bean(GeoServerResourceLoader.class);
try {
// Copy the default property file into the data directory
//URL url = RemoteProcessFactoryConfigurationWatcher.class.getResource(xmppServerEmbeddedCertFile.trim());
//if (url != null) {
this.certificateFile = loader.createFile(xmppServerEmbeddedCertFile.trim());
loader.copyFromClassPath(xmppServerEmbeddedCertFile.trim(), this.certificateFile/*,
RemoteProcessFactoryConfigurationWatcher.class*/);
//}
this.certificateFile = loader.find(xmppServerEmbeddedCertFile.trim());
this.certificatePassword = xmppServerEmbeddedCertPwd.trim();
} catch (IOException e) {
if (LOGGER.isLoggable(Level.WARNING)) {
LOGGER.log(Level.WARNING, e.getMessage(), e);
}
}
}
}
}
}
}