001/*
002 * Stallion Core: A Modern Web Framework
003 *
004 * Copyright (C) 2015 - 2016 Stallion Software LLC.
005 *
006 * This program is free software: you can redistribute it and/or modify it under the terms of the
007 * GNU General Public License as published by the Free Software Foundation, either version 2 of
008 * the License, or (at your option) any later version. This program is distributed in the hope that
009 * it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
010 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
011 * License for more details. You should have received a copy of the GNU General Public License
012 * along with this program.  If not, see <http://www.gnu.org/licenses/gpl-2.0.html>.
013 *
014 *
015 *
016 */
017
018package io.stallion.boot;
019
020import io.stallion.Context;
021import io.stallion.asyncTasks.AsyncCoordinator;
022import io.stallion.plugins.PluginRegistry;
023import io.stallion.restfulEndpoints.EndpointsRegistry;
024import io.stallion.requests.RequestHandler;
025import io.stallion.restfulEndpoints.RestEndpointBase;
026import io.stallion.restfulEndpoints.SlugRegistry;
027import io.stallion.services.Log;
028import io.stallion.settings.Settings;
029
030import org.eclipse.jetty.server.Server;
031import sun.misc.Signal;
032import sun.misc.SignalHandler;
033
034import javax.servlet.MultipartConfigElement;
035import java.text.MessageFormat;
036import java.util.Map;
037
038
039public class StallionServer implements StallionRunAction<ServeCommandOptions> {
040
041    @Override
042    public String getActionName() {
043        return "serve";
044    }
045
046    @Override
047    public String getHelp() {
048        return "run the Stallion HTTP server";
049    }
050
051    @Override
052    public void loadApp(ServeCommandOptions options) {
053        AppContextLoader.loadCompletely(options);
054        AppContextLoader.instance().startAllServices();
055    }
056
057    @Override
058    public ServeCommandOptions newCommandOptions() {
059        return new ServeCommandOptions();
060    }
061
062    @Override
063    public void execute(ServeCommandOptions options) throws Exception {
064
065
066
067
068        // Start the server
069        Server server = new Server(Settings.instance().getPort());
070        server.setHandler(RequestHandler.instance());
071
072
073        server.start();
074
075        System.out.print("-------------------------------------------------------\n");
076        System.out.print(MessageFormat.format(
077                "Final registration count: {1} controllers. {2} plugins. {3} endpoints. {4} slugs. V=3\n",
078                Settings.instance().getPort(),
079                Context.dal().size(),
080                PluginRegistry.instance().getJavaPluginByName().size(),
081                EndpointsRegistry.instance().getEndpoints().size(),
082                SlugRegistry.instance().getSlugMap().size()
083        ));
084
085
086        // If we are in debug mode, file system changes will send a signal, which
087        // will then be caught, triggering a reload.
088        if (MainRunner.isIsDebugRunner()) {
089            sun.misc.Signal.handle(new Signal("INT"), new InterruptHandler(server));
090            sun.misc.Signal.handle(new Signal("USR2"), new ReloadHandler(server));
091            MainRunner.setupWatchers(Settings.instance().getTargetFolder());
092        }
093
094
095        System.out.print("-------------------------------------------------------\n");
096        String art = "" +
097                "         _,_\n" +
098                "        ;'._\\\n" +
099                "       ';) \\._,     Stallion server now running on port " + Settings.instance().getPort() + ".\n" +
100                "        /  /`-'\n" +
101                "     ~~( )/\n" +
102                "        )))\n" +
103                "        \\\\\\";
104        System.out.print(art);
105        System.out.print("\n-------------------------------------------------------\n");
106
107
108        server.join();
109
110        System.out.println("Shutting down async coordinator");
111        AsyncCoordinator.gracefulShutdown();
112
113    }
114
115    public class ReloadHandler implements SignalHandler {
116        private Server server;
117
118        public ReloadHandler(Server server) {
119            this.server = server;
120        }
121
122        @Override
123        public void handle(sun.misc.Signal signal) {
124            if (server.isStopped()) {
125                return;
126            }
127            try {
128                MainRunner.setDoReload(true);
129                AsyncCoordinator.gracefulShutdown();
130                server.stop();
131            } catch (Exception e) {
132                throw new RuntimeException(e);
133            }
134        }
135
136    }
137
138
139    public class InterruptHandler implements SignalHandler {
140        private Server server;
141
142        public InterruptHandler(Server server) {
143            this.server = server;
144        }
145
146        @Override
147        public void handle(sun.misc.Signal signal) {
148            System.out.println("Interrupted!");
149            if (server.isStopped()) {
150                System.exit(0);
151            }
152            try {
153                AsyncCoordinator.gracefulShutdown();
154                server.stop();
155            } catch (Exception e) {
156                throw new RuntimeException(e);
157            }
158        }
159    }
160}