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.core.listener;
017
018import com.jfinal.config.Constants;
019import com.jfinal.config.Interceptors;
020import com.jfinal.config.Routes;
021import com.jfinal.kit.LogKit;
022import com.jfinal.template.Engine;
023import io.jboot.aop.jfinal.JfinalHandlers;
024import io.jboot.aop.jfinal.JfinalPlugins;
025import io.jboot.app.JbootApplicationConfig;
026import io.jboot.core.weight.WeightUtil;
027import io.jboot.utils.ClassScanner;
028import io.jboot.utils.ClassUtil;
029import io.jboot.utils.StrUtil;
030
031import java.util.ArrayList;
032import java.util.HashSet;
033import java.util.List;
034import java.util.Set;
035import java.util.function.Predicate;
036
037public class JbootAppListenerManager implements JbootAppListener {
038
039    private static JbootAppListenerManager me = new JbootAppListenerManager();
040
041    public static JbootAppListenerManager me() {
042        return me;
043    }
044
045    private List<JbootAppListener> listeners = new ArrayList<>();
046
047    private JbootAppListenerManager() {
048
049        String listener = JbootApplicationConfig.get().getListener();
050
051        String listenerPackage = JbootApplicationConfig.get().getListenerPackage();
052        Set<String> packages = StrUtil.isNotBlank(listenerPackage) && !"*".equals(listenerPackage.trim())
053                ? StrUtil.splitToSet(listenerPackage, ";") : new HashSet<>();
054
055        if (StrUtil.isBlank(listener) || "*".equals(listener.trim())) {
056            List<Class<JbootAppListener>> allListeners = ClassScanner.scanSubClass(JbootAppListener.class, true);
057            allListeners.removeIf((Predicate<Class<? extends JbootAppListener>>) c ->
058                    c == JbootAppListenerManager.class || c == JbootAppListenerBase.class);
059
060            allListeners.forEach(clazz -> {
061                if (isMatchedPackage(packages, clazz.getCanonicalName())) {
062                    JbootAppListener appListener = ClassUtil.newInstance(clazz);
063                    if (appListener != null) {
064                        listeners.add(appListener);
065                    }
066                }
067            });
068        } else {
069            StrUtil.splitToSet(listener, ";").forEach(className -> {
070                if (isMatchedPackage(packages, className)) {
071                    JbootAppListener appListener = ClassUtil.newInstance(className);
072                    if (appListener != null) {
073                        listeners.add(appListener);
074                    } else {
075                        // log 组件还未配置,无法使用 log 组件输出
076                        System.err.println("Can not create JbootAppListener by class: " + className);
077                    }
078                }
079            });
080        }
081
082        WeightUtil.sort(listeners);
083    }
084
085    private boolean isMatchedPackage(Set<String> packages, String className) {
086        //matched all
087        if (packages == null || packages.isEmpty()) {
088            return true;
089        }
090
091        for (String packageString : packages) {
092            if (className.startsWith(packageString)) {
093                return true;
094            }
095        }
096        return false;
097    }
098
099    public List<JbootAppListener> getListeners() {
100        return listeners;
101    }
102
103    @Override
104    public void onInit() {
105        eachListeners(new TriggerThrowable() {
106            @Override
107            public void trigger(JbootAppListener listener) {
108                listener.onInit();
109            }
110
111            @Override
112            public void throwable(Throwable ex) {
113                //在 onConstantConfigBefore 的时候, log 组件未初始化,无法使用
114                ex.printStackTrace();
115            }
116        });
117    }
118
119    @Override
120    public void onConstantConfigBefore(Constants constants) {
121        eachListeners(new TriggerThrowable() {
122            @Override
123            public void trigger(JbootAppListener listener) {
124                listener.onConstantConfigBefore(constants);
125            }
126
127            @Override
128            public void throwable(Throwable ex) {
129                //在 onConstantConfigBefore 的时候, log 组件未初始化,无法使用
130                ex.printStackTrace();
131            }
132        });
133    }
134
135    @Override
136    public void onConstantConfig(Constants constants) {
137        eachListeners(listener -> listener.onConstantConfig(constants));
138    }
139
140    @Override
141    public void onRouteConfig(Routes routes) {
142        eachListeners(listener -> listener.onRouteConfig(routes));
143    }
144
145    @Override
146    public void onEngineConfig(Engine engine) {
147        eachListeners(listener -> listener.onEngineConfig(engine));
148    }
149
150    @Override
151    public void onPluginConfig(JfinalPlugins plugins) {
152        eachListeners(listener -> listener.onPluginConfig(plugins));
153    }
154
155    @Override
156    public void onInterceptorConfig(Interceptors interceptors) {
157        eachListeners(listener -> listener.onInterceptorConfig(interceptors));
158    }
159
160
161    @Override
162    public void onHandlerConfig(JfinalHandlers handlers) {
163        eachListeners(listener -> listener.onHandlerConfig(handlers));
164    }
165
166    @Override
167    public void onStartBefore() {
168        eachListeners(JbootAppListener::onStartBefore);
169    }
170
171    @Override
172    public void onStart() {
173        eachListeners(JbootAppListener::onStart);
174    }
175
176    @Override
177    public void onStartFinish() {
178        eachListeners(JbootAppListener::onStartFinish);
179    }
180
181    @Override
182    public void onStop() {
183        eachListeners(JbootAppListener::onStop);
184    }
185
186    private void eachListeners(TriggerThrowable triggerThrowable) {
187        for (JbootAppListener listener : listeners) {
188            try {
189                triggerThrowable.trigger(listener);
190            } catch (Throwable ex) {
191                triggerThrowable.throwable(ex);
192            }
193        }
194    }
195
196    @FunctionalInterface
197    private interface TriggerThrowable {
198        void trigger(JbootAppListener listener);
199
200        default void throwable(Throwable ex) {
201            LogKit.error(ex.toString(), ex);
202        }
203    }
204}