1 package org.cyclopsgroup.jmxterm.cc;
2
3 import java.io.IOException;
4 import java.io.PrintWriter;
5 import java.util.ArrayList;
6 import java.util.List;
7 import java.util.Map;
8 import java.util.Set;
9 import java.util.concurrent.locks.Lock;
10 import java.util.concurrent.locks.ReentrantLock;
11
12 import javax.management.JMException;
13 import javax.management.remote.JMXServiceURL;
14
15 import org.apache.commons.lang3.ArrayUtils;
16 import org.apache.commons.lang3.StringUtils;
17 import org.apache.commons.lang3.Validate;
18 import org.cyclopsgroup.caff.token.EscapingValueTokenizer;
19 import org.cyclopsgroup.caff.token.TokenEvent;
20 import org.cyclopsgroup.caff.token.TokenEventHandler;
21 import org.cyclopsgroup.caff.token.ValueTokenizer;
22 import org.cyclopsgroup.jcli.ArgumentProcessor;
23 import org.cyclopsgroup.jmxterm.Command;
24 import org.cyclopsgroup.jmxterm.CommandFactory;
25 import org.cyclopsgroup.jmxterm.JavaProcessManager;
26 import org.cyclopsgroup.jmxterm.Session;
27 import org.cyclopsgroup.jmxterm.io.CommandInput;
28 import org.cyclopsgroup.jmxterm.io.CommandOutput;
29 import org.cyclopsgroup.jmxterm.io.RuntimeIOException;
30 import org.cyclopsgroup.jmxterm.io.VerboseLevel;
31
32
33
34
35
36
37 public class CommandCenter {
38 private static final String COMMAND_DELIMITER = "&&";
39 static final String ESCAPE_CHAR_REGEX = "(?<!\\\\)#";
40
41
42
43
44 final ValueTokenizer argTokenizer = new EscapingValueTokenizer();
45
46
47
48
49 final CommandFactory commandFactory;
50
51 private final Lock lock = new ReentrantLock();
52
53 private final JavaProcessManager processManager;
54
55
56
57
58 final Session session;
59
60
61
62
63
64
65
66
67 public CommandCenter(CommandOutput output, CommandInput input) throws IOException {
68 this(output, input, new PredefinedCommandFactory());
69 }
70
71
72
73
74
75
76
77
78
79 public CommandCenter(CommandOutput output, CommandInput input, CommandFactory commandFactory)
80 throws IOException {
81 Validate.notNull(output, "Output can't be NULL");
82 Validate.notNull(commandFactory, "Command factory can't be NULL");
83 processManager = new JPMFactory().getProcessManager();
84 this.session = new SessionImpl(output, input, processManager);
85 this.commandFactory = commandFactory;
86
87 }
88
89
90
91
92 public void close() {
93 session.close();
94 }
95
96
97
98
99
100
101 public void connect(JMXServiceURL url, Map<String, Object> env) throws IOException {
102 Validate.notNull(url, "URL can't be NULL");
103 session.connect(url, env);
104 }
105
106 private void doExecute(String command) throws JMException {
107 command = StringUtils.trimToNull(command);
108
109 if (command == null) {
110 return;
111 }
112
113 if (command.startsWith("#")) {
114 return;
115 }
116
117
118
119 command = command.split(ESCAPE_CHAR_REGEX)[0]
120 .replace("\\#", "#");
121
122 if (command.indexOf(COMMAND_DELIMITER) != -1) {
123 String[] commands = StringUtils.split(command, COMMAND_DELIMITER);
124 for (String c : commands) {
125 execute(c);
126 }
127 return;
128 }
129
130
131 final List<String> args = new ArrayList<String>();
132 argTokenizer.parse(command, new TokenEventHandler() {
133 public void handleEvent(TokenEvent event) {
134 args.add(event.getToken());
135 }
136 });
137 String commandName = args.remove(0);
138
139 String[] commandArgs = args.toArray(ArrayUtils.EMPTY_STRING_ARRAY);
140
141 try {
142 doExecute(commandName, commandArgs, command);
143 } catch (IOException e) {
144 throw new RuntimeIOException("Runtime IO exception: " + e.getMessage(), e);
145 }
146 }
147
148
149 @SuppressWarnings("unchecked")
150 private void doExecute(String commandName, String[] commandArgs, String originalCommand)
151 throws JMException, IOException {
152 Command cmd = commandFactory.createCommand(commandName);
153 if (cmd instanceof HelpCommand) {
154 ((HelpCommand) cmd).setCommandCenter(this);
155 }
156 ArgumentProcessor<Command> ap =
157 (ArgumentProcessor<Command>) ArgumentProcessor.forType(cmd.getClass());
158
159 ap.process(commandArgs, cmd);
160
161 if (cmd.isHelp()) {
162 ap.printHelp(new PrintWriter(System.out, true));
163 return;
164 }
165 cmd.setSession(session);
166
167 lock.lock();
168 try {
169 cmd.execute();
170 } finally {
171 lock.unlock();
172 }
173 }
174
175
176
177
178
179
180
181
182 public boolean execute(String command) {
183 try {
184 doExecute(command);
185 return true;
186 } catch (JMException e) {
187 session.output.printError(e);
188 return false;
189 } catch (RuntimeException e) {
190 session.output.printError(e);
191 return false;
192 }
193 }
194
195
196
197
198 public Set<String> getCommandNames() {
199 return commandFactory.getCommandTypes().keySet();
200 }
201
202
203
204
205
206 public Class<? extends Command> getCommandType(String name) {
207 return commandFactory.getCommandTypes().get(name);
208 }
209
210
211
212
213 public final JavaProcessManager getProcessManager() {
214 return processManager;
215 }
216
217
218
219
220 public boolean isClosed() {
221 return session.isClosed();
222 }
223
224
225
226
227 public void setVerboseLevel(VerboseLevel verboseLevel) {
228 session.setVerboseLevel(verboseLevel);
229 }
230 }