001/**
002 * Copyright (c) 2015-2022, Michael Yang 杨福海 (fuhai999@gmail.com).
003 * <p>
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 * <p>
008 * http://www.apache.org/licenses/LICENSE-2.0
009 * <p>
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016package io.jboot.app;
017
018import com.jfinal.server.undertow.UndertowConfig;
019import com.jfinal.server.undertow.UndertowServer;
020import com.jfinal.server.undertow.WebBuilder;
021import io.jboot.app.config.JbootConfigManager;
022import io.jboot.app.undertow.JbootUndertowConfig;
023import io.jboot.app.undertow.JbootUndertowServer;
024import io.jboot.utils.StrUtil;
025import io.undertow.Undertow;
026
027import javax.servlet.DispatcherType;
028import java.util.function.Consumer;
029
030public class JbootApplication {
031
032    public static void main(String[] args) {
033        run(args);
034    }
035
036    public static void run(String[] args) {
037        start(createServer(args));
038    }
039
040    public static void run(String[] args, JbootWebBuilderConfiger configer) {
041        start(createServer(args, configer));
042    }
043
044    public static void start(UndertowServer server) {
045        server.start();
046        String resourceLoaderEnable = JbootConfigManager.me().getConfigValue("jboot.app.resourceLoaderEnable");
047        if (ApplicationUtil.isDevMode() && !"false".equalsIgnoreCase(resourceLoaderEnable)) {
048            new JbootResourceLoader().start();
049        }
050    }
051
052    public static void setBootArg(String key, Object value) {
053        JbootConfigManager.setBootArg(key, value);
054    }
055
056    /**
057     * 创建 Undertow 服务器,public 用于可以给第三方创建创建着急的 Server
058     *
059     * @param args
060     * @return 返回 UndertowServer
061     */
062    public static UndertowServer createServer(String[] args) {
063        JbootApplicationConfig appConfig = ApplicationUtil.getAppConfig(args);
064        return createServer(appConfig, createUndertowConfig(appConfig), null, null);
065    }
066
067    /**
068     * 创建 Undertow 服务器,public 用于可以给第三方创建创建着急的 Server
069     * <p>
070     * JbootApplication.start(JbootApplication.createServer(args,new MyWebBuilderConfiger()))
071     *
072     * @param args
073     * @param configer 可以通过 Configer 来进行自定义配置
074     * @return
075     */
076    public static UndertowServer createServer(String[] args, JbootWebBuilderConfiger configer) {
077        JbootApplicationConfig appConfig = ApplicationUtil.getAppConfig(args);
078        return createServer(appConfig, createUndertowConfig(appConfig), configer);
079    }
080
081
082    public static UndertowServer createServer(String[] args, JbootWebBuilderConfiger configer, Consumer<Undertow.Builder> builder) {
083        JbootApplicationConfig appConfig = ApplicationUtil.getAppConfig(args);
084        return createServer(appConfig, createUndertowConfig(appConfig), configer, builder);
085    }
086
087
088    public static UndertowServer createServer(String[] args, Consumer<Undertow.Builder> builder) {
089        JbootApplicationConfig appConfig = ApplicationUtil.getAppConfig(args);
090        return createServer(appConfig, createUndertowConfig(appConfig), null, builder);
091    }
092
093
094    public static UndertowServer createServer(JbootApplicationConfig appConfig
095            , UndertowConfig undertowConfig
096            , JbootWebBuilderConfiger configer) {
097        return createServer(appConfig, undertowConfig, configer, null);
098    }
099
100
101    public static UndertowServer createServer(JbootApplicationConfig appConfig
102            , UndertowConfig undertowConfig
103            , JbootWebBuilderConfiger configer
104            , Consumer<Undertow.Builder> builder) {
105
106        ApplicationUtil.printBannerInfo(appConfig);
107        ApplicationUtil.printApplicationInfo(appConfig);
108        ApplicationUtil.printClassPath();
109
110        return new JbootUndertowServer(undertowConfig)
111                .configWeb(webBuilder -> {
112                    tryAddContenTypes(webBuilder);
113                    tryAddMetricsSupport(webBuilder);
114                    tryAddShiroSupport(webBuilder);
115                    tryAddWebSocketSupport(webBuilder);
116                    if (configer != null) {
117                        configer.onConfig(webBuilder);
118                    }
119                }).onStart(builder);
120    }
121
122
123    public static UndertowConfig createUndertowConfig(JbootApplicationConfig appConfig) {
124        UndertowConfig undertowConfig = new JbootUndertowConfig(appConfig.getJfinalConfig());
125        undertowConfig.addSystemClassPrefix("io.jboot.app");
126        undertowConfig.addHotSwapClassPrefix("io.jboot");
127        return undertowConfig;
128    }
129
130
131    private static void tryAddContenTypes(WebBuilder webBuilder) {
132        HttpContentTypes.init(webBuilder.getDeploymentInfo());
133    }
134
135
136    private static void tryAddMetricsSupport(WebBuilder webBuilder) {
137        String url = ApplicationUtil.getConfigValue("jboot.metric.adminServletMapping");
138        String reporter = ApplicationUtil.getConfigValue("jboot.metric.reporter");
139        if (url != null && reporter != null) {
140            webBuilder.addServlet("MetricsAdminServlet", "com.codahale.metrics.servlets.AdminServlet")
141                    .addServletMapping("MetricsAdminServlet", url.endsWith("/*") ? url : url + "/*");
142            webBuilder.addListener("io.jboot.support.metric.JbootMetricServletContextListener");
143            webBuilder.addListener("io.jboot.support.metric.JbootHealthCheckServletContextListener");
144        }
145    }
146
147
148    private static void tryAddShiroSupport(WebBuilder webBuilder) {
149        String iniConfig = ApplicationUtil.getConfigValue("jboot.shiro.ini");
150        if (iniConfig != null) {
151            String urlMapping = ApplicationUtil.getConfigValue("jboot.shiro.urlMapping");
152            if (urlMapping == null) {
153                urlMapping = "/*";
154            }
155            String filterClass = StrUtil.defaultIfBlank(ApplicationUtil.getConfigValue("jboot.shiro.filter"),
156                    "io.jboot.support.shiro.JbootShiroFilter");
157
158            webBuilder.addListener("org.apache.shiro.web.env.EnvironmentLoaderListener");
159            webBuilder.addFilter("shiro", filterClass)
160                    .addFilterUrlMapping("shiro", urlMapping, DispatcherType.REQUEST);
161            webBuilder.getDeploymentInfo().addInitParameter("shiroEnvironmentClass",
162                    "io.jboot.support.shiro.JbootShiroWebEnvironment");
163        }
164    }
165
166    private static void tryAddWebSocketSupport(WebBuilder webBuilder) {
167        String websocketEndpoint = ApplicationUtil.getConfigValue("jboot.web.webSocketEndpoint");
168        if (websocketEndpoint != null && websocketEndpoint.trim().length() > 0) {
169            String[] classStrings = websocketEndpoint.split(",");
170            for (String c : classStrings) {
171                webBuilder.addWebSocketEndpoint(c.trim());
172            }
173        }
174    }
175
176
177}