protected void addExtension(ExtensionWrapper extension)
      throws NoSuchExtensionException, ExtensionInitializationException,
          ExtensionAlreadyLoadedException, DuplicateExtensionException {
    if (extension == null || extension.getExtension() == null) {
      throw new IllegalArgumentException("Extension cannot be null");
    }
    if (has(extension.getName())) {
      throw new DuplicateExtensionException(extension.getName());
    }
    @SuppressWarnings("unchecked")
    final ProxiedExtensionWrapper wrapper = new ProxiedExtensionWrapper(extension);
    if (extension.getExtension() instanceof PerpetualExtension) {
      wrapper.setOnBeforeUnload(
          new ExtensionWrapperEventCallback() {

            @Override
            public <E> void execute(ExtensionWrapper<E> wrapper) {
              throw new IllegalStateException("Extension cannot be unloaded: " + wrapper.getName());
            }
          });
    }
    console.debug("Extension found: " + extension.getName());
    extensions.put(extension.getName(), wrapper);
    if (extension.getExtension() instanceof AutoLoadedExtension) {
      console.debug("Extension auto-loaded: " + extension.getName());
      load(extension.getName());
    }
  }
 @Override
 public void execute(String command)
     throws InvalidCommandException, AmbiguousCommandException, ConsoleCommandExecutionException {
   command = command.trim();
   String target = "";
   if (command.matches("\\S+:.*")) {
     target = command.substring(0, command.indexOf(":"));
     command = command.substring(command.indexOf(":") + 1).trim();
     for (ProxiedExtensionWrapper wrapper : extensions.values()) {
       if (wrapper.getNamespace().equals(target)) {
         wrapper.execute(command);
         target = "";
         break;
       }
     }
     if (!target.isEmpty()) {
       throw new IllegalStateException("No such namespace: " + target);
     }
     return;
   }
   final Set<ExtensionWrapper> namespaces = new HashSet<ExtensionWrapper>();
   for (String name : loaded) {
     ProxiedExtensionWrapper wrapper = extensions.get(name);
     if (wrapper.knows(command)) {
       namespaces.add(wrapper);
     }
   }
   if (namespaces.isEmpty()) {
     throw new InvalidCommandException("Invalid command: " + command);
   }
   if (namespaces.size() == 1) {
     final ExtensionWrapper wrapper = namespaces.iterator().next();
     wrapper.execute(command);
     return;
   }
   final String[] strings = new String[namespaces.size()];
   int i = 0;
   for (ExtensionWrapper namespace : namespaces) {
     strings[i++] = namespace.getNamespace();
   }
   throw new AmbiguousCommandException(command, strings);
 }