Index: trunk/java-utils/src/main/java/de/ugoe/cs/util/console/CommandExecuter.java
===================================================================
--- trunk/java-utils/src/main/java/de/ugoe/cs/util/console/CommandExecuter.java	(revision 2260)
+++ trunk/java-utils/src/main/java/de/ugoe/cs/util/console/CommandExecuter.java	(revision 2281)
@@ -12,5 +12,4 @@
 //   See the License for the specific language governing permissions and
 //   limitations under the License.
-
 
 package de.ugoe.cs.util.console;
@@ -81,6 +80,6 @@
      * </p>
      */
-    private List<String> commandPackageList;
-    
+    private List<CommandPackage> commandPackageList;
+
     /**
      * <p>
@@ -108,5 +107,5 @@
      */
     private CommandExecuter() {
-        commandPackageList = new ArrayList<String>();
+        commandPackageList = new ArrayList<CommandPackage>();
     }
 
@@ -121,9 +120,10 @@
      *             thrown if the package name is null or empty string
      */
-    public void addCommandPackage(String pkg) {
+    public void addCommandPackage(String pkg, ClassLoader loader) {
         if ("".equals(pkg) || pkg == null) {
             throw new IllegalArgumentException("package name must not be null or empty string");
         }
-        commandPackageList.add(pkg);
+        commandPackageList.add(new CommandPackage(pkg, loader));
+        availableCommands = null;
     }
 
@@ -148,13 +148,9 @@
     public void exec(String command) {
         Console.commandNotification(command);
-        Command cmd = null;
         CommandParser parser = new CommandParser();
         parser.parse(command);
-        for (int i = 0; cmd == null && i < commandPackageList.size(); i++) {
-            cmd = loadCMD(commandPackageList.get(i) + "." + cmdPrefix + parser.getCommandName());
-        }
-        if (cmd == null) { // check if command is available as default command
-            cmd = loadCMD(defaultPackage + "." + cmdPrefix + parser.getCommandName());
-        }
+
+        Command cmd = getCMD(parser.getCommandName());
+
         if (cmd == null) {
             Console.println("Unknown command");
@@ -186,45 +182,12 @@
      *         otherwise
      */
-    public Command loadCMD(String className) {
-        Command cmd = null;
-        try {
-            Class<?> cmdClass = Class.forName(className);
-            cmd = (Command) cmdClass.getDeclaredConstructor().newInstance();
-        }
-        catch (NoClassDefFoundError e) {
-            String[] splitResult = e.getMessage().split("CMD");
-            String correctName = splitResult[splitResult.length - 1].replace(")", "");
-            Console.println("Did you mean " + correctName + "?");
-        }
-        catch (ClassNotFoundException e) {}
-        catch (IllegalAccessException e) {}
-        catch (InstantiationException e) {}
-        catch (InvocationTargetException e) {}
-        catch (NoSuchMethodException e) {}
-        catch (ClassCastException e) {
-            Console.traceln(Level.WARNING, className + "found, but does not implement Command");
-        }
-        return cmd;
-    }
-    
-    /**
-     * <p>
-     * Helper method that loads a class and tries to cast it to {@link Command}.
-     * </p>
-     * 
-     * @param className
-     *            qualified name of the class (including package name)
-     * @return if class is available and implement {@link Command} and instance of the class, null
-     *         otherwise
-     */
     public Command getCMD(String commandName) {
-        Command cmd = null;
-        for (int i = 0; cmd == null && i < commandPackageList.size(); i++) {
-            cmd = loadCMD(commandPackageList.get(i) + "." + cmdPrefix + commandName);
-        }
-        if (cmd == null) { // check if command is available as default command
-            cmd = loadCMD(defaultPackage + "." + cmdPrefix + commandName);
-        }
-        return cmd;
+        for (Command candidate : getAvailableCommands()) {
+            if (candidate.getClass().getSimpleName().equals(cmdPrefix + commandName)) {
+                return candidate;
+            }
+        }
+
+        return null;
     }
 
@@ -239,22 +202,22 @@
     public Command[] getAvailableCommands() {
         if (availableCommands == null) {
-            List<Command> commands = new ArrayList<Command>();
-            List<String> packages = new ArrayList<String>();
+            // List<Command> commands = new ArrayList<Command>();
+            List<CommandPackage> packages = new ArrayList<CommandPackage>();
             packages.addAll(commandPackageList);
-            packages.add(defaultPackage);
+            packages.add(new CommandPackage(defaultPackage, this.getClass().getClassLoader()));
 
             FilenameFilter filter = new FilenameFilter() {
                 @Override
                 public boolean accept(File dir, String name) {
-                    return
-                        (name != null) && (name.startsWith(cmdPrefix)) && (name.endsWith(".class"));
+                    return (name != null) && (name.startsWith(cmdPrefix)) &&
+                        (name.endsWith(".class"));
                 }
             };
 
-            SortedSet<String> classNames = new TreeSet<String>(new Comparator<String>() {
+            SortedSet<Command> commands = new TreeSet<Command>(new Comparator<Command>() {
                 @Override
-                public int compare(String arg1, String arg2) {
-                    String str1 = arg1.substring(arg1.lastIndexOf('.') + cmdPrefix.length() + 1);
-                    String str2 = arg2.substring(arg2.lastIndexOf('.') + cmdPrefix.length() + 1);
+                public int compare(Command arg1, Command arg2) {
+                    String str1 = arg1.getClass().getSimpleName().substring(cmdPrefix.length());
+                    String str2 = arg2.getClass().getSimpleName().substring(cmdPrefix.length());
                     return str1.compareTo(str2);
                 }
@@ -262,8 +225,14 @@
             });
 
-            for (String packageName : packages) {
-                String path = packageName.replace('.', '/');
+            for (CommandPackage commandPackage : packages) {
+                String path = commandPackage.getPackageName().replace('.', '/');
                 try {
-                    Enumeration<URL> resources = ClassLoader.getSystemResources(path);
+                    ClassLoader loader = commandPackage.getClassLoader();
+
+                    if (loader == null) {
+                        loader = ClassLoader.getSystemClassLoader();
+                    }
+
+                    Enumeration<URL> resources = loader.getResources(path);
 
                     while (resources.hasMoreElements()) {
@@ -272,12 +241,17 @@
 
                         if (packageDir.isDirectory()) {
-                        	File[] classFiles = packageDir.listFiles(filter);
-                        	if (classFiles != null) {
-                        		for (File classFile : classFiles) {
-                        			String className = classFile.getName().substring
-                        					(0, classFile.getName().lastIndexOf('.'));
-                        			classNames.add(packageName + "." + className);
-                        		}
-                        	}
+                            File[] classFiles = packageDir.listFiles(filter);
+                            if (classFiles != null) {
+                                for (File classFile : classFiles) {
+                                    String className = classFile.getName()
+                                        .substring(0, classFile.getName().lastIndexOf('.'));
+                                    Class<?> clazz =
+                                        loader.loadClass(commandPackage.getPackageName() + "." +
+                                            className);
+                                    if (Command.class.isAssignableFrom(clazz)) {
+                                      commands.add((Command) clazz.getConstructor().newInstance());
+                                    }
+                                }
+                            }
                         }
                         else {
@@ -298,9 +272,15 @@
                                         entry = jarInputStream.getNextJarEntry();
                                         if ((entry != null) && (!entry.isDirectory()) &&
-                                                (entry.getName().startsWith(path)))
+                                            (entry.getName().startsWith(path)))
                                         {
-                                            String className = entry.getName().substring
-                                                (path.length() + 1, entry.getName().lastIndexOf('.'));
-                                            classNames.add(packageName + "." + className);
+                                            String className = entry.getName()
+                                                .substring(path.length() + 1,
+                                                           entry.getName().lastIndexOf('.'));
+                                            Class<?> clazz =
+                                                loader.loadClass(commandPackage.getPackageName() +
+                                                    "." + className);
+                                            if (Command.class.isAssignableFrom(clazz)) {
+                                                commands.add((Command) clazz.getConstructor().newInstance());
+                                            }
                                         }
                                     }
@@ -309,6 +289,7 @@
                                 catch (Exception e) {
                                     e.printStackTrace();
-                                    Console.traceln(Level.WARNING, "could not read contents of " +
-                                                    "jar " + jarFile);
+                                    Console
+                                        .traceln(Level.WARNING,
+                                                 "could not read contents of " + "jar " + jarFile);
                                 }
                                 finally {
@@ -323,24 +304,43 @@
                 }
                 catch (IOException e) {
-                    Console.traceln
-                        (Level.WARNING, "could not read commands of package " + packageName);
+                    Console.traceln(Level.WARNING, "could not read commands of package " +
+                        commandPackage.getPackageName());
+                }
+                catch (ClassNotFoundException e) {
+                    Console.traceln(Level.WARNING, "could not load a command of package " +
+                        commandPackage.getPackageName() + ": " + e);
+                }
+                catch (InstantiationException e) {
+                    Console.traceln(Level.WARNING, "could not load a command of package " +
+                        commandPackage.getPackageName() + ": " + e);
+                }
+                catch (IllegalAccessException e) {
+                    Console.traceln(Level.WARNING, "could not load a command of package " +
+                        commandPackage.getPackageName() + ": " + e);
+                }
+                catch (IllegalArgumentException e) {
+                    Console.traceln(Level.WARNING, "could not load a command of package " +
+                        commandPackage.getPackageName() + ": " + e);
+                }
+                catch (InvocationTargetException e) {
+                    Console.traceln(Level.WARNING, "could not load a command of package " +
+                        commandPackage.getPackageName() + ": " + e);
+                }
+                catch (NoSuchMethodException e) {
+                    Console.traceln(Level.WARNING, "could not load a command of package " +
+                        commandPackage.getPackageName() + ": " + e);
+                }
+                catch (SecurityException e) {
+                    Console.traceln(Level.WARNING, "could not load a command of package " +
+                        commandPackage.getPackageName() + ": " + e);
                 }
             }
 
-            for (String className : classNames) {
-                // class may still be inner classes. Therefore load the command, to
-                // see if it is really available and a command.
-                Command cmd = loadCMD(className);
-                if (cmd != null) {
-                    commands.add(cmd);
-                }
-            }
-
             availableCommands = commands.toArray(new Command[commands.size()]);
         }
-        
+
         return Arrays.copyOf(availableCommands, availableCommands.length);
     }
-    
+
     /**
      * <p>
@@ -351,6 +351,12 @@
      */
     public List<String> getCommandPackages() {
-        List<String> commandPackageListCopy = new ArrayList<String>(commandPackageList);
-        commandPackageListCopy.add(0, defaultPackage);
+        List<String> commandPackageListCopy = new ArrayList<>();
+
+        commandPackageListCopy.add(defaultPackage);
+
+        for (CommandPackage pkg : commandPackageList) {
+            commandPackageListCopy.add(pkg.getPackageName());
+        }
+
         return commandPackageListCopy;
     }
@@ -359,10 +365,11 @@
      * <p>
      * this method method performs an auto completion of the provided String as far as possible
-     * regarding the available commands. It auto completes to the full command name, if only
-     * one command matches the given prefix. It auto completes to the common denominator, if
-     * several commands match the prefix
+     * regarding the available commands. It auto completes to the full command name, if only one
+     * command matches the given prefix. It auto completes to the common denominator, if several
+     * commands match the prefix
      * </p>
      *
-     * @param commandPrefix the prefix to be auto completed
+     * @param commandPrefix
+     *            the prefix to be auto completed
      * 
      * @return as described
@@ -370,12 +377,53 @@
     public String autoCompleteCommand(String commandPrefix) {
         Command[] commands = getAvailableCommands();
-        
+
         String[] completions = new String[commands.length];
-        
+
         for (int i = 0; i < commands.length; i++) {
             completions[i] = commands[i].getClass().getSimpleName().substring(3);
         }
-        
+
         return StringTools.autocomplete(commandPrefix, completions);
     }
+
+    /**
+     * represents a command package with a package name and the class loader to use
+     */
+    private class CommandPackage {
+        /**
+         * the name of the represented package
+         */
+        private String packageName;
+
+        /**
+         * the class loader to use to load the package
+         */
+        private ClassLoader classLoader;
+
+        /**
+         * <p>
+         * instantiate the fields
+         * </p>
+         */
+        public CommandPackage(String packageName, ClassLoader classLoader) {
+            super();
+            this.packageName = packageName;
+            this.classLoader = classLoader;
+        }
+
+        /**
+         * @return the packageName
+         */
+        public String getPackageName() {
+            return packageName;
+        }
+
+        /**
+         * @return the classLoader
+         */
+        public ClassLoader getClassLoader() {
+            return classLoader;
+        }
+
+    }
 }
