package nl.topicus.konijn.xmpp;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import nl.topicus.konijn.xmpp.authorization.AccountManagementBridge;
import nl.topicus.konijn.xmpp.modules.bind.CustomBindIQDictionary;
import nl.topicus.konijn.xmpp.modules.custom.CustomMessageDictionary;
import nl.topicus.konijn.xmpp.modules.md5digest.DigestMD5StanzaDictionary;
import nl.topicus.konijn.xmpp.modules.session.CustomSessionDictionary;
import nl.topicus.konijn.xmpp.modules.sources.VioletSourcesDictionary;
import nl.topicus.konijn.xmpp.util.BunniePresenceCache;
import nl.topicus.konijn.xmpp.util.CustomResourceRegistry;
import nl.topicus.konijn.xmpp.util.CustomStanzaRelayBroker;
import nl.topicus.konijn.xmpp.util.MyServerRuntimeContext;
import org.apache.vysper.storage.StorageProviderRegistry;
import org.apache.vysper.xmpp.addressing.EntityImpl;
import org.apache.vysper.xmpp.authentication.SASLMechanism;
import org.apache.vysper.xmpp.cryptography.BogusTrustManagerFactory;
import org.apache.vysper.xmpp.cryptography.InputStreamBasedTLSContextFactory;
import org.apache.vysper.xmpp.delivery.OfflineStanzaReceiver;
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.core.base.BaseStreamStanzaDictionary;
import org.apache.vysper.xmpp.modules.core.compatibility.jabber_iq_auth.JabberIQAuthDictionary;
import org.apache.vysper.xmpp.modules.core.starttls.StartTLSStanzaDictionary;
import org.apache.vysper.xmpp.modules.extension.xep0077_inbandreg.InBandRegistrationModule;
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.Endpoint;
import org.apache.vysper.xmpp.server.ServerFeatures;
import org.apache.vysper.xmpp.server.ServerRuntimeContext;
import org.apache.wicket.Application;
/**
* Custom XMPPServer entity. The original one does not give us room to edit the
* dictionary and other important parts we need to re-invent without touching
* the base code.
*
* @author Joost Limburg
*
*/
public class MyXMPPServer {
private final List<SASLMechanism> saslMechanisms = new ArrayList<SASLMechanism>();
private String serverDomain;
private MyServerRuntimeContext serverRuntimeContext;
private StorageProviderRegistry storageProviderRegistry;
private InputStream tlsCertificate;
private String tlsCertificatePassword;
private Application app;
private String tlsKeyStoreType;
private final List<Endpoint> endpoints = new ArrayList<Endpoint>();
private final List<Module> initialModules = new ArrayList<Module>();
public MyXMPPServer(String domain, Application app) {
this.serverDomain = domain;
this.setApp(app);
// default list of SASL mechanisms
// saslMechanisms.add(new Plain());
// add default modules
initialModules.add(new InBandRegistrationModule());
initialModules.add(new ServiceDiscoveryModule());
initialModules.add(new RosterModule());
}
public void setSASLMechanisms(List<SASLMechanism> validMechanisms) {
saslMechanisms.addAll(validMechanisms);
}
public void setStorageProviderRegistry(
StorageProviderRegistry storageProviderRegistry) {
this.storageProviderRegistry = storageProviderRegistry;
}
public void setTLSCertificateInfo(File certificate, String password)
throws FileNotFoundException {
tlsCertificate = new FileInputStream(certificate);
tlsCertificatePassword = password;
}
public void setTLSCertificateInfo(InputStream certificate, String password) {
setTLSCertificateInfo(certificate, password, null);
}
public void setTLSCertificateInfo(InputStream certificate, String password,
String keyStoreType) {
tlsCertificate = certificate;
tlsCertificatePassword = password;
tlsKeyStoreType = keyStoreType;
}
public void addEndpoint(Endpoint endpoint) {
endpoints.add(endpoint);
}
public void start() throws Exception {
BogusTrustManagerFactory bogusTrustManagerFactory = new BogusTrustManagerFactory();
InputStreamBasedTLSContextFactory tlsContextFactory = new InputStreamBasedTLSContextFactory(
tlsCertificate);
tlsContextFactory.setPassword(tlsCertificatePassword);
tlsContextFactory.setTrustManagerFactory(bogusTrustManagerFactory);
if (tlsKeyStoreType != null) {
tlsContextFactory.setKeyStoreType(tlsKeyStoreType);
}
List<HandlerDictionary> dictionaries = new ArrayList<HandlerDictionary>();
addCoreDictionaries(dictionaries);
CustomResourceRegistry resourceRegistry = new CustomResourceRegistry();
EntityImpl serverEntity = new EntityImpl(null, serverDomain, null);
AccountManagementBridge accountManagement = (AccountManagementBridge) storageProviderRegistry
.retrieve(AccountManagementBridge.class);
OfflineStanzaReceiver offlineReceiver = (OfflineStanzaReceiver) storageProviderRegistry
.retrieve(OfflineStorageProvider.class);
DeliveringInternalInboundStanzaRelay internalStanzaRelay = new DeliveringInternalInboundStanzaRelay(
serverEntity, resourceRegistry, accountManagement,
offlineReceiver);
DeliveringExternalInboundStanzaRelay externalStanzaRelay = new DeliveringExternalInboundStanzaRelay();
CustomStanzaRelayBroker stanzaRelayBroker = new CustomStanzaRelayBroker();
stanzaRelayBroker.setInternalRelay(internalStanzaRelay);
stanzaRelayBroker.setExternalRelay(externalStanzaRelay);
ServerFeatures serverFeatures = new ServerFeatures();
serverFeatures.setAuthenticationMethods(saslMechanisms);
serverRuntimeContext = new MyServerRuntimeContext(serverEntity,
stanzaRelayBroker, serverFeatures, dictionaries,
resourceRegistry);
serverRuntimeContext.setApplication(app);
serverRuntimeContext.setPresenceCache(new BunniePresenceCache());
serverRuntimeContext
.setStorageProviderRegistry(storageProviderRegistry);
serverRuntimeContext.setTlsContextFactory(tlsContextFactory);
for (Module module : initialModules) {
serverRuntimeContext.addModule(module);
}
stanzaRelayBroker.setServerRuntimeContext(serverRuntimeContext);
internalStanzaRelay.setServerRuntimeContext(serverRuntimeContext);
externalStanzaRelay.setServerRuntimeContext(serverRuntimeContext);
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();
}
for (Module module : serverRuntimeContext.getModules()) {
try {
module.close();
} catch (RuntimeException e) {
// ignore
}
}
serverRuntimeContext.getServerConnectorRegistry().close();
}
public void addModule(Module module) {
if (serverRuntimeContext != null) {
serverRuntimeContext.addModule(module);
} else {
initialModules.add(module);
}
}
private void addCoreDictionaries(List<HandlerDictionary> dictionaries) {
dictionaries.add(new BaseStreamStanzaDictionary());
dictionaries.add(new StartTLSStanzaDictionary());
dictionaries.add(new DigestMD5StanzaDictionary());
dictionaries.add(new CustomBindIQDictionary());
dictionaries.add(new VioletSourcesDictionary());
dictionaries.add(new CustomSessionDictionary());
dictionaries.add(new JabberIQAuthDictionary());
dictionaries.add(new CustomMessageDictionary());
}
public ServerRuntimeContext getServerRuntimeContext() {
return serverRuntimeContext;
}
public void setApp(Application app) {
this.app = app;
}
public Application getApp() {
return app;
}
}