// Copyright © 2012-2020 VLINGO LABS. All rights reserved. // // This Source Code Form is subject to the terms of the // Mozilla Public License, v. 2.0. If a copy of the MPL // was not distributed with this file, You can obtain // one at https://mozilla.org/MPL/2.0/. package io.vlingo.http.resource; import io.vlingo.actors.ActorInstantiator; import io.vlingo.actors.Definition; import io.vlingo.actors.Stage; import io.vlingo.actors.Stoppable; import io.vlingo.common.Completes; import io.vlingo.http.Filters; import io.vlingo.http.resource.Configuration.Sizing; import io.vlingo.http.resource.Configuration.Timing; import io.vlingo.wire.channel.RefreshableSelector; /** * The protocol of the HTTP {@code Server}, as well as factory methods for starting it. * The factory methods will initialize the vlingo-wire {@code RefreshableSelector} as * non-refreshing unless you initialize if prior to starting the {@code Server}. * <p> * NOTE: Override the {@code Server} initialization of RefreshableSelector initialization * by using the {@code withCountedThreshold()} count-based refreshing initialization or the * {@code withTimedThreshold()} time-based refreshing initialization prior to starting the * {@code Server}. This may be done just following the {@code World} start up. */ public interface Server extends Stoppable { public static Server startWith(final Stage stage) { return startWith(stage, Properties.properties); } /** * Answer a new {@code Server} with the given configuration and characteristics. * @param stage the Stage in which the Server lives * @param properties the java.util.Properties with properties named per vlingo-http.properties * @return Server */ public static Server startWith(final Stage stage, java.util.Properties properties) { final Configuration configuration = Configuration.defineWith(properties); final Resources resources = Loader.loadResources(properties); return startWith( stage, resources, configuration.port(), configuration.sizing(), configuration.timing()); } /** * Answer a new {@code Server} with the given configuration and characteristics. * @param stage the Stage in which the Server lives * @param resources the Resource with URI descriptions that the Server understands * @param port the int socket port the Server will run on * @param sizing the Sizing such as pool and buffer sizes * @param timing the Timing such as probe interval and missing content timeout * @return Server */ public static Server startWith( final Stage stage, final Resources resources, final int port, final Sizing sizing, final Timing timing) { return startWith(stage, resources, Filters.none(), port, sizing, timing); } /** * Answer a new {@code Server} with the given configuration and characteristics. * @param stage the Stage in which the Server lives * @param resources the Resource with URI descriptions that the Server understands * @param filters the Filters used to process requests before dispatching to a resource * @param port the int socket port the Server will run on * @param sizing the Sizing such as pool and buffer sizes * @param timing the Timing such as probe interval and missing content timeout * @return Server */ public static Server startWith( final Stage stage, final Resources resources, final Filters filters, final int port, final Sizing sizing, final Timing timing) { return startWith(stage, resources, filters, port, sizing, timing, "queueMailbox", "queueMailbox"); } /** * Answer a new {@code Server} with the given configuration and characteristics. * <p> * WARNING: The Server has been tested with the {@code "queueMailbox"} mailbox type. * This factory method enables you to change that default to another type. If you do * change the mailbox type you do so at your own risk. * * @param stage the Stage in which the Server lives * @param resources the Resource with URI descriptions that the Server understands * @param filters the Filters used to process requests before dispatching to a resource * @param port the int socket port the Server will run on * @param sizing the Sizing such as pool and buffer sizes * @param timing the Timing such as probe interval and missing content timeout * @param severMailboxTypeName the String name of the mailbox to used by the Server * @param channelMailboxTypeName the String name of the mailbox to use by the socket channel * @return Server */ public static Server startWith( final Stage stage, final Resources resources, final Filters filters, final int port, final Sizing sizing, final Timing timing, final String severMailboxTypeName, final String channelMailboxTypeName) { // this may be overridden by using a different RefreshableSelector // initialization that supports a count- or time-based refresh // prior to starting the Server. RefreshableSelector.withNoThreshold(stage.world().defaultLogger()); final Server server = stage.actorFor( Server.class, Definition.has( ServerActor.class, new ServerInstantiator(resources, filters, port, sizing, timing, channelMailboxTypeName), severMailboxTypeName, ServerActor.ServerName), stage.world().addressFactory().withHighId(), stage.world().defaultLogger()); server.startUp(); return server; } public static Server startWithAgent( final Stage stage, final Resources resources, final int port, final int dispatcherPoolSize) { return startWithAgent(stage, resources, Filters.none(), port, dispatcherPoolSize); } public static Server startWithAgent( final Stage stage, final Resources resources, final Filters filters, final int port, final int dispatcherPoolSize) { return startWithAgent(stage, resources, filters, port, dispatcherPoolSize, "queueMailbox"); } public static Server startWithAgent( final Stage stage, final Resources resources, final Filters filters, final int port, final int dispatcherPoolSize, final String severMailboxTypeName) { final Server server = stage.actorFor( Server.class, Definition.has( ServerActor.class, new ServerWithAgentInstantiator(resources, filters, port, dispatcherPoolSize), severMailboxTypeName, ServerActor.ServerName), stage.world().addressFactory().withHighId(), stage.world().defaultLogger()); server.startUp(); return server; } Completes<Boolean> shutDown(); Completes<Boolean> startUp(); static class ServerInstantiator implements ActorInstantiator<ServerActor> { private static final long serialVersionUID = 1085685844717413620L; private final Resources resources; private final Filters filters; private final int port; private final Sizing sizing; private final Timing timing; private final String channelMailboxTypeName; public ServerInstantiator( final Resources resources, final Filters filters, final int port, final Sizing sizing, final Timing timing, final String channelMailboxTypeName) { this.resources = resources; this.filters = filters; this.port = port; this.sizing = sizing; this.timing = timing; this.channelMailboxTypeName = channelMailboxTypeName; } @Override public ServerActor instantiate() { try { return new ServerActor(resources, filters, port, sizing, timing, channelMailboxTypeName); } catch (Exception e) { throw new IllegalArgumentException("Failed to instantiate " + type() + " because: " + e.getMessage(), e); } } @Override public Class<ServerActor> type() { return ServerActor.class; } } static class ServerWithAgentInstantiator implements ActorInstantiator<ServerActor> { private static final long serialVersionUID = 9035408940262040413L; private final Resources resources; private final Filters filters; private final int port; private final int dispatcherPoolSize; public ServerWithAgentInstantiator(final Resources resources, final Filters filters, final int port, final int dispatcherPoolSize) { this.resources = resources; this.filters = filters; this.port = port; this.dispatcherPoolSize = dispatcherPoolSize; } @Override public ServerActor instantiate() { try { return new ServerActor(resources, filters, port, dispatcherPoolSize); } catch (Exception e) { throw new IllegalArgumentException("Failed to instantiate " + type() + " because: " + e.getMessage(), e); } } @Override public Class<ServerActor> type() { return ServerActor.class; } } }