001/* 002 * jPOS Project [http://jpos.org] 003 * Copyright (C) 2000-2026 jPOS Software SRL 004 * 005 * This program is free software: you can redistribute it and/or modify 006 * it under the terms of the GNU Affero General Public License as 007 * published by the Free Software Foundation, either version 3 of the 008 * License, or (at your option) any later version. 009 * 010 * This program is distributed in the hope that it will be useful, 011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 013 * GNU Affero General Public License for more details. 014 * 015 * You should have received a copy of the GNU Affero General Public License 016 * along with this program. If not, see <http://www.gnu.org/licenses/>. 017 */ 018 019package org.jpos.q2; 020 021import java.io.IOException; 022import java.util.ArrayList; 023import java.util.List; 024import java.util.regex.Matcher; 025import java.util.regex.Pattern; 026 027import org.jline.terminal.Terminal; 028import org.jpos.iso.ISOUtil; 029 030public class CLICommandInterface { 031 CLIContext ctx; 032 List<String> prefixes = new ArrayList<String>(); 033 034 public List<String> getPrefixes() { 035 return prefixes; 036 } 037 038 public CLICommandInterface(CLIContext ctx) { 039 this.ctx = ctx; 040 } 041 042 public void addPrefix(String prefix) { 043 prefixes.add(prefix); 044 } 045 046 public void execCommand(String line) throws IOException { 047 String args[] = parseCommand(line); 048 if (args.length == 0) { 049 return; 050 } 051 String verbatimCmd = args[0]; 052 String command = args[0].toUpperCase(); 053 String className = command; 054 055 for (String prefix : prefixes) { 056 if (!command.contains(".")) { 057 className = prefix + command; 058 } 059 try { 060 Object cmd = getCommand(className); 061 if (cmd != null) { 062 try { 063 args[0] = ISOUtil.unPadLeft(line, ' '); // full line 064 if (cmd instanceof CLISubSystem) { 065 CLISubSystem ss = (CLISubSystem) cmd; 066 ctx.getCLI().setPrompt(ss.getPrompt(ctx, args), ss.getCompletionPrefixes(ctx, args)); 067 } 068 if (cmd instanceof CLICommand) { 069 ((CLICommand) cmd).exec(ctx, args); 070 } else if (cmd instanceof Command) { 071 Terminal t = ctx.getReader().getTerminal(); 072 ((Command) cmd).exec (t.input(), t.output(), t.output(), args); 073 } 074 return; 075 } catch (Exception ex) { 076 ctx.printThrowable(ex); 077 } 078 } 079 } catch (ClassNotFoundException ignored) { 080 // NOPMD 081 } catch (Exception ex) { 082 ctx.printThrowable(ex); 083 break; 084 } 085 } 086 ctx.println("Invalid command '" + verbatimCmd + "'"); 087 } 088 089 private Object getCommand(String className) throws ClassNotFoundException, InstantiationException, IllegalAccessException { 090 final ClassLoader cl = Thread.currentThread().getContextClassLoader(); 091 return cl.loadClass(className).newInstance(); 092 } 093 094 public String[] parseCommand(String line) throws IOException { 095 if (line == null) { 096 return new String[0]; 097 } 098 099 List<String> matchList = new ArrayList<String>(); 100 Pattern regex = Pattern.compile("[^\\s\"']+|\"([^\"]*)\"|'([^']*)'"); 101 Matcher regexMatcher = regex.matcher(line); 102 while (regexMatcher.find()) { 103 if (regexMatcher.group(1) != null) { 104 // Add double-quoted string without the quotes 105 matchList.add(regexMatcher.group(1)); 106 } else if (regexMatcher.group(2) != null) { 107 // Add single-quoted string without the quotes 108 matchList.add(regexMatcher.group(2)); 109 } else { 110 // Add unquoted word 111 matchList.add(regexMatcher.group()); 112 } 113 } 114 String[] args = new String[matchList.size()]; 115 matchList.toArray(args); 116 return args; 117 } 118}