Skip to content

Commit 3927f28

Browse files
committed
CommandService: don't run Command/Module hybrids
Unfortunately, running such a command (e.g., DynamicCommand) results in the command instance -- and not a CommandModule -- being returned by ModuleService#run. Rather than fix the API and break backwards compatibility, we apply a band-aid for now: this commit checks for that situation and proactively throws an IllegalArgumentException, rather than throwing a cryptic ClassCastException after the fact. This commit is also dedicated to Richard Domander.
1 parent 13e4ec3 commit 3927f28

File tree

1 file changed

+25
-0
lines changed

1 file changed

+25
-0
lines changed

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

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
import org.scijava.event.EventHandler;
4242
import org.scijava.event.EventService;
4343
import org.scijava.log.LogService;
44+
import org.scijava.module.Module;
4445
import org.scijava.module.ModuleService;
4546
import org.scijava.plugin.AbstractPTService;
4647
import org.scijava.plugin.Parameter;
@@ -182,6 +183,7 @@ public <C extends Command> Future<CommandModule> run(
182183
public Future<CommandModule> run(final CommandInfo info,
183184
final boolean process, final Object... inputs)
184185
{
186+
validateModuleType(info);
185187
@SuppressWarnings({ "rawtypes", "unchecked" })
186188
final Future<CommandModule> future =
187189
(Future) moduleService.run(info, process, inputs);
@@ -192,6 +194,7 @@ public Future<CommandModule> run(final CommandInfo info,
192194
public Future<CommandModule> run(final CommandInfo info,
193195
final boolean process, final Map<String, Object> inputMap)
194196
{
197+
validateModuleType(info);
195198
@SuppressWarnings({ "rawtypes", "unchecked" })
196199
final Future<CommandModule> future =
197200
(Future) moduleService.run(info, process, inputMap);
@@ -348,4 +351,26 @@ private <PT extends SciJavaPlugin> List<PluginInfo<?>> downcast(
348351
return typedPlugins;
349352
}
350353

354+
/**
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.
359+
*/
360+
private void validateModuleType(final CommandInfo info) {
361+
try {
362+
final Class<?> commandClass = info.loadDelegateClass();
363+
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.");
369+
}
370+
}
371+
catch (final ClassNotFoundException exc) {
372+
throw new IllegalStateException("Command class unavailable: " + //
373+
info.getDelegateClassName(), exc);
374+
}
375+
}
351376
}

0 commit comments

Comments
 (0)