/* * Copyright 2008-2009 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package net.hasor.rsf.console; import io.netty.bootstrap.ServerBootstrap; import io.netty.channel.ChannelInitializer; import io.netty.channel.ChannelPipeline; import io.netty.channel.EventLoopGroup; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.socket.SocketChannel; import io.netty.channel.socket.nio.NioServerSocketChannel; import io.netty.handler.codec.DelimiterBasedFrameDecoder; import io.netty.handler.codec.Delimiters; import io.netty.handler.codec.string.StringDecoder; import io.netty.handler.codec.string.StringEncoder; import io.netty.handler.logging.LogLevel; import io.netty.handler.logging.LoggingHandler; import net.hasor.core.AppContext; import net.hasor.core.EventListener; import net.hasor.core.Hasor; import net.hasor.core.LifeModule; import net.hasor.rsf.InterAddress; import net.hasor.rsf.RsfApiBinder; import net.hasor.rsf.RsfContext; import net.hasor.rsf.RsfModule; import net.hasor.rsf.domain.RsfConstants; import net.hasor.rsf.utils.NameThreadFactory; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.net.UnknownHostException; import java.util.HashSet; import java.util.Set; /** * RSF终端管理器插件。 * @version : 2016年2月18日 * @author 赵永春(zyc@hasor.net) */ public class RsfConsoleModule extends RsfModule implements LifeModule { protected static Logger logger = LoggerFactory.getLogger(RsfConstants.LoggerName_Console); private StringDecoder stringDecoder = new StringDecoder(); private StringEncoder stringEncoder = new StringEncoder(); private TelnetHandler telnetHandler = null; private InterAddress bindAddress = null; private EventLoopGroup workerGroup = null; // @Override public void loadModule(RsfApiBinder apiBinder) throws Throwable { logger.info("rsfConsole -> init consoleModule."); // final Set<Class<?>> rsfCommandSet = new HashSet<Class<?>>(apiBinder.getEnvironment().findClass(RsfCommand.class)); rsfCommandSet.remove(RsfCommand.class); if (rsfCommandSet.isEmpty()) { if (logger.isWarnEnabled()) { logger.warn("event -> init failed , not found any @RsfCommand."); } return; } for (final Class<?> commandClass : rsfCommandSet) { if (commandClass == RsfCommand.class || !RsfInstruct.class.isAssignableFrom(commandClass)) { continue; } if (!commandClass.getPackage().isAnnotationPresent(RsfSearchInclude.class)) { continue; } logger.info("rsfConsole -> new order {}.", commandClass); apiBinder.bindType(RsfInstruct.class).uniqueName().to((Class<? extends RsfInstruct>) commandClass); } // } @Override public void onStart(AppContext appContext) throws Throwable { RsfContext rsfContext = appContext.getInstance(RsfContext.class); if (rsfContext == null) { logger.error("rsfConsole -> RsfContext is null."); return; } //1.初始化常量配置。 this.workerGroup = new NioEventLoopGroup(1, new NameThreadFactory("RSF-Console", appContext.getClassLoader())); this.telnetHandler = new TelnetHandler(rsfContext); int consolePort = rsfContext.getSettings().getConsolePort(); String consoleAddress = rsfContext.getSettings().getBindAddress(); String formUnit = rsfContext.getSettings().getUnitName(); try { this.bindAddress = new InterAddress(consoleAddress, consolePort, formUnit); } catch (Throwable e) { throw new UnknownHostException(e.getMessage()); } logger.info("rsfConsole -> starting... at {}", this.bindAddress); // //2.启动Telnet。 try { ServerBootstrap b = new ServerBootstrap(); b.group(workerGroup, workerGroup); b.channel(NioServerSocketChannel.class); b.handler(new LoggingHandler(LogLevel.INFO)); b.childHandler(new ChannelInitializer<SocketChannel>() { @Override public void initChannel(SocketChannel ch) throws Exception { ChannelPipeline pipeline = ch.pipeline(); pipeline.addLast(new DelimiterBasedFrameDecoder(8192, Delimiters.lineDelimiter())); pipeline.addLast(stringDecoder); pipeline.addLast(stringEncoder); pipeline.addLast(telnetHandler); } }); b.bind(this.bindAddress.getHost(), this.bindAddress.getPort()).sync().await(); } catch (Throwable e) { logger.error("rsfConsole -> start failed, " + e.getMessage(), e); this.shutdown(); } logger.info("rsfConsole -> - bindSocket at {}", this.bindAddress); // //3.注册shutdown事件,以保证在shutdown时可以停止Telnet。 Hasor.addShutdownListener(rsfContext.getEnvironment(), new EventListener<AppContext>() { @Override public void onEvent(String event, AppContext eventData) throws Throwable { shutdown(); } }); } public void shutdown() { if (this.workerGroup != null) { logger.info("rsfConsole -> shutdown."); this.workerGroup.shutdownGracefully(); } } @Override public void onStop(AppContext appContext) throws Throwable { } }