Rev 73 | Details | Compare with Previous | Last modification | View Log | SVN | RSS feed
| Rev | Author | Line No. | Line |
|---|---|---|---|
| 15 | arune | 1 | /* |
| 2 | * CmdKernel.java |
||
| 3 | * |
||
| 4 | * Created on den 23 augusti 2003, 13:47 |
||
| 5 | */ |
||
| 6 | package Macbeth; |
||
| 7 | |||
| 8 | import java.io.*; |
||
| 9 | import java.util.*; |
||
| 10 | import java.awt.event.WindowListener; |
||
| 11 | import java.awt.event.WindowEvent; |
||
| 12 | import javax.swing.*; |
||
| 13 | import Macbeth.System.*; |
||
| 14 | //import Macbeth.Utilities.*; |
||
| 15 | import com.jgoodies.plaf.plastic.Plastic3DLookAndFeel; |
||
| 16 | |||
| 17 | /** |
||
| 18 | * A custon kernel that provides command prompt, counts |
||
| 19 | * number of handled packets, and also keeps |
||
| 20 | * track of kernel uptime. |
||
| 21 | * @author Jimmy |
||
| 22 | */ |
||
| 23 | public class CmdKernel extends MbKernel { |
||
| 24 | //Remembers at what time (in milliseconds) the kernel was started (needed for uptime calculation) |
||
| 25 | private long startTime; |
||
| 26 | //references to all launched module GUIs are stored in this hashmap |
||
| 27 | private Map loadedModuleGUIs; |
||
| 28 | |||
| 29 | /** |
||
| 30 | * Creates a new instance of CmdKernel. |
||
| 31 | * @param configfile The XML configuration file for this kernel. |
||
| 32 | */ |
||
| 33 | public CmdKernel(String configfile) { |
||
| 34 | super(configfile); |
||
| 35 | } |
||
| 36 | |||
| 37 | /** |
||
| 38 | * Gets a short description of the kernel. This should |
||
| 39 | * be kept short (1-2 lines) and should be formatted as |
||
| 40 | * plain text. |
||
| 41 | * @return A short description of the kernel. |
||
| 42 | */ |
||
| 43 | public String description() { |
||
| 44 | return "Basic command-line kernel"; |
||
| 45 | } |
||
| 46 | |||
| 47 | /** |
||
| 48 | * Creates a new instance of CmdKernel. |
||
| 49 | * Default configuration file name will be used. |
||
| 50 | */ |
||
| 51 | public CmdKernel() { |
||
| 52 | super("Config\\Kernel.xml"); |
||
| 53 | } |
||
| 54 | |||
| 55 | /** |
||
| 56 | * Starts up this kernel. |
||
| 57 | */ |
||
| 58 | public void startup() throws MbStartupException { |
||
| 59 | //startup MbKernel |
||
| 60 | super.startup(); |
||
| 61 | try { |
||
| 62 | _debug.println("Loading Swing look and feel (for module GUIs)"); |
||
| 63 | //UIManager.setLookAndFeel(new ExtWindowsLookAndFeel()); |
||
| 64 | UIManager.setLookAndFeel(new Plastic3DLookAndFeel()); |
||
| 65 | } catch (Exception e) { |
||
| 66 | } |
||
| 67 | startTime = System.currentTimeMillis(); |
||
| 68 | /*our hashmap must be synchronized since module GUIs, which are |
||
| 69 | JFrames, and thus separate threads, will access it at the same |
||
| 70 | time as we do*/ |
||
| 71 | loadedModuleGUIs = Collections.synchronizedMap(new HashMap(32)); |
||
| 72 | } |
||
| 73 | |||
| 74 | /** |
||
| 75 | * Shuts down this kernel. |
||
| 76 | */ |
||
| 77 | public void shutdown() { |
||
| 78 | //must synchronize iterator |
||
| 79 | synchronized(loadedModuleGUIs) { |
||
| 80 | //kill all opened module GUI windows |
||
| 81 | Iterator it = loadedModuleGUIs.values().iterator(); |
||
| 82 | while (it.hasNext()) { |
||
| 83 | ModuleGUIWindow w = (ModuleGUIWindow)it.next(); |
||
| 84 | w.dispose(); |
||
| 85 | } |
||
| 86 | } |
||
| 87 | //shut down MbKernel |
||
| 88 | super.shutdown(); |
||
| 89 | } |
||
| 90 | |||
| 91 | /** |
||
| 92 | * Gets the kernel uptime. |
||
| 93 | * @return Uptime in seconds |
||
| 94 | */ |
||
| 95 | private int getUptime() { |
||
| 96 | //uptime in msec |
||
| 97 | long uptime = System.currentTimeMillis()-startTime; |
||
| 98 | //in secs |
||
| 99 | float uptimeSecs = uptime/1000F; |
||
| 100 | return (int)(uptimeSecs+0.5); |
||
| 101 | } |
||
| 102 | |||
| 103 | /** |
||
| 104 | * Finds out whether or not a module has a graphical user interface. |
||
| 105 | * @param moduleName The name of the module class. |
||
| 106 | * @return True if this module has a GUI, false otherwise (or if module wasn't found). |
||
| 107 | */ |
||
| 108 | public boolean moduleHasGUI(String moduleName) { |
||
| 109 | //get the module |
||
| 110 | MbModule m = (MbModule)loadedModules.get(moduleName); |
||
| 111 | if (m!=null) { |
||
| 112 | //get its interfaces |
||
| 113 | Class[] interfaces = m.getClass().getInterfaces(); |
||
| 114 | //check whether the module implements the MbModuleGUI interface |
||
| 115 | for (int i=0; i<interfaces.length; i++) { |
||
| 116 | if (interfaces[i].getName().equals("Macbeth.System.MbModuleGUI")) { |
||
| 117 | return true; |
||
| 118 | } |
||
| 119 | } |
||
| 120 | } |
||
| 121 | return false; |
||
| 122 | } |
||
| 123 | |||
| 124 | /** |
||
| 125 | * Loads the GUI for the specified module. |
||
| 126 | * @param moduleName The classname of the module whose GUI should be loaded. |
||
| 127 | */ |
||
| 128 | public void loadModuleGUI(String moduleName) { |
||
| 129 | //if a GUI is already launched for this module |
||
| 130 | if (loadedModuleGUIs.containsKey(moduleName)) { |
||
| 131 | //do nothing |
||
| 132 | _info.println("This GUI is already loaded!"); |
||
| 133 | return; |
||
| 134 | //else, if this module does have a GUI |
||
| 135 | } else if (moduleHasGUI(moduleName)) { |
||
| 136 | //TODO: maybe this window needs to be saved in a list so it can be shut down when module is unloaded? |
||
| 137 | //create a new window for the GUI |
||
| 138 | MbModuleGUI i = (MbModuleGUI)loadedModules.get(moduleName); |
||
| 139 | ModuleGUIWindow w = new ModuleGUIWindow(moduleName); |
||
| 140 | //and render GUI into this window |
||
| 141 | i.renderGUI(w.getContentPane()); |
||
| 142 | w.setTitle(moduleName); |
||
| 143 | w.pack(); |
||
| 144 | w.setVisible(true); |
||
| 145 | } else { |
||
| 146 | _info.println("Module '" + moduleName + "' doesn't have a GUI!"); |
||
| 147 | } |
||
| 148 | } |
||
| 149 | |||
| 150 | /** |
||
| 151 | * Starts a command prompt, and returns when user types one of the exit commands. |
||
| 152 | */ |
||
| 153 | private void cmdPrompt() { |
||
| 154 | BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in)); |
||
| 155 | String cmd = ""; |
||
| 156 | String args[] = new String[0]; |
||
| 157 | while (true) { |
||
| 158 | System.out.println("[" + name() + ":" + internetTransport.ourPort + "]"); |
||
| 159 | //try to get command line input |
||
| 160 | try { |
||
| 161 | cmd = stdin.readLine(); |
||
| 162 | } catch (IOException ioError) { |
||
| 163 | //don't care |
||
| 164 | } |
||
| 165 | //now, split cmd into args |
||
| 166 | args = cmd.split(" "); |
||
| 167 | //don't execute the following code if cmd is empty |
||
| 168 | if (args.length<=0 || cmd.equals("")) { |
||
| 169 | continue; |
||
| 170 | } |
||
| 171 | if (args[0].equalsIgnoreCase("exit") || args[0].equalsIgnoreCase("quit") || args[0].equalsIgnoreCase("q")) { |
||
| 172 | //these commands shut down the kernel |
||
| 173 | System.out.println("Quitting..."); |
||
| 174 | break; |
||
| 175 | } |
||
| 176 | else if (args[0].equalsIgnoreCase("info")) { |
||
| 177 | //this command shows kernel info |
||
| 178 | System.out.println("Kernel information:"); |
||
| 179 | System.out.println(" Name: " + name()); |
||
| 180 | System.out.println(" Internet server at port: " + internetTransport.ourPort); |
||
| 181 | //uptime info |
||
| 182 | int uptime = getUptime(); |
||
| 183 | int seconds = uptime % 60; |
||
| 184 | int minutes = (uptime / 60) % 60; |
||
| 185 | int hours = (uptime / 3600) % 24; |
||
| 186 | int days = uptime / 3600 / 24; |
||
| 187 | System.out.println(" Uptime: " + days + " days, " + hours + " hours, " + minutes + " minutes, " + seconds + " secs"); |
||
| 188 | //transport info |
||
| 189 | System.out.println(" Packet transport systems:"); |
||
| 190 | int packetsSentTotal = 0; |
||
| 191 | Iterator it = packetTransports.iterator(); |
||
| 192 | while (it.hasNext()) { |
||
| 193 | MbPacketTransport pt = (MbPacketTransport)it.next(); |
||
| 194 | if (pt!=null) { |
||
| 195 | System.out.println(" - " + pt.getName()); |
||
| 196 | System.out.println(" Packets sent: " + pt.packetsSent); |
||
| 197 | System.out.println(" Packets received: " + pt.packetsReceived); |
||
| 198 | packetsSentTotal += pt.packetsSent; |
||
| 199 | } |
||
| 200 | } |
||
| 201 | //packet info |
||
| 202 | System.out.println(" Avarage kernel workload: " + (float)packetsSentTotal/(float)uptime + " packets/sec (a packet every " + (float)uptime/(float)packetsSentTotal + " sec)"); |
||
| 203 | //queue size |
||
| 204 | System.out.println(" Current packet queue size: " + packetQueue.getSize() + " packets"); |
||
| 205 | } |
||
| 206 | else if (args[0].equalsIgnoreCase("kernels")) { |
||
| 207 | //this command shows a list of other known kernels |
||
| 208 | System.out.println("Listing known kernels (edit your config-file to add more):"); |
||
| 209 | String[] kernels = internetTransport.kernelList.getNameList(); |
||
| 210 | for (int i=0; i<kernels.length; i++) { |
||
| 211 | System.out.println(" name: " + kernels[i] + ", hostname: " + internetTransport.kernelList.getAddress(kernels[i]).getHostname() + ", port: " + internetTransport.kernelList.getAddress(kernels[i]).getPort()); |
||
| 212 | } |
||
| 213 | } |
||
| 214 | else if (args[0].equalsIgnoreCase("modules")) { |
||
| 215 | //this command lists loaded modules |
||
| 216 | System.out.println("Listing loaded modules:"); |
||
| 217 | Iterator it = loadedModules.keySet().iterator(); |
||
| 218 | while (it.hasNext()) { |
||
| 219 | String moduleName = (String) it.next(); |
||
| 220 | MbModule m = (MbModule) loadedModules.get(moduleName); |
||
| 221 | System.out.println(" - '" + moduleName + "'" + (moduleHasGUI(moduleName) ? " [has GUI!]" : "")); |
||
| 222 | System.out.println(" description: " + m.description()); |
||
| 223 | } |
||
| 224 | } |
||
| 225 | else if (args[0].equalsIgnoreCase("modulelist")) { |
||
| 226 | //this command lists loaded modules |
||
| 227 | System.out.println("Complete module list (not all are loaded!):"); |
||
| 228 | Iterator it = moduleList.keySet().iterator(); |
||
| 229 | while (it.hasNext()) { |
||
| 230 | String moduleName = (String)it.next(); |
||
| 231 | MbModule m = (MbModule)loadedModules.get(moduleName); |
||
| 232 | System.out.println(" - '" + moduleName + "'" + (m!=null ? " [Loaded]" : "")); |
||
| 233 | } |
||
| 234 | } |
||
| 235 | else if (args[0].equalsIgnoreCase("gui")) { |
||
| 236 | //this command shows or hides a modules gui |
||
| 237 | if (args.length >= 2) { |
||
| 238 | System.out.println("Loading new GUI for '" + args[1] + "'..."); |
||
| 239 | MbModule m = (MbModule)loadedModules.get(args[1]); |
||
| 240 | if (m != null) { |
||
| 241 | loadModuleGUI(args[1]); |
||
| 242 | } else { |
||
| 243 | System.out.println("Module '" + args[1] + "' is not loaded!"); |
||
| 244 | } |
||
| 245 | } else { |
||
| 246 | System.out.println("Error in command line: To few parameters"); |
||
| 247 | } |
||
| 248 | } |
||
| 249 | else if (args[0].equalsIgnoreCase("load")) { |
||
| 250 | //this command starts up a specified module |
||
| 251 | if (args.length >= 2) { |
||
| 252 | try { |
||
| 253 | if (!loadModule(args[1])) { |
||
| 254 | System.out.println("Module '" + args[1] + "' is already loaded!"); |
||
| 255 | } |
||
| 256 | } catch (MbModuleNotFoundException e) { |
||
| 257 | System.out.println("Module '" + args[1] + "' could not be found!"); |
||
| 258 | } catch (MbModuleLoadException e) { |
||
| 259 | _errors.println("'" + args[1] + "' failed to load! (" + e + ")"); |
||
| 260 | } |
||
| 261 | } else { |
||
| 262 | System.out.println("Error in command line: To few parameters"); |
||
| 263 | } |
||
| 264 | } |
||
| 265 | else if (args[0].equalsIgnoreCase("unload")) { |
||
| 266 | //this command shuts down a specified module |
||
| 267 | if (args.length >= 2) { |
||
| 268 | if (!unloadModule(args[1])) { |
||
| 269 | System.out.println("Module '" + args[1] + "' is not loaded!"); |
||
| 270 | } |
||
| 271 | } |
||
| 272 | else { |
||
| 273 | System.out.println("Error in command line: To few parameters"); |
||
| 274 | } |
||
| 275 | } |
||
| 276 | else if (args[0].equalsIgnoreCase("data")) { |
||
| 277 | //this command prints all contents of the data repository |
||
| 278 | if (args.length >= 2) { |
||
| 279 | System.out.println("Listing contents of the '" + args[1] + "' data reposotory:"); |
||
| 280 | MbModule m = (MbModule) loadedModules.get(args[1]); |
||
| 281 | if (m != null) { |
||
| 282 | System.out.println(m.getDataRepository().listContents()); |
||
| 283 | } else { |
||
| 284 | System.out.println("Module '" + args[1] + "' not found!"); |
||
| 285 | } |
||
| 286 | } |
||
| 287 | else { |
||
| 288 | System.out.println("Listing contents of the kernel data repository:"); |
||
| 289 | System.out.println(dataRepository.listContents()); |
||
| 290 | } |
||
| 291 | } |
||
| 292 | else if (args[0].equalsIgnoreCase("do")) { |
||
| 293 | //this command tells the kernel or a module to perform an action |
||
| 294 | if (args.length >= 2) { |
||
| 295 | try { |
||
| 296 | String name = args[1]; |
||
| 297 | String params = (args.length >= 3 ? args[2] : null); |
||
| 298 | this.performAction(new MbAction(name, params)); |
||
| 299 | } catch (MbActionNotPerformedException e) { |
||
| 300 | System.out.println("Action could not be performed! (" + e.getMessage() + ")"); |
||
| 301 | } |
||
| 302 | } else { |
||
| 303 | System.out.println("Not enough parameters"); |
||
| 304 | } |
||
| 305 | } |
||
| 306 | else if (args[0].equalsIgnoreCase("help")) { |
||
| 307 | System.out.println("Available Commands:"); |
||
| 308 | System.out.println(" exit/quit/q - shut down kernel"); |
||
| 309 | System.out.println(" help - shows this help page"); |
||
| 310 | System.out.println(" info - shows some info about this kernel"); |
||
| 311 | System.out.println(" kernels - shows list of other known kernels"); |
||
| 312 | System.out.println(" modules - shows a list of loaded modules"); |
||
| 313 | System.out.println(" modulelist - shows a list of installed modules"); |
||
| 314 | System.out.println(" load <modulename> - loads and starts up a specified module"); |
||
| 315 | System.out.println(" unload <modulename> - unloads and shuts down a specified module"); |
||
| 316 | System.out.println(" gui <modulename> - loads the specified module's GUI"); |
||
| 317 | System.out.println(" data - lists the contents of the kernel data repository"); |
||
| 318 | System.out.println(" data <modulename> - lists the contents of a modules data repository"); |
||
| 319 | } |
||
| 320 | else { |
||
| 321 | System.out.println("Unknown command. Type \"help\" for a list of commands"); |
||
| 322 | } |
||
| 323 | } |
||
| 324 | } |
||
| 325 | |||
| 326 | /** |
||
| 327 | * Program entry point. |
||
| 328 | * @param args The command line arguments. |
||
| 329 | */ |
||
| 330 | public static void main(String[] args) { |
||
| 331 | String configFile = "Config\\Kernel.xml"; |
||
| 332 | //config file can also be specified with command line args |
||
| 333 | if (args.length>0) { |
||
| 334 | configFile = args[0]; |
||
| 335 | } |
||
| 336 | //create new kernel |
||
| 337 | CmdKernel k = new CmdKernel(configFile); |
||
| 338 | try { |
||
| 339 | //try to start up kernel |
||
| 340 | k.startup(); |
||
| 341 | } catch (MbStartupException e) { |
||
| 342 | System.err.println("Failed to start up kernel! (message: '" + e.getMessage() + "')"); |
||
| 343 | k.shutdown(); |
||
| 344 | System.exit(1); |
||
| 345 | } |
||
| 346 | //start kernel command prompt |
||
| 347 | k.cmdPrompt(); |
||
| 348 | //when command prompt returns, it's time to shut down |
||
| 349 | k.shutdown(); |
||
| 350 | } |
||
| 351 | |||
| 352 | /** |
||
| 353 | * A standalone window for a module GUI. |
||
| 354 | */ |
||
| 355 | private class ModuleGUIWindow extends JFrame implements WindowListener { |
||
| 356 | private String moduleName; |
||
| 357 | |||
| 358 | /** |
||
| 359 | * Launches a new GUI window. |
||
| 360 | * @param moduleName The name of the module. |
||
| 361 | */ |
||
| 362 | public ModuleGUIWindow(String moduleName) { |
||
| 363 | super(); |
||
| 364 | this.moduleName = moduleName; |
||
| 365 | setDefaultCloseOperation(DISPOSE_ON_CLOSE); |
||
| 366 | addWindowListener(this); |
||
| 367 | } |
||
| 368 | |||
| 369 | public void windowOpened(WindowEvent e) { |
||
| 370 | //put a reference to this window into the hashmap |
||
| 371 | loadedModuleGUIs.put(moduleName,this); |
||
| 372 | } |
||
| 373 | |||
| 374 | public void windowClosed(WindowEvent e) { |
||
| 375 | //remove our reference from the hashmap |
||
| 376 | loadedModuleGUIs.remove(moduleName); |
||
| 377 | } |
||
| 378 | |||
| 379 | public void windowClosing(WindowEvent e) {} |
||
| 380 | public void windowIconified(WindowEvent e) {} |
||
| 381 | public void windowDeiconified(WindowEvent e) {} |
||
| 382 | public void windowActivated(WindowEvent e) {} |
||
| 383 | public void windowDeactivated(WindowEvent e) {} |
||
| 384 | } |
||
| 385 | } |