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.config.Interceptors;
019import com.jfinal.config.Plugins;
020import com.jfinal.core.JFinal;
021import com.jfinal.plugin.IPlugin;
022import io.jboot.app.config.JbootConfigManager;
023import io.jboot.core.JbootCoreConfig;
024
025import java.lang.reflect.Method;
026import java.text.DecimalFormat;
027import java.util.List;
028import java.util.concurrent.locks.Condition;
029import java.util.concurrent.locks.ReentrantLock;
030
031/**
032 * @author michael yang (fuhai999@gmail.com)
033 * @Date: 2020/3/24
034 */
035public class JbootSimpleApplication {
036
037    private static final ReentrantLock LOCK = new ReentrantLock();
038    private static final Condition STOP = LOCK.newCondition();
039
040    public static void main(String[] args) {
041        run(args);
042    }
043
044    public static void setBootArg(String key, Object value) {
045        JbootConfigManager.setBootArg(key, value);
046    }
047
048    public static void run(String[] args) {
049
050        long startTimeMillis = System.currentTimeMillis();
051
052        JbootApplicationConfig appConfig = ApplicationUtil.getAppConfig(args);
053        ApplicationUtil.printBannerInfo(appConfig);
054        ApplicationUtil.printApplicationInfo(appConfig);
055        ApplicationUtil.printClassPath();
056
057        JbootCoreConfig coreConfig = new JbootCoreConfig();
058        new SimpleServer(coreConfig, startTimeMillis).start();
059    }
060
061
062    static class SimpleServer extends Thread {
063
064        private final JbootCoreConfig coreConfig;
065        private final long startTimeMillis;
066        private final Plugins plugins = new Plugins();
067        private final Interceptors interceptors = new Interceptors();
068
069        public SimpleServer(JbootCoreConfig coreConfig, long startTimeMillis) {
070            this.coreConfig = coreConfig;
071            this.startTimeMillis = startTimeMillis;
072
073            doInitJFinalPathKit();
074            doInitCoreConfig();
075        }
076
077
078        private void doInitJFinalPathKit() {
079            try {
080                Class<?> c = JbootSimpleApplication.class.getClassLoader().loadClass("com.jfinal.kit.PathKit");
081                Method setWebRootPath = c.getMethod("setWebRootPath", String.class);
082                String webRootPath = PathKitExt.getWebRootPath();
083                setWebRootPath.invoke(null, webRootPath);
084
085                // -------
086                Method setRootClassPath = c.getMethod("setRootClassPath", String.class);
087                String rootClassPath = PathKitExt.getRootClassPath();
088                setRootClassPath.invoke(null, rootClassPath);
089            } catch (Exception ex) {
090                throw new RuntimeException(ex);
091            }
092        }
093
094        private void doInitCoreConfig() {
095
096            //constants
097            coreConfig.configConstant(JFinal.me().getConstants());
098
099            //aop interceptors
100            coreConfig.configInterceptor(interceptors);
101
102            //plugins
103            coreConfig.configPlugin(plugins);
104            startPlugins();
105
106            //on start
107            coreConfig.onStart();
108        }
109
110        private void startPlugins() {
111            List<IPlugin> pluginList = plugins.getPluginList();
112            if (pluginList == null) {
113                return;
114            }
115
116            for (IPlugin plugin : pluginList) {
117                try {
118                    if (plugin.start() == false) {
119                        String message = "Plugin start error: " + plugin.getClass().getName();
120                        throw new RuntimeException(message);
121                    }
122                } catch (Exception e) {
123                    String message = "Plugin start error: " + plugin.getClass().getName() + ". \n" + e.getMessage();
124                    throw new RuntimeException(message, e);
125                }
126            }
127        }
128
129        @Override
130        public void run() {
131            String seconds = new DecimalFormat("#.#").format((System.currentTimeMillis() - startTimeMillis) / 1000F);
132            System.out.println("JbootApplication has started in " + seconds + " seconds. Welcome To The Jboot World (^_^)\n\n");
133
134            initShutdownHook();
135            startAwait();
136        }
137
138
139        private void initShutdownHook() {
140            Runtime.getRuntime().addShutdownHook(new Thread(() -> {
141                System.out.println("\nJbootApplication shutdown, please wait ...... ");
142                try {
143                    coreConfig.onStop();
144                } catch (Exception e) {
145                    System.out.println("JbootApplication shutdown exception: " + e.toString());
146                }
147                System.out.println("JbootApplication has exited, all services stopped.");
148                try {
149                    LOCK.lock();
150                    STOP.signal();
151                } finally {
152                    LOCK.unlock();
153                }
154            }, "jboot-simple-application-hook"));
155        }
156
157
158        private void startAwait() {
159            try {
160                LOCK.lock();
161                STOP.await();
162            } catch (InterruptedException e) {
163                System.out.println("JbootApplication has stopped, interrupted by other thread!");
164            } finally {
165                LOCK.unlock();
166            }
167        }
168
169
170    }
171
172}