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

Last change on this file since 825 was 825, checked in by davidb, 10 years ago

SVN test

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