source: trunk/src/org/expeditee/actions/Actions.java@ 826

Last change on this file since 826 was 826, checked in by bln4, 10 years ago

Inserting a temp comment.

File size: 27.7 KB
Line 
1package org.expeditee.actions;
2
3/* Test to help debug SVN concurrent commit/update problem */
4
5import java.awt.GraphicsEnvironment;;
6import java.io.File;
7import java.io.IOException;
8import java.lang.reflect.Constructor;
9import java.lang.reflect.Method;
10import java.lang.reflect.Modifier;
11import java.net.URL;
12import java.net.URI;
13import java.net.URLDecoder;
14import java.net.JarURLConnection;
15import java.rmi.UnexpectedException;
16import java.util.ArrayList;
17import java.util.Collection;
18import java.util.Enumeration;
19import java.util.HashMap;
20import java.util.LinkedList;
21import java.util.List;
22import java.util.Set;
23import java.util.jar.JarEntry;
24import java.util.jar.JarFile;
25import java.util.zip.ZipEntry;
26
27import org.expeditee.agents.Agent;
28import org.expeditee.gui.DisplayIO;
29import org.expeditee.gui.Frame;
30import org.expeditee.gui.FrameGraphics;
31import org.expeditee.gui.FrameIO;
32import org.expeditee.gui.FrameUtils;
33import org.expeditee.gui.FreeItems;
34import org.expeditee.gui.MessageBay;
35import org.expeditee.io.Conversion;
36import org.expeditee.items.Item;
37import org.expeditee.items.ItemUtils;
38import org.expeditee.items.Text;
39import org.expeditee.reflection.PackageLoader;
40import org.expeditee.settings.UserSettings;
41import org.expeditee.simple.SString;
42import org.expeditee.stats.Logger;
43
44/**
45 * The Action class is used to launch Actions and Agents.
46 *
47 * This class checks all class files in the same directory, and reads in and adds all the methods from them. The methods
48 * are stored in a Hashtable so that the lowercase method names can be mapped to the correctly capatilized method names
49 * (to provide case-insensitivity)
50 *
51 * When adding an action to a class in the actions folder the following must be considered: <li>If the first parameter
52 * is of type Frame, the current frame will be passed as a parameter. <li>If the next param is of type Item the item on
53 * the end of the cursor will be passed or the item that was clicked to execute the action if nothing is on the end of
54 * the cursor. current frame or item.</li> <li>If there are multiple overloads for the same method they should be
55 * declared in order of the methods with the most parameteres to least parameters.</li>
56 */
57public class Actions {
58
59 private static final String INVALID_PARAMETERS_ERROR = "Invalid parameters for agent: "; //$NON-NLS-1$
60
61 //Temp comment
62
63 // the currently running agent (if there is one)
64 private static Agent _Agent = null;
65
66 // maps lower case method names to the method
67 private static HashMap<String, Method> _Actions = new HashMap<String, Method>();
68
69 // map lower case fonts to capitalized fonts
70 private static HashMap<String, String> _Fonts = new HashMap<String, String>();
71
72 // maps lower case JAG class names to capitalized JAG full class names
73 private static HashMap<String, String> _JAGs = new HashMap<String, String>();
74
75 // maps lower case IW class names to capitalized IW names
76 private static HashMap<String, String> _IWs = new HashMap<String, String>();
77
78 public static final String ROOT_PACKAGE = "org.expeditee.";
79
80 // Package and class file locations
81 public static final String ACTIONS_PACKAGE = ROOT_PACKAGE + "actions.";
82
83 public static final String AGENTS_PACKAGE = ROOT_PACKAGE + "agents.";
84
85 public static final String WIDGET_PACKAGE = ROOT_PACKAGE + "items.widgets.";
86
87 public static final String CHARTS_PACKAGE = ROOT_PACKAGE + "items.widgets.charts.";
88
89 public static final String NAVIGATIONS_CLASS = ROOT_PACKAGE + "actions.NavigationActions";
90
91 // public static Class[] getClasses(String pckgname)
92 // throws ClassNotFoundException {
93 // ArrayList<Class> classes = new ArrayList<Class>();
94 // // Get a File object for the package
95 // File directory = null;
96 // // Must be a forward slash for loading resources
97 // String path = pckgname.replace('.', '/');
98 // System.err.println("Get classes: " + path);
99 // try {
100 // ClassLoader cld = Thread.currentThread().getContextClassLoader();
101 // if (cld == null) {
102 // throw new ClassNotFoundException("Can't get class loader.");
103 // }
104 // URL resource = null;
105 // try {
106 // Enumeration<URL> resources = cld.getResources(path);
107 // System.err.println(resources);
108 // while (resources.hasMoreElements()) {
109 // URL url = resources.nextElement();
110 // // Ingore the classes in the test folder when we are running
111 // // the program from Eclipse
112 // // This doesnt apply when running directly from the jar
113 // // because the test classes are not compiled into the jar.
114 // // TODO change this so it is only done when running from
115 // // Eclipse... if it causes problems again!!
116 // // if (!url.toString().toLowerCase().contains("/tests/")) {
117 // resource = url;
118 // // break;
119 // // }
120 // }
121 // } catch (Exception e) {
122 // e.printStackTrace();
123 // }
124 // if (resource == null) {
125 // throw new ClassNotFoundException("No resource for " + path);
126 // }
127 // directory = new File(resource.getFile());
128 // } catch (NullPointerException x) {
129 // x.printStackTrace();
130 // throw new ClassNotFoundException(pckgname + " (" + directory
131 // + ") does not appear to be a valid package");
132 // }
133 // // System.out.println("Path:" + directory.getPath());
134 // int splitPoint = directory.getPath().indexOf('!');
135 // if (splitPoint > 0) {
136 // try {
137 // String jarName = directory.getPath().substring(
138 // "file:".length(), splitPoint);
139 // // Windows HACK
140 // if (jarName.indexOf(":") >= 0)
141 // jarName = jarName.substring(1);
142 //
143 // if (jarName.indexOf("%20") > 0) {
144 // jarName = jarName.replace("%20", " ");
145 // }
146 // // System.out.println("JarName:" + jarName);
147 // JarFile jarFile = new JarFile(jarName);
148 //
149 // Enumeration entries = jarFile.entries();
150 // int classCount = 0;
151 // while (entries.hasMoreElements()) {
152 // ZipEntry entry = (ZipEntry) entries.nextElement();
153 // String className = entry.getName();
154 // if (className.startsWith(path)) {
155 // if (className.endsWith(".class")
156 // && !className.contains("$")) {
157 // classCount++;
158 // // The forward slash below is a forwards slash for
159 // // both windows and linux
160 // classes.add(Class.forName(className.substring(0,
161 // className.length() - 6).replace('/', '.')));
162 // }
163 // }
164 // }
165 // jarFile.close();
166 // // System.out.println("Loaded " + classCount + " classes from "
167 // // + pckgname);
168 //
169 // } catch (Exception e) {
170 // e.printStackTrace();
171 // }
172 //
173 // } else {
174 //
175 // if (directory.exists()) {
176 // // Get the list of the files contained in the package
177 // String[] files = directory.list();
178 // for (int i = 0; i < files.length; i++) {
179 // // we are only interested in .class files
180 // if (files[i].endsWith(".class") && !files[i].contains("$")
181 // && !files[i].equals("Actions.class")) {
182 // // removes the .class extension
183 // classes
184 // .add(Class.forName(pckgname
185 // + files[i].substring(0, files[i]
186 // .length() - 6)));
187 // }
188 // }
189 // } else {
190 // throw new ClassNotFoundException("The package '" + pckgname +
191 // "' in the directory '" + directory
192 // + "' does not appear to be a valid package");
193 // }
194 // }
195 // Class[] classesA = new Class[classes.size()];
196 // classes.toArray(classesA);
197 // return classesA;
198 // }
199
200 /**
201 * Clears out the Action and JAG Hashtables and refills them. Normally this is only called once when the system
202 * starts.
203 *
204 * @return a warning message if there were any problems loading agents or actions.
205 */
206 public static Collection<String> Init() {
207
208 Collection<String> warnings = new LinkedList<String>();
209 List<Class<?>> classes;
210
211 try {
212 classes = PackageLoader.getClassesNew(AGENTS_PACKAGE);
213
214 for (Class clazz : classes) {
215 String name = clazz.getSimpleName();
216 // maps lower case name to correct capitalised name
217 _JAGs.put(name.toLowerCase(), clazz.getName());
218 }
219
220
221 classes = PackageLoader.getClassesNew(WIDGET_PACKAGE);
222
223 for (Class clazz : classes) {
224 String name = clazz.getSimpleName();
225 // maps lower case name to correct capitalised name
226 _IWs.put(name.toLowerCase(), WIDGET_PACKAGE + name);
227 }
228
229
230 classes = PackageLoader.getClassesNew(CHARTS_PACKAGE);
231
232 for (Class clazz : classes) {
233 String name = clazz.getSimpleName();
234 // maps lower case name to correct capitalised name
235 _IWs.put("charts." + name.toLowerCase(), CHARTS_PACKAGE + name);
236 }
237 } catch (ClassNotFoundException e) {
238 System.err.println("ClassNotFoundException");
239 e.printStackTrace();
240 } catch (Exception e) {
241 warnings.add("You must have Java 1.5 or higher to run Expeditee");
242 warnings.add(e.getMessage());
243 e.printStackTrace();
244 }
245
246 try {
247 classes = PackageLoader.getClassesNew(ACTIONS_PACKAGE);
248
249 for (Class clazz : classes) {
250 String name = clazz.getSimpleName();
251 // Ignore the test classes
252 if (name.toLowerCase().contains("test"))
253 continue;
254 // read in all the methods from the class
255 try {
256 // System.out.println(name)
257 LoadMethods(Class.forName(ACTIONS_PACKAGE + name));
258 } catch (ClassNotFoundException e) {
259 Logger.Log(e);
260 e.printStackTrace();
261 }
262 }
263 } catch (Exception e) {
264 warnings.add(e.getMessage());
265 }
266 return warnings;
267 }
268
269 /**
270 * Temporary, if a plugin system is devised then this would porbably become redundant. For now this allows external
271 * agents to be included.
272 *
273 * @param fullClassNames
274 * A set of full class names, that is, the class package and name. For
275 * example" "org.myplugin.agents.SerializedSearch"
276 *
277 * @return A collection of classes their were omitted because either there was a name clash with existing agents or
278 * did not exist. i.e. is completely successful this will be empty. Never null.
279 *
280 * @throws NullPointerException
281 * If fullClassNames is null.
282 *
283 */
284 public static Collection<String> addAgents(Set<String> fullClassNames) {
285 if (fullClassNames == null)
286 throw new NullPointerException("fullClassNames");
287
288 List<String> omittedAgents = new LinkedList<String>();
289
290 for (String fullName : fullClassNames) {
291
292 if (fullName == null || fullName.length() == 0)
293 continue;
294
295 boolean didAdd = false;
296
297 try {
298 // Does the class even exist?
299 Class<?> c = Class.forName(fullName);
300
301 String name = c.getSimpleName().toLowerCase();
302
303 if (!_JAGs.containsKey(name)) {
304
305 _JAGs.put(name, fullName);
306 didAdd = true;
307
308 }
309
310 } catch (ClassNotFoundException e) { // Nope it does not exist
311 e.printStackTrace();
312 }
313
314 if (!didAdd)
315 omittedAgents.add(fullName);
316
317 }
318
319 return omittedAgents;
320 }
321
322 /**
323 * Loads all the Methods that meet the requirements checked by MethodCheck into the hashtable.
324 *
325 * @param c
326 * The Class to load the Methods from.
327 */
328 public static void LoadMethods(Class<?> c) {
329 assert (c != null);
330
331 // list of methods to test
332 Method[] toLoad = c.getMethods();
333
334 for (Method m : toLoad) {
335 // only allow methods with the right modifiers
336 if (MethodCheck(m)) {
337 String lowercaseName = m.getName().toLowerCase();
338 if (!(_Actions.containsKey(lowercaseName)))
339 _Actions.put(lowercaseName, m);
340 else {
341 int i = 0;
342 while (_Actions.containsKey(lowercaseName + i))
343 i++;
344
345 _Actions.put(lowercaseName + i, m);
346 }
347
348 }
349 }
350 }
351
352 /**
353 * Checks if the given Method corresponds to the restrictions of Action commands, namely: Declared (not inherited),
354 * Public, and Static, with a void return type.
355 *
356 * @param m
357 * The Method to check
358 * @return True if the Method meets the above conditions, false otherwise.
359 */
360 private static boolean MethodCheck(Method m) {
361 int mods = m.getModifiers();
362
363 // check the method is declared (not inherited)
364 if ((mods & Method.DECLARED) != Method.DECLARED)
365 return false;
366
367 // check the method is public
368 if ((mods & Modifier.PUBLIC) != Modifier.PUBLIC)
369 return false;
370
371 // check the method is static
372 if ((mods & Modifier.STATIC) != Modifier.STATIC)
373 return false;
374
375 // if we have not returned yet, then the tests have all passed
376 return true;
377 }
378
379 /**
380 * Performs the given action command. The source Frame and Item are given because they are required by some actions.
381 * Note that the source frame does not have to be the Item's parent Frame.
382 *
383 * @param source
384 * The Frame that the action should apply to
385 * @param launcher
386 * The Item that has the action assigned to it
387 * @param command
388 * The action to perform
389 */
390 public static Object PerformAction(Frame source, Item launcher, String command) throws Exception {
391 // if (!command.equalsIgnoreCase("Restore"))
392 // FrameIO.SaveFrame(source, false);
393 // TODO make restore UNDO the changes made by the last action
394
395 // separate method name and parameter names
396 String mname = getName(command);
397 command = command.substring(mname.length()).trim();
398 // If no params are provided get them from a text item on the cursor
399 if (command.length() == 0 && launcher instanceof Text && launcher.isFloating()) {
400 command = launcher.getText();
401 }
402
403 // Strip off the @ from annotation items
404 if (mname.startsWith("@"))
405 mname = mname.substring(1);
406
407 mname = mname.trim();
408 String lowercaseName = mname.toLowerCase();
409 // check for protection on frame
410 if (ItemUtils.ContainsTag(source.getItems(), "@No" + mname)) {
411 throw new RuntimeException("Frame is protected by @No" + mname + " tag.");
412 }
413
414 // retrieve methods that match the name
415 Method toRun = _Actions.get(lowercaseName);
416
417 // if this is not the name of a method, it may be the name of an agent
418 if (toRun == null) {
419 LaunchAgent(mname, command, source, launcher);
420 return null;
421 }
422
423 // Need to save the frame if we are navigating away from it so we dont
424 // loose changes
425 if (toRun.getDeclaringClass().getName().equals(NAVIGATIONS_CLASS)) {
426 FrameIO.SaveFrame(DisplayIO.getCurrentFrame());
427 }
428
429 // if there are duplicate methods with the same name
430 List<Method> possibles = new LinkedList<Method>();
431 possibles.add(toRun);
432 int i = 0;
433 while (_Actions.containsKey(lowercaseName + i)) {
434 possibles.add(_Actions.get(lowercaseName + i));
435 i++;
436 }
437
438 for (Method possible : possibles) {
439 // try first with the launching item as a parameter
440
441 // run method
442 try {
443 // convert parameters to objects and get the method to invoke
444 Object[] parameters = CreateObjects(possible, source, launcher, command);
445 // Check that there are the same amount of params
446 if (parameters == null) {
447 continue;
448 }
449
450 return possible.invoke(null, parameters);
451 } catch (Exception e) {
452 Logger.Log(e);
453 e.printStackTrace();
454 }
455 }
456 // If the actions was not found... then it is run as an agent
457 assert (possibles.size() > 0);
458 throw new RuntimeException("Incorrect parameters for " + mname);
459 }
460
461 /**
462 * Launches an agent with the given name, and passes in the given parameters
463 *
464 * @param name
465 * The name of the JAG to load
466 * @param parameters
467 * The parameters to pass to the JAG
468 * @param source
469 * The starting Frame that the JAG is being launched on
470 */
471 private static void LaunchAgent(String name, String parameters, Frame source, Item clicked) throws Exception {
472 // Use the correct case version for printing error messages
473 String nameWithCorrectCase = name;
474 name = name.toLowerCase();
475
476 String fullClassName = AGENTS_PACKAGE + name;
477
478 try {
479 // check for stored capitalisation
480 if (_JAGs.containsKey(name)) {
481 fullClassName = _JAGs.get(name);
482 } else if (name.endsWith("tree")) {
483 parameters = name.substring(0, name.length() - "tree".length()) + " " + parameters;
484 fullClassName = AGENTS_PACKAGE + "writetree";
485
486 } else if (name.endsWith("frame")) {
487 parameters = name.substring(0, name.length() - "frame".length()) + " " + parameters;
488 fullClassName = AGENTS_PACKAGE + "writeframe";
489 }
490
491 // load the JAG class
492 Class<?> agentClass = Class.forName(fullClassName);
493
494 // get the constructor for the JAG class
495 Constructor<?> con = null;
496 Constructor<?>[] constructors = agentClass.getConstructors();
497 Object[] params = null;
498
499 parameters = parameters.trim();
500 // determine correct parameters for constructor
501 for (Constructor<?> c : constructors) {
502 Class<?>[] paramTypes = c.getParameterTypes();
503 int paramCount = paramTypes.length;
504 if (paramCount > 0 && parameters.length() > 0) {
505 params = new Object[paramCount];
506 String[] paramStrings = parameters.split("\\s+");
507 /**
508 * Any extra parameters will be treated as the rest of the string if the last param is a string
509 */
510 if (paramCount > paramStrings.length) {
511 continue;
512 }
513
514 /**
515 * If there are extra parameters the last param must be a String
516 */
517 int lastParam = paramTypes.length - 1;
518
519 if (paramCount < paramStrings.length && !paramTypes[lastParam].equals(String.class)) {
520 continue;
521 }
522
523 try {
524 for (int i = 0; i < paramCount; i++) {
525 SString nextParam = new SString(paramStrings[i]);
526 params[i] = null;
527 if (paramTypes[i].equals(int.class) || paramTypes[i].equals(Integer.class)) {
528 params[i] = nextParam.integerValue().intValue();
529 } else if (paramTypes[i].equals(long.class) || paramTypes[i].equals(Long.class)) {
530 params[i] = nextParam.integerValue();
531 } else if (paramTypes[i].equals(double.class) || paramTypes[i].equals(Double.class)) {
532 params[i] = nextParam.doubleValue();
533 } else if (paramTypes[i].equals(float.class) || paramTypes[i].equals(Float.class)) {
534 params[i] = nextParam.doubleValue().floatValue();
535 } else if (paramTypes[i].equals(boolean.class) || paramTypes[i].equals(Boolean.class)) {
536 params[i] = nextParam.booleanValue();
537 } else if (paramTypes[i].equals(String.class)) {
538 params[i] = nextParam.stringValue();
539 } else {
540 throw new UnexpectedException("Unexpected type " + paramTypes[i].getClass().toString());
541 }
542 }
543 } catch (Exception e) {
544 continue;
545 }
546
547 if (paramCount < paramStrings.length) {
548
549 /**
550 * Append extra params on the end of the last string param
551 */
552 String s = params[lastParam].toString();
553 for (int i = paramCount; i < paramStrings.length; i++) {
554 s += ' ' + paramStrings[i];
555 }
556 params[lastParam] = s;
557 }
558
559 con = c;
560 break;
561 } else if (c.getParameterTypes().length == 0 && con == null) {
562 con = c;
563 params = null;
564 }
565 }
566
567 // if there is no constructor, return
568 if (con == null) {
569 throw new RuntimeException(INVALID_PARAMETERS_ERROR + nameWithCorrectCase);
570 }
571
572 // create the JAG
573 Agent toLaunch = (Agent) con.newInstance(params);
574
575 LaunchAgent(toLaunch, source, clicked);
576
577 } catch (ClassNotFoundException cnf) {
578 _Agent = null;
579 throw new RuntimeException("'" + nameWithCorrectCase + "' is not an action or agent.");
580 }
581 }
582
583 public static void LaunchAgent(String name, String parameters, Frame source) throws Exception {
584 LaunchAgent(name, parameters, source, null);
585 }
586
587 /**
588 * Launches an agent from an already instantiated object.
589 *
590 * @param agent
591 * The agent to launch. Must not be null.
592 *
593 * @param source
594 * The calling frame that launched it. Must not be null.
595 *
596 * @param itemParam
597 * The item parameter for the agent.
598 *
599 * @throws NullPointerException
600 * if any of the arguments are null.
601 */
602 public static void LaunchAgent(Agent agent, Frame source, Item itemParam) {
603
604 if (agent == null)
605 throw new NullPointerException("agent");
606 if (source == null)
607 throw new NullPointerException("source");
608 // if (itemParam == null) throw new NullPointerException("itemParam");
609
610 String nameWithCorrectCase = agent.getClass().getSimpleName();
611
612 try {
613
614 // create the JAG
615 _Agent = agent;
616
617 Thread t = new Thread(_Agent);
618 t.setPriority(Thread.MIN_PRIORITY);
619
620 if (FreeItems.textOnlyAttachedToCursor()) {
621 itemParam = FreeItems.getItemAttachedToCursor();
622 }
623
624 // check for errors during initialisation
625 if (!_Agent.initialise(source, itemParam)) {
626 _Agent = null;
627 throw new RuntimeException("Error initialising agent: " + nameWithCorrectCase);
628 }
629
630 // save the current frame (if necesssary)
631 // TODO make this nicer... ie. make Format an action rather than an
632 // agent and save frames only before running agents
633 if (!nameWithCorrectCase.equalsIgnoreCase("format") && !nameWithCorrectCase.equalsIgnoreCase("sort")) {
634 FrameUtils.LeavingFrame(source);
635 }
636
637 if (_Agent.hasResultString()) {
638 // Just run the agent on this thread... dont run it in the
639 // background
640 t.run();
641 String result = _Agent.toString();
642 // Attach the result to the cursor
643 if (FreeItems.textOnlyAttachedToCursor()) {
644 Item resultItem = FreeItems.getItemAttachedToCursor();
645 resultItem.setText(result);
646 }
647 // if there is a completion frame, then display it to the user
648 } else {
649 t.start();
650 if (_Agent.hasResultFrame()) {
651 // TODO We want to be able to navigate through the frames as
652 // the results are loading
653 Frame next = _Agent.getResultFrame();
654 FrameUtils.DisplayFrame(next, true, true);
655 }
656 }
657 } catch (Exception e) {
658 _Agent = null;
659 e.printStackTrace();
660 throw new RuntimeException("Error creating Agent: '" + nameWithCorrectCase + "'");
661 }
662 FrameGraphics.refresh(false);
663 }
664
665 /**
666 * Used to determine if the previously launched agent is still executing.
667 *
668 * @return True if the last Agent is still executing, False otherwise.
669 */
670 public static boolean isAgentRunning() {
671 if (_Agent != null)
672 return _Agent.isRunning();
673
674 return false;
675 }
676
677 /**
678 * Stops the currently running Agent (If there is one) by calling Agent.stop(). Note: This may not stop the Agent
679 * immediately, but the Agent should terminate as soon as it is safe to do so.
680 */
681 public static void stopAgent() {
682 if (_Agent != null && _Agent.isRunning()) {
683 MessageBay.errorMessage("Stopping Agent...");
684 _Agent.stop();
685 }
686 }
687
688 public static void interruptAgent() {
689 if (_Agent != null) {
690 _Agent.interrupt();
691 }
692 }
693
694 /**
695 * Converts the given String of values into an array of Objects
696 *
697 * @param launcher
698 * The Item used to launch the action, it may be required as a parameter
699 * @param values
700 * A list of space separated String values to convert to objects
701 * @return The created array of Objects
702 */
703 public static Object[] CreateObjects(Method method, Frame source, Item launcher, String values) {
704 // The parameter types that should be created from the given String
705 Class<?>[] paramTypes = method.getParameterTypes();
706
707 int paramCount = paramTypes.length;
708 // if the method has no parameters
709 if (paramCount == 0)
710 return new Object[0];
711
712 Object[] objects = new Object[paramCount];
713 int ind = 0;
714
715 /*
716 * if the first class in the list is a frame or item, it is the source or launcher length must be at least one
717 * if we are still running
718 */
719 if (paramTypes[ind] == Frame.class) {
720 objects[ind] = source;
721 ind++;
722 }
723
724 // Check if the second item is an item
725 if (paramCount > ind && Item.class.isAssignableFrom(paramTypes[ind])) {
726 objects[ind] = launcher;
727 ind++;
728 }// If there is stuff on the cursor use it for the rest of the params
729 else if (launcher != null && launcher.isFloating()) {
730 values = launcher.getText();
731 }
732
733 String param = values;
734 // convert the rest of the objects
735 for (; ind < objects.length; ind++) {
736 // check if its the last param and combine
737 if (values.length() > 0 && ind == objects.length - 1) {
738 param = values.trim();
739 // check if its a string
740 if (param.length() > 0 && param.charAt(0) == '"') {
741 int endOfString = param.indexOf('"', 1);
742 if (endOfString > 0) {
743 param = param.substring(1, endOfString);
744 }
745 }
746 } else {// strip off the next value
747 param = ParseValue(values);
748 values = RemainingParams(values);
749 }
750 // convert the value to an object
751 try {
752 Object o = Conversion.Convert(paramTypes[ind], param);
753 if (o == null)
754 return null;
755 objects[ind] = o;
756 } catch (Exception e) {
757 return null;
758 }
759 }
760
761 return objects;
762 }
763
764 /**
765 * Returns a string containing the remaining params after ignoring the first one.
766 *
767 * @param params
768 * a space sparated list of N parameters
769 * @return the remaining N - 1 parameters
770 */
771 public static String RemainingParams(String params) {
772 if (params.length() == 0)
773 return null;
774
775 // remove leading and trailing spaces
776 params = params.trim();
777
778 // if there are no more parameters, we are done
779 if (params.indexOf(" ") < 0) {
780 return "";
781 }
782
783 // Check if we have a string parameter
784 if (params.charAt(0) == '"') {
785 int endOfString = params.indexOf('"', 1);
786 if (endOfString > 0) {
787 if (endOfString > params.length())
788 return "";
789 return params.substring(endOfString + 1).trim();
790 }
791 }
792
793 return params.substring(params.indexOf(" ")).trim();
794 }
795
796 /**
797 * Returns the first value in the space separated String of parameters passed in. Strings are enclosed in double
798 * quotes.
799 *
800 * @param params
801 * The String of space separated values
802 * @return The first value in the String
803 */
804 public static String ParseValue(String params) {
805 if (params.length() == 0)
806 return null;
807
808 // remove leading and trailing spaces
809 String param = params.trim();
810
811 // Check if we have a string parameter
812 if (param.charAt(0) == '"') {
813 int endOfString = param.indexOf('"', 1);
814 if (endOfString > 0)
815 return param.substring(1, endOfString);
816 }
817
818 // if there are no more parameters, we are done
819 if (param.indexOf(" ") < 0) {
820 return param;
821 }
822
823 return param.substring(0, param.indexOf(" "));
824 }
825
826 /**
827 * Separates the name of the given command from any parameters and returns them
828 *
829 * @param command
830 * The String to separate out the Action or Agent name from
831 * @return The name of the Action of Agent with parameters stripped off
832 */
833 private static String getName(String command) {
834 if (command.indexOf(" ") < 0)
835 return command;
836
837 return command.substring(0, command.indexOf(" "));
838 }
839
840 /**
841 * Gets an uncapitalized font name and returns the capitalized font name. The capitalized form can be used with the
842 * Font.decoded method to get a corresponding Font object.
843 *
844 * @param fontName
845 * a font name in mixed case
846 * @return the correct capitalized form of the font name
847 */
848 public static String getCapitalizedFontName(String fontName) {
849 // Initialize the fonts if they have not already been loaded
850 initFonts();
851 return _Fonts.get(fontName.toLowerCase());
852 }
853
854 /**
855 * Initialise the fontsList if it has not been done already
856 */
857 private static void initFonts() {
858 if (_Fonts.size() == 0) {
859 String[] availableFonts = GraphicsEnvironment.getLocalGraphicsEnvironment().getAvailableFontFamilyNames();
860 for (String s : availableFonts) {
861 _Fonts.put(s.toLowerCase(), s);
862 }
863 }
864 }
865
866 public static HashMap<String, String> getFonts() {
867 initFonts();
868 return _Fonts;
869 }
870
871 public static Object PerformActionCatchErrors(Frame current, Item launcher, String command) {
872 try {
873 return PerformAction(current, launcher, command);
874 } catch (RuntimeException e) {
875 e.printStackTrace();
876 MessageBay.errorMessage("Action failed: " + e.getMessage());
877 } catch (Exception e) {
878 e.printStackTrace();
879 MessageBay.errorMessage("Action failed: " + e.getClass().getSimpleName());
880 }
881 return null;
882 }
883
884 /**
885 * Gets the full class path for a widget with a given case insensitive name.
886 *
887 * @param widgetName
888 * @return
889 */
890 public static String getClassName(String widgetName) {
891 return _IWs.get(widgetName.toLowerCase());
892 }
893
894 static List<String> getActions() {
895 List<String> actionNames = new LinkedList<String>();
896 for (Method m : _Actions.values()) {
897 StringBuilder sb = new StringBuilder();
898 sb.append(m.getName());
899 for (Class<?> c : m.getParameterTypes()) {
900 sb.append(" ").append(c.getSimpleName());
901 }
902 actionNames.add(sb.toString());
903 }
904
905 return actionNames;
906 }
907
908 static List<String> getAgents() {
909 List<String> agentNames = new LinkedList<String>();
910
911 for (String s : _JAGs.values()) {
912 agentNames.add(s.substring(s.lastIndexOf('.') + 1));
913 }
914
915 return agentNames;
916 }
917}
Note: See TracBrowser for help on using the repository browser.