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