/* * JEF - Copyright 2009-2010 Jiyi (mr.jiyi@gmail.com) * * 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 jef.ui.console; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.util.concurrent.locks.ReentrantLock; import jef.common.log.LogUtil; import jef.tools.ArrayUtils; import jef.tools.Assert; import jef.tools.StringUtils; import jef.tools.ThreadUtils; import jef.ui.ConsoleConversation; import jef.ui.ConsoleShell; public abstract class AbstractConsoleShell implements ConsoleShell { protected jef.tools.support.ThreadLocal<ConsoleShell> sub=new jef.tools.support.ThreadLocal<ConsoleShell>(); protected ConsoleShell parent; private ConsoleWaiter waiter; protected boolean keepgoing = true; protected String cmd=null; protected final ReentrantLock lock=new ReentrantLock();//线程同步锁 /** * 会话将获取Console的下一个输入。如果一直没输入则将阻塞等待 * @param conv * @param msg * @param validValues * @return */ public String getInput(ConsoleConversation<?> conv,String msg,String... validValues){ ConsoleWaiter oldWaiter=waiter; //如果有某个对话正在等待状态 while(oldWaiter!=null){ ThreadUtils.doWait(oldWaiter); oldWaiter=waiter; } //将当前线程注册进等待状态 ConsoleWaiter myWaiter=new ConsoleWaiter(validValues); LogUtil.show(msg); waiter=myWaiter; ThreadUtils.doWait(myWaiter); return myWaiter.get(); } protected ConsoleShell getSubShell(){ return sub.get(); } public AbstractConsoleShell(ConsoleShell parent){ this.parent=parent; } public final ShellResult perform(String str,boolean show,String... params) { //process Waiter if(waiter!=null && waiter.get()==null){//有会话正在等待输入。 ConsoleWaiter theWaiter=waiter; if(theWaiter.set(str)){ waiter=null; ThreadUtils.doNotifyAll(theWaiter); System.out.print(getPrompt()); }else{ LogUtil.show("Invalid Input, you must input:"+StringUtils.join(theWaiter.validValues,"/")); } return ShellResult.CONTINUE; } //trim处理 str=StringUtils.trimToNull(str); if (str == null) { ShellResult r=performNull(); if(!r.needProcess()){ return r; }else{ str=r.getCmd(); } } //process sub shell if(sub.get()!=null){ ShellResult rst=sub.get().perform(str, show,params); if(rst==ShellResult.TERMINATE){ endSubShell(null); return ShellResult.CONTINUE; }else if(rst==ShellResult.CONTINUE){ return rst; }else{ str=rst.getCmd(); } } //process my custom; ShellResult result=performCommand(str,params); if(show)System.out.print(getPrompt()); return result; } /** * 当直接敲回车时的处理方式 * @return */ protected ShellResult performNull() { System.out.print(getPrompt()); return ShellResult.CONTINUE; } protected void startNewShell(ConsoleShell newShell) { Assert.isNull(sub.get()); sub.set(newShell); } protected void endSubShell(Thread t){ if(t==null){ ConsoleShell shell=sub.get(); if(shell==null)return; shell.exit(); sub.set(null); }else{ ConsoleShell shell=sub.getExistValue(t); if(shell==null)return; shell.exit(); sub.set(t, null); } System.out.print(getPrompt()); } protected abstract ShellResult performCommand(String str, String... params); static class ConsoleWaiter{ String input = null; String[] validValues; ConsoleWaiter(String[] validValues){ this.validValues=validValues; } String get(){ return input; } boolean set(String str){ if(validValues.length==0 || ArrayUtils.containsIgnoreCase(validValues, str)){ this.input=str; return true; } return false; } } /** * 向控制台发送命令 * @param str */ public void sendCommand(String str,String user){ if(user==null){ //本地命令,由键盘监听线程调用 lock.lock(); //等待解锁,即等待上一条命令执行完毕 lock.unlock(); cmd=str; ThreadUtils.doNotify(lock);//告诉主线程开始工作。 }else{//来自网络服务器发来的远程命令,当前线程为网络服务线程,直接在当前线程运行。 if(perform(str, true,user)==ShellResult.TERMINATE)stop(); } } /** * 终止控制台 */ public void stop(){ this.keepgoing=false; if(!lock.isLocked())ThreadUtils.doNotify(lock); } /** * 监听本地的键盘输入 * @author Administrator */ protected class InputListener extends Thread{ BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); public InputListener(){ super(); setDaemon(true);//为守护线程 } public void run() { while(true){ String str=readline(); sendCommand(str,null); } } private String readline() { try { String str = br.readLine(); if (str == null) str = "q"; return str; } catch (IOException e) { LogUtil.exception(e); return null; } } } }