/** * 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.waveprotocol.box.server; import java.io.File; import java.util.Collection; import org.apache.commons.configuration.ConfigurationException; import org.swellrt.server.box.events.DeltaBasedEventSource; import org.swellrt.server.box.events.EventDispatcher; import org.swellrt.server.box.events.EventRule; import org.swellrt.server.box.events.EventsModule; import org.swellrt.server.box.events.dummy.DummyDispatcher; import org.swellrt.server.box.events.gcm.GCMDispatcher; import org.swellrt.server.box.events.http.HttpDispatcher; import org.swellrt.server.box.index.ModelIndexerDispatcher; import org.swellrt.server.box.index.ModelIndexerModule; import org.swellrt.server.box.servlet.EmailModule; import org.swellrt.server.box.servlet.SwellRtServlet; import org.waveprotocol.box.common.comms.WaveClientRpc.ProtocolWaveClientRpc; import org.waveprotocol.box.server.authentication.AccountStoreHolder; import org.waveprotocol.box.server.authentication.SessionManager; import org.waveprotocol.box.server.executor.ExecutorsModule; import org.waveprotocol.box.server.frontend.ClientFrontend; import org.waveprotocol.box.server.frontend.WaveClientRpcImpl; import org.waveprotocol.box.server.persistence.AccountStore; import org.waveprotocol.box.server.persistence.PersistenceException; import org.waveprotocol.box.server.persistence.PersistenceModule; import org.waveprotocol.box.server.persistence.SignerInfoStore; import org.waveprotocol.box.server.robots.agent.passwd.PasswordAdminRobot; import org.waveprotocol.box.server.robots.agent.passwd.PasswordRobot; import org.waveprotocol.box.server.robots.agent.registration.RegistrationRobot; import org.waveprotocol.box.server.robots.agent.welcome.WelcomeRobot; import org.waveprotocol.box.server.robots.passive.RobotsGateway; import org.waveprotocol.box.server.rpc.AttachmentInfoServlet; import org.waveprotocol.box.server.rpc.AttachmentServlet; import org.waveprotocol.box.server.rpc.AuthenticationServlet; import org.waveprotocol.box.server.rpc.WindowIdFilter; import org.waveprotocol.box.server.rpc.ServerRpcProvider; import org.waveprotocol.box.server.shutdown.ShutdownManager; import org.waveprotocol.box.server.shutdown.ShutdownPriority; import org.waveprotocol.box.server.shutdown.Shutdownable; import org.waveprotocol.box.server.stat.RequestScopeFilter; import org.waveprotocol.box.server.stat.StatuszServlet; import org.waveprotocol.box.server.stat.TimingFilter; import org.waveprotocol.box.server.waveserver.PerUserWaveViewBus; import org.waveprotocol.box.server.waveserver.PerUserWaveViewDistpatcher; import org.waveprotocol.box.server.waveserver.WaveBus; import org.waveprotocol.box.server.waveserver.WaveServerException; import org.waveprotocol.box.server.waveserver.WaveletProvider; import org.waveprotocol.box.stat.StatService; import org.waveprotocol.wave.crypto.CertPathStore; import org.waveprotocol.wave.federation.FederationTransport; import org.waveprotocol.wave.federation.noop.NoOpFederationModule; import org.waveprotocol.wave.model.wave.ParticipantIdUtil; import org.waveprotocol.wave.util.logging.Log; import com.google.inject.AbstractModule; import com.google.inject.Guice; import com.google.inject.Injector; import com.google.inject.Key; import com.google.inject.Module; import com.google.inject.name.Names; import com.typesafe.config.Config; import com.typesafe.config.ConfigFactory; /** * Wave Server entrypoint. */ public class ServerMain { private static final Log LOG = Log.get(ServerMain.class); public static void main(String... args) { try { Module coreSettings = new AbstractModule() { @Override protected void configure() { Config config = ConfigFactory.load().withFallback( ConfigFactory.parseFile(new File("config/application.conf")).withFallback( ConfigFactory.parseFile(new File("config/reference.conf")))); bind(Config.class).toInstance(config); bind(Key.get(String.class, Names.named(CoreSettingsNames.WAVE_SERVER_DOMAIN))) .toInstance(config.getString("core.wave_server_domain")); } }; run(coreSettings); } catch (PersistenceException e) { LOG.severe("PersistenceException when running server:", e); } catch (ConfigurationException e) { LOG.severe("ConfigurationException when running server:", e); } catch (WaveServerException e) { LOG.severe("WaveServerException when running server:", e); } } public static void run(Module coreSettings) throws PersistenceException, ConfigurationException, WaveServerException { Injector injector = Guice.createInjector(coreSettings); Module profilingModule = injector.getInstance(StatModule.class); ExecutorsModule executorsModule = injector.getInstance(ExecutorsModule.class); injector = injector.createChildInjector(profilingModule, executorsModule); Config config = injector.getInstance(Config.class); Module serverModule = injector.getInstance(ServerModule.class); Module federationModule = buildFederationModule(injector); // Module robotApiModule = new RobotApiModule(); PersistenceModule persistenceModule = injector.getInstance(PersistenceModule.class); // Module searchModule = injector.getInstance(SearchModule.class); Module modelIndexerModule = injector.getInstance(ModelIndexerModule.class); // SwellRT Module eventsModule = injector.getInstance(EventsModule.class); // SwellRT // Module profileFetcherModule = injector.getInstance(ProfileFetcherModule.class); Module emailModule = injector.getInstance(EmailModule.class); // SwellRT // injector = injector.createChildInjector(serverModule, persistenceModule, robotApiModule, // federationModule, searchModule, profileFetcherModule); injector = injector.createChildInjector(serverModule, persistenceModule, federationModule, eventsModule, modelIndexerModule, emailModule); ServerRpcProvider server = injector.getInstance(ServerRpcProvider.class); WaveBus waveBus = injector.getInstance(WaveBus.class); String domain = config.getString("core.wave_server_domain"); if (!ParticipantIdUtil.isDomainAddress(ParticipantIdUtil.makeDomainAddress(domain))) { throw new WaveServerException("Invalid wave domain: " + domain); } initializeServer(injector, domain); initializeServlets(server, config); // initializeRobotAgents(server); // initializeRobots(injector, waveBus); initializeFrontend(injector, server); initializeFederation(injector); // initializeSearch(injector, waveBus); initializeShutdownHandler(server); initializeSwellRt(injector, waveBus); LOG.info("Starting server"); server.startWebSocketServer(injector); } private static Module buildFederationModule(Injector settingsInjector) throws ConfigurationException { return settingsInjector.getInstance(NoOpFederationModule.class); } private static void initializeServer(Injector injector, String waveDomain) throws PersistenceException, WaveServerException { AccountStore accountStore = injector.getInstance(AccountStore.class); accountStore.initializeAccountStore(); AccountStoreHolder.init(accountStore, waveDomain); // Initialize the SignerInfoStore. CertPathStore certPathStore = injector.getInstance(CertPathStore.class); if (certPathStore instanceof SignerInfoStore) { ((SignerInfoStore)certPathStore).initializeSignerInfoStore(); } // Initialize the server. WaveletProvider waveServer = injector.getInstance(WaveletProvider.class); waveServer.initialize(); } private static void initializeServlets(ServerRpcProvider server, Config config) { // server.addServlet("/gadget/gadgetlist", GadgetProviderServlet.class); server.addServlet(AttachmentServlet.ATTACHMENT_URL + "/*", AttachmentServlet.class); server.addServlet(AttachmentServlet.THUMBNAIL_URL + "/*", AttachmentServlet.class); server.addServlet(AttachmentInfoServlet.ATTACHMENTS_INFO_URL, AttachmentInfoServlet.class); server.addServlet(SessionManager.SIGN_IN_URL, AuthenticationServlet.class); // server.addServlet("/auth/signout*", SignOutServlet.class); // server.addServlet("/auth/register*", UserRegistrationServlet.class); // server.addServlet("/locale/*", LocaleServlet.class); // server.addServlet("/fetch/*", FetchServlet.class); // server.addServlet("/search/*", SearchServlet.class); // server.addServlet("/notification/*", NotificationServlet.class); // server.addServlet("/robot/dataapi", DataApiServlet.class); // server.addServlet(DataApiOAuthServlet.DATA_API_OAUTH_PATH + "/*", // DataApiOAuthServlet.class); // server.addServlet("/robot/dataapi/rpc", DataApiServlet.class); // server.addServlet("/robot/register/*", RobotRegistrationServlet.class); // server.addServlet("/robot/rpc", ActiveApiServlet.class); // server.addServlet("/webclient/remote_logging", // RemoteLoggingServiceImpl.class); // server.addServlet("/profile/*", FetchProfilesServlet.class); // server.addServlet("/waveref/*", WaveRefServlet.class); // String gadgetServerHostname = config.getString("core.gadget_server_hostname"); // int gadgetServerPort = config.getInt("core.gadget_server_port"); // LOG.info("Starting GadgetProxyServlet for " + gadgetServerHostname + ":" + gadgetServerPort); // server.addTransparentProxy("/gadgets/*", // "http://" + gadgetServerHostname + ":" + gadgetServerPort + "/gadgets", "/gadgets"); // // server.addServlet("/", WaveClientServlet.class); // Profiling server.addFilter("/*", RequestScopeFilter.class); boolean enableProfiling = config.getBoolean("core.enable_profiling"); if (enableProfiling) { server.addFilter("/*", TimingFilter.class); server.addServlet(StatService.STAT_URL, StatuszServlet.class); } // DSWG experimental // server.addServlet("/shared/*", DSFileServlet.class); // SwellRt server.addServlet("/swell/*", SwellRtServlet.class); } private static void initializeRobots(Injector injector, WaveBus waveBus) { RobotsGateway robotsGateway = injector.getInstance(RobotsGateway.class); waveBus.subscribe(robotsGateway); } private static void initializeRobotAgents(ServerRpcProvider server) { server.addServlet(PasswordRobot.ROBOT_URI + "/*", PasswordRobot.class); server.addServlet(PasswordAdminRobot.ROBOT_URI + "/*", PasswordAdminRobot.class); server.addServlet(WelcomeRobot.ROBOT_URI + "/*", WelcomeRobot.class); server.addServlet(RegistrationRobot.ROBOT_URI + "/*", RegistrationRobot.class); } private static void initializeFrontend(Injector injector, ServerRpcProvider server) throws WaveServerException { ClientFrontend frontend = injector.getInstance(ClientFrontend.class); ProtocolWaveClientRpc.Interface rpcImpl = WaveClientRpcImpl.create(frontend, false); server.registerService(ProtocolWaveClientRpc.newReflectiveService(rpcImpl)); } private static void initializeFederation(Injector injector) { FederationTransport federationManager = injector.getInstance(FederationTransport.class); federationManager.startFederation(); } private static void initializeSearch(Injector injector, WaveBus waveBus) throws WaveServerException { PerUserWaveViewDistpatcher waveViewDistpatcher = injector.getInstance(PerUserWaveViewDistpatcher.class); PerUserWaveViewBus.Listener listener = injector.getInstance(PerUserWaveViewBus.Listener.class); waveViewDistpatcher.addListener(listener); waveBus.subscribe(waveViewDistpatcher); // WaveIndexer waveIndexer = injector.getInstance(WaveIndexer.class); // waveIndexer.remakeIndex(); } private static void initializeShutdownHandler(final ServerRpcProvider server) { ShutdownManager.getInstance().register(new Shutdownable() { @Override public void shutdown() throws Exception { server.stopServer(); } }, ServerMain.class.getSimpleName(), ShutdownPriority.Server); } private static void initializeSwellRt(Injector injector, WaveBus waveBus) { // Initialize Indexer ModelIndexerDispatcher indexerDispatcher = injector.getInstance(ModelIndexerDispatcher.class); // try { // indexerDispatcher.initialize(); // } catch (WaveServerException e) { // LOG.warning("Error initializating SwellRtIndexerDispatcher", e); // } waveBus.subscribe(indexerDispatcher); // Initialize Events // TODO get rules as inject. dependency Collection<EventRule> rules = EventRule.fromFile(System.getProperty("event-rules.config.file", "config/event-rules.config")); EventDispatcher eventDispatcher = injector.getInstance(EventDispatcher.class); eventDispatcher.setRules(rules); eventDispatcher.subscribe(injector.getInstance(DummyDispatcher.class), DummyDispatcher.NAME); eventDispatcher.subscribe(injector.getInstance(GCMDispatcher.class), GCMDispatcher.NAME); eventDispatcher.subscribe(injector.getInstance(HttpDispatcher.class), HttpDispatcher.NAME); DeltaBasedEventSource eventSource = injector.getInstance(DeltaBasedEventSource.class); waveBus.subscribe(eventSource); } }