Skip to content

Commit a67c719

Browse files
committed
CommandService: fix the DynamicCommand run hack
With 3927f28, we tried to avoid a scenario where ClassCastException is thrown when running a command that implements Module (e.g. DynamicCommand). Unfortunately, that fix is problematic because the command no longer actually runs; this breaks e.g. OptionsPlugins launched from the menu. Instead, let's run it, but return null for the result, and log an informative debug message. This should be no worse than originally.
1 parent a973b72 commit a67c719

File tree

1 file changed

+21
-20
lines changed

1 file changed

+21
-20
lines changed

src/main/java/org/scijava/command/DefaultCommandService.java

Lines changed: 21 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -183,22 +183,16 @@ public <C extends Command> Future<CommandModule> run(
183183
public Future<CommandModule> run(final CommandInfo info,
184184
final boolean process, final Object... inputs)
185185
{
186-
validateModuleType(info);
187-
@SuppressWarnings({ "rawtypes", "unchecked" })
188-
final Future<CommandModule> future =
189-
(Future) moduleService.run(info, process, inputs);
190-
return future;
186+
final Future<Module> future = moduleService.run(info, process, inputs);
187+
return validateFuture(future, info);
191188
}
192189

193190
@Override
194191
public Future<CommandModule> run(final CommandInfo info,
195192
final boolean process, final Map<String, Object> inputMap)
196193
{
197-
validateModuleType(info);
198-
@SuppressWarnings({ "rawtypes", "unchecked" })
199-
final Future<CommandModule> future =
200-
(Future) moduleService.run(info, process, inputMap);
201-
return future;
194+
final Future<Module> future = moduleService.run(info, process, inputMap);
195+
return validateFuture(future, info);
202196
}
203197

204198
// -- PTService methods --
@@ -352,25 +346,32 @@ private <PT extends SciJavaPlugin> List<PluginInfo<?>> downcast(
352346
}
353347

354348
/**
355-
* A HACK to prevent calling run when the resultant module will not be a
356-
* {@link CommandModule}. This is an API design flaw in CommandService
357-
* currently, but for now work around it rather than breaking backwards API
358-
* compatibility.
349+
* A HACK to avoid {@link ClassCastException} when calling run when the
350+
* resultant module will not be a {@link CommandModule}. This is an API design
351+
* flaw in CommandService currently, but for now we work around it rather than
352+
* breaking backwards API compatibility.
359353
*/
360-
private void validateModuleType(final CommandInfo info) {
354+
private Future<CommandModule> validateFuture(final Future<Module> future,
355+
final CommandInfo info)
356+
{
361357
try {
362358
final Class<?> commandClass = info.loadDelegateClass();
363359
if (Module.class.isAssignableFrom(commandClass)) {
364-
throw new IllegalArgumentException("Cannot use " +
365-
"commandService.run(commandClass, ...) " +
366-
"with classes that extend Module directly. Please call " +
367-
"moduleService.run(commandService.getCommand(commandClass), ...) " +
368-
"instead.");
360+
log.debug("The command '" + info.getIdentifier() +
361+
"' extends Module directly. Due to a design flaw in the " +
362+
"CommandService API, the result cannot be coerced to a " +
363+
"Future<CommandModule>, so null will be returned instead. " +
364+
"If you need the resulting module, please instead call " +
365+
"moduleService.run(commandService.getCommand(commandClass), ...).");
366+
return null;
369367
}
370368
}
371369
catch (final ClassNotFoundException exc) {
372370
throw new IllegalStateException("Command class unavailable: " + //
373371
info.getDelegateClassName(), exc);
374372
}
373+
@SuppressWarnings({ "rawtypes", "unchecked" })
374+
final Future<CommandModule> result = (Future) future;
375+
return result;
375376
}
376377
}

0 commit comments

Comments
 (0)